generated from StanfordBDHG/SwiftPackageTemplate
-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Lift to SpeziLLM ## ♻️ Current situation & Problem Dependent on old version of SpeziLLM ## ⚙️ Release Notes - Update to SpeziLLM version 0.7.0 ## 📚 Documentation Proper docs included ## ✅ Testing All tests passing ## 📝 Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md): - [x] I agree to follow the [Code of Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md).
- Loading branch information
1 parent
07c2e56
commit 9a171a2
Showing
41 changed files
with
1,317,434 additions
and
205 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 0 additions & 111 deletions
111
Sources/SpeziFHIRInterpretation/Resources/Localizable.xcstrings
This file was deleted.
Oops, something went wrong.
123 changes: 123 additions & 0 deletions
123
Sources/SpeziFHIRLLM/FHIRInterpretation/MultipleResources/FHIRGetResourceLLMFunction.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// | ||
// This source file is part of the Stanford Spezi project | ||
// | ||
// SPDX-FileCopyrightText: 2023 Stanford University | ||
// | ||
// SPDX-License-Identifier: MIT | ||
// | ||
|
||
import os | ||
import SpeziFHIR | ||
import SpeziLLMOpenAI | ||
|
||
|
||
struct FHIRGetResourceLLMFunction: LLMFunction { | ||
static let logger = Logger(subsystem: "edu.stanford.spezi.fhir", category: "SpeziFHIRLLM") | ||
|
||
static let name = "get_resources" | ||
static let description = String(localized: "FUNCTION_DESCRIPTION") | ||
|
||
private let fhirStore: FHIRStore | ||
private let resourceSummary: FHIRResourceSummary | ||
|
||
|
||
@Parameter var resources: [String] | ||
|
||
|
||
init( | ||
fhirStore: FHIRStore, | ||
resourceSummary: FHIRResourceSummary, | ||
resourceCountLimit: Int, | ||
allowedResourcesFunctionCallIdentifiers: Set<String>? = nil // swiftlint:disable:this discouraged_optional_collection | ||
) { | ||
self.fhirStore = fhirStore | ||
self.resourceSummary = resourceSummary | ||
|
||
// Only take newest values of the health records | ||
var allResourcesFunctionCallIdentifiers = Set(fhirStore.allResourcesFunctionCallIdentifier.suffix(resourceCountLimit)) | ||
|
||
// If identifiers are restricted, filter for only allowed function call identifiers of health records. | ||
if let allowedResourcesFunctionCallIdentifiers { | ||
allResourcesFunctionCallIdentifiers.formIntersection(allowedResourcesFunctionCallIdentifiers) | ||
} | ||
|
||
_resources = Parameter( | ||
description: String(localized: "PARAMETER_DESCRIPTION"), | ||
enumValues: Array(allResourcesFunctionCallIdentifiers) | ||
) | ||
} | ||
|
||
|
||
func execute() async throws -> String? { | ||
var functionOutput: [String] = [] | ||
|
||
try await withThrowingTaskGroup(of: [String].self) { outerGroup in | ||
// Iterate over all requested resources by the LLM | ||
for requestedResource in resources { | ||
outerGroup.addTask { | ||
// Fetch relevant FHIR resources matching the resources requested by the LLM | ||
var fittingResources = fhirStore.llmRelevantResources.filter { $0.functionCallIdentifier.contains(requestedResource) } | ||
|
||
// Stores output of nested task group summarizing fitting resources | ||
var nestedFunctionOutputResults = [String]() | ||
|
||
guard !fittingResources.isEmpty else { | ||
nestedFunctionOutputResults.append( | ||
String( | ||
localized: "The medical record does not include any FHIR resources for the search term \(requestedResource)." | ||
) | ||
) | ||
return [] | ||
} | ||
|
||
// Filter out fitting resources (if greater than 64 entries) | ||
fittingResources = filterFittingResources(fittingResources) | ||
|
||
try await withThrowingTaskGroup(of: String.self) { innerGroup in | ||
// Iterate over fitting resources and summarizing them | ||
for resource in fittingResources { | ||
innerGroup.addTask { | ||
try await summarizeResource(fhirResource: resource, resourceType: requestedResource) | ||
} | ||
} | ||
|
||
for try await nestedResult in innerGroup { | ||
nestedFunctionOutputResults.append(nestedResult) | ||
} | ||
} | ||
|
||
return nestedFunctionOutputResults | ||
} | ||
} | ||
|
||
for try await result in outerGroup { | ||
functionOutput.append(contentsOf: result) | ||
} | ||
} | ||
|
||
return functionOutput.joined(separator: "\n\n") | ||
} | ||
|
||
private func summarizeResource(fhirResource: FHIRResource, resourceType: String) async throws -> String { | ||
let summary = try await resourceSummary.summarize(resource: fhirResource) | ||
Self.logger.debug("Summary of appended FHIR resource \(resourceType): \(summary.description)") | ||
return String(localized: "This is the summary of the requested \(resourceType):\n\n\(summary.description)") | ||
} | ||
|
||
private func filterFittingResources(_ fittingResources: [FHIRResource]) -> [FHIRResource] { | ||
Self.logger.debug("Overall fitting Resources: \(fittingResources.count)") | ||
|
||
var fittingResources = fittingResources | ||
|
||
if fittingResources.count > 64 { | ||
fittingResources = fittingResources.lazy.sorted(by: { $0.date ?? .distantPast < $1.date ?? .distantPast }).suffix(64) | ||
Self.logger.debug( | ||
""" | ||
Reduced to the following 64 resources: \(fittingResources.map { $0.functionCallIdentifier }.joined(separator: ",")) | ||
""" | ||
) | ||
} | ||
|
||
return fittingResources | ||
} | ||
} |
Oops, something went wrong.