Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove LLM Functionality from Package #24

Merged
merged 6 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 4 additions & 24 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,13 @@ let package = Package(
products: [
.library(name: "SpeziFHIR", targets: ["SpeziFHIR"]),
.library(name: "SpeziFHIRHealthKit", targets: ["SpeziFHIRHealthKit"]),
.library(name: "SpeziFHIRLLM", targets: ["SpeziFHIRLLM"]),
.library(name: "SpeziFHIRMockPatients", targets: ["SpeziFHIRMockPatients"])
],
dependencies: [
.package(url: "https://github.com/apple/FHIRModels", .upToNextMinor(from: "0.6.0")),
.package(url: "https://github.com/StanfordBDHG/HealthKitOnFHIR", .upToNextMinor(from: "0.2.11")),
.package(url: "https://github.com/StanfordSpezi/Spezi", from: "1.8.0"),
.package(url: "https://github.com/StanfordSpezi/SpeziHealthKit", .upToNextMinor(from: "0.6.0")),
.package(url: "https://github.com/StanfordSpezi/SpeziLLM", .upToNextMinor(from: "0.8.4")),
.package(url: "https://github.com/StanfordSpezi/SpeziStorage", from: "1.2.1"),
.package(url: "https://github.com/StanfordSpezi/SpeziChat", .upToNextMinor(from: "0.2.1")),
.package(url: "https://github.com/StanfordSpezi/SpeziSpeech", from: "1.1.0")
.package(url: "https://github.com/StanfordSpezi/SpeziHealthKit", .upToNextMinor(from: "0.6.0"))
] + swiftLintPackage(),
targets: [
.target(
Expand All @@ -54,23 +49,6 @@ let package = Package(
],
plugins: [] + swiftLintPlugin()
),
.target(
name: "SpeziFHIRLLM",
dependencies: [
.target(name: "SpeziFHIR"),
.product(name: "Spezi", package: "Spezi"),
.product(name: "ModelsR4", package: "FHIRModels"),
.product(name: "SpeziLLM", package: "SpeziLLM"),
.product(name: "SpeziLLMOpenAI", package: "SpeziLLM"),
.product(name: "SpeziLocalStorage", package: "SpeziStorage"),
.product(name: "SpeziChat", package: "SpeziChat"),
.product(name: "SpeziSpeechSynthesizer", package: "SpeziSpeech")
],
resources: [
.process("Resources")
],
plugins: [] + swiftLintPlugin()
),
.target(
name: "SpeziFHIRMockPatients",
dependencies: [
Expand All @@ -85,7 +63,9 @@ let package = Package(
.testTarget(
name: "SpeziFHIRTests",
dependencies: [
.target(name: "SpeziFHIR")
.target(name: "SpeziFHIR"),
.product(name: "HealthKitOnFHIR", package: "HealthKitOnFHIR"),
.product(name: "SpeziHealthKit", package: "SpeziHealthKit")
],
plugins: [] + swiftLintPlugin()
)
Expand Down
335 changes: 335 additions & 0 deletions Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,335 @@
//
// This source file is part of the Stanford Spezi open source project
//
// SPDX-FileCopyrightText: 2024 Stanford University and the project authors (see CONTRIBUTORS.md)
//
// SPDX-License-Identifier: MIT
//

import Foundation
import ModelsDSTU2
import ModelsR4


extension FHIRResource {
/// A computed property that generates an extended description of a FHIR resource.
/// - Returns: A brief description of the resource, or an empty string if no description is available.
public var resourceDescription: String {
switch versionedResource {
case let .r4(resource):
switch resource {
case let patient as ModelsR4.Patient:
return constructPatientDescription(patient)
case let observation as ModelsR4.Observation:
return constructeObservationDescription(observation)
default:
return ""
}
default:
return ""
}
}

Check warning on line 31 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L17-L31

Added lines #L17 - L31 were not covered by tests

/// A computed property that generates a short description of a FHIR resource.
/// - Returns: A brief description of the resource, or an empty string if no description is available.
public var shortResourceDescription: String {
switch versionedResource {
case let .r4(resource):
switch resource {
case let patient as ModelsR4.Patient:
return constructShortPatientDescription(patient)
case let observation as ModelsR4.Observation:
return constructeShortObservationDescription(observation)
default:
return ""
}
default:
return ""
}
}

Check warning on line 49 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L35-L49

Added lines #L35 - L49 were not covered by tests


private func constructShortPatientDescription(_ patient: ModelsR4.Patient) -> String {
"""
Patient name is \(patientNameToString(patient)), gender is \(patientGenderToString(patient)). Born: \(patientBirthDateToString(patient)). Main communication language is \(patientLanguageToString(patient)).
"""
}

Check warning on line 56 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L52-L56

Added lines #L52 - L56 were not covered by tests

private func constructeShortObservationDescription(_ observation: ModelsR4.Observation) -> String {
"""
This \(splitCamel(resourceType)) is \(observationCodeToString(observation)), value: \(observationValueToString(observation)) at \(observationEffectiveDateTimeToString(observation)).
"""
}

Check warning on line 62 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L58-L62

Added lines #L58 - L62 were not covered by tests


private func constructPatientDescription(_ patient: ModelsR4.Patient) -> String {
"""
The name for this patient is \(patientNameToString(patient)).
The gender for this patient is \(patientGenderToString(patient)).
The birth date for this patient is \(patientBirthDateToString(patient)).
The communication language for this patient is \(patientLanguageToString(patient)).
"""
}

Check warning on line 72 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L65-L72

Added lines #L65 - L72 were not covered by tests

private func constructeObservationDescription(_ observation: ModelsR4.Observation) -> String {
"""
The type of information in this entry is \(splitCamel(resourceType)).
The status for this \(splitCamel(resourceType)) is \(observationStatusToString(observation)).
The category of this obervarion is \(observationCategoryToString(observation)).
The code for this observation is \(observationCodeToString(observation)).
The observation was effectove date time on \(observationEffectiveDateTimeToString(observation)).
The value \(observationTypeToString(observation)) for this observation is \(observationValueToString(observation)).
"""
}

Check warning on line 83 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L74-L83

Added lines #L74 - L83 were not covered by tests

private func patientNameToString(_ patient: ModelsR4.Patient) -> String {
guard let name = patient.name?.first?.text else {
return "N/A"
}
return name.value?.string ?? "N/A"
}

Check warning on line 90 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L85-L90

Added lines #L85 - L90 were not covered by tests

private func patientGenderToString(_ patient: ModelsR4.Patient) -> String {
guard let gender = patient.gender?.value?.rawValue else {
return "N/A"
}
return gender
}

Check warning on line 97 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L92-L97

Added lines #L92 - L97 were not covered by tests

private func patientBirthDateToString(_ patient: ModelsR4.Patient) -> String {
guard let birthDate = patient.birthDate?.valueDescription else {
return "N/A"
}

if let brithDate = try? patient.birthDate?.value?.asNSDate(),
let years = Calendar.current.dateComponents([.year], from: brithDate, to: .now).year {
return birthDate + " (\(years) years old)"
}

return birthDate
}

Check warning on line 110 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L99-L110

Added lines #L99 - L110 were not covered by tests

private func patientLanguageToString(_ patient: ModelsR4.Patient) -> String {
guard let language = patient.communication?.first?.language.coding?.first?.code else {
return "N/A"
}
return language.valueDescription
}

Check warning on line 117 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L112-L117

Added lines #L112 - L117 were not covered by tests

private func observationStatusToString(_ observation: ModelsR4.Observation) -> String {
guard let status = observation.status.value?.rawValue else {
return "N/A"
}
return status
}

Check warning on line 124 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L119-L124

Added lines #L119 - L124 were not covered by tests

private func observationCategoryToString(_ observation: ModelsR4.Observation) -> String {
guard let category = observation.category else {
return "N/A"
}
let joinedCoding = category.compactMap(\.coding).joined()
let joinedCodingDisplay = joinedCoding.compactMap { $0.display?.value?.string }.joined(separator: ", ")
return joinedCodingDisplay
}

Check warning on line 133 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L126-L133

Added lines #L126 - L133 were not covered by tests

private func observationCodeToString(_ observation: ModelsR4.Observation) -> String {
guard let coding = observation.code.coding else {
return "N/A"
}
return coding.compactMap { $0.display?.value?.string }.joined(separator: ", ")
}

Check warning on line 140 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L135-L140

Added lines #L135 - L140 were not covered by tests

private func observationEffectiveDateTimeToString(_ observation: ModelsR4.Observation) -> String {
guard let effectiveDateTime = observation.effective else {
return "N/A"
}
switch effectiveDateTime {
case let .dateTime(value):
return value.valueDescription
case let .instant(value):
return value.valueDescription
case let .period(value):
return value.valueDescription
case let .timing(value):
return value.valueDescription
}
}

Check warning on line 156 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L142-L156

Added lines #L142 - L156 were not covered by tests

private func observationTypeToString(_ observation: ModelsR4.Observation) -> String {
guard let value = observation.value else {
return "N/A"
}
return value.typeName
}

Check warning on line 163 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L158-L163

Added lines #L158 - L163 were not covered by tests

private func observationValueToString(_ observation: ModelsR4.Observation) -> String {
switch observation.value {
case let .boolean(boolean):
return boolean.valueDescription
case let .dateTime(dateTime):
return dateTime.valueDescription
case let .string(string):
return string.valueDescription
case let .quantity(quantity):
return quantity.valueDescription
case let .integer(integer):
return integer.valueDesciption
case let .period(period):
return period.valueDescription
case let .time(time):
return time.valueDescription
case let .range(range):
return range.valueDescription
default:
return ""
}
}

Check warning on line 186 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L165-L186

Added lines #L165 - L186 were not covered by tests

fileprivate func splitCamel(_ text: String) -> String {
var newText = text.trimmingCharacters(in: .whitespacesAndNewlines)

newText = newText.replacingOccurrences(
of: #"([a-z])([A-Z])"#,
with: "$1 $2",
options: .regularExpression
)

newText = newText.replacingOccurrences(
of: #"([A-Z]+)([A-Z][a-z])"#,
with: "$1 $2",
options: .regularExpression
)

return newText.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
}

Check warning on line 204 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L188-L204

Added lines #L188 - L204 were not covered by tests
}


extension ModelsR4.Observation.ValueX {
var typeName: String {
switch self {
case .boolean: "boolean"
case .codeableConcept: "codeable concept"
case .dateTime: "date time"
case .integer: "number"
case .period: "period"
case .quantity: "quantity"
case .range: "range"
case .ratio: "ratio"
case .sampledData: "sampled data"
case .string: "string"
case .time: "time"
}
}

Check warning on line 223 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L209-L223

Added lines #L209 - L223 were not covered by tests
}

extension ModelsR4.FHIRPrimitive where PrimitiveType == ModelsR4.FHIRBool {
var valueDescription: String {
guard let value = self.value?.bool else {
return "N/A"
}
return "\(value)"
}

Check warning on line 232 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L227-L232

Added lines #L227 - L232 were not covered by tests
}

extension ModelsR4.FHIRPrimitive where PrimitiveType == ModelsR4.FHIRDate {
var valueDescription: String {
guard let value = try? self.value?.asNSDate() else {
return "N/A"
}
return "\(value.formatted(.dateTime))"
}

Check warning on line 241 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L236-L241

Added lines #L236 - L241 were not covered by tests
}

extension ModelsR4.FHIRPrimitive where PrimitiveType == ModelsR4.FHIRDecimal {
var valueDescription: String {
guard let value = self.value?.decimal else {
return "N/A"
}
return NSDecimalNumber(decimal: value).stringValue
}

Check warning on line 250 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L245-L250

Added lines #L245 - L250 were not covered by tests
}

extension ModelsR4.FHIRPrimitive where PrimitiveType == ModelsR4.FHIRString {
var valueDescription: String {
guard let value = self.value?.string else {
return "N/A"
}
return value
}

Check warning on line 259 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L254-L259

Added lines #L254 - L259 were not covered by tests
}

extension ModelsR4.FHIRPrimitive where PrimitiveType == ModelsR4.FHIRInteger {
var valueDesciption: String {
guard let value = self.value?.integer else {
return "N/A"
}
return String(value)
}

Check warning on line 268 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L263-L268

Added lines #L263 - L268 were not covered by tests
}

extension ModelsR4.FHIRPrimitive where PrimitiveType == ModelsR4.DateTime {
var valueDescription: String {
guard let value = try? self.value?.asNSDate() else {
return "N/A"
}
return "\(value.formatted(.dateTime))"
}

Check warning on line 277 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L272-L277

Added lines #L272 - L277 were not covered by tests
}

extension ModelsR4.FHIRPrimitive where PrimitiveType == ModelsR4.FHIRTime {
var valueDescription: String {
guard let value = self.value else {
return "N/A"
}
return value.description
}

Check warning on line 286 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L281-L286

Added lines #L281 - L286 were not covered by tests
}

extension ModelsR4.FHIRPrimitive where PrimitiveType == ModelsR4.Instant {
var valueDescription: String {
guard let value = try? self.value?.asNSDate() else {
return "N/A"
}
return "\(value.formatted(.dateTime))"
}

Check warning on line 295 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L290-L295

Added lines #L290 - L295 were not covered by tests
}

extension ModelsR4.Period {
var valueDescription: String {
guard let valueStart = try? self.start?.value?.asNSDate(),
let valueEnd = try? self.end?.value?.asNSDate() else {
return "N/A"
}
return "\(valueStart.formatted(.dateTime)) - \(valueEnd.formatted(.dateTime))"
}

Check warning on line 305 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L299-L305

Added lines #L299 - L305 were not covered by tests
}

extension ModelsR4.Range {
var valueDescription: String {
guard let valueLow = self.low?.value?.value,
let valueHigh = self.high?.value?.value else {
return "N/A"
}
return "\(valueLow) - \(valueHigh)"
}

Check warning on line 315 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L309-L315

Added lines #L309 - L315 were not covered by tests
}

extension ModelsR4.Quantity {
var valueDescription: String {
guard let value = self.value?.value?.decimal,
let unit = self.unit?.value else {
return "N/A"
}
return "\(value) \(unit)"
}

Check warning on line 325 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L319-L325

Added lines #L319 - L325 were not covered by tests
}

extension ModelsR4.Timing {
var valueDescription: String {
guard let value = self.event?.compactMap({ $0.valueDescription }).joined() else {
return "N/A"
}
return value
}

Check warning on line 334 in Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIR/Extensions/FHIRResource+Flattener.swift#L329-L334

Added lines #L329 - L334 were not covered by tests
}
1 change: 1 addition & 0 deletions Sources/SpeziFHIRHealthKit/FHIRStore+HealthKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@

let decoder = JSONDecoder()
let resourceProxy = try decoder.decode(ModelsDSTU2.ResourceProxy.self, from: fhirResource.data)

Check warning on line 54 in Sources/SpeziFHIRHealthKit/FHIRStore+HealthKit.swift

View check run for this annotation

Codecov / codecov/patch

Sources/SpeziFHIRHealthKit/FHIRStore+HealthKit.swift#L54

Added line #L54 was not covered by tests
return FHIRResource(
versionedResource: .dstu2(resourceProxy.get()),
displayName: clinicalResource.displayName
Expand Down
Loading
Loading