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

Add LLM functionality from SpeziFHIR #53

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
295 changes: 170 additions & 125 deletions LLMonFHIR.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "ba25e03f96176869eb16eff816add82265b9f18b602261a3f50d9822f350899a",
"originHash" : "535b0c5bb44aca8b4a92e6d2f131607f666201afdd05d89e99288ab9a1943554",
"pins" : [
{
"identity" : "fhirmodels",
Expand All @@ -15,80 +15,44 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordBDHG/HealthKitOnFHIR.git",
"state" : {
"revision" : "b0cfe35a2263a517b22196b559d2dd1d1e2afcd9",
"version" : "0.2.9"
}
},
{
"identity" : "llama.cpp",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordBDHG/llama.cpp",
"state" : {
"revision" : "6839853a321778906e210a33ee2c6aec52f34c97",
"version" : "0.3.3"
}
},
{
"identity" : "openai",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordBDHG/OpenAI",
"state" : {
"revision" : "1ad95dd531d7c854a3f98f588b0eb68fa83e8a8c",
"version" : "0.2.9"
"revision" : "87a9257e6fa37407f3437e4a0bf21dd09a4ea7c5",
"version" : "0.2.11"
}
},
{
"identity" : "spezi",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/Spezi",
"state" : {
"revision" : "c43e4fa3d3938a847de2b677091a34ddaea5bc76",
"version" : "1.2.3"
"revision" : "4513a697572e8e1faea1e0ee52e6fad4b8d3dd8d",
"version" : "1.8.0"
}
},
{
"identity" : "spezichat",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziChat",
"state" : {
"revision" : "aaa10d71431b78ece8bf29f95c0050632714984d",
"version" : "0.2.0"
}
},
{
"identity" : "spezifhir",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziFHIR",
"state" : {
"revision" : "4357bd22bfe3b27bd9beec52330bca62d10ee202",
"version" : "0.6.2"
"revision" : "940ffbec504849968305d9f956344a4f35b6cd48",
"version" : "0.2.1"
}
},
{
"identity" : "spezifoundation",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziFoundation",
"state" : {
"revision" : "4781d96a09587f3d47ac3f3e71d197149b288146",
"version" : "1.1.3"
"revision" : "5b4ad1b343154b52a68c33a6bfe02d9cb07cb9dc",
"version" : "2.0.0"
}
},
{
"identity" : "spezihealthkit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziHealthKit.git",
"state" : {
"revision" : "1e9cb5a6036ac7f4ff37ea1c3ed4898103339ad1",
"version" : "0.5.3"
}
},
{
"identity" : "spezillm",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziLLM",
"state" : {
"revision" : "3663884f23e55c67c875a97c5da08ed172ea02ac",
"version" : "0.8.3"
"revision" : "fbdec78fcb2f90d6338f1968e21dd11fbee65070",
"version" : "0.6.0"
}
},
{
Expand All @@ -114,8 +78,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziStorage.git",
"state" : {
"revision" : "9d04bc622c65002aee704b4de5735970a6e19f46",
"version" : "1.1.0"
"revision" : "0f4a54430e51f82d29da63a7ce5f61bad7dfb9cd",
"version" : "1.2.1"
}
},
{
Expand All @@ -127,6 +91,15 @@
"version" : "1.4.0"
}
},
{
"identity" : "swift-atomics",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-atomics.git",
"state" : {
"revision" : "cd142fd2f64be2100422d658e7411e39489da985",
"version" : "1.2.0"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
</CommandLineArgument>
<CommandLineArgument
argument = "--testMode"
isEnabled = "NO">
isEnabled = "YES">
</CommandLineArgument>
</CommandLineArguments>
</LaunchAction>
Expand Down
145 changes: 145 additions & 0 deletions LLMonFHIR/FHIR Views/FHIRResourcesView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
//
// This source file is part of the Stanford Spezi project
//
// SPDX-FileCopyrightText: 2023 Stanford University
//
// SPDX-License-Identifier: MIT
//

import SpeziFHIR
import SwiftUI


/// Displays a `List` of all available FHIR resources.
///
/// The ``FHIRResourcesView`` displays a SwiftUI `List` of all available resources in the `SpeziFHIR` [`FHIRStore`](https://swiftpackageindex.com/stanfordspezi/spezifhir/documentation/spezifhir/fhirstore).
/// The FHIR resources are displayed in sections, for example conditions, medications etc.
/// In order to simply locating a concrete FHIR resource, the ``FHIRResourcesView`` provides a search bar on top of the `List`.
///
/// The ``FHIRResourcesView`` contains an optional content as well as action `View` that are located on top of the resource `List` and can be configured via ``FHIRResourcesView/init(navigationTitle:contentView:actionView:)``.
/// The content and action `View`s are placed within the Swift `List` as a `Section`, enabling proper visual integration with the remainder of the `List`.
///
/// - Warning: Ensure that the `SpeziFHIR` [`FHIRStore`](https://swiftpackageindex.com/stanfordspezi/spezifhir/documentation/spezifhir/fhirstore) is properly set up and accessible within the SwiftUI `Environment`.
///
/// ### Usage
///
/// The example below showcases a minimal example of using the ``FHIRResourcesView``.
///
/// ```swift
/// struct ResourcesView: View {
/// var body: some View {
/// FHIRResourcesView(navigationTitle: "...") {
/// Button("Some Action") {
/// // Action to perform
/// // ...
/// }
/// }
/// }
/// }
/// ```
public struct FHIRResourcesView<ContentView: View, ActionView: View>: View {
@Environment(FHIRStore.self) private var fhirStore
@State private var searchText = ""

private let navigationTitle: Text
private let contentView: ContentView
private let actionView: ActionView


public var body: some View {
List {
Section {
contentView
}

if searchText.isEmpty {
Section {
actionView
}
}

if fhirStore.allResources.filterByDisplayName(with: searchText).isEmpty {
Text("FHIR_RESOURCES_EMPTY_SEARCH_MESSAGE")
} else {
resourcesSection
}

Section { } footer: {
Text("Total Number of Resources: \(fhirStore.allResources.count)")
}
}
.searchable(text: $searchText)
.navigationDestination(for: FHIRResource.self) { resource in
InspectResourceView(resource: resource)
}
.navigationTitle(navigationTitle)
}

@ViewBuilder private var resourcesSection: some View {
section(for: \.conditions, sectionName: String(localized: "Conditions"))
section(for: \.diagnostics, sectionName: String(localized: "Diagnostics"))
section(for: \.encounters, sectionName: String(localized: "Encounters"))
section(for: \.immunizations, sectionName: String(localized: "Immunizations"))
section(for: \.medications, sectionName: String(localized: "Medications"))
section(for: \.observations, sectionName: String(localized: "Observations"))
section(for: \.procedures, sectionName: String(localized: "Procedures"))
section(for: \.otherResources, sectionName: String(localized: "Other Resources"))
}


/// Creates a ``FHIRResourcesView`` displaying a `List` of all available FHIR resources.
///
/// - Parameters:
/// - navigationTitle: The localized title displayed for purposes of navigation.
/// - contentView: A custom content `View` that is displayed as the first `Section` of the `List`.
/// - actionView: A custom action `View` that is displayed as the second `Section` of the `List`. Only shown if no search `String` is present.
public init(
navigationTitle: LocalizedStringResource,
@ViewBuilder contentView: () -> ContentView = { EmptyView() },
@ViewBuilder _ actionView: () -> ActionView = { EmptyView() }
) {
self.navigationTitle = Text(navigationTitle)
self.contentView = contentView()
self.actionView = actionView()
}

/// Creates a ``FHIRResourcesView`` displaying a `List` of all available FHIR resources.
///
/// - Parameters:
/// - navigationTitle: The title displayed for purposes of navigation.
/// - contentView: A custom content `View` that is displayed as the first `Section` of the `List`.
/// - actionView: A custom action `View` that is displayed as the second `Section` of the `List`. Only shown if no search `String` is present.
@_disfavoredOverload
public init<Title: StringProtocol>(
navigationTitle: Title,
@ViewBuilder contentView: () -> ContentView = { EmptyView() },
@ViewBuilder _ actionView: () -> ActionView = { EmptyView() }
) {
self.navigationTitle = Text(verbatim: String(navigationTitle))
self.contentView = contentView()
self.actionView = actionView()
}


private func section(for keyPath: KeyPath<FHIRStore, [FHIRResource]>, sectionName: String) -> some View {
var resources = fhirStore[keyPath: keyPath]

if !searchText.isEmpty {
resources = resources.filterByDisplayName(with: searchText)
}

guard !resources.isEmpty else {
return AnyView(EmptyView())
}

return AnyView(
Section(sectionName) {
ForEach(resources) { resource in
NavigationLink(value: resource) {
FHIRResourceSummaryView(resource: resource)
}
}
}
)
}
}
Loading
Loading