Update app.py
Browse files
app.py
CHANGED
@@ -1,9 +1,8 @@
|
|
1 |
import os
|
|
|
2 |
import spaces
|
3 |
import gradio as gr
|
4 |
|
5 |
-
import torch
|
6 |
-
from peft import PeftModel
|
7 |
from transformers import AutoConfig, AutoModelForCausalLM, AutoTokenizer
|
8 |
from huggingface_hub import login as hf_login
|
9 |
|
@@ -12,21 +11,14 @@ from pydantic import BaseModel
|
|
12 |
|
13 |
hf_login(token=os.getenv("HF_TOKEN"))
|
14 |
|
15 |
-
model_name = "meta-llama/Llama-3.2-1B-Instruct"
|
16 |
model_name = "gregorlied/Llama-3.2-1B-Instruct-Medical-Report-Summarization-FP32"
|
17 |
-
device = 'cuda' if torch.cuda.is_available() else 'cpu'
|
18 |
-
|
19 |
-
model = AutoModelForCausalLM.from_pretrained(
|
20 |
-
model_name,
|
21 |
-
device_map="auto",
|
22 |
-
# torch_dtype=torch.bfloat16,
|
23 |
-
attn_implementation='eager',
|
24 |
-
trust_remote_code=True,
|
25 |
-
)
|
26 |
|
27 |
-
#
|
28 |
-
#
|
29 |
-
#
|
|
|
|
|
|
|
30 |
|
31 |
class Person(BaseModel):
|
32 |
life_style: str
|
@@ -58,16 +50,12 @@ xgr_logits_processor = xgr.contrib.hf.LogitsProcessor(compiled_grammar)
|
|
58 |
|
59 |
prompt = """You are a text extraction system for clinical reports.
|
60 |
Please extract relevant clinical information from the report.
|
61 |
-
|
62 |
### Instructions
|
63 |
-
|
64 |
- Use the JSON Schema given below.
|
65 |
- Return only a valid JSON object – no markdown, no comments.
|
66 |
- If no relevant facts are given for a field, set its value to "N/A".
|
67 |
- If multile relevant facts are given for a field, separate them with "; ".
|
68 |
-
|
69 |
### JSON Schema
|
70 |
-
|
71 |
{
|
72 |
'life_style': '',
|
73 |
'family_history': '',
|
@@ -85,12 +73,118 @@ Please extract relevant clinical information from the report.
|
|
85 |
'age': '',
|
86 |
'gender': '',
|
87 |
}
|
88 |
-
|
89 |
### Clinical Report
|
90 |
"""
|
91 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
@spaces.GPU(duration=60)
|
93 |
-
def summarize(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
if not text.strip():
|
95 |
return "Please enter some text to summarize."
|
96 |
|
@@ -105,9 +199,9 @@ def summarize(text):
|
|
105 |
add_generation_prompt=True,
|
106 |
enable_thinking=False, # only relevant for qwen
|
107 |
)
|
108 |
-
|
109 |
-
model_inputs = tokenizer([text], return_tensors="pt").to(device)
|
110 |
|
|
|
|
|
111 |
generated_ids = model.generate(
|
112 |
input_ids=model_inputs["input_ids"],
|
113 |
attention_mask = model_inputs["attention_mask"],
|
@@ -119,100 +213,212 @@ def summarize(text):
|
|
119 |
max_new_tokens=2048,
|
120 |
logits_processor=[xgr_logits_processor]
|
121 |
)
|
122 |
-
|
123 |
generated_ids = [
|
124 |
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
|
125 |
]
|
126 |
|
127 |
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)
|
128 |
-
|
|
|
129 |
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
choices=[
|
162 |
-
"Signs and Symptoms",
|
163 |
-
"Comorbidities",
|
164 |
-
]
|
165 |
-
)
|
166 |
|
167 |
-
|
168 |
-
gr.CheckboxGroup(
|
169 |
-
label="Medical Assesments",
|
170 |
-
choices=[
|
171 |
-
"Diagnostic Techniques and Procedures",
|
172 |
-
"Laboratory Values",
|
173 |
-
"Pathology",
|
174 |
-
"Diagnosis",
|
175 |
-
]
|
176 |
-
)
|
177 |
-
gr.CheckboxGroup(
|
178 |
-
label="Therapy and Results",
|
179 |
-
choices=[
|
180 |
-
"Pharmacological Therapy",
|
181 |
-
"Interventional Therapy",
|
182 |
-
"Patient Outcome Assessment",
|
183 |
-
]
|
184 |
-
)
|
185 |
|
186 |
-
with
|
187 |
-
|
188 |
|
189 |
-
with gr.
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
|
198 |
-
with gr.
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
216 |
|
217 |
if __name__ == "__main__":
|
218 |
demo.launch()
|
|
|
1 |
import os
|
2 |
+
import ast
|
3 |
import spaces
|
4 |
import gradio as gr
|
5 |
|
|
|
|
|
6 |
from transformers import AutoConfig, AutoModelForCausalLM, AutoTokenizer
|
7 |
from huggingface_hub import login as hf_login
|
8 |
|
|
|
11 |
|
12 |
hf_login(token=os.getenv("HF_TOKEN"))
|
13 |
|
|
|
14 |
model_name = "gregorlied/Llama-3.2-1B-Instruct-Medical-Report-Summarization-FP32"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
+
# model = AutoModelForCausalLM.from_pretrained(
|
17 |
+
# model_name,
|
18 |
+
# device_map="auto",
|
19 |
+
# attn_implementation='eager',
|
20 |
+
# trust_remote_code=True,
|
21 |
+
# )
|
22 |
|
23 |
class Person(BaseModel):
|
24 |
life_style: str
|
|
|
50 |
|
51 |
prompt = """You are a text extraction system for clinical reports.
|
52 |
Please extract relevant clinical information from the report.
|
|
|
53 |
### Instructions
|
|
|
54 |
- Use the JSON Schema given below.
|
55 |
- Return only a valid JSON object – no markdown, no comments.
|
56 |
- If no relevant facts are given for a field, set its value to "N/A".
|
57 |
- If multile relevant facts are given for a field, separate them with "; ".
|
|
|
58 |
### JSON Schema
|
|
|
59 |
{
|
60 |
'life_style': '',
|
61 |
'family_history': '',
|
|
|
73 |
'age': '',
|
74 |
'gender': '',
|
75 |
}
|
|
|
76 |
### Clinical Report
|
77 |
"""
|
78 |
|
79 |
+
def generate_html_tables(data, selected_fields):
|
80 |
+
key_label_map = {
|
81 |
+
'age': 'Age',
|
82 |
+
'gender': 'Gender',
|
83 |
+
'life_style': 'Lifestyle',
|
84 |
+
'social_history': 'Social Background',
|
85 |
+
'medical_surgical_history': 'Personal',
|
86 |
+
'family_history': 'Family Members',
|
87 |
+
'signs_symptoms': 'Symptoms',
|
88 |
+
'comorbidities': 'Comorbid Conditions',
|
89 |
+
'diagnostic_techniques_procedures': 'Diagnostic Procedures',
|
90 |
+
'laboratory_values': 'Laboratory Results',
|
91 |
+
'pathology': 'Pathology Report',
|
92 |
+
'diagnosis': 'Diagnosis',
|
93 |
+
'interventional_therapy': 'Interventional Therapy',
|
94 |
+
'pharmacological_therapy': 'Pharmacological Therapy',
|
95 |
+
'patient_outcome_assessment': 'Patient Outcome',
|
96 |
+
}
|
97 |
+
|
98 |
+
label_key_map = {v: k for k, v in key_label_map.items()}
|
99 |
+
|
100 |
+
categories = {
|
101 |
+
"Personal Information": ["Age", "Gender", "Lifestyle", "Social Background"],
|
102 |
+
"Medical History": ["Personal", "Family Members"],
|
103 |
+
"Clinical Presentation": ["Symptoms", "Comorbid Conditions"],
|
104 |
+
"Medical Assessment": ["Diagnostic Procedures", "Laboratory Results", "Pathology Report"],
|
105 |
+
"Diagnosis": ["Diagnosis"],
|
106 |
+
"Treatment": ["Interventional Therapy", "Pharmacological Therapy"],
|
107 |
+
"Patient Outcome": ["Patient Outcome"],
|
108 |
+
}
|
109 |
+
|
110 |
+
def format_bullets(value):
|
111 |
+
items = [item.strip() for item in value.split(";") if item.strip()]
|
112 |
+
if not items:
|
113 |
+
return "<i>Not Available</i>"
|
114 |
+
if len(items) == 1:
|
115 |
+
return items[0]
|
116 |
+
return "<ul style='margin: 0; padding-left: 1.2em'>" + "".join(f"<li>{item}</li>" for item in items) + "</ul>"
|
117 |
+
|
118 |
+
table_style = (
|
119 |
+
"width: 100%;"
|
120 |
+
"table-layout: fixed;"
|
121 |
+
"border-collapse: collapse;"
|
122 |
+
"word-wrap: break-word;"
|
123 |
+
"height: 100%;"
|
124 |
+
)
|
125 |
+
|
126 |
+
th_td_style_first = (
|
127 |
+
"padding: 8px;"
|
128 |
+
"border: 1px solid #ccc;"
|
129 |
+
"vertical-align: top;"
|
130 |
+
"text-align: left;"
|
131 |
+
"height: 30px;"
|
132 |
+
"overflow: hidden;"
|
133 |
+
)
|
134 |
+
|
135 |
+
th_td_style_other = (
|
136 |
+
"padding: 8px;"
|
137 |
+
"border: 1px solid #ccc;"
|
138 |
+
"vertical-align: top;"
|
139 |
+
"text-align: left;"
|
140 |
+
)
|
141 |
+
|
142 |
+
html_tables = []
|
143 |
+
for section, labels in categories.items():
|
144 |
+
section_fields = [label for label in labels if label in selected_fields]
|
145 |
+
if section_fields:
|
146 |
+
table_html = f"<h3 style='margin-bottom: 0.5em;'>{section}</h3>"
|
147 |
+
table_html += f"<table style='{table_style}'>"
|
148 |
+
table_html += f"<tr><th style='{th_td_style_first}; width: 150px;'>Field</th><th style='{th_td_style_first};'>Details</th></tr>"
|
149 |
+
for label in section_fields:
|
150 |
+
key = label_key_map[label]
|
151 |
+
value = data.get(key, "N/A")
|
152 |
+
details = "<i>Not Available</i>" if value == "N/A" else format_bullets(value)
|
153 |
+
table_html += f"<tr><td style='{th_td_style_other}; width: 150px;'><b>{label}</b></td><td style='{th_td_style_other}'>{details}</td></tr>"
|
154 |
+
table_html += "</table>"
|
155 |
+
html_tables.append(table_html)
|
156 |
+
|
157 |
+
i = 0
|
158 |
+
grouped_html = ""
|
159 |
+
while i < len(html_tables):
|
160 |
+
num_per_row = 2 if i < 4 else 3
|
161 |
+
row_tables = html_tables[i:i+num_per_row]
|
162 |
+
grouped_html += (
|
163 |
+
"<div style='display: flex; gap: 1em; margin-bottom: 2em; align-items: stretch;'>"
|
164 |
+
)
|
165 |
+
for table in row_tables:
|
166 |
+
grouped_html += (
|
167 |
+
"<div style='flex: 1; min-width: 0; display: flex; flex-direction: column;'>"
|
168 |
+
f"{table}"
|
169 |
+
"</div>"
|
170 |
+
)
|
171 |
+
grouped_html += "</div>"
|
172 |
+
i += num_per_row
|
173 |
+
|
174 |
+
return f"<div style='font-family: sans-serif;'>{grouped_html}</div>"
|
175 |
+
|
176 |
@spaces.GPU(duration=60)
|
177 |
+
def summarize(
|
178 |
+
text,
|
179 |
+
personal_info,
|
180 |
+
medical_history,
|
181 |
+
clinical_presentation,
|
182 |
+
medical_assessment,
|
183 |
+
diagnosis,
|
184 |
+
treatment,
|
185 |
+
patient_outcome,
|
186 |
+
):
|
187 |
+
|
188 |
if not text.strip():
|
189 |
return "Please enter some text to summarize."
|
190 |
|
|
|
199 |
add_generation_prompt=True,
|
200 |
enable_thinking=False, # only relevant for qwen
|
201 |
)
|
|
|
|
|
202 |
|
203 |
+
"""
|
204 |
+
model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
|
205 |
generated_ids = model.generate(
|
206 |
input_ids=model_inputs["input_ids"],
|
207 |
attention_mask = model_inputs["attention_mask"],
|
|
|
213 |
max_new_tokens=2048,
|
214 |
logits_processor=[xgr_logits_processor]
|
215 |
)
|
|
|
216 |
generated_ids = [
|
217 |
output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
|
218 |
]
|
219 |
|
220 |
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)
|
221 |
+
"""
|
222 |
+
response = ["{'life_style': 'N/A', 'family_history': 'N/A', 'social_history': 'N/A', 'medical_surgical_history': 'Ménié–disease; Hypothyroidism; Type B1 thymoma; Adrenal insufficiency; Sputum stasis; Pulmonary infection', 'signs_symptoms': 'Tiredness; Muscle weakness; Cachexia; Decreased muscular strength; Bilateral rigid auricles; Calcified auricles', 'comorbidities': 'Ménié–disease; Hypothyroidism', 'diagnostic_techniques_procedures': 'Chest X-ray; Magnetic resonance imaging scan; Metyrapone test', 'diagnosis': 'Type B1 thymoma; Hypothyroidism; Myasthenia gravis; Adrenal insufficiency; Pulmonary infection', 'laboratory_values': 'Cortisol: 51nmol/L; TSH: 11.9mU/L; Free T4: 11.2pmol/L; LH: 6.5U/L; FSH: 10.9U/L; Testosterone: 3.4nmol/L; Prolactin: 0.49U/L; IGF-1: 7.8nmol/L', 'pathology': 'Pituitary hypoplasia', 'pharmacological_therapy': 'Levothyroxine; Betahistine; Phenylephrine; Norepinephrine; Hydrocortisone', 'interventional_therapy': 'Surgery; Tracheostomy', 'patient_outcome_assessment': 'Discharged to the ward; Weaned off ventilator; Discharged to ward on 21st POD', 'age': '68 year', 'gender': 'Male'}"]
|
223 |
|
224 |
+
try:
|
225 |
+
data = ast.literal_eval(response[0])
|
226 |
+
except:
|
227 |
+
data = {
|
228 |
+
'life_style': '',
|
229 |
+
'family_history': '',
|
230 |
+
'social_history': '',
|
231 |
+
'medical_surgical_history': '',
|
232 |
+
'signs_symptoms': '',
|
233 |
+
'comorbidities': '',
|
234 |
+
'diagnostic_techniques_procedures': '',
|
235 |
+
'diagnosis': '',
|
236 |
+
'laboratory_values': '',
|
237 |
+
'pathology': '',
|
238 |
+
'pharmacological_therapy': '',
|
239 |
+
'interventional_therapy': '',
|
240 |
+
'patient_outcome_assessment': '',
|
241 |
+
'age': '',
|
242 |
+
'gender': '',
|
243 |
+
}
|
244 |
+
|
245 |
+
selected_fields = []
|
246 |
+
selected_fields += personal_info
|
247 |
+
selected_fields += medical_history
|
248 |
+
selected_fields += clinical_presentation
|
249 |
+
selected_fields += medical_assessment
|
250 |
+
selected_fields += diagnosis
|
251 |
+
selected_fields += treatment
|
252 |
+
selected_fields += patient_outcome
|
253 |
+
|
254 |
+
return generate_html_tables(data, selected_fields)
|
|
|
|
|
|
|
|
|
|
|
255 |
|
256 |
+
with gr.Blocks() as demo:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
|
258 |
+
# need to be combined with `hf_oauth: true` in README.md
|
259 |
+
# button = gr.LoginButton("Sign in")
|
260 |
|
261 |
+
with gr.Column():
|
262 |
+
gr.HTML("""
|
263 |
+
<div align="center">
|
264 |
+
<img src="https://huggingface.co/spaces/gregorlied/playground/resolve/main/assets/LlamaMD-logo.png" alt="LlamaMD Logo" width="120" style="margin-bottom: 10px;">
|
265 |
+
<h2><strong>LlamaMD</strong></h2>
|
266 |
+
<p><em>Structured Information Extraction from Clinical Reports</em></p>
|
267 |
+
</div>
|
268 |
+
""")
|
269 |
|
270 |
+
with gr.Tabs():
|
271 |
+
with gr.Tab("LLamaMD"):
|
272 |
+
with gr.Row():
|
273 |
+
input_text = gr.Textbox(
|
274 |
+
label="Clinical Report",
|
275 |
+
autoscroll=False,
|
276 |
+
lines=15,
|
277 |
+
max_lines=15,
|
278 |
+
placeholder="Paste your clinical report here...",
|
279 |
+
value="A 57-year-old male presented with fever (38.9°C), chest pain, cough, and progressive dyspnea. The patient exhibited tachypnea (34 breaths/min) and tachycardia (134 bpm). Auscultation revealed decreased breath sounds in both lung bases, with crackles on the left. A chest X-ray revealed bilateral pleural opacities and enlargement of the cardiac silhouette ( A). Echocardiography showed moderate pericardial effusion affecting the entire cardiac silhouette. Pericardiocentesis yielded 250 mL of exudative fluid. A CT scan of the chest showed pneumonia in the left lower lobe, bilateral pleural effusion, and moderate pericardial effusion ( B). Thoracentesis was performed and yielded 1,050 mL of exudative fluid. Laboratory tests yielded the following data: white blood cell count, 11.78 × 109 cells/L (84.3% neutrophils, 4.3% lymphocytes, and 9.1% monocytes); platelet count, 512 × 109/L; serum C-reactive protein, 31.27 mg/dL; serum creatinine, 0.94 mg/dL; serum sodium, 133 mEq/L; and serum potassium, 3.72 mEq/L. Examination of the pleural fluid showed a pH of 7.16, a glucose level of 4.5 mg/dL, proteins at 49.1 g/L, and an LDH content of 1,385 U/L. A urinary pneumococcal antigen test was positive. Pleural fluid culture was positive for S. pneumoniae. The patient was treated for four weeks with amoxicillin-clavulanate (2.2 g/8 h, i.v.) plus levofloxacin (500 mg twice a day), together with a nonsteroidal anti-inflammatory drug (ibuprofen, 800 mg/day), after which there was nearly complete resolution of the alterations seen on the chest X-ray and CT scan.",
|
280 |
+
)
|
281 |
+
|
282 |
+
with gr.Accordion("Advanced Settings", open=False):
|
283 |
+
with gr.Row():
|
284 |
+
with gr.Column():
|
285 |
+
personal_info = gr.CheckboxGroup(
|
286 |
+
label="Personal Information",
|
287 |
+
choices=[
|
288 |
+
"Age",
|
289 |
+
"Gender",
|
290 |
+
"Lifestyle",
|
291 |
+
"Social Background",
|
292 |
+
],
|
293 |
+
value=[
|
294 |
+
"Age",
|
295 |
+
"Gender",
|
296 |
+
"Lifestyle",
|
297 |
+
"Social Background",
|
298 |
+
],
|
299 |
+
)
|
300 |
+
|
301 |
+
with gr.Column():
|
302 |
+
medical_history = gr.CheckboxGroup(
|
303 |
+
label="Medical History",
|
304 |
+
choices=[
|
305 |
+
"Personal",
|
306 |
+
"Family Members",
|
307 |
+
],
|
308 |
+
value=[
|
309 |
+
"Personal",
|
310 |
+
"Family Members",
|
311 |
+
],
|
312 |
+
)
|
313 |
+
|
314 |
+
with gr.Row():
|
315 |
+
with gr.Column():
|
316 |
+
clinical_presentation = gr.CheckboxGroup(
|
317 |
+
label="Clinical Presentation",
|
318 |
+
choices=[
|
319 |
+
"Symptoms",
|
320 |
+
"Comorbid Conditions",
|
321 |
+
],
|
322 |
+
value=[
|
323 |
+
"Symptoms",
|
324 |
+
"Comorbid Conditions",
|
325 |
+
],
|
326 |
+
)
|
327 |
+
with gr.Column():
|
328 |
+
medical_assessment = gr.CheckboxGroup(
|
329 |
+
label="Medical Assessment",
|
330 |
+
choices=[
|
331 |
+
"Diagnostic Procedures",
|
332 |
+
"Laboratory Results",
|
333 |
+
"Pathology Report",
|
334 |
+
],
|
335 |
+
value=[
|
336 |
+
"Diagnostic Procedures",
|
337 |
+
"Laboratory Results",
|
338 |
+
"Pathology Report",
|
339 |
+
],
|
340 |
+
)
|
341 |
+
|
342 |
+
with gr.Row():
|
343 |
+
with gr.Column():
|
344 |
+
diagnosis = gr.CheckboxGroup(
|
345 |
+
label="Diagnosis",
|
346 |
+
choices=[
|
347 |
+
"Diagnosis",
|
348 |
+
],
|
349 |
+
value=[
|
350 |
+
"Diagnosis",
|
351 |
+
],
|
352 |
+
)
|
353 |
+
with gr.Column():
|
354 |
+
treatment = gr.CheckboxGroup(
|
355 |
+
label="Treatment",
|
356 |
+
choices=[
|
357 |
+
"Interventional Therapy",
|
358 |
+
"Pharmacological Therapy",
|
359 |
+
],
|
360 |
+
value=[
|
361 |
+
"Interventional Therapy",
|
362 |
+
"Pharmacological Therapy",
|
363 |
+
],
|
364 |
+
)
|
365 |
+
with gr.Column():
|
366 |
+
patient_outcome = gr.CheckboxGroup(
|
367 |
+
label="Patient Outcome",
|
368 |
+
choices=[
|
369 |
+
"Patient Outcome",
|
370 |
+
],
|
371 |
+
value=[
|
372 |
+
"Patient Outcome",
|
373 |
+
],
|
374 |
+
)
|
375 |
+
|
376 |
+
with gr.Row():
|
377 |
+
summarize_btn = gr.Button("Extract")
|
378 |
+
|
379 |
+
with gr.Row():
|
380 |
+
output_text = gr.HTML()
|
381 |
+
|
382 |
+
summarize_btn.click(
|
383 |
+
fn=summarize,
|
384 |
+
inputs=[input_text, personal_info, medical_history, clinical_presentation, medical_assessment, diagnosis, treatment, patient_outcome],
|
385 |
+
outputs=output_text,
|
386 |
+
show_progress=True,
|
387 |
+
)
|
388 |
|
389 |
+
with gr.Tab("Help"):
|
390 |
+
gr.Markdown("""### Personal Information
|
391 |
+
|
392 |
+
**Age**: Age of the patient.<br>
|
393 |
+
**Gender**: Gender of the patient.<br>
|
394 |
+
**Lifestyle**: Daily habits and activities of the patient (e.g. alcohol consumption, diet, smoking status).<br>
|
395 |
+
**Social Background**: Social factors of the patient (e.g. housing situation, marital status).<br>
|
396 |
+
### Medical History
|
397 |
+
**Personal**: Past medical conditions, previous surgeries or treatments of the patient.<br>
|
398 |
+
**Family Members**: Relevant medical conditions or genetic disorders in the patient’s family (e.g. cancer, heart disease).<br>
|
399 |
+
### Clinical Presentation
|
400 |
+
**Symptoms**: Current symptoms of the patient.<br>
|
401 |
+
**Comorbid Conditions**: Other medical conditions of the patient that may influence the treatment.<br>
|
402 |
+
### Medical Assessment
|
403 |
+
**Diagnostic Procedures**: Description of the diagnostic tests or procedures performed (e.g. X-rays, MRIs)<br>
|
404 |
+
**Laboratory Results**: Results foom laboratory test (e.g. blood counts, electrolyte levels)<br>
|
405 |
+
**Pathology Report**: Findings from pathological examinations (e.g. biopsy results)<br>
|
406 |
+
### Diagnosis
|
407 |
+
**Diagnosis**: All levels of diagnosis mentioned in the report.<br>
|
408 |
+
### Treatment
|
409 |
+
**Interventional Therapy**: Medications prescribed to the patient.<br>
|
410 |
+
**Pharmacological Therapy**: Information on surgical or non-surgical interventions performed.<br>
|
411 |
+
### Patient Outcome
|
412 |
+
**Patient Outcome**: Evaluation of the patient’s health status at the end of treatment.<br>
|
413 |
+
""")
|
414 |
+
|
415 |
+
with gr.Tab("About"):
|
416 |
+
gr.Markdown("""LlamaMD is a project developed as part of the "NLP for Social Good" course at TU Berlin.
|
417 |
+
|
418 |
+
The goal of this project is to perform structured information extraction from clinical reports, helping doctors to have more time for their patients.
|
419 |
+
|
420 |
+
The system is based on `meta-llama/Llama-3.2-1B-Instruct`, which has been fine-tuned on the ELMTEX dataset.
|
421 |
+
""")
|
422 |
|
423 |
if __name__ == "__main__":
|
424 |
demo.launch()
|