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

Llm filter data #67

Merged
merged 34 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a0c606a
stash
apgupta3303 Feb 29, 2024
acb5b8e
Merge branch 'main' of https://github.com/CS342/2024-Intake into scro…
apgupta3303 Feb 29, 2024
874b569
saving changes
apgupta3303 Feb 29, 2024
d2af10b
saving changes
apgupta3303 Feb 29, 2024
1f3ce82
Adding scrollable view
apgupta3303 Feb 29, 2024
b69721f
adding scrollable view
apgupta3303 Mar 6, 2024
1d64529
stsah
apgupta3303 Mar 6, 2024
42c27f3
stash
apgupta3303 Mar 8, 2024
5b74270
merge conflicts
apgupta3303 Mar 8, 2024
4174981
updating localizable
apgupta3303 Mar 8, 2024
8daece8
fixing package errors
apgupta3303 Mar 8, 2024
fca7f0e
linting
apgupta3303 Mar 8, 2024
dcd1492
added patient information and fixed reaction view
apgupta3303 Mar 9, 2024
54ac96d
small changes
apgupta3303 Mar 9, 2024
d763997
Adding merge errors
apgupta3303 Mar 9, 2024
ae360a9
fixing duolicate
apgupta3303 Mar 9, 2024
63a9a3c
removing scoial history for this push
apgupta3303 Mar 9, 2024
6fbec51
Adding framwork for social history
apgupta3303 Mar 9, 2024
7cac733
stash
apgupta3303 Mar 10, 2024
f738fe3
stash
apgupta3303 Mar 10, 2024
5e765af
Adding LLM filtering class and applied class to conditions
apgupta3303 Mar 10, 2024
92b8c69
Adding filter allergies
apgupta3303 Mar 11, 2024
fcd7e34
Adding progress views
apgupta3303 Mar 11, 2024
91d30ed
Merge branch 'main' into LLMFilterData
apgupta3303 Mar 11, 2024
8c68d04
swiftlint
apgupta3303 Mar 11, 2024
802ee93
Merge branch 'main' into LLMFilterData
apgupta3303 Mar 11, 2024
64b9b50
Fixing REUSE
apgupta3303 Mar 11, 2024
84ba02a
merge
apgupta3303 Mar 11, 2024
7bd1ec0
swiftlint
apgupta3303 Mar 11, 2024
5d81f35
Reuse
apgupta3303 Mar 11, 2024
c91620f
Merge branch 'main' into LLMFilterData
nriedman Mar 11, 2024
868a963
Merge branch 'main' into LLMFilterData
apgupta3303 Mar 11, 2024
a78f8fe
adding new updates to main
apgupta3303 Mar 11, 2024
583795d
Merge branch 'LLMFilterData' of https://github.com/CS342/2024-Intake …
apgupta3303 Mar 11, 2024
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
10 changes: 9 additions & 1 deletion Intake.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@
5A2B9FAB2B69E430005CA63F /* FHIRStore+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A2B9FAA2B69E430005CA63F /* FHIRStore+Extensions.swift */; };
5A2B9FB62B6AFE5D005CA63F /* AllergyRecords.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A2B9FB52B6AFE5D005CA63F /* AllergyRecords.swift */; };
5A2B9FBC2B6C7B29005CA63F /* ReactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A2B9FBB2B6C7B29005CA63F /* ReactionView.swift */; };
5AAB83A72B9C04E70008407A /* LLMFiltering.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AAB83A62B9C04E70008407A /* LLMFiltering.swift */; };
5AAB83B32B9EBB070008407A /* ReactionSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AAB83B22B9EBB070008407A /* ReactionSectionView.swift */; };
5AEA5F212B82DDD000F1577A /* LLMAssistantView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F202B82DDD000F1577A /* LLMAssistantView.swift */; };
5AEA5F2C2B8680F300F1577A /* AddAllergy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F2B2B8680F300F1577A /* AddAllergy.swift */; };
5AEA5F3B2B90081B00F1577A /* ScrollablePDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AEA5F3A2B90081B00F1577A /* ScrollablePDF.swift */; };
Expand All @@ -112,8 +114,8 @@
A9DFE8A92ABE551400428242 /* AccountButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9DFE8A82ABE551400428242 /* AccountButton.swift */; };
A9FE7AD02AA39BAB0077B045 /* AccountSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FE7ACF2AA39BAB0077B045 /* AccountSheet.swift */; };
ACAA47812B571C800032D21F /* Questionnaire.json in Resources */ = {isa = PBXBuildFile; fileRef = ACAA47802B571C7F0032D21F /* Questionnaire.json */; };
ACF862BE2B96E29600ACBA1E /* ExportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACF862BD2B96E29600ACBA1E /* ExportView.swift */; };
ACDF32ED2B9D0F4300B127E2 /* MenstrualHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACFFA1D02B8FD8BB0006E6D4 /* MenstrualHistory.swift */; };
ACF862BE2B96E29600ACBA1E /* ExportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACF862BD2B96E29600ACBA1E /* ExportView.swift */; };
ACFFA1CE2B8FD7190006E6D4 /* SmokingHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACFFA1CD2B8FD7190006E6D4 /* SmokingHistory.swift */; };
F42AB1D22B6379B5002E13A6 /* SpeziLLM in Frameworks */ = {isa = PBXBuildFile; productRef = F42AB1D12B6379B5002E13A6 /* SpeziLLM */; };
F42AB1D42B6379B5002E13A6 /* SpeziLLMLocal in Frameworks */ = {isa = PBXBuildFile; productRef = F42AB1D32B6379B5002E13A6 /* SpeziLLMLocal */; };
Expand Down Expand Up @@ -211,6 +213,8 @@
5A2B9FAA2B69E430005CA63F /* FHIRStore+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FHIRStore+Extensions.swift"; sourceTree = "<group>"; };
5A2B9FB52B6AFE5D005CA63F /* AllergyRecords.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllergyRecords.swift; sourceTree = "<group>"; };
5A2B9FBB2B6C7B29005CA63F /* ReactionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReactionView.swift; sourceTree = "<group>"; };
5AAB83A62B9C04E70008407A /* LLMFiltering.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LLMFiltering.swift; sourceTree = "<group>"; };
5AAB83B22B9EBB070008407A /* ReactionSectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionSectionView.swift; sourceTree = "<group>"; };
5AEA5F202B82DDD000F1577A /* LLMAssistantView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LLMAssistantView.swift; sourceTree = "<group>"; };
5AEA5F2B2B8680F300F1577A /* AddAllergy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAllergy.swift; sourceTree = "<group>"; };
5AEA5F3A2B90081B00F1577A /* ScrollablePDF.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollablePDF.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -479,6 +483,7 @@
5AEA5F2B2B8680F300F1577A /* AddAllergy.swift */,
5AEA5F492B96F63A00F1577A /* AllergyLLMAssistant.swift */,
5A2B9FBB2B6C7B29005CA63F /* ReactionView.swift */,
5AAB83B22B9EBB070008407A /* ReactionSectionView.swift */,
5AEA5F462B93034A00F1577A /* ReactionPDF.swift */,
51A360152B965819004E7E12 /* AllergyLLMAssistant.swift */,
);
Expand Down Expand Up @@ -537,6 +542,7 @@
2FE5DC2D29EDD792004B9AB4 /* Resources */,
2FC9759D2978E30800BA99FE /* Supporting Files */,
5AEA5F3A2B90081B00F1577A /* ScrollablePDF.swift */,
5AAB83A62B9C04E70008407A /* LLMFiltering.swift */,
5AEA5F412B90710B00F1577A /* EditPatient.swift */,
);
path = Intake;
Expand Down Expand Up @@ -889,8 +895,10 @@
566155292AB8447C00209B80 /* Package+LicenseType.swift in Sources */,
5680DD392AB8983D004E6D4A /* PackageCell.swift in Sources */,
5AEA5F422B90710B00F1577A /* EditPatient.swift in Sources */,
5AAB83A72B9C04E70008407A /* LLMFiltering.swift in Sources */,
F42AB1EC2B6DBF21002E13A6 /* SummaryView.swift in Sources */,
2F5E32BD297E05EA003432F8 /* IntakeDelegate.swift in Sources */,
5AAB83B32B9EBB070008407A /* ReactionSectionView.swift in Sources */,
511827962B740192002033A0 /* SurgeryView.swift in Sources */,
2FE5DC5229EDD7FA004B9AB4 /* IntakeScheduler.swift in Sources */,
5AEA5F3B2B90081B00F1577A /* ScrollablePDF.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"originHash" : "cdbe60a3382a8a962c7fcc00210e56e13314cb3e246d0e01fe8e25a1268623d8",
"pins" : [
{
"identity" : "abseil-cpp-binary",
Expand Down Expand Up @@ -231,8 +230,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziHealthKit.git",
"state" : {
"revision" : "35628084d3977aa897015b0b0c21cfe4d556f1aa",
"version" : "0.5.2"
"revision" : "1e9cb5a6036ac7f4ff37ea1c3ed4898103339ad1",
"version" : "0.5.3"
}
},
{
Expand Down Expand Up @@ -380,5 +379,5 @@
}
}
],
"version" : 3
"version" : 2
}
38 changes: 0 additions & 38 deletions Intake/Allergy Records/AddAllergy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,44 +54,6 @@ struct EditAllergyView: View {
}
}

struct ReactionSectionView: View {
@Environment(DataStore.self) private var data
var index: Int

var body: some View {
Form { // Use Form instead of List
Section(header: headerTitle) {
@Bindable var data = data
ForEach($data.allergyData[index].reaction) { $item in
HStack {
TextField("Reactions", text: $item.reaction)
}
}
.onDelete(perform: delete)
Button(action: {
data.allergyData[index].reaction.append(ReactionItem(reaction: ""))
}) {
HStack {
Image(systemName: "plus.circle.fill")
.accessibilityLabel(Text("ADD_REACTION"))
Text("Add Field")
}
}
}
}
}

private var headerTitle: some View {
HStack {
Text("Reactions")
Spacer()
EditButton()
}
}
func delete(at offsets: IndexSet) {
data.allergyData[index].reaction.remove(atOffsets: offsets)
}
}

// #Preview {
// EditAllergyView(allergyItem: AllergyItem(allergy: "", reaction: []), showingReaction: <#T##Binding<Bool>#>, allergyRecords: <#T##Binding<[AllergyItem]>#>, showingReaction: .constant(true), allergyRecords: .constant([]))
Expand Down
86 changes: 73 additions & 13 deletions Intake/Allergy Records/AllergyRecords.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import Foundation
import ModelsR4
import SpeziFHIR
import SpeziLLM
import SpeziLLMOpenAI
import SwiftUI

struct AllergyItem: Identifiable, Equatable {
Expand All @@ -25,10 +27,6 @@
}
}

// struct ReactionViewDetails {
// var showingReaction: Bool
// var
// }

struct ChatButton: View {
// Use @Binding to create a two-way binding to the parent view's showingChat state
Expand All @@ -54,20 +52,35 @@
@Environment(FHIRStore.self) private var fhirStore
@Environment(NavigationPathWrapper.self) private var navigationPath
@Environment(DataStore.self) private var data
@Environment(LoadedWrapper.self) private var loaded

@State private var showingReaction = false
@State private var selectedIndex = 0
@State private var showingChat = false
@State private var presentingAccount = false

@LLMSessionProvider<LLMOpenAISchema> var session: LLMOpenAISession

var body: some View {
VStack {
allergyForm
SubmitButton(nextView: NavigationViews.menstrual)
.padding()
if loaded.allergyData {
VStack {
allergyForm
SubmitButton(nextView: NavigationViews.menstrual)
.padding()
}
.sheet(isPresented: $showingChat, content: chatSheetView)
.sheet(isPresented: $showingReaction, content: editAllergySheetView)
} else {
ProgressView()
.task {
do {
try await loadAllergies()
} catch {
print("Failed to load")
}
loaded.allergyData = true
}

Check warning on line 82 in Intake/Allergy Records/AllergyRecords.swift

View check run for this annotation

Codecov / codecov/patch

Intake/Allergy Records/AllergyRecords.swift#L65-L82

Added lines #L65 - L82 were not covered by tests
}
.onAppear(perform: loadAllergies)
.sheet(isPresented: $showingChat, content: chatSheetView)
.sheet(isPresented: $showingReaction, content: editAllergySheetView)
}
private var allergyForm: some View {
Form {
Expand Down Expand Up @@ -102,7 +115,37 @@
}
}
}

init() {
let systemPrompt = """
You are a helpful assistant that filters lists of allergies. You will be given\
an array of strings. Each string will be the name of a allergy.

For example, if you are given the following list:
Mammography (procedure), Certification procedure (procedure), Cytopathology\
procedure, preparation of smear, genital source (procedure), Transplant of kidney\
(procedure),

you should return something like this:
Transplant of kidney, Mammography.

Check warning on line 130 in Intake/Allergy Records/AllergyRecords.swift

View check run for this annotation

Codecov / codecov/patch

Intake/Allergy Records/AllergyRecords.swift#L119-L130

Added lines #L119 - L130 were not covered by tests

In your response, return only the name of the allergy. Remove words in parenthesis
like (disorder), so "Aortic valve stenosis (disorder)" would turn to "Aortic valve stenosis".

Do not make anything up, and do not change the name of the condition under any
circumstances. Thank you!
"""

self._session = LLMSessionProvider(
schema: LLMOpenAISchema(
parameters: .init(
modelType: .gpt3_5Turbo,
systemPrompt: systemPrompt
)
)
)
}

Check warning on line 147 in Intake/Allergy Records/AllergyRecords.swift

View check run for this annotation

Codecov / codecov/patch

Intake/Allergy Records/AllergyRecords.swift#L132-L147

Added lines #L132 - L147 were not covered by tests

private func allergyEntryRow(index: Int) -> some View {
HStack {
Text(data.allergyData[index].allergy)
Expand Down Expand Up @@ -145,8 +188,20 @@
private func editAllergySheetView() -> some View {
EditAllergyView(index: selectedIndex, showingReaction: $showingReaction)
}

private func removeTextWithinParentheses(from string: String) -> String {
let pattern = "\\s*\\([^)]+\\)"
do {
let regex = try NSRegularExpression(pattern: pattern)
let range = NSRange(string.startIndex..., in: string)
return regex.stringByReplacingMatches(in: string, options: [], range: range, withTemplate: "")
} catch {
print("Invalid regex: \(error.localizedDescription)")
return string
}
}

Check warning on line 202 in Intake/Allergy Records/AllergyRecords.swift

View check run for this annotation

Codecov / codecov/patch

Intake/Allergy Records/AllergyRecords.swift#L192-L202

Added lines #L192 - L202 were not covered by tests

private func loadAllergies() {
private func loadAllergies() async throws {

Check warning on line 204 in Intake/Allergy Records/AllergyRecords.swift

View check run for this annotation

Codecov / codecov/patch

Intake/Allergy Records/AllergyRecords.swift#L204

Added line #L204 was not covered by tests
var allergies: [FHIRString] = []
var allReactions: [[ReactionItem]] = []
let intolerances = fhirStore.allergyIntolerances
Expand All @@ -162,7 +217,9 @@
for reaction in reactions {
let manifestations = reaction.manifestation
for manifestation in manifestations {
reactionsForAllergy.append(ReactionItem(reaction: manifestation.text?.value?.string ?? "Default"))
var reactionName = manifestation.text?.value?.string
reactionName = removeTextWithinParentheses(from: reactionName ?? "")
reactionsForAllergy.append(ReactionItem(reaction: reactionName ?? ""))

Check warning on line 222 in Intake/Allergy Records/AllergyRecords.swift

View check run for this annotation

Codecov / codecov/patch

Intake/Allergy Records/AllergyRecords.swift#L220-L222

Added lines #L220 - L222 were not covered by tests
}
}
}
Expand All @@ -180,6 +237,9 @@
)
}
}

let filter = LLMFiltering(session: session, data: data)
try await filter.filterAllergies()

Check warning on line 242 in Intake/Allergy Records/AllergyRecords.swift

View check run for this annotation

Codecov / codecov/patch

Intake/Allergy Records/AllergyRecords.swift#L240-L242

Added lines #L240 - L242 were not covered by tests
}

func delete(at offsets: IndexSet) {
Expand Down
26 changes: 8 additions & 18 deletions Intake/Allergy Records/ReactionPDF.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,16 @@
@Binding private var showingReaction: Bool
var body: some View {
NavigationView {
ReactionSectionView(index: index)
// VStack {
// Form {
// ForEach(data.allergyData[index].reaction) { item in
// Text(item.reaction)
// }
// }
// .navigationTitle("Medical History")
//// .navigationTitle("\(data.allergyData[index].allergy) Reactions")
// .navigationBarItems(trailing: EditButton())
// }
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
HStack {
Text("\(data.allergyData[index].allergy) Reactions")
.lineLimit(1) // Ensure the title is single-lined
.truncationMode(.tail)
.font(.headline) // Adjust the font size if needed
VStack {
Form {
if data.allergyData[index].reaction.isEmpty {
Text("No Reactions")
}
ForEach(data.allergyData[index].reaction) { item in
Text(item.reaction)

Check warning on line 31 in Intake/Allergy Records/ReactionPDF.swift

View check run for this annotation

Codecov / codecov/patch

Intake/Allergy Records/ReactionPDF.swift#L25-L31

Added lines #L25 - L31 were not covered by tests
}
}
.navigationTitle("\(data.allergyData[index].allergy) Reactions")

Check warning on line 34 in Intake/Allergy Records/ReactionPDF.swift

View check run for this annotation

Codecov / codecov/patch

Intake/Allergy Records/ReactionPDF.swift#L34

Added line #L34 was not covered by tests
}
}
}
Expand Down
56 changes: 56 additions & 0 deletions Intake/Allergy Records/ReactionSectionView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// ReactionSectionView.swift
// Intake
//
// Created by Akash Gupta on 3/10/24.
//
// This source file is part of the Intake based on the Stanford Spezi Template Application project
//
// SPDX-FileCopyrightText: 2023 Stanford University
//
// SPDX-License-Identifier: MIT
//

import Foundation
import SpeziFHIR
import SwiftUI


struct ReactionSectionView: View {
@Environment(DataStore.self) private var data
var index: Int

var body: some View {
Form { // Use Form instead of List
Section(header: headerTitle) {
@Bindable var data = data
ForEach($data.allergyData[index].reaction) { $item in
HStack {
TextField("Reactions", text: $item.reaction)
}
}
.onDelete(perform: delete)
Button(action: {
data.allergyData[index].reaction.append(ReactionItem(reaction: ""))
}) {
HStack {
Image(systemName: "plus.circle.fill")
.accessibilityLabel(Text("ADD_REACTION"))
Text("Add Field")
}
}
}
}
}

Check warning on line 44 in Intake/Allergy Records/ReactionSectionView.swift

View check run for this annotation

Codecov / codecov/patch

Intake/Allergy Records/ReactionSectionView.swift#L23-L44

Added lines #L23 - L44 were not covered by tests

private var headerTitle: some View {
HStack {
Text("Reactions")
Spacer()
EditButton()
}
}
func delete(at offsets: IndexSet) {
data.allergyData[index].reaction.remove(atOffsets: offsets)
}

Check warning on line 55 in Intake/Allergy Records/ReactionSectionView.swift

View check run for this annotation

Codecov / codecov/patch

Intake/Allergy Records/ReactionSectionView.swift#L46-L55

Added lines #L46 - L55 were not covered by tests
}
8 changes: 8 additions & 0 deletions Intake/Intake.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ class ReachedEndWrapper {
var surgeriesLoaded = false
}

@Observable
class LoadedWrapper {
var conditionData = false
var allergyData = false
}

@main
struct Intake: App {
@UIApplicationDelegateAdaptor(IntakeDelegate.self) var appDelegate
Expand All @@ -60,6 +66,7 @@ struct Intake: App {
let navigationPath = NavigationPathWrapper()
let data = DataStore()
let reachedEnd = ReachedEndWrapper()
let loaded = LoadedWrapper()

var body: some Scene {
WindowGroup {
Expand All @@ -78,6 +85,7 @@ struct Intake: App {
.environment(navigationPath)
.environment(data)
.environment(reachedEnd)
.environment(loaded)
}
}
}
Loading
Loading