abjasrees commited on
Commit
c872cb2
Β·
verified Β·
1 Parent(s): 9fdbf51

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +266 -17
app.py CHANGED
@@ -3,11 +3,12 @@
3
  import os
4
  import tempfile
5
  import hashlib
 
6
  import gradio as gr
7
 
8
  from embedding_manager import EmbeddingManager
9
  from summarizer import PatientChartSummarizer
10
- from hedis_engine import HedisComplianceEngine
11
 
12
  APP_TITLE = "ChartWise AI"
13
  DEFAULT_MEASURE_YEAR = 2024
@@ -17,6 +18,11 @@ DEFAULT_MEASURE_YEAR = 2024
17
  _VDB_CACHE = {}
18
  _LAST_HASH = None # optional: for quick reuse/debug
19
 
 
 
 
 
 
20
  def _pdf_hash(pdf_bytes: bytes) -> str:
21
  return hashlib.sha256(pdf_bytes).hexdigest()
22
 
@@ -52,6 +58,72 @@ def _get_vectordb_from_bytes(pdf_bytes: bytes):
52
  except Exception:
53
  pass
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  # --- Handlers ---
56
  def generate_patient_summary(pdf_file):
57
  try:
@@ -67,23 +139,158 @@ def generate_patient_summary(pdf_file):
67
  except Exception as e:
68
  return f"❌ Error processing chart: {e}"
69
 
70
- def generate_hedis_analysis(pdf_file, measure_name, measurement_year):
 
 
 
71
  try:
72
  if pdf_file is None:
73
- return "⚠️ Please upload a PDF file first."
 
 
 
 
 
 
74
  if not measure_name:
75
- return "⚠️ Please enter a HEDIS measure code (e.g., COL, BCS, CCS)."
 
 
 
 
 
 
76
  if not measurement_year:
77
- return "⚠️ Please enter a measurement year."
 
 
 
 
 
 
78
 
79
  # Reuse embeddings if already built for this file
80
  vectordb = _get_vectordb_from_bytes(pdf_file)
81
 
82
- hedis = HedisComplianceEngine(vectordb, measure_name, int(measurement_year))
83
- result = hedis.run()
84
- return result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  except Exception as e:
86
- return f"❌ Error processing HEDIS analysis: {e}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
  # --- Gradio Theme ---
89
  simple_theme = gr.themes.Soft(
@@ -101,7 +308,7 @@ simple_theme = gr.themes.Soft(
101
  # --- Interface ---
102
  with gr.Blocks(theme=simple_theme, title="ChartWise AI") as interface:
103
  gr.HTML("<h1 style='text-align:center;color:#1e40af;'>πŸ₯ ChartWise AI</h1>")
104
- gr.HTML("<p style='text-align:center;color:#64748b;'>Patient Chart Analysis &amp; HEDIS Compliance</p>")
105
 
106
  with gr.Row(equal_height=True):
107
  # Left: Patient Summary
@@ -115,9 +322,9 @@ with gr.Blocks(theme=simple_theme, title="ChartWise AI") as interface:
115
  height=400
116
  )
117
 
118
- # Right: HEDIS
119
  with gr.Column():
120
- gr.HTML("<h3 style='color:#1e40af;'>🎯 HEDIS Measure Analysis</h3>")
121
  hedis_measure = gr.Textbox(
122
  label="HEDIS Measure Code",
123
  placeholder="e.g., COL, BCS, CCS, AAB",
@@ -129,16 +336,58 @@ with gr.Blocks(theme=simple_theme, title="ChartWise AI") as interface:
129
  precision=0,
130
  info="e.g., 2024"
131
  )
132
- hedis_btn = gr.Button("🎯 Run HEDIS Analysis", variant="secondary")
 
133
  hedis_output = gr.Markdown(
134
  label="HEDIS Analysis Results",
135
- value="Enter measure and year, then click 'Run HEDIS Analysis'.",
136
- height=400
137
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
  # Wire events
140
- summary_btn.click(fn=generate_patient_summary, inputs=[pdf_upload], outputs=[summary_output])
141
- hedis_btn.click(fn=generate_hedis_analysis, inputs=[pdf_upload, hedis_measure, measurement_year], outputs=[hedis_output])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
143
  # Spaces auto-runs the script; these hints are fine, too:
144
  if __name__ == "__main__":
 
3
  import os
4
  import tempfile
5
  import hashlib
6
+ import json
7
  import gradio as gr
8
 
9
  from embedding_manager import EmbeddingManager
10
  from summarizer import PatientChartSummarizer
11
+ from interactive_hedis_engine import InteractiveHedisComplianceEngine
12
 
13
  APP_TITLE = "ChartWise AI"
14
  DEFAULT_MEASURE_YEAR = 2024
 
18
  _VDB_CACHE = {}
19
  _LAST_HASH = None # optional: for quick reuse/debug
20
 
21
+ # Global state for interactive HEDIS analysis
22
+ _CURRENT_ENGINE = None
23
+ _CURRENT_CRITERIA = None
24
+ _ANALYSIS_STATE = "idle" # idle, criteria_review, analysis_complete
25
+
26
  def _pdf_hash(pdf_bytes: bytes) -> str:
27
  return hashlib.sha256(pdf_bytes).hexdigest()
28
 
 
58
  except Exception:
59
  pass
60
 
61
+ def format_criteria_for_display(criteria: dict) -> str:
62
+ """Format criteria dictionary into markdown for display."""
63
+ if "raw_output" in criteria:
64
+ return f"```\n{criteria['raw_output']}\n```"
65
+
66
+ markdown = f"# HEDIS Measure Criteria\n\n"
67
+
68
+ if "measure" in criteria:
69
+ markdown += f"**πŸ“‹ Measure:** {criteria['measure']}\n\n"
70
+
71
+ if "required_tests" in criteria:
72
+ markdown += f"## πŸ”¬ Required Tests/Procedures\n"
73
+ if isinstance(criteria['required_tests'], list):
74
+ for test in criteria['required_tests']:
75
+ markdown += f"β€’ {test}\n"
76
+ else:
77
+ markdown += f"{criteria['required_tests']}\n"
78
+ markdown += "\n"
79
+
80
+ if "required_medications" in criteria:
81
+ markdown += f"## πŸ’Š Required Medications\n"
82
+ if isinstance(criteria['required_medications'], list):
83
+ for med in criteria['required_medications']:
84
+ markdown += f"β€’ {med}\n"
85
+ else:
86
+ markdown += f"{criteria['required_medications']}\n"
87
+ markdown += "\n"
88
+
89
+ if "codes" in criteria:
90
+ markdown += f"## 🏷️ Relevant Codes\n"
91
+ if isinstance(criteria['codes'], dict):
92
+ for code_type, codes in criteria['codes'].items():
93
+ markdown += f"**{code_type}:** {codes}\n"
94
+ else:
95
+ markdown += f"{criteria['codes']}\n"
96
+ markdown += "\n"
97
+
98
+ if "timeframes" in criteria:
99
+ markdown += f"## ⏰ Timeframes\n"
100
+ if isinstance(criteria['timeframes'], dict):
101
+ for requirement, timeframe in criteria['timeframes'].items():
102
+ markdown += f"**{requirement}:** {timeframe}\n"
103
+ else:
104
+ markdown += f"{criteria['timeframes']}\n"
105
+ markdown += "\n"
106
+
107
+ if "inclusions" in criteria:
108
+ markdown += f"## βœ… Inclusion Criteria\n"
109
+ if isinstance(criteria['inclusions'], list):
110
+ for inclusion in criteria['inclusions']:
111
+ markdown += f"β€’ {inclusion}\n"
112
+ else:
113
+ markdown += f"{criteria['inclusions']}\n"
114
+ markdown += "\n"
115
+
116
+ if "exclusions" in criteria:
117
+ markdown += f"## ❌ Exclusion Criteria\n"
118
+ if isinstance(criteria['exclusions'], list):
119
+ for exclusion in criteria['exclusions']:
120
+ markdown += f"β€’ {exclusion}\n"
121
+ else:
122
+ markdown += f"{criteria['exclusions']}\n"
123
+ markdown += "\n"
124
+
125
+ return markdown
126
+
127
  # --- Handlers ---
128
  def generate_patient_summary(pdf_file):
129
  try:
 
139
  except Exception as e:
140
  return f"❌ Error processing chart: {e}"
141
 
142
+ def start_hedis_analysis(pdf_file, measure_name, measurement_year):
143
+ """Start interactive HEDIS analysis by getting initial criteria."""
144
+ global _CURRENT_ENGINE, _CURRENT_CRITERIA, _ANALYSIS_STATE
145
+
146
  try:
147
  if pdf_file is None:
148
+ return (
149
+ "⚠️ Please upload a PDF file first.",
150
+ gr.update(visible=False),
151
+ gr.update(visible=False),
152
+ gr.update(visible=False),
153
+ gr.update(visible=False)
154
+ )
155
  if not measure_name:
156
+ return (
157
+ "⚠️ Please enter a HEDIS measure code (e.g., COL, BCS, CCS).",
158
+ gr.update(visible=False),
159
+ gr.update(visible=False),
160
+ gr.update(visible=False),
161
+ gr.update(visible=False)
162
+ )
163
  if not measurement_year:
164
+ return (
165
+ "⚠️ Please enter a measurement year.",
166
+ gr.update(visible=False),
167
+ gr.update(visible=False),
168
+ gr.update(visible=False),
169
+ gr.update(visible=False)
170
+ )
171
 
172
  # Reuse embeddings if already built for this file
173
  vectordb = _get_vectordb_from_bytes(pdf_file)
174
 
175
+ # Create engine and get initial criteria
176
+ _CURRENT_ENGINE = InteractiveHedisComplianceEngine(vectordb, measure_name, int(measurement_year))
177
+ _CURRENT_CRITERIA = _CURRENT_ENGINE.get_hedis_criteria_with_feedback()
178
+ _ANALYSIS_STATE = "criteria_review"
179
+
180
+ criteria_display = format_criteria_for_display(_CURRENT_CRITERIA)
181
+
182
+ return (
183
+ criteria_display,
184
+ gr.update(visible=True), # suggestions textbox
185
+ gr.update(visible=True), # approve button
186
+ gr.update(visible=True), # modify button
187
+ gr.update(visible=True) # cancel button
188
+ )
189
+ except Exception as e:
190
+ _ANALYSIS_STATE = "idle"
191
+ return (
192
+ f"❌ Error getting HEDIS criteria: {e}",
193
+ gr.update(visible=False),
194
+ gr.update(visible=False),
195
+ gr.update(visible=False),
196
+ gr.update(visible=False)
197
+ )
198
+
199
+ def approve_criteria():
200
+ """Approve current criteria and proceed with full analysis."""
201
+ global _CURRENT_ENGINE, _CURRENT_CRITERIA, _ANALYSIS_STATE
202
+
203
+ try:
204
+ if _ANALYSIS_STATE != "criteria_review" or _CURRENT_ENGINE is None:
205
+ return (
206
+ "❌ No criteria to approve. Please start a new analysis.",
207
+ gr.update(visible=False),
208
+ gr.update(visible=False),
209
+ gr.update(visible=False),
210
+ gr.update(visible=False)
211
+ )
212
+
213
+ # Set approved criteria and run full analysis
214
+ _CURRENT_ENGINE.hedis_criteria = _CURRENT_CRITERIA
215
+ result = _CURRENT_ENGINE.run_full_analysis()
216
+ _ANALYSIS_STATE = "analysis_complete"
217
+
218
+ return (
219
+ f"## βœ… Analysis Complete\n\n{result}",
220
+ gr.update(visible=False),
221
+ gr.update(visible=False),
222
+ gr.update(visible=False),
223
+ gr.update(visible=False)
224
+ )
225
  except Exception as e:
226
+ _ANALYSIS_STATE = "idle"
227
+ return (
228
+ f"❌ Error running analysis: {e}",
229
+ gr.update(visible=False),
230
+ gr.update(visible=False),
231
+ gr.update(visible=False),
232
+ gr.update(visible=False)
233
+ )
234
+
235
+ def modify_criteria(suggestions):
236
+ """Modify criteria based on suggestions."""
237
+ global _CURRENT_ENGINE, _CURRENT_CRITERIA, _ANALYSIS_STATE
238
+
239
+ try:
240
+ if _ANALYSIS_STATE != "criteria_review" or _CURRENT_ENGINE is None:
241
+ return (
242
+ "❌ No criteria to modify. Please start a new analysis.",
243
+ gr.update(visible=False),
244
+ gr.update(visible=False),
245
+ gr.update(visible=False),
246
+ gr.update(visible=False)
247
+ )
248
+
249
+ if not suggestions.strip():
250
+ return (
251
+ "⚠️ Please provide suggestions for modification.",
252
+ gr.update(visible=True),
253
+ gr.update(visible=True),
254
+ gr.update(visible=True),
255
+ gr.update(visible=True)
256
+ )
257
+
258
+ # Get modified criteria
259
+ _CURRENT_CRITERIA = _CURRENT_ENGINE.get_hedis_criteria_with_feedback(suggestions.strip())
260
+ criteria_display = format_criteria_for_display(_CURRENT_CRITERIA)
261
+
262
+ return (
263
+ f"## πŸ”„ Modified Criteria\n\n{criteria_display}",
264
+ gr.update(visible=True, value=""), # clear suggestions
265
+ gr.update(visible=True),
266
+ gr.update(visible=True),
267
+ gr.update(visible=True)
268
+ )
269
+ except Exception as e:
270
+ _ANALYSIS_STATE = "idle"
271
+ return (
272
+ f"❌ Error modifying criteria: {e}",
273
+ gr.update(visible=False),
274
+ gr.update(visible=False),
275
+ gr.update(visible=False),
276
+ gr.update(visible=False)
277
+ )
278
+
279
+ def cancel_analysis():
280
+ """Cancel the current analysis."""
281
+ global _CURRENT_ENGINE, _CURRENT_CRITERIA, _ANALYSIS_STATE
282
+
283
+ _CURRENT_ENGINE = None
284
+ _CURRENT_CRITERIA = None
285
+ _ANALYSIS_STATE = "idle"
286
+
287
+ return (
288
+ "❌ Analysis cancelled. You can start a new analysis.",
289
+ gr.update(visible=False),
290
+ gr.update(visible=False),
291
+ gr.update(visible=False),
292
+ gr.update(visible=False)
293
+ )
294
 
295
  # --- Gradio Theme ---
296
  simple_theme = gr.themes.Soft(
 
308
  # --- Interface ---
309
  with gr.Blocks(theme=simple_theme, title="ChartWise AI") as interface:
310
  gr.HTML("<h1 style='text-align:center;color:#1e40af;'>πŸ₯ ChartWise AI</h1>")
311
+ gr.HTML("<p style='text-align:center;color:#64748b;'>Patient Chart Analysis &amp; Interactive HEDIS Compliance</p>")
312
 
313
  with gr.Row(equal_height=True):
314
  # Left: Patient Summary
 
322
  height=400
323
  )
324
 
325
+ # Right: Interactive HEDIS
326
  with gr.Column():
327
+ gr.HTML("<h3 style='color:#1e40af;'>🎯 Interactive HEDIS Analysis</h3>")
328
  hedis_measure = gr.Textbox(
329
  label="HEDIS Measure Code",
330
  placeholder="e.g., COL, BCS, CCS, AAB",
 
336
  precision=0,
337
  info="e.g., 2024"
338
  )
339
+ start_hedis_btn = gr.Button("🎯 Start HEDIS Analysis", variant="secondary")
340
+
341
  hedis_output = gr.Markdown(
342
  label="HEDIS Analysis Results",
343
+ value="Enter measure and year, then click 'Start HEDIS Analysis' to begin interactive review.",
344
+ height=300
345
  )
346
+
347
+ # Interactive feedback components (initially hidden)
348
+ with gr.Group():
349
+ suggestions_input = gr.Textbox(
350
+ label="Suggestions for Criteria Modification",
351
+ placeholder="Enter your suggestions to modify the criteria...",
352
+ visible=False,
353
+ lines=3
354
+ )
355
+
356
+ with gr.Row():
357
+ approve_btn = gr.Button("βœ… Approve & Continue", variant="primary", visible=False)
358
+ modify_btn = gr.Button("πŸ”„ Modify Criteria", variant="secondary", visible=False)
359
+ cancel_btn = gr.Button("❌ Cancel Analysis", visible=False)
360
 
361
  # Wire events
362
+ summary_btn.click(
363
+ fn=generate_patient_summary,
364
+ inputs=[pdf_upload],
365
+ outputs=[summary_output]
366
+ )
367
+
368
+ start_hedis_btn.click(
369
+ fn=start_hedis_analysis,
370
+ inputs=[pdf_upload, hedis_measure, measurement_year],
371
+ outputs=[hedis_output, suggestions_input, approve_btn, modify_btn, cancel_btn]
372
+ )
373
+
374
+ approve_btn.click(
375
+ fn=approve_criteria,
376
+ inputs=[],
377
+ outputs=[hedis_output, suggestions_input, approve_btn, modify_btn, cancel_btn]
378
+ )
379
+
380
+ modify_btn.click(
381
+ fn=modify_criteria,
382
+ inputs=[suggestions_input],
383
+ outputs=[hedis_output, suggestions_input, approve_btn, modify_btn, cancel_btn]
384
+ )
385
+
386
+ cancel_btn.click(
387
+ fn=cancel_analysis,
388
+ inputs=[],
389
+ outputs=[hedis_output, suggestions_input, approve_btn, modify_btn, cancel_btn]
390
+ )
391
 
392
  # Spaces auto-runs the script; these hints are fine, too:
393
  if __name__ == "__main__":