Skip to content

Commit

Permalink
Update Mock Patient Selection and other Bug Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
PSchmiedmayer committed Nov 21, 2023
1 parent ce2dc23 commit 2700a05
Show file tree
Hide file tree
Showing 16 changed files with 444 additions and 182 deletions.
17 changes: 14 additions & 3 deletions Sources/SpeziFHIRInterpretation/FHIRResourceInterpreter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,22 @@ public class FHIRResourceInterpreter {


extension FHIRPrompt {
static let interpretation: FHIRPrompt = {
/// Prompt used to interpret FHIR resources
///
/// This prompt is used by the ``FHIRResourceInterpreter``.
public static let interpretation: FHIRPrompt = {
FHIRPrompt(
storageKey: "prompt.interpretation",
localizedDescription: String(localized: "Interpretation Prompt"),
defaultPrompt: String(localized: "FHIR_RESOURCE_INTERPRETATION_PROMPT \(FHIRPrompt.promptPlaceholder) \(Locale.preferredLanguages[0])")
localizedDescription: String(
localized: "Interpretation Prompt",
bundle: .module,
comment: "Title of the interpretation prompt."
),
defaultPrompt: String(
localized: "Interpretation Prompt Content",
bundle: .module,
comment: "Content of the interpretation prompt."
)
)
}()
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class FHIRResourceProcesser {
private func systemPrompt(forResource resource: FHIRResource) -> Chat {
Chat(
role: .system,
content: prompt.prompt.replacingOccurrences(of: FHIRPrompt.promptPlaceholder, with: resource.jsonDescription)
content: prompt.prompt(withFHIRResource: resource.jsonDescription)
)
}
}
17 changes: 14 additions & 3 deletions Sources/SpeziFHIRInterpretation/FHIRResourceSummary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,22 @@ public class FHIRResourceSummary {


extension FHIRPrompt {
static let summary: FHIRPrompt = {
/// Prompt used to summarize FHIR resources
///
/// This prompt is used by the ``FHIRResourceSummary``.
public static let summary: FHIRPrompt = {
FHIRPrompt(
storageKey: "prompt.summary",
localizedDescription: String(localized: "Summary Prompt"),
defaultPrompt: String(localized: "FHIR_RESOURCE_SUMMARY_PROMPT \(FHIRPrompt.promptPlaceholder) \(Locale.preferredLanguages[0])")
localizedDescription: String(
localized: "Summary Prompt",
bundle: .module,
comment: "Title of the summary prompt."
),
defaultPrompt: String(
localized: "Summary Prompt Content",
bundle: .module,
comment: "Content of the summary prompt."
)
)
}()
}
91 changes: 20 additions & 71 deletions Sources/SpeziFHIRInterpretation/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
@@ -1,137 +1,86 @@
{
"sourceLanguage" : "en",
"strings" : {
"Chat with the user in the same language they chat in.\nChat with the user in %@" : {
"comment" : "The passed in string is the current locale of the device as a IETF BCP 47 language tag.",
"Customize the %@." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Chat with the user in the same language they chat in.\nChat with the user in %@"
"value" : "Customize the %@."
}
}
}
},
"Customize the %@ prompt." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Customize the %@ prompt."
}
}
}
},
"FHIR_MULTIPLE_RESOURCE_INTERPRETATION_PROMPT %@" : {
"extractionState" : "stale",
"Interpretation Prompt" : {
"comment" : "Title of the interpretation prompt.",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Your task is to interpret FHIR resources from the user's clinical records.\nThroughout the conversation with the user, use the get_resource_titles function to obtain the FHIR health resources necessary to properly answer the users question. For example, if the user asks about their allergies, you must use get_resource_titles to output the FHIR resource titles for allergy records so you can then use them to answer the question. The output of get_resource_titles has to be the name of a resource or resources with the exact same title as in the list provided.\n\nAnswer the users question, the health record provided is not always related. The end goal is to answer the users question in the best way possible.\n\nInterpret the resources by explaining its data relevant to the user's health.\nExplain the relevant medical context in a language understandable by a user who is not a medical professional.\nYou should provide factual and precise information in a compact summary in short responses.\n\nTell the user that they can ask any question about their health records and then create a short summary of the main categories of health records of the user which you have access to. These are the resource titles:\n%@\n\nImmediately return a short summary of the users health records to start the conversation.\nThe initial summary should be a short and simple summary with the following specifications:\n1. Short summary of the health records categories\n2. 5th grade reading level\n3. End with a question asking user if they have any questions. Make sure that this question is not generic but specific to their health records.\nDo not introduce yourself at the beginning, and start with your interpretation.\nMake sure your response is in the same language the user writes to you in.\nThe tense should be present."
"value" : "Interpretation Prompt"
}
}
}
},
"FHIR_RESOURCE_INTERPRETATION_PROMPT %@" : {
"extractionState" : "stale",
"Interpretation Prompt Content" : {
"comment" : "Content of the interpretation prompt.",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Your task is to interpret the following FHIR resource from the user's clinical record.\n\nInterpret the resource by explaining its data relevant to the user's health.\nExplain the relevant medical context in a language understandable by a user who is not a medical professional.\nYou should provide factual and precise information in a compact summary in short responses.\n\nThe following JSON representation defines the FHIR resource that you should interpret:\n%@\n\nImmediately return an interpretation to the user, starting the conversation.\nDo not introduce yourself at the beginning, and start with your interpretation."
}
}
}
},
"FHIR_RESOURCE_INTERPRETATION_PROMPT %@ %@" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "FHIR_RESOURCE_INTERPRETATION_PROMPT %1$@ %2$@"
"value" : "Your task is to interpret the following FHIR resource from the user's clinical record.\n\nInterpret the resource by explaining its data relevant to the user's health.\nExplain the relevant medical context in a language understandable by a user who is not a medical professional.\nYou should provide factual and precise information in a compact summary in short responses.\n\nThe following JSON representation defines the FHIR resource that you should interpret:\n{{FHIR_RESOURCE}}\n\nImmediately return an interpretation to the user, starting the conversation.\nDo not introduce yourself at the beginning, and start with your interpretation.\n\nChat with the user in the same language they chat in.\nChat with the user in {{LOCALE}}"
}
}
}
},
"FHIR_RESOURCE_SUMMARY_PROMPT %@" : {
"extractionState" : "stale",
"Load Resource Summary" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Your task is to interpret the following FHIR resource from the user's clinical record.\n \nThe following JSON representation defines the FHIR resource that you should interpret:\n%@\n \nProvide a short one-sentence summary of the resource in less than 40 words. \nEnsure that the summary only focuses on the essential information that a patient would need and, e.g., excludes the person who prescribed a medication or similar metadata.\nDo NOT respond with more content than the single line containing the summary.\nDirectly provide the content without any additional structure."
"value" : "Load Resource Summary"
}
}
}
},
"FHIR_RESOURCE_SUMMARY_PROMPT %@ %@" : {
"Place %@ at the position in the prompt where the FHIR resource should be inserted. Optionally place %@ where you would like to insert the current locale." : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "FHIR_RESOURCE_SUMMARY_PROMPT %1$@ %2$@"
}
}
}
},
"Interpretation Prompt" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Interpretation Prompt"
}
}
}
},
"Interpretation Prompt for Multiple Resources" : {
"extractionState" : "stale",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Interpretation Prompt for Multiple Resources"
}
}
}
},
"Load Resource Summary" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Load Resource Summary"
"value" : "Place %1$@ at the position in the prompt where the FHIR resource should be inserted. Optionally place %2$@ where you would like to insert the current locale."
}
}
}
},
"Place %@ at the position in the prompt where the FHIR resource should be inserted." : {
"Save Prompt" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Place %@ at the position in the prompt where the FHIR resource should be inserted."
"value" : "Save Prompt"
}
}
}
},
"Save Prompt" : {
"Summary Prompt" : {
"comment" : "Title of the summary prompt.",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Save Prompt"
"value" : "Summary Prompt"
}
}
}
},
"Summary Prompt" : {
"Summary Prompt Content" : {
"comment" : "Content of the summary prompt.",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Summary Prompt"
"value" : "Your task is to interpret FHIR resources from the user's clinical records.\nThroughout the conversation with the user, use the get_resource_titles function to obtain the FHIR health resources necessary to properly answer the users question. For example, if the user asks about their allergies, you must use get_resource_titles to output the FHIR resource titles for allergy records so you can then use them to answer the question. The output of get_resource_titles has to be the name of a resource or resources with the exact same title as in the list provided.\n\nAnswer the users question, the health record provided is not always related. The end goal is to answer the users question in the best way possible.\n\nInterpret the resources by explaining its data relevant to the user's health.\nExplain the relevant medical context in a language understandable by a user who is not a medical professional.\nYou should provide factual and precise information in a compact summary in short responses.\n\nTell the user that they can ask any question about their health records and then create a short summary of the main categories of health records of the user which you have access to. These are the resource titles:\n{{FHIR_RESOURCE}}\n\nImmediately return a short summary of the users health records to start the conversation.\nThe initial summary should be a short and simple summary with the following specifications:\n1. Short summary of the health records categories\n2. 5th grade reading level\n3. End with a question asking user if they have any questions. Make sure that this question is not generic but specific to their health records.\nDo not introduce yourself at the beginning, and start with your interpretation.\nMake sure your response is in the same language the user writes to you in.\nThe tense should be present. \n\nChat with the user in the same language they chat in.\nChat with the user in {{LOCALE}}"
}
}
}
Expand Down
40 changes: 24 additions & 16 deletions Sources/SpeziFHIRInterpretation/Settings/FHIRPrompt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,22 @@ import Foundation


/// Handle dynamic, localized LLM prompts for FHIR resources.
public struct FHIRPrompt {
/// Placeholder for dynamic content in prompts.
public static let promptPlaceholder = "%@"
public struct FHIRPrompt: Hashable {
/// Placeholder for FHIR resource in prompts.
public static let fhirResourcePlaceholder = "{{FHIR_RESOURCE}}"
/// Placeholder for the current locale in a prompt
public static let localePlaceholder = "{{LOCALE}}"

/// The key used for storing and retrieving the prompt.
public let storageKey: String
/// A human-readable description of the prompt, localized as needed.
public let localizedDescription: String
/// The default prompt text to be used if no custom prompt is set.
public let defaultPrompt: String

/// The current prompt, either from UserDefaults or the default, appended with a localized message that adapts to the user's language settings.
public var prompt: String {
var prompt = UserDefaults.standard.string(forKey: storageKey) ?? defaultPrompt

prompt += String(
localized:
"""
Chat with the user in the same language they chat in.
Chat with the user in \(Locale.preferredLanguages[0])
""",
comment: "The passed in string is the current locale of the device as a IETF BCP 47 language tag."
)

return prompt
UserDefaults.standard.string(forKey: storageKey) ?? defaultPrompt
}


Expand All @@ -58,4 +49,21 @@ public struct FHIRPrompt {
public func save(prompt: String) {
UserDefaults.standard.set(prompt, forKey: storageKey)
}

public func hash(into hasher: inout Hasher) {
hasher.combine(storageKey)
}

/// Creates a prompt based in the variable input.
///
/// Use ``FHIRPrompt/fhirResourcePlaceholder`` and ``FHIRPrompt/localePlaceholder`` to define the elements that should be replaced.
/// - Parameters:
/// - resource: The resource that should be inserted in the prompt.
/// - locale: The current locale that should be inserted in the prompt.
/// - Returns: The constructed prompt.
public func prompt(withFHIRResource resource: String, locale: String = Locale.preferredLanguages[0]) -> String {
prompt
.replacingOccurrences(of: FHIRPrompt.fhirResourcePlaceholder, with: resource)
.replacingOccurrences(of: FHIRPrompt.localePlaceholder, with: locale)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ public struct PromptSettingsView: View {

public var body: some View {
VStack(spacing: 16) {
Text("Customize the \(promptType.localizedDescription.lowercased()) prompt.")
Text("Customize the \(promptType.localizedDescription.lowercased()).")
.multilineTextAlignment(.leading)
TextEditor(text: $prompt)
.fontDesign(.monospaced)
Text("Place \(FHIRPrompt.promptPlaceholder) at the position in the prompt where the FHIR resource should be inserted.")
Text("Place \(FHIRPrompt.fhirResourcePlaceholder) at the position in the prompt where the FHIR resource should be inserted. Optionally place \(FHIRPrompt.localePlaceholder) where you would like to insert the current locale.")
.multilineTextAlignment(.leading)
.font(.caption)
Button(
Expand Down
Loading

0 comments on commit 2700a05

Please sign in to comment.