Muhammadidrees commited on
Commit
bd57f6c
Β·
verified Β·
1 Parent(s): b4961fa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +220 -79
app.py CHANGED
@@ -1,115 +1,256 @@
 
1
  import gradio as gr
2
- import torch
3
  from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
 
 
 
4
 
5
- MODEL_ID = "Muhammadidrees/bioLLM"
6
 
7
- #import gradio as gr
8
- from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
 
 
9
 
10
- # Load your model from Hugging Face Hub
11
- # MODEL_ID = "Muhammadidrees/MedicalInsights"
 
 
 
 
 
12
 
13
- tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
14
- model = AutoModelForCausalLM.from_pretrained(MODEL_ID, device_map="auto")
15
- pipe = pipeline("text-generation", model=model, tokenizer=tokenizer)
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
- # Function to build structured input and query the LLM
 
 
 
 
 
 
 
 
 
19
  def analyze(
20
  albumin, creatinine, glucose, crp, mcv, rdw, alp,
21
  wbc, lymph, age, gender, height, weight
22
  ):
23
- # Calculate BMI (hidden from user, only passed to LLM)
24
  try:
25
- height_m = height / 100 # cm β†’ m
26
- bmi = round(weight / (height_m ** 2), 2)
 
 
 
 
 
27
  except Exception:
28
  bmi = "N/A"
29
 
30
- # System-style instruction
31
  system_prompt = (
32
- "You are an advanced AI medical assistant. "
33
- "Analyze the patient’s biomarkers and demographics. "
34
- "Provide a structured assessment including: "
35
- """Executive Summary,System-Specific Analysis,Personalized Action Plan,Interaction Alerts,Longevity Metrics,Enhanced AI Insights & Longitudinal Risk
36
-
37
- """ )
38
-
39
- # Construct patient profile input
40
- patient_input = f"""
41
- Patient Profile:
42
- - Age: {age}
43
- - Gender: {gender}
44
- - Height: {height} cm
45
- - Weight: {weight} kg
46
- - BMI: {bmi}
47
-
48
- Lab Values:
49
- - Albumin: {albumin} g/dL
50
- - Creatinine: {creatinine} mg/dL
51
- - Glucose: {glucose} mg/dL
52
- - C-Reactive Protein: {crp} mg/L
53
- - Mean Cell Volume: {mcv} fL
54
- - Red Cell Distribution Width: {rdw} %
55
- - Alkaline Phosphatase: {alp} U/L
56
- - White Blood Cell Count: {wbc} K/uL
57
- - Lymphocyte Percentage: {lymph} %
58
- """
59
 
60
- prompt = system_prompt + "\n" + patient_input
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
- # Call LLM (exclude echoed input)
63
- result = pipe(
64
- prompt,
65
- max_new_tokens=2000,
66
- do_sample=True,
67
- temperature=0.6,
68
- return_full_text=False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  )
70
- return result[0]["generated_text"].strip()
71
 
 
72
 
73
- # Build Gradio UI
74
- with gr.Blocks() as demo:
75
- gr.Markdown("## πŸ§ͺ Medical Insights AI β€” Enter Patient Data")
 
 
 
 
 
76
 
77
- with gr.Row():
78
- albumin = gr.Number(label="Albumin (g/dL)")
79
- wbc = gr.Number(label="White Blood Cell Count (K/uL)")
80
 
81
- with gr.Row():
82
- creatinine = gr.Number(label="Creatinine (mg/dL)")
83
- lymph = gr.Number(label="Lymphocyte Percentage (%)")
 
 
 
 
84
 
85
- with gr.Row():
86
- glucose = gr.Number(label="Glucose (mg/dL)")
87
- age = gr.Number(label="Age (years)")
88
 
89
- with gr.Row():
90
- crp = gr.Number(label="C-Reactive Protein (mg/L)")
91
- gender = gr.Dropdown(choices=["Male", "Female"], label="Gender")
 
 
 
 
 
92
 
93
- with gr.Row():
94
- mcv = gr.Number(label="Mean Cell Volume (fL)")
95
- height = gr.Number(label="Height (cm)")
 
 
 
96
 
97
  with gr.Row():
98
- rdw = gr.Number(label="Red Cell Distribution Width (%)")
99
- weight = gr.Number(label="Weight (kg)")
 
 
 
 
100
 
101
- with gr.Row():
102
- alp = gr.Number(label="Alkaline Phosphatase (U/L)")
 
 
 
103
 
104
- analyze_btn = gr.Button("πŸ”Ž Analyze")
105
- output = gr.Textbox(label="AI Medical Assessment", lines=12)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
- # Run analysis
108
  analyze_btn.click(
109
  fn=analyze,
110
- inputs=[albumin, creatinine, glucose, crp, mcv, rdw, alp,
111
- wbc, lymph, age, gender, height, weight],
112
- outputs=output
113
  )
114
 
115
- demo.launch()
 
 
 
 
1
+ # app.py
2
  import gradio as gr
 
3
  from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
4
+ import os
5
+ import torch
6
+ import re
7
 
8
+ MODEL_ID = "Muhammadidrees/BioLLM"
9
 
10
+ # -----------------------
11
+ # Load tokenizer + model safely (GPU or CPU)
12
+ # -----------------------
13
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
14
 
15
+ # Try a few loading strategies so this works on GPU or CPU Spaces
16
+ try:
17
+ # Preferred: let HF decide device placement (works for GPU-enabled Spaces)
18
+ model = AutoModelForCausalLM.from_pretrained(MODEL_ID)
19
+ except Exception:
20
+ # Fallback: force CPU (slower but safe)
21
+ model = AutoModelForCausalLM.from_pretrained(MODEL_ID, torch_dtype=torch.float32, low_cpu_mem_usage=True)
22
 
23
+ # Create pipeline
24
+ pipe = pipeline("text-generation", model=model, tokenizer=tokenizer, device=0 if torch.cuda.is_available() else -1)
 
25
 
26
+ # -----------------------
27
+ # Helper: robust section splitter
28
+ # -----------------------
29
+ def split_report(text):
30
+ """
31
+ Split model output into left (sections 1-4) and right (sections 5-6).
32
+ Accepts various markers for robustness.
33
+ """
34
+ # Normalize whitespace
35
+ text = text.strip()
36
+ # Common markers that indicate tabular/insights section
37
+ markers = [
38
+ "5. Tabular Mapping",
39
+ "5. Tabular",
40
+ "Tabular Mapping",
41
+ "Tabular & AI Insights",
42
+ "πŸ“Š Tabular",
43
+ "## 5",
44
+ ]
45
+ # Find earliest marker occurrence
46
+ idx = None
47
+ for m in markers:
48
+ pos = text.find(m)
49
+ if pos != -1:
50
+ if idx is None or pos < idx:
51
+ idx = pos
52
+ if idx is None:
53
+ # fallback: try splitting at "Enhanced AI Insights" or "Enhanced AI"
54
+ fallback = text.find("Enhanced AI Insights")
55
+ if fallback == -1:
56
+ fallback = text.find("Enhanced AI")
57
+ idx = fallback if fallback != -1 else None
58
 
59
+ if idx is None:
60
+ # couldn't find a split marker -> put everything in left
61
+ return text, ""
62
+ left = text[:idx].strip()
63
+ right = text[idx:].strip()
64
+ return left, right
65
+
66
+ # -----------------------
67
+ # The analyze function
68
+ # -----------------------
69
  def analyze(
70
  albumin, creatinine, glucose, crp, mcv, rdw, alp,
71
  wbc, lymph, age, gender, height, weight
72
  ):
73
+ # Validate/constrain inputs
74
  try:
75
+ age = int(age)
76
+ except Exception:
77
+ age = age
78
+ try:
79
+ height = float(height)
80
+ weight = float(weight)
81
+ bmi = round(weight / ((height / 100) ** 2), 2) if height > 0 else "N/A"
82
  except Exception:
83
  bmi = "N/A"
84
 
 
85
  system_prompt = (
86
+ "You are a professional AI Medical Assistant.\n"
87
+ "You are analyzing patient demographics (age, height, weight) and Levine biomarker panel values.\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
+ "The Levine biomarker panel includes:\n"
90
+ "- Albumin\n"
91
+ "- Creatinine\n"
92
+ "- Glucose\n"
93
+ "- C-reactive protein (CRP)\n"
94
+ "- Mean Cell Volume (MCV)\n"
95
+ "- Red Cell Distribution Width (RDW)\n"
96
+ "- Alkaline Phosphatase (ALP)\n"
97
+ "- White Blood Cell count (WBC)\n"
98
+ "- Lymphocyte percentage\n\n"
99
+
100
+ "STRICT RULES:\n"
101
+ "- Use ONLY the 9 biomarkers above + age, height, weight.\n"
102
+ "- DO NOT use or invent other lab results (e.g., cholesterol, vitamin D, ferritin, ALT, AST, urine results).\n"
103
+ "- If a section cannot be addressed with available data, explicitly state: 'Not available from current biomarkers.'\n"
104
+ "- Do not give absolute longevity scores. Instead, summarize trends (e.g., 'No major abnormalities suggesting elevated short-term risk.').\n"
105
+ "- Nutrient status (Iron, B12, Folate) can only be suggested as possible IF supported by MCV + RDW patterns, but never stated as confirmed.\n"
106
+ "- Interpret ALP cautiously: mention bone vs liver as possible sources, but highlight that more tests would be required to confirm.\n"
107
+ "- Always highlight limitations where applicable.\n\n"
108
+
109
+ "OUTPUT FORMAT (strict, structured, and professional):\n\n"
110
+
111
+ "1. Executive Summary\n"
112
+ " - Top Priority Issues (based only on provided biomarkers)\n"
113
+ " - Key Strengths\n\n"
114
+
115
+ "2. System-Specific Analysis\n"
116
+ " - Blood Health (MCV, RDW, Lymphocytes, WBC)\n"
117
+ " - Protein & Liver Health (Albumin, ALP)\n"
118
+ " - Kidney Health (Creatinine)\n"
119
+ " - Metabolic Health (Glucose, CRP)\n"
120
+ " - Anthropometrics (Age, Height, Weight, BMI)\n"
121
+ " - Other systems: Always state 'Not available from current biomarkers.' if data missing\n\n"
122
 
123
+ "3. Personalized Action Plan\n"
124
+ " - Medical (tests/consults related only to biomarkers β€” e.g., repeat CBC, iron studies if anemia suspected)\n"
125
+ " - Nutrition (diet & supplements grounded ONLY in biomarker findings β€” e.g., protein intake if albumin low, anti-inflammatory foods if CRP elevated)\n"
126
+ " - Lifestyle (hydration, exercise, sleep β€” general guidance contextualized by BMI and biomarkers)\n"
127
+ " - Testing (only mention ferritin, B12, folate, GGT, etc. as follow-up β€” but clarify these are NOT part of current data)\n\n"
128
+
129
+ "4. Interaction Alerts\n"
130
+ " - Describe ONLY interactions among provided biomarkers (e.g., RDW with MCV for anemia trends, ALP bone/liver origin, WBC with CRP for infection/inflammation)\n\n"
131
+
132
+ "5. Tabular Mapping\n"
133
+ " - This section must always include a Markdown table.\n"
134
+ " - The table must contain exactly four columns:\n"
135
+ " | Biomarker | Value | Status (Low/Normal/High) | AI-Inferred Insight |\n"
136
+ " - Include ALL 9 Levine biomarkers (Albumin, Creatinine, Glucose, CRP, MCV, RDW, ALP, WBC, Lymphocytes).\n"
137
+ " - The first row after the header must begin directly with 'Albumin'.\n"
138
+ " - Do NOT add any index numbers (0,1,2...) or empty rows.\n"
139
+ " - Each biomarker must appear exactly once as a separate row.\n\n"
140
+
141
+ "6. Enhanced AI Insights & Longitudinal Risk\n"
142
+ " - Subclinical nutrient predictions ONLY if patterns (MCV + RDW) suggest it β€” state as possible, not confirmed.\n"
143
+ " - ALP interpretation limited to bone vs liver origin (uncertain without further tests).\n"
144
+ " - WBC & lymphocyte balance for immunity.\n"
145
+ " - Risk framing: Highlight if biomarkers suggest resilience or potential stress, but avoid absolute longevity claims.\n\n"
146
+
147
+ "STYLE REQUIREMENTS:\n"
148
+ "- Use clear section headings and bullet points.\n"
149
+ "- Keep language professional, concise, and client-friendly.\n"
150
+ "- Format tables cleanly in Markdown.\n"
151
+ "- Present output beautifully, like a polished medical summary.\n"
152
+ )
153
+
154
+ patient_input = (
155
+ f"Patient Profile:\n"
156
+ f"- Age: {age}\n"
157
+ f"- Gender: {gender}\n"
158
+ f"- Height: {height} cm\n"
159
+ f"- Weight: {weight} kg\n"
160
+ f"- BMI: {bmi}\n\n"
161
+ "Lab Values:\n"
162
+ f"- Albumin: {albumin} g/dL\n"
163
+ f"- Creatinine: {creatinine} mg/dL\n"
164
+ f"- Glucose: {glucose} mg/dL\n"
165
+ f"- CRP: {crp} mg/L\n"
166
+ f"- MCV: {mcv} fL\n"
167
+ f"- RDW: {rdw} %\n"
168
+ f"- ALP: {alp} U/L\n"
169
+ f"- WBC: {wbc} K/uL\n"
170
+ f"- Lymphocytes: {lymph} %\n"
171
  )
 
172
 
173
+ prompt = system_prompt + "\n" + patient_input
174
 
175
+ # Generate
176
+ # Keep generation parameters conservative for Spaces
177
+ gen = pipe(prompt,
178
+ max_new_tokens=2500,
179
+ do_sample=True,
180
+ temperature=0.001,
181
+ top_p=0.9,
182
+ return_full_text=False)
183
 
184
+ # Extract generated text
185
+ generated = gen[0].get("generated_text") or gen[0].get("text") or str(gen[0])
186
+ generated = generated.strip()
187
 
188
+ # Clean: some models repeat prompt β€” attempt to strip prompt if present
189
+ # Remove leading prompt echo if it appears
190
+ if patient_input.strip() in generated:
191
+ generated = generated.split(patient_input.strip())[-1].strip()
192
+ # Also remove repeated instructions
193
+ if system_prompt.strip() in generated:
194
+ generated = generated.split(system_prompt.strip())[-1].strip()
195
 
196
+ # Split into left/right panels
197
+ left_md, right_md = split_report(generated)
 
198
 
199
+ # If the model output is empty or too short, return a helpful fallback
200
+ if len(left_md) < 50 and len(right_md) < 50:
201
+ fallback = (
202
+ "⚠️ The model returned an unexpectedly short response. Try re-running the report.\n\n"
203
+ "**Patient Profile:**\n" + patient_input
204
+ )
205
+ return fallback, ""
206
+ return left_md, right_md
207
 
208
+ # -----------------------
209
+ # Build Gradio app
210
+ # -----------------------
211
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
212
+ gr.Markdown("# πŸ₯ AI Medical Biomarker Dashboard")
213
+ gr.Markdown("Enter lab values and demographics β€” Report is generated in two panels (Summary & Table/Insights).")
214
 
215
  with gr.Row():
216
+ with gr.Column(scale=1):
217
+ gr.Markdown("### πŸ‘€ Demographics")
218
+ age = gr.Number(label="Age", value=45)
219
+ gender = gr.Dropdown(["Male", "Female"], label="Gender", value="Male")
220
+ height = gr.Number(label="Height (cm)", value=174)
221
+ weight = gr.Number(label="Weight (kg)", value=75)
222
 
223
+ gr.Markdown("### 🩸 Blood Panel")
224
+ wbc = gr.Number(label="WBC (K/uL)", value=6.5)
225
+ lymph = gr.Number(label="Lymphocytes (%)", value=30)
226
+ mcv = gr.Number(label="MCV (fL)", value=88)
227
+ rdw = gr.Number(label="RDW (%)", value=13)
228
 
229
+ with gr.Column(scale=1):
230
+ gr.Markdown("### 🧬 Chemistry Panel")
231
+ albumin = gr.Number(label="Albumin (g/dL)", value=4.2)
232
+ creatinine = gr.Number(label="Creatinine (mg/dL)", value=0.9)
233
+ glucose = gr.Number(label="Glucose (mg/dL)", value=92)
234
+ crp = gr.Number(label="CRP (mg/L)", value=1.0)
235
+ alp = gr.Number(label="ALP (U/L)", value=70)
236
+
237
+ analyze_btn = gr.Button("πŸ”¬ Generate Report", variant="primary")
238
+
239
+ with gr.Row():
240
+ with gr.Column(scale=1):
241
+ gr.Markdown("### πŸ“ Summary & Action Plan")
242
+ left_output = gr.Markdown(value="Press *Generate Report* to create the analysis.")
243
+ with gr.Column(scale=1):
244
+ gr.Markdown("### πŸ“Š Tabular & AI Insights")
245
+ right_output = gr.Markdown(value="Tabular mapping and enhanced insights will appear here.")
246
 
 
247
  analyze_btn.click(
248
  fn=analyze,
249
+ inputs=[albumin, creatinine, glucose, crp, mcv, rdw, alp, wbc, lymph, age, gender, height, weight],
250
+ outputs=[left_output, right_output]
 
251
  )
252
 
253
+
254
+ # Launch (HF Spaces expects this pattern)
255
+ if __name__ == "__main__":
256
+ demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))