diff --git a/src/Informedica.OpenAI.Lib/Extraction.fs b/src/Informedica.OpenAI.Lib/Extraction.fs index b152ce5..63b2ae9 100644 --- a/src/Informedica.OpenAI.Lib/Extraction.fs +++ b/src/Informedica.OpenAI.Lib/Extraction.fs @@ -149,8 +149,27 @@ module Extraction = let _ = JsonConvert.DeserializeObject<{| frequencies : int list; timeUnit : string |}>(s) s |> Ok with - | e -> $"The answer: {s} was not correct because:\n{e.ToString()}" |> Error + | e -> $"The answer: |{s}| was not correct because:\n{e.ToString()}" |> Error Prompts.User.frequencyText timeUnit zero |> Message.userWithValidator validator - |> extract jsonFreq model zero \ No newline at end of file + |> extract jsonFreq model zero + + + let extractDoseQuantities json model substanceUnit adjustUnit timeUnit = + let zero = {| quantities = [||]|} + let validator = + fun s -> + try + let _ = JsonConvert.DeserializeObject<{| quantities : {| minQty : float; maxQty : float; unit : string |}[]|}>(s) + s |> Ok + with + | e -> + let msg = $"The answer: {s} was not correct because:\n{e.ToString()}" + printfn $"{msg}" + msg + |> Error + + Prompts.User.minMaxDoseText substanceUnit adjustUnit timeUnit + |> Message.userWithValidator validator + |> extract json model zero diff --git a/src/Informedica.OpenAI.Lib/Notebooks/ExtractFrequencies.ipynb b/src/Informedica.OpenAI.Lib/Notebooks/ExtractFrequencies.ipynb index 9bd03ea..a7b3a75 100644 --- a/src/Informedica.OpenAI.Lib/Notebooks/ExtractFrequencies.ipynb +++ b/src/Informedica.OpenAI.Lib/Notebooks/ExtractFrequencies.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 57, + "execution_count": 82, "metadata": { "dotnet_interactive": { "language": "fsharp" @@ -21,12 +21,12 @@ "open FSharpPlus.Data\n", "open Informedica.Utils.Lib.BCL\n", "\n", - "open Informedica.OpenAI.Lib\n" + "open Informedica.OpenAI.Lib" ] }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 83, "metadata": { "dotnet_interactive": { "language": "fsharp" @@ -37,20 +37,21 @@ }, "outputs": [], "source": [ - "let test model =\n", + "let inline test extract print sysInput model texts =\n", " [\n", - " for (text, exp) in Texts.testUnitTexts do\n", + " for (text, exp) in texts do\n", " let act, msgs =\n", - " [\n", - " Prompts.System.systemDoseQuantityExpert text\n", - " |> Message.system\n", - " ]\n", + " text\n", + " |> sysInput\n", " |> State.run\n", - " (Ollama.Extract.frequencies model text)\n", + " (extract model text)\n", "\n", - " msgs |> List.iter Message.print\n", + " msgs |> print\n", "\n", - " 1 // need to implement: if act = exp then 1 else 0\n", + " if act = exp then 1 \n", + " else \n", + " printfn $\"## Failed test: {act} is not {exp}\"\n", + " 0\n", " , (act, exp)\n", " , text\n", " ]" @@ -58,7 +59,7 @@ }, { "cell_type": "code", - "execution_count": 59, + "execution_count": 86, "metadata": { "dotnet_interactive": { "language": "fsharp" @@ -163,284 +164,203 @@ "{\"frequencies\":[3],\"timeUnit\":\"dag\"}\n", "\n", "\n", - "## System:\n", - "You are an expert on medication prescribing, preparation and administration. You will give\n", - "exact answers. If there is no possible answer return an empty string.\n", - "You will be asked to extract structured information from the following text between ''':\n", - "\n", - "'''\n", - "acetylsalicylzuur\n", - "1 maand tot 18 jaar Startdosering:Acetylsalicylzuur: 30 - 50 mg/kg/dag in 3 - 4 doses. Max: 3.000 mg/dag.\n", - "'''\n", - "\n", - "ONLY respond if the response is actually present in the text. If the response cannot be extracted\n", - "respond with an empty string for a textfield or zero for a number field.\n", - "\n", - "Respond in JSON\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the unit of measurement for the medication substance (substance unit)\n", - "from the medication dosage information contained in the text.\n", - "\n", - "Use schema: { substanceUnit: string }\n", - "\n", - "Here are some examples and expected output:\n", - " - For \"mg/kg/dag\", return: \"{ \"substanceUnit\": \"mg\" }\"\n", - " - For \"g/m2/dag\", return: \"{ \"substanceUnit\": \"g\" }\"\n", - " - For \"IE/m2\", return: \"{ \"substanceUnit\": \"IE\" }\"\n", - " - For \"mg/2 dagen\", return: \"{ \"substanceUnit\": \"mg\" }\"\n", - "\n", - "\n", - "## Answer:\n", - "{\"substanceUnit\":\"mg\"}\n", - "\n", - "\n", "## Question:\n", - "Use the provided schema to extract the unit of measurement by which a medication dose is adjusted,\n", - "such as patient weight or body surface area, from the medication dosage information contained in the text.\n", - "\n", - "Use schema : { adjustUnit: string }\n", + "Use the provided schema to extract all mentioned dose quantities.\n", + "A quantity should match the regular expresion between the ticks '(\\d+(\\.\\d+)?\\s?(mg)(\\/(kg|dag|keer|dosis))?(\\s?\\/\\s?(kg|dag|keer|dosis))?\\s)'\n", + "\n", + "Return dose quantities as a list of JSON\n", + "Use schema :\n", + "{\n", + " \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"quantities\": {\n", + " \"type\": \"array\",\n", + " \"items\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"minQty\": {\n", + " \"type\": \"number\",\n", + " \"minimum\": 0\n", + " },\n", + " \"maxQty\": {\n", + " \"type\": \"number\",\n", + " \"minimum\": 0\n", + " },\n", + " \"unit\": {\n", + " \"type\": \"string\",\n", + " \"enum\": [\"mg\", \"mg/kg\"]\n", + " }\n", + " },\n", + " \"required\": [\"minQty\", \"maxQty\", \"unit\"]\n", + " }\n", + " }\n", + " },\n", + " \"required\": [\"quantities\"]\n", + "}\n", "\n", - "Here are some examples and expected output:\n", - "- For \"mg/kg/dag\", return: \"{ \"adjustUnit\": \"kg\" }\"\n", - "- For \"mg/kg\", return: \"{ \"adjustUnit\": \"kg\" }\"\n", - "- For \"mg/m2/dag\", return: \"{ \"adjustUnit\": \"m2\" }\"\n", - "- For \"mg/m2\", return: \"{ \"adjustUnit\": \"m2\" }\"\n", - "\n", - "If extraction is not possible return: \"{\"adjustUnit\":\"\"}\"\n", "Respond in JSON\n", "\n", "\n", "## Answer:\n", - "{\"adjustUnit\":\"kg\"}\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the time unit from the medication dosage information contained in the text.\n", - "The timeunit is the unit by which the frequency of administration is measured.\n", - "\n", - "Use schema : { timeUnit: string }\n", - "\n", - "Here are some examples and expected output:\n", - "- For \"mg/kg/dag\", return: \"{ \"timeUnit\": \"dag\" }\"\n", - "- For \"mg/kg\", return: \"{ \"timeUnit\": \"\" }\"\n", - "- For \"mg/m2/week\", return: \"{ \"timeUnit\": \"week\" }\"\n", - "- For \"mg/2 dagen\", return: \"{ \"timeUnit\": \"2 dagen\" }\"\n", - "- For \"per week\", return \"{ \"timeUnit\": \"week\" }\"\n", - "- For \"per dag\", return \"{ \"timeUnit\": \"week\" }\"\n", - "\n", - "If extraction is not possible return: \"{\"timeUnit\":\"\"}\"\n", - "Respond in JSON\n", - "\n", - "\n", - "## Answer:\n", - "{\"timeUnit\":\"dag\"}\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the frequencies by which the drug can be administered.\n", - "The frequencies field in the schema should be an array of integers.\n", + "{\"quantities\":[{\"maxQty\":0.05,\"minQty\":0.125,\"unit\":\"mg\"},{\"maxQty\":3.0,\"minQty\":1.0,\"unit\":\"mg/dag\"}]}\n", + "\n", + "## Failed test: { doseQuantities = [|{ maxQty = 0.05\n", + " minQty = 0.125\n", + " unit = \"mg\" }; { maxQty = 3.0\n", + " minQty = 1.0\n", + " unit = \"mg/dag\" }|]\n", + " doseUnits = { adjustUnit = \"kg\"\n", + " substanceUnit = \"mg\"\n", + " timeUnit = \"dag\" }\n", + " freqs = { frequencies = [3]\n", + " timeUnit = \"dag\" } } is not { doseQuantities = [|{ maxQty = 0.25\n", + " minQty = 0.125\n", + " unit = \"mg\" }|]\n", + " doseUnits = { adjustUnit = \"kg\"\n", + " substanceUnit = \"mg\"\n", + " timeUnit = \"dag\" }\n", + " freqs = { frequencies = [3]\n", + " timeUnit = \"dag\" } }\n", + "score: 0\n" + ] + } + ], + "source": [ + "let calcScore = List.sumBy (fun (s, _, _) -> s)\n", + "\n", + "\n", + "let testLocal =\n", + " let sysInput text = \n", + " [\n", + " Prompts.System.systemDoseQuantityExpert text\n", + " |> Message.system\n", + " ]\n", + "\n", + " [\n", + "// Ollama.Models.llama2\n", + "// Ollama.Models.gemma\n", + "// Ollama.Models.openhermes\n", + "// Ollama.Models.llama2\n", + "// Ollama.Models.``llama-pro``\n", + "// Ollama.Models.``openchat:7b``\n", + "// Ollama.Models.``llama2:13b-chat``\n", + " Ollama.Models.mistral\n", + " ]\n", + " |> List.map (fun model -> \n", + " printf $\"- Testing: {model}: \"\n", + " let s = \n", + " Texts.testMinMaxDoseQtyTexts\n", + " |> List.take 1\n", + " |> test \n", + " Ollama.Extract.minMaxDose \n", + " (List.iter Message.print) \n", + " sysInput\n", + " model\n", + " printfn $\"score: {s |> calcScore}\"\n", + " model, s\n", + " ) " + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "dotnet_interactive": { + "language": "fsharp" + }, + "polyglot_notebook": { + "kernelName": "fsharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ "\n", - "Use schema : { frequencies: []; timeUnit: string }\n", "\n", - "Note that the frequencies should be possible times of administrations per dag\n", - "If extraction is not possible return: \"{\"frequencies\":[],\"timeUnit\":\"dag\"}\"\n", - "Respond in JSON\n", + "## And the winner is: mistral with a high score: 1 from 6\n", + "## Score: 0\n", + "## Text:\n", "\n", + "alprazolam\n", + "6 jaar tot 18 jaar Startdosering: 0,125 mg/dag, éénmalig. Onderhoudsdosering: Op geleide van klinisch beeld verhogen met stappen van 0,125-0,25 mg/dosis tot max 0,05 mg/kg/dag in 3 doses. Max: 3 mg/dag. Advies inname/toediening: De dagdosis indien mogelijk verdelen over 3 doses.Bij plotselinge extreme slapeloosheid: alleen voor de nacht innemen; dosering op geleide van effect ophogen tot max 0,05 mg/kg, maar niet hoger dan 3 mg/dag.De effectiviteit bij de behandeling van acute angst is discutabel.\n", "\n", - "## Answer:\n", - "{\"frequencies\":[3,4],\"timeUnit\":\"dag\"}\n", + "## Score: 0\n", + "## Text:\n", "\n", + "acetylsalicylzuur\n", + "1 maand tot 18 jaar Startdosering:Acetylsalicylzuur: 30 - 50 mg/kg/dag in 3 - 4 doses. Max: 3.000 mg/dag.\n", "\n", - "## System:\n", - "You are an expert on medication prescribing, preparation and administration. You will give\n", - "exact answers. If there is no possible answer return an empty string.\n", - "You will be asked to extract structured information from the following text between ''':\n", + "## Score: 0\n", + "## Text:\n", "\n", - "'''\n", "paracetamol\n", "Oraal: Bij milde tot matige pijn en/of koorts: volgens het Kinderformularium van het NKFK bij een leeftijd van 1 maand–18 jaar: 10–15 mg/kg lichaamsgewicht per keer, zo nodig 4×/dag, max. 60 mg/kg/dag en max. 4 g/dag.\n", - "'''\n", - "\n", - "ONLY respond if the response is actually present in the text. If the response cannot be extracted\n", - "respond with an empty string for a textfield or zero for a number field.\n", - "\n", - "Respond in JSON\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the unit of measurement for the medication substance (substance unit)\n", - "from the medication dosage information contained in the text.\n", - "\n", - "Use schema: { substanceUnit: string }\n", - "\n", - "Here are some examples and expected output:\n", - " - For \"mg/kg/dag\", return: \"{ \"substanceUnit\": \"mg\" }\"\n", - " - For \"g/m2/dag\", return: \"{ \"substanceUnit\": \"g\" }\"\n", - " - For \"IE/m2\", return: \"{ \"substanceUnit\": \"IE\" }\"\n", - " - For \"mg/2 dagen\", return: \"{ \"substanceUnit\": \"mg\" }\"\n", - "\n", - "\n", - "## Answer:\n", - "{\"substanceUnit\":\"mg\"}\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the unit of measurement by which a medication dose is adjusted,\n", - "such as patient weight or body surface area, from the medication dosage information contained in the text.\n", - "\n", - "Use schema : { adjustUnit: string }\n", - "\n", - "Here are some examples and expected output:\n", - "- For \"mg/kg/dag\", return: \"{ \"adjustUnit\": \"kg\" }\"\n", - "- For \"mg/kg\", return: \"{ \"adjustUnit\": \"kg\" }\"\n", - "- For \"mg/m2/dag\", return: \"{ \"adjustUnit\": \"m2\" }\"\n", - "- For \"mg/m2\", return: \"{ \"adjustUnit\": \"m2\" }\"\n", - "\n", - "If extraction is not possible return: \"{\"adjustUnit\":\"\"}\"\n", - "Respond in JSON\n", - "\n", - "\n", - "## Answer:\n", - "{\"adjustUnit\":\"kg\"}\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the time unit from the medication dosage information contained in the text.\n", - "The timeunit is the unit by which the frequency of administration is measured.\n", - "\n", - "Use schema : { timeUnit: string }\n", - "\n", - "Here are some examples and expected output:\n", - "- For \"mg/kg/dag\", return: \"{ \"timeUnit\": \"dag\" }\"\n", - "- For \"mg/kg\", return: \"{ \"timeUnit\": \"\" }\"\n", - "- For \"mg/m2/week\", return: \"{ \"timeUnit\": \"week\" }\"\n", - "- For \"mg/2 dagen\", return: \"{ \"timeUnit\": \"2 dagen\" }\"\n", - "- For \"per week\", return \"{ \"timeUnit\": \"week\" }\"\n", - "- For \"per dag\", return \"{ \"timeUnit\": \"week\" }\"\n", - "\n", - "If extraction is not possible return: \"{\"timeUnit\":\"\"}\"\n", - "Respond in JSON\n", - "\n", - "\n", - "## Answer:\n", - "{\"timeUnit\":\"dag\"}\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the frequencies by which the drug can be administered.\n", - "The frequencies field in the schema should be an array of integers.\n", - "\n", - "Use schema : { frequencies: []; timeUnit: string }\n", - "\n", - "Note that the frequencies should be possible times of administrations per dag\n", - "If extraction is not possible return: \"{\"frequencies\":[],\"timeUnit\":\"dag\"}\"\n", - "Respond in JSON\n", - "\n", - "\n", - "## Answer:\n", - "{\"frequencies\":[4],\"timeUnit\":\"dag\"}\n", "\n", + "## Score: 0\n", + "## Text:\n", "\n", - "## System:\n", - "You are an expert on medication prescribing, preparation and administration. You will give\n", - "exact answers. If there is no possible answer return an empty string.\n", - "You will be asked to extract structured information from the following text between ''':\n", - "\n", - "'''\n", "amitriptyline\n", "6 jaar tot 18 jaar Startdosering: voor de nacht: 10 mg/dag in 1 dosisOnderhoudsdosering: langzaam ophogen met 10 mg/dag per 4-6 weken naar 10 - 30 mg/dag in 1 dosis. Max: 30 mg/dag. Behandeling met amitriptyline mag niet plotseling worden gestaakt vanwege het optreden van ontwenningsverschijnselen; de dosering moet geleidelijk worden verminderd.Uit de studie van Powers (2017) blijkt dat de werkzaamheid van amitriptyline bij migraine profylaxe niet effectiever is t.o.v. placebo. Desondanks menen experts dat in individuele gevallen behandeling met amitriptyline overwogen kan worden.\n", - "'''\n", - "\n", - "ONLY respond if the response is actually present in the text. If the response cannot be extracted\n", - "respond with an empty string for a textfield or zero for a number field.\n", - "\n", - "Respond in JSON\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the unit of measurement for the medication substance (substance unit)\n", - "from the medication dosage information contained in the text.\n", - "\n", - "Use schema: { substanceUnit: string }\n", - "\n", - "Here are some examples and expected output:\n", - " - For \"mg/kg/dag\", return: \"{ \"substanceUnit\": \"mg\" }\"\n", - " - For \"g/m2/dag\", return: \"{ \"substanceUnit\": \"g\" }\"\n", - " - For \"IE/m2\", return: \"{ \"substanceUnit\": \"IE\" }\"\n", - " - For \"mg/2 dagen\", return: \"{ \"substanceUnit\": \"mg\" }\"\n", - "\n", - "\n", - "## Answer:\n", - "{\"substanceUnit\":\"mg\"}\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the unit of measurement by which a medication dose is adjusted,\n", - "such as patient weight or body surface area, from the medication dosage information contained in the text.\n", - "\n", - "Use schema : { adjustUnit: string }\n", - "\n", - "Here are some examples and expected output:\n", - "- For \"mg/kg/dag\", return: \"{ \"adjustUnit\": \"kg\" }\"\n", - "- For \"mg/kg\", return: \"{ \"adjustUnit\": \"kg\" }\"\n", - "- For \"mg/m2/dag\", return: \"{ \"adjustUnit\": \"m2\" }\"\n", - "- For \"mg/m2\", return: \"{ \"adjustUnit\": \"m2\" }\"\n", - "\n", - "If extraction is not possible return: \"{\"adjustUnit\":\"\"}\"\n", - "Respond in JSON\n", - "\n", - "\n", - "## Answer:\n", - "{\"adjustUnit\":\"\"}\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the time unit from the medication dosage information contained in the text.\n", - "The timeunit is the unit by which the frequency of administration is measured.\n", - "\n", - "Use schema : { timeUnit: string }\n", - "\n", - "Here are some examples and expected output:\n", - "- For \"mg/kg/dag\", return: \"{ \"timeUnit\": \"dag\" }\"\n", - "- For \"mg/kg\", return: \"{ \"timeUnit\": \"\" }\"\n", - "- For \"mg/m2/week\", return: \"{ \"timeUnit\": \"week\" }\"\n", - "- For \"mg/2 dagen\", return: \"{ \"timeUnit\": \"2 dagen\" }\"\n", - "- For \"per week\", return \"{ \"timeUnit\": \"week\" }\"\n", - "- For \"per dag\", return \"{ \"timeUnit\": \"week\" }\"\n", - "\n", - "If extraction is not possible return: \"{\"timeUnit\":\"\"}\"\n", - "Respond in JSON\n", - "\n", - "\n", - "## Answer:\n", - "{\"timeUnit\":\"dag\"}\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the frequencies by which the drug can be administered.\n", - "The frequencies field in the schema should be an array of integers.\n", - "\n", - "Use schema : { frequencies: []; timeUnit: string }\n", - "\n", - "Note that the frequencies should be possible times of administrations per dag\n", - "If extraction is not possible return: \"{\"frequencies\":[],\"timeUnit\":\"dag\"}\"\n", - "Respond in JSON\n", "\n", + "## Score: 0\n", + "## Text:\n", "\n", - "## Answer:\n", - "{\"frequencies\":[1],\"timeUnit\":\"dag\"}\n", + "aciclovir\n", + "3 maanden tot 18 jaar 1.500 mg/m2/dag in 3 doses.Behandelduur: Herpes encefalitis: 14-21 dagen Varicella zoster: 7 dagen\n", "\n", + "## Score: 1\n", + "## Text:\n", "\n", + "aprepitant\n", + "3 jaar tot 18 jaar en < 40 kg 2 maal per week 40 mg/dosis verdeeld over de week.\n", + "\n" + ] + } + ], + "source": [ + "testLocal \n", + "|> List.maxBy (fun (model, xs) -> xs |> calcScore)\n", + "|> fun (m, s) -> printfn $\"\\n\\n## And the winner is: {m} with a high score: {s |> calcScore} from {Texts.testUnitTexts |> List.length}\"\n", + "\n", + "testLocal\n", + "|> List.collect (fun (m, xs) -> xs)\n", + "|> List.groupBy (fun (_, _, t) -> t)\n", + "|> List.map (fun (txt, s) -> s |> calcScore, txt)\n", + "|> List.sortBy fst\n", + "|> List.iter (fun (s, t) ->\n", + " printfn $\"## Score: {s}\"\n", + " printfn $\"## Text:\\n{t}\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": { + "dotnet_interactive": { + "language": "fsharp" + }, + "polyglot_notebook": { + "kernelName": "fsharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "- Testing: gpt-4-turbo-preview: \n", "## System:\n", "You are an expert on medication prescribing, preparation and administration. You will give\n", "exact answers. If there is no possible answer return an empty string.\n", "You will be asked to extract structured information from the following text between ''':\n", "\n", "'''\n", - "aciclovir\n", - "3 maanden tot 18 jaar 1.500 mg/m2/dag in 3 doses.Behandelduur: Herpes encefalitis: 14-21 dagen Varicella zoster: 7 dagen\n", + "alprazolam\n", + "6 jaar tot 18 jaar Startdosering: 0,125 mg/dag, éénmalig. Onderhoudsdosering: Op geleide van klinisch beeld verhogen met stappen van 0,125-0,25 mg/dosis tot max 0,05 mg/kg/dag in 3 doses. Max: 3 mg/dag. Advies inname/toediening: De dagdosis indien mogelijk verdelen over 3 doses.Bij plotselinge extreme slapeloosheid: alleen voor de nacht innemen; dosering op geleide van effect ophogen tot max 0,05 mg/kg, maar niet hoger dan 3 mg/dag.De effectiviteit bij de behandeling van acute angst is discutabel.\n", "'''\n", "\n", "ONLY respond if the response is actually present in the text. If the response cannot be extracted\n", @@ -463,27 +383,7 @@ "\n", "\n", "## Answer:\n", - "{\"substanceUnit\":\"mg/m2\"}\n", - "\n", - "\n", - "## Question:\n", - "The answer: {\"substanceUnit\":\"mg/m2\"} was not correct because of mg/m2 is not a valid unit, this is not one unit but 2 units, just one unit should be extracted, so, the extracted unit should not contain '/'. Please try again answering:\n", - "\n", - "\n", - "Use the provided schema to extract the unit of measurement for the medication substance (substance unit)\n", - "from the medication dosage information contained in the text.\n", - "\n", - "Use schema: { substanceUnit: string }\n", - "\n", - "Here are some examples and expected output:\n", - " - For \"mg/kg/dag\", return: \"{ \"substanceUnit\": \"mg\" }\"\n", - " - For \"g/m2/dag\", return: \"{ \"substanceUnit\": \"g\" }\"\n", - " - For \"IE/m2\", return: \"{ \"substanceUnit\": \"IE\" }\"\n", - " - For \"mg/2 dagen\", return: \"{ \"substanceUnit\": \"mg\" }\"\n", - "\n", - "\n", - "## Answer:\n", - "{\"substanceUnit\":\"mg\"}\n", + "{ \"substanceUnit\": \"mg\" }\n", "\n", "\n", "## Question:\n", @@ -503,7 +403,7 @@ "\n", "\n", "## Answer:\n", - "{\"adjustUnit\":\"m2\"}\n", + "{ \"adjustUnit\": \"kg\" }\n", "\n", "\n", "## Question:\n", @@ -525,7 +425,7 @@ "\n", "\n", "## Answer:\n", - "{\"timeUnit\":\"dag\"}\n", + "{ \"timeUnit\": \"dag\" }\n", "\n", "\n", "## Question:\n", @@ -540,119 +440,121 @@ "\n", "\n", "## Answer:\n", - "{\"frequencies\":[3],\"timeUnit\":\"dag\"}\n", - "\n", - "\n", - "## System:\n", - "You are an expert on medication prescribing, preparation and administration. You will give\n", - "exact answers. If there is no possible answer return an empty string.\n", - "You will be asked to extract structured information from the following text between ''':\n", - "\n", - "'''\n", - "aprepitant\n", - "3 jaar tot 18 jaar en < 40 kg 2 maal per week 40 mg/dosis verdeeld over de week.\n", - "'''\n", - "\n", - "ONLY respond if the response is actually present in the text. If the response cannot be extracted\n", - "respond with an empty string for a textfield or zero for a number field.\n", - "\n", - "Respond in JSON\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the unit of measurement for the medication substance (substance unit)\n", - "from the medication dosage information contained in the text.\n", - "\n", - "Use schema: { substanceUnit: string }\n", - "\n", - "Here are some examples and expected output:\n", - " - For \"mg/kg/dag\", return: \"{ \"substanceUnit\": \"mg\" }\"\n", - " - For \"g/m2/dag\", return: \"{ \"substanceUnit\": \"g\" }\"\n", - " - For \"IE/m2\", return: \"{ \"substanceUnit\": \"IE\" }\"\n", - " - For \"mg/2 dagen\", return: \"{ \"substanceUnit\": \"mg\" }\"\n", - "\n", - "\n", - "## Answer:\n", - "{\"substanceUnit\":\"mg\"}\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the unit of measurement by which a medication dose is adjusted,\n", - "such as patient weight or body surface area, from the medication dosage information contained in the text.\n", - "\n", - "Use schema : { adjustUnit: string }\n", - "\n", - "Here are some examples and expected output:\n", - "- For \"mg/kg/dag\", return: \"{ \"adjustUnit\": \"kg\" }\"\n", - "- For \"mg/kg\", return: \"{ \"adjustUnit\": \"kg\" }\"\n", - "- For \"mg/m2/dag\", return: \"{ \"adjustUnit\": \"m2\" }\"\n", - "- For \"mg/m2\", return: \"{ \"adjustUnit\": \"m2\" }\"\n", - "\n", - "If extraction is not possible return: \"{\"adjustUnit\":\"\"}\"\n", - "Respond in JSON\n", - "\n", - "\n", - "## Answer:\n", - "{\"adjustUnit\":null}\n", - "\n", - "\n", - "## Question:\n", - "Use the provided schema to extract the time unit from the medication dosage information contained in the text.\n", - "The timeunit is the unit by which the frequency of administration is measured.\n", - "\n", - "Use schema : { timeUnit: string }\n", - "\n", - "Here are some examples and expected output:\n", - "- For \"mg/kg/dag\", return: \"{ \"timeUnit\": \"dag\" }\"\n", - "- For \"mg/kg\", return: \"{ \"timeUnit\": \"\" }\"\n", - "- For \"mg/m2/week\", return: \"{ \"timeUnit\": \"week\" }\"\n", - "- For \"mg/2 dagen\", return: \"{ \"timeUnit\": \"2 dagen\" }\"\n", - "- For \"per week\", return \"{ \"timeUnit\": \"week\" }\"\n", - "- For \"per dag\", return \"{ \"timeUnit\": \"week\" }\"\n", - "\n", - "If extraction is not possible return: \"{\"timeUnit\":\"\"}\"\n", - "Respond in JSON\n", - "\n", - "\n", - "## Answer:\n", - "{\"timeUnit\":\"week\"}\n", + "{ \"frequencies\": [3], \"timeUnit\": \"dag\" }\n", "\n", "\n", "## Question:\n", - "Use the provided schema to extract the frequencies by which the drug can be administered.\n", - "The frequencies field in the schema should be an array of integers.\n", - "\n", - "Use schema : { frequencies: []; timeUnit: string }\n", + "Use the provided schema to extract all mentioned dose quantities.\n", + "A quantity should match the regular expresion: (\\d+(\\.\\d+)?\\s?(mg)(\\/(kg|dag|keer|dosis))?(\\s?\\/\\s?(kg|dag|keer|dosis))?\\s)\n", + "\n", + "Return dose quantities as a list of JSON\n", + "Use schema :\n", + "{\n", + " \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"quantities\": {\n", + " \"type\": \"array\",\n", + " \"items\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"minQty\": {\n", + " \"type\": \"number\",\n", + " \"minimum\": 0\n", + " },\n", + " \"maxQty\": {\n", + " \"type\": \"number\",\n", + " \"minimum\": 0\n", + " },\n", + " \"unit\": {\n", + " \"type\": \"string\",\n", + " \"enum\": [\"mg\", \"mg/kg\"]\n", + " }\n", + " },\n", + " \"required\": [\"minQty\", \"maxQty\", \"unit\"]\n", + " }\n", + " }\n", + " },\n", + " \"required\": [\"quantities\"]\n", + "}\n", "\n", - "Note that the frequencies should be possible times of administrations per week\n", - "If extraction is not possible return: \"{\"frequencies\":[],\"timeUnit\":\"week\"}\"\n", "Respond in JSON\n", "\n", "\n", "## Answer:\n", - "{\"frequencies\":[2],\"timeUnit\":\"week\"}\n", - "\n", - "score: 6\n" + "{\n", + " \"quantities\": [\n", + " {\n", + " \"minQty\": 0.125,\n", + " \"maxQty\": 0.125,\n", + " \"unit\": \"mg\"\n", + " },\n", + " {\n", + " \"minQty\": 0.125,\n", + " \"maxQty\": 0.25,\n", + " \"unit\": \"mg\"\n", + " },\n", + " {\n", + " \"minQty\": 0.05,\n", + " \"maxQty\": 0.05,\n", + " \"unit\": \"mg/kg\"\n", + " },\n", + " {\n", + " \"minQty\": 3,\n", + " \"maxQty\": 3,\n", + " \"unit\": \"mg\"\n", + " }\n", + " ]\n", + "}\n", + "\n", + "## Failed test: { doseQuantities =\n", + " [|{ maxQty = 0.125\n", + " minQty = 0.125\n", + " unit = \"mg\" }; { maxQty = 0.25\n", + " minQty = 0.125\n", + " unit = \"mg\" }; { maxQty = 0.05\n", + " minQty = 0.05\n", + " unit = \"mg/kg\" }; { maxQty = 3.0\n", + " minQty = 3.0\n", + " unit = \"mg\" }|]\n", + " doseUnits = { adjustUnit = \"kg\"\n", + " substanceUnit = \"mg\"\n", + " timeUnit = \"dag\" }\n", + " freqs = { frequencies = [3]\n", + " timeUnit = \"dag\" } } is not { doseQuantities = [|{ maxQty = 0.25\n", + " minQty = 0.125\n", + " unit = \"mg\" }|]\n", + " doseUnits = { adjustUnit = \"kg\"\n", + " substanceUnit = \"mg\"\n", + " timeUnit = \"dag\" }\n", + " freqs = { frequencies = [3]\n", + " timeUnit = \"dag\" } }\n", + "score: 0\n" ] } ], "source": [ - "let calcScore = List.sumBy (fun (s, _, _) -> s)\n", + "let testChatGPT =\n", "\n", - "\n", - "let testResults =\n", " [\n", - "// Ollama.Models.llama2\n", - "// Ollama.Models.gemma\n", - "// Ollama.Models.openhermes\n", - " Ollama.Models.mistral\n", - "// Ollama.Models.``llama-pro``\n", - "// Ollama.Models.``openchat:7b``\n", - "// Ollama.Models.``llama2:13b-chat``\n", + " OpenAI.Models.``gpt-4-turbo-preview``\n", " ]\n", " |> List.map (fun model -> \n", + " let sysInput text =\n", + " let msg =\n", + " text\n", + " |> Prompts.System.systemDoseQuantityExpert\n", + " |> Message.system\n", + " OpenAI.Chat.defaultChatInput model msg []\n", " printf $\"- Testing: {model}: \"\n", - " let s = model |> test\n", + " let s = \n", + " Texts.testMinMaxDoseQtyTexts\n", + " |> List.take 1 \n", + " |> test \n", + " OpenAI.Extract.minMaxDose \n", + " OpenAI.Chat.print \n", + " sysInput\n", + " model\n", " printfn $\"score: {s |> calcScore}\"\n", " model, s\n", " ) " @@ -660,7 +562,7 @@ }, { "cell_type": "code", - "execution_count": 60, + "execution_count": 6, "metadata": { "dotnet_interactive": { "language": "fsharp" @@ -676,52 +578,22 @@ "text": [ "\n", "\n", - "## And the winner is: mistral with a high score: 6 from 6\n", + "## And the winner is: gpt-4-turbo-preview with a high score: 1 from 6\n", "## Score: 1\n", "## Text:\n", "\n", "alprazolam\n", "6 jaar tot 18 jaar Startdosering: 0,125 mg/dag, éénmalig. Onderhoudsdosering: Op geleide van klinisch beeld verhogen met stappen van 0,125-0,25 mg/dosis tot max 0,05 mg/kg/dag in 3 doses. Max: 3 mg/dag. Advies inname/toediening: De dagdosis indien mogelijk verdelen over 3 doses.Bij plotselinge extreme slapeloosheid: alleen voor de nacht innemen; dosering op geleide van effect ophogen tot max 0,05 mg/kg, maar niet hoger dan 3 mg/dag.De effectiviteit bij de behandeling van acute angst is discutabel.\n", - "\n", - "## Score: 1\n", - "## Text:\n", - "\n", - "acetylsalicylzuur\n", - "1 maand tot 18 jaar Startdosering:Acetylsalicylzuur: 30 - 50 mg/kg/dag in 3 - 4 doses. Max: 3.000 mg/dag.\n", - "\n", - "## Score: 1\n", - "## Text:\n", - "\n", - "paracetamol\n", - "Oraal: Bij milde tot matige pijn en/of koorts: volgens het Kinderformularium van het NKFK bij een leeftijd van 1 maand–18 jaar: 10–15 mg/kg lichaamsgewicht per keer, zo nodig 4×/dag, max. 60 mg/kg/dag en max. 4 g/dag.\n", - "\n", - "## Score: 1\n", - "## Text:\n", - "\n", - "amitriptyline\n", - "6 jaar tot 18 jaar Startdosering: voor de nacht: 10 mg/dag in 1 dosisOnderhoudsdosering: langzaam ophogen met 10 mg/dag per 4-6 weken naar 10 - 30 mg/dag in 1 dosis. Max: 30 mg/dag. Behandeling met amitriptyline mag niet plotseling worden gestaakt vanwege het optreden van ontwenningsverschijnselen; de dosering moet geleidelijk worden verminderd.Uit de studie van Powers (2017) blijkt dat de werkzaamheid van amitriptyline bij migraine profylaxe niet effectiever is t.o.v. placebo. Desondanks menen experts dat in individuele gevallen behandeling met amitriptyline overwogen kan worden.\n", - "\n", - "## Score: 1\n", - "## Text:\n", - "\n", - "aciclovir\n", - "3 maanden tot 18 jaar 1.500 mg/m2/dag in 3 doses.Behandelduur: Herpes encefalitis: 14-21 dagen Varicella zoster: 7 dagen\n", - "\n", - "## Score: 1\n", - "## Text:\n", - "\n", - "aprepitant\n", - "3 jaar tot 18 jaar en < 40 kg 2 maal per week 40 mg/dosis verdeeld over de week.\n", "\n" ] } ], "source": [ - "testResults \n", + "testChatGPT \n", "|> List.maxBy (fun (model, xs) -> xs |> calcScore)\n", "|> fun (m, s) -> printfn $\"\\n\\n## And the winner is: {m} with a high score: {s |> calcScore} from {Texts.testUnitTexts |> List.length}\"\n", "\n", - "testResults\n", + "testChatGPT\n", "|> List.collect (fun (m, xs) -> xs)\n", "|> List.groupBy (fun (_, _, t) -> t)\n", "|> List.map (fun (txt, s) -> s |> calcScore, txt)\n", diff --git a/src/Informedica.OpenAI.Lib/Ollama.fs b/src/Informedica.OpenAI.Lib/Ollama.fs index aceee11..7986b21 100644 --- a/src/Informedica.OpenAI.Lib/Ollama.fs +++ b/src/Informedica.OpenAI.Lib/Ollama.fs @@ -269,7 +269,9 @@ module Ollama = |> JsonConvert.DeserializeObject<'ReturnType> |> Ok with - | e -> e.ToString() |> Error + | e -> + $"{resp.Response.message.content.Trim()}\ncannot be serialized because:\n{e.ToString()}" + |> Error ) return resp @@ -350,7 +352,7 @@ module Ollama = else let updatedMessage = { attemptMessage with - Content = $"The answer: {answer} was not correct because of %s{err}. Please try again answering:\n\n%s{original.Content}" + Content = $"The answer: |{answer}| was not correct because of %s{err}. Please try again answering:\n\n%s{original.Content}" } return! validateLoop false messages updatedMessage | Error err -> @@ -451,6 +453,7 @@ module Ollama = let ``dolphin-mixtral:8x7b-v2.6`` = "dolphin-mixtral:8x7b-v2.6" + let llama3 = "llama3" let runLlama2 = run Models.llama2 @@ -572,6 +575,7 @@ Can you try again answering? module Extract = open FSharpPlus + open FSharpPlus.Control let inline private getJson model zero (msg : Message) (msgs : Message list) = @@ -586,12 +590,22 @@ Can you try again answering? let doseUnits model text = - - Extraction.createDoseUnits - getJson - getJson - getJson - model text + let parseEmpty s = if s |> String.isNullOrWhiteSpace then "" else s + monad { + let! doseUnits = + Extraction.createDoseUnits + getJson + getJson + getJson + model text + let doseUnits = + {| + substanceUnit = doseUnits.substanceUnit |> parseEmpty + adjustUnit = doseUnits.adjustUnit |> parseEmpty + timeUnit = doseUnits.timeUnit |> parseEmpty + |} + return doseUnits + } let frequencies model text = @@ -607,3 +621,21 @@ Can you try again answering? freqs = freqs |} } + + + let minMaxDose model text = + monad { + let! freqs = frequencies model text + let su, au, tu = + freqs.doseUnits.substanceUnit + , if freqs.doseUnits.adjustUnit |> String.IsNullOrEmpty then None else freqs.doseUnits.adjustUnit |> Some + , if freqs.doseUnits.timeUnit |> String.IsNullOrEmpty then None else freqs.doseUnits.timeUnit |> Some + let! minMaxDose = + Extraction.extractDoseQuantities + getJson + model su au tu + return + {| freqs with + doseQuantities = minMaxDose.quantities + |} + } \ No newline at end of file diff --git a/src/Informedica.OpenAI.Lib/OpenAI.fs b/src/Informedica.OpenAI.Lib/OpenAI.fs index 91d0302..aa0bd46 100644 --- a/src/Informedica.OpenAI.Lib/OpenAI.fs +++ b/src/Informedica.OpenAI.Lib/OpenAI.fs @@ -291,7 +291,6 @@ module OpenAI = if not reTry then return Error err else - let updatedInput = { input with messages = @@ -552,3 +551,21 @@ Can you try again answering? freqs = freqs |} } + + + let minMaxDose model text = + monad { + let! freqs = frequencies model text + let su, au, tu = + freqs.doseUnits.substanceUnit + , if freqs.doseUnits.adjustUnit |> String.IsNullOrEmpty then None else freqs.doseUnits.adjustUnit |> Some + , if freqs.doseUnits.timeUnit |> String.IsNullOrEmpty then None else freqs.doseUnits.timeUnit |> Some + let! minMaxDose = + Extraction.extractDoseQuantities + getJson + model su au tu + return + {| freqs with + doseQuantities = minMaxDose.quantities + |} + } \ No newline at end of file diff --git a/src/Informedica.OpenAI.Lib/Prompts.fs b/src/Informedica.OpenAI.Lib/Prompts.fs index f9d2536..969f15a 100644 --- a/src/Informedica.OpenAI.Lib/Prompts.fs +++ b/src/Informedica.OpenAI.Lib/Prompts.fs @@ -133,3 +133,58 @@ Use schema : { frequencies: []; timeUnit: string } """ $"{s}\nNote that the frequencies should be possible times of administrations per {timeUnit}" |> addZeroCase zero + + + let minMaxDoseText (substanceUnit: string) (adjustUnit: string option) (timeUnit: string option) = + let regex = + let secUnit, thirdUnit = + match adjustUnit, timeUnit with + | None, None -> "keer|dosis", "keer|dosis" + | Some au, Some tu -> + $"{au}|{tu}|keer|dosis", + $"{au}|{tu}|keer|dosis" + | None, Some tu -> + $"{tu}|keer|dosis", + $"{tu}" + | Some au, None -> + $"{au}|keer|dosis", + $"{au}|keer|dosis" + + $"(\d+(\.\d+)?\s?({substanceUnit})(\/({secUnit}))?(\s?\/\s?({thirdUnit}))?\s)" + + """ +Use the provided schema to extract all mentioned dose quantities. +A quantity should match the regular expresion between the ticks '[REGEX]' + +Return dose quantities as a list of JSON +Use schema : +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "quantities": { + "type": "array", + "items": { + "type": "object", + "properties": { + "minQty": { + "type": "number", + "minimum": 0 + }, + "maxQty": { + "type": "number", + "minimum": 0 + }, + "unit": { + "type": "string", + "enum": ["mg", "mg/kg"] + } + }, + "required": ["minQty", "maxQty", "unit"] + } + } + }, + "required": ["quantities"] +} + +Respond in JSON""".Replace("[REGEX]", regex) diff --git a/src/Informedica.OpenAI.Lib/Texts.fs b/src/Informedica.OpenAI.Lib/Texts.fs index faa3f77..492a836 100644 --- a/src/Informedica.OpenAI.Lib/Texts.fs +++ b/src/Informedica.OpenAI.Lib/Texts.fs @@ -65,6 +65,103 @@ aprepitant |> List.map (fun (text, su, au, tu) -> text, {| substanceUnit = su; adjustUnit = au; timeUnit = tu |}) + let testFrequencyTexts = + [ + """ +alprazolam +6 jaar tot 18 jaar Startdosering: 0,125 mg/dag, éénmalig. Onderhoudsdosering: Op geleide van klinisch beeld verhogen met stappen van 0,125-0,25 mg/dosis tot max 0,05 mg/kg/dag in 3 doses. Max: 3 mg/dag. Advies inname/toediening: De dagdosis indien mogelijk verdelen over 3 doses.Bij plotselinge extreme slapeloosheid: alleen voor de nacht innemen; dosering op geleide van effect ophogen tot max 0,05 mg/kg, maar niet hoger dan 3 mg/dag.De effectiviteit bij de behandeling van acute angst is discutabel. +""" + , "mg", "kg", "dag", [3] + + """ +acetylsalicylzuur +1 maand tot 18 jaar Startdosering:Acetylsalicylzuur: 30 - 50 mg/kg/dag in 3 - 4 doses. Max: 3.000 mg/dag. +""" + , "mg", "kg", "dag", [3;4] + + """ +paracetamol +Oraal: Bij milde tot matige pijn en/of koorts: volgens het Kinderformularium van het NKFK bij een leeftijd van 1 maand–18 jaar: 10–15 mg/kg lichaamsgewicht per keer, zo nodig 4×/dag, max. 60 mg/kg/dag en max. 4 g/dag. +""" + , "mg", "kg", "dag", [4] + + """ +amitriptyline +6 jaar tot 18 jaar Startdosering: voor de nacht: 10 mg/dag in 1 dosisOnderhoudsdosering: langzaam ophogen met 10 mg/dag per 4-6 weken naar 10 - 30 mg/dag in 1 dosis. Max: 30 mg/dag. Behandeling met amitriptyline mag niet plotseling worden gestaakt vanwege het optreden van ontwenningsverschijnselen; de dosering moet geleidelijk worden verminderd.Uit de studie van Powers (2017) blijkt dat de werkzaamheid van amitriptyline bij migraine profylaxe niet effectiever is t.o.v. placebo. Desondanks menen experts dat in individuele gevallen behandeling met amitriptyline overwogen kan worden. +""" + , "mg", "", "dag", [1] + + """ +aciclovir +3 maanden tot 18 jaar 1.500 mg/m2/dag in 3 doses.Behandelduur: Herpes encefalitis: 14-21 dagen Varicella zoster: 7 dagen +""" + , "mg", "m2", "dag", [3] + + """ +aprepitant +3 jaar tot 18 jaar en < 40 kg 2 maal per week 40 mg/dosis verdeeld over de week. +""" + , "mg", "", "week", [2] + + ] + |> List.map (fun (text, su, au, tu, fr) -> + text, + {| + doseUnits = {| substanceUnit = su; adjustUnit = au; timeUnit = tu |} + freqs = {| frequencies = fr; timeUnit = tu |} + |} + ) + + + let testMinMaxDoseQtyTexts = + [ + """ +alprazolam +6 jaar tot 18 jaar Startdosering: 0,125 mg/dag, éénmalig. Onderhoudsdosering: Op geleide van klinisch beeld verhogen met stappen van 0,125-0,25 mg/dosis tot max 0,05 mg/kg/dag in 3 doses. Max: 3 mg/dag. Advies inname/toediening: De dagdosis indien mogelijk verdelen over 3 doses.Bij plotselinge extreme slapeloosheid: alleen voor de nacht innemen; dosering op geleide van effect ophogen tot max 0,05 mg/kg, maar niet hoger dan 3 mg/dag.De effectiviteit bij de behandeling van acute angst is discutabel. +""" + , "mg", "kg", "dag", [3], (0.125, 0.25) + + """ +acetylsalicylzuur +1 maand tot 18 jaar Startdosering:Acetylsalicylzuur: 30 - 50 mg/kg/dag in 3 - 4 doses. Max: 3.000 mg/dag. +""" + , "mg", "kg", "dag", [3;4], (0., 0.) + + """ +paracetamol +Oraal: Bij milde tot matige pijn en/of koorts: volgens het Kinderformularium van het NKFK bij een leeftijd van 1 maand–18 jaar: 10–15 mg/kg lichaamsgewicht per keer, zo nodig 4×/dag, max. 60 mg/kg/dag en max. 4 g/dag. +""" + , "mg", "kg", "dag", [4], (0., 0.) + + """ +amitriptyline +6 jaar tot 18 jaar Startdosering: voor de nacht: 10 mg/dag in 1 dosisOnderhoudsdosering: langzaam ophogen met 10 mg/dag per 4-6 weken naar 10 - 30 mg/dag in 1 dosis. Max: 30 mg/dag. Behandeling met amitriptyline mag niet plotseling worden gestaakt vanwege het optreden van ontwenningsverschijnselen; de dosering moet geleidelijk worden verminderd.Uit de studie van Powers (2017) blijkt dat de werkzaamheid van amitriptyline bij migraine profylaxe niet effectiever is t.o.v. placebo. Desondanks menen experts dat in individuele gevallen behandeling met amitriptyline overwogen kan worden. +""" + , "mg", "", "dag", [1], (0., 0.) + + """ +aciclovir +3 maanden tot 18 jaar 1.500 mg/m2/dag in 3 doses.Behandelduur: Herpes encefalitis: 14-21 dagen Varicella zoster: 7 dagen +""" + , "mg", "m2", "dag", [3], (0., 0.) + + """ +aprepitant +3 jaar tot 18 jaar en < 40 kg 2 maal per week 40 mg/dosis verdeeld over de week. +""" + , "mg", "", "week", [2], (40., 40.) + + ] + |> List.map (fun (text, su, au, tu, fr, minMaxQty) -> + text, + {| + doseUnits = {| substanceUnit = su; adjustUnit = au; timeUnit = tu |} + freqs = {| frequencies = fr; timeUnit = tu |} + doseQuantities = [|{| minQty = minMaxQty |> fst; maxQty = minMaxQty |> snd; unit = su|}|] + |} + ) + + let systemDoseIndicationExpert = """ You are an expert on medication prescribing, preparation and administration. You have to answer questions about texts that describing a drug dose.