Distopia22 commited on
Commit
c953011
·
1 Parent(s): 7fc2f35

Updated the frontend styling

Browse files
Files changed (2) hide show
  1. HOW_TO_SETUP.md +469 -0
  2. app.py +412 -147
HOW_TO_SETUP.md ADDED
@@ -0,0 +1,469 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🚀 ICD-CPT Frontend Gradio - Setup Guide
2
+
3
+ This guide will help you set up the ICD-CPT Coding Assistant frontend on your local machine and deploy to Hugging Face Spaces.
4
+
5
+ ---
6
+
7
+ ## 📋 Table of Contents
8
+
9
+ 1. [Prerequisites](#prerequisites)
10
+ 2. [Clone the Repository](#clone-the-repository)
11
+ 3. [Local Setup](#local-setup)
12
+ 4. [Test on Local Machine](#test-on-local-machine)
13
+ 5. [Push to Hugging Face Space](#push-to-hugging-face-space)
14
+ 6. [Troubleshooting](#troubleshooting)
15
+
16
+ ---
17
+
18
+ ## 🔧 Prerequisites
19
+
20
+ Before you begin, ensure you have the following installed:
21
+
22
+ ### Required Software:
23
+
24
+ - **Python 3.10 or higher** - [Download Python](https://www.python.org/downloads/)
25
+ - **Git** - [Download Git](https://git-scm.com/downloads)
26
+ - **Hugging Face Account** - [Sign up here](https://huggingface.co/join)
27
+ - **Code Editor** (VS Code, PyCharm, or any editor)
28
+
29
+ ### Verify Installations:
30
+
31
+ ```bash
32
+ # Check Python version
33
+ python --version
34
+ # Should show: Python 3.10.x or higher
35
+
36
+ # Check Git version
37
+ git --version
38
+ # Should show: git version 2.x.x
39
+
40
+ # Check pip
41
+ pip --version
42
+ ```
43
+
44
+ ---
45
+
46
+ ## 📥 Clone the Repository
47
+
48
+ ### Option 1: Clone from Hugging Face (If you have access)
49
+
50
+ ```bash
51
+ # Create a project folder
52
+ mkdir icd-cpt-project
53
+ cd icd-cpt-project
54
+
55
+ # Clone the Hugging Face Space
56
+ git clone https://huggingface.co/spaces/Distopia22/icd-cpt-coding-gradio
57
+
58
+ # Navigate into the folder
59
+ cd icd-cpt-coding-gradio
60
+ ```
61
+
62
+ ### Option 2: Download ZIP (If no git access)
63
+
64
+ 1. Go to: `https://huggingface.co/spaces/Distopia22/icd-cpt-coding-gradio`
65
+ 2. Click on **"Files and versions"** tab
66
+ 3. Click **"⋮"** (three dots) → **"Download repository"**
67
+ 4. Extract the ZIP file
68
+ 5. Open terminal in extracted folder
69
+
70
+ ---
71
+
72
+ ## 💻 Local Setup
73
+
74
+ ### Step 1: Create Virtual Environment (Recommended)
75
+
76
+ **Windows:**
77
+
78
+ ```bash
79
+ # Create virtual environment
80
+ python -m venv venv
81
+
82
+ # Activate virtual environment
83
+ venv\Scripts\activate
84
+ ```
85
+
86
+ **Mac/Linux:**
87
+
88
+ ```bash
89
+ # Create virtual environment
90
+ python3 -m venv venv
91
+
92
+ # Activate virtual environment
93
+ source venv/bin/activate
94
+ ```
95
+
96
+ You should see `(venv)` in your terminal prompt.
97
+
98
+ ### Step 2: Install Dependencies
99
+
100
+ ```bash
101
+ # Upgrade pip
102
+ pip install --upgrade pip
103
+
104
+ # Install required packages
105
+ pip install -r requirements.txt
106
+ ```
107
+
108
+ **Expected output:**
109
+
110
+ ```
111
+ Successfully installed gradio-4.16.0 requests-2.31.0 ...
112
+ ```
113
+
114
+ ### Step 3: Verify Installation
115
+
116
+ ```bash
117
+ # Check installed packages
118
+ pip list
119
+
120
+ # Should show:
121
+ # gradio 4.16.0
122
+ # requests 2.31.0
123
+ # ...
124
+ ```
125
+
126
+ ---
127
+
128
+ ## 🧪 Test on Local Machine
129
+
130
+ ### Step 1: Configure Backend API URL
131
+
132
+ Before running, ensure the backend API URL is correct in `app.py`.
133
+
134
+ **Open `app.py` and find line 147:**
135
+
136
+ ```python
137
+ value="https://Distopia22-icd-cpt-coding-api.hf.space",
138
+ ```
139
+
140
+ **Verify this URL is accessible:**
141
+
142
+ - Open browser: `https://Distopia22-icd-cpt-coding-api.hf.space/docs`
143
+ - Should show FastAPI Swagger docs
144
+ - If not accessible, ask for correct backend URL
145
+
146
+ ### Step 2: Run the Application Locally
147
+
148
+ ```bash
149
+ # Make sure you're in the frontend-gradio folder
150
+ # and virtual environment is activated (venv)
151
+
152
+ # Run the Gradio app
153
+ python app.py
154
+ ```
155
+
156
+ **Expected output:**
157
+
158
+ ```
159
+ Running on local URL: http://127.0.0.1:7860
160
+
161
+ To create a public link, set `share=True` in `launch()`.
162
+ ```
163
+
164
+ ### Step 3: Open in Browser
165
+
166
+ 1. **Open your browser**
167
+ 2. **Go to:** `http://127.0.0.1:7860` or `http://localhost:7860`
168
+ 3. **You should see:** The ICD-10 & CPT Coding Assistant interface
169
+
170
+ ### Step 4: Test the Application
171
+
172
+ #### Test 1: Check API Status
173
+
174
+ 1. Click **"⚙️ API Configuration"** to expand
175
+ 2. Verify Backend API URL is correct
176
+ 3. Click **"🔍 Check API Status"**
177
+ 4. Should show: ✅ **"API Status: healthy"**
178
+
179
+ #### Test 2: Load Example
180
+
181
+ 1. Click **"📄 Load Example"** button
182
+ 2. Provider notes should populate with example text
183
+
184
+ #### Test 3: Analyze Provider Notes
185
+
186
+ 1. With example loaded, click **"🔬 Analyze & Generate Codes"**
187
+ 2. Wait 5-10 seconds
188
+ 3. Check **"📋 Overall Summary"** appears
189
+ 4. Click **"🏥 ICD-10 Codes"** tab - should show codes
190
+ 5. Click **"💼 CPT Codes"** tab - should show codes
191
+
192
+ #### Test 4: Custom Input
193
+
194
+ 1. Click **"🗑️ Clear All"**
195
+ 2. Enter your own provider notes:
196
+ ```
197
+ Patient with type 2 diabetes mellitus, uncontrolled.
198
+ HbA1c 9.2%. Discussed diet and medication compliance.
199
+ Adjusted insulin dosing.
200
+ ```
201
+ 3. Click **"🔬 Analyze & Generate Codes"**
202
+ 4. Verify results appear
203
+
204
+ ### Step 5: Stop the Application
205
+
206
+ Press `Ctrl + C` in terminal to stop the server.
207
+
208
+ ---
209
+
210
+ ## 🚀 Push to Hugging Face Space
211
+
212
+ Once you've tested locally and made changes, follow these steps to deploy.
213
+
214
+ ### Step 1: Get Hugging Face Access Token
215
+
216
+ 1. **Log in to Hugging Face:** `https://huggingface.co`
217
+ 2. **Click your profile** (top right) → **Settings**
218
+ 3. **Click "Access Tokens"** (left sidebar)
219
+ 4. **Click "New token"**
220
+ 5. **Configure:**
221
+ - Name: `icd-cpt-deploy`
222
+ - Role: **Write**
223
+ 6. **Click "Generate token"**
224
+ 7. **Copy the token** (starts with `hf_...`)
225
+ 8. **Save it securely** - you won't see it again!
226
+
227
+ ### Step 2: Configure Git for Hugging Face
228
+
229
+ ```bash
230
+ # Set your Hugging Face username
231
+ git config --global user.name "YourHuggingFaceUsername"
232
+
233
+ # Set your email
234
+ git config --global user.email "your.email@example.com"
235
+ ```
236
+
237
+ ### Step 3: Initialize Git (If Not Already Done)
238
+
239
+ ```bash
240
+ # Check if git is initialized
241
+ git status
242
+
243
+ # If error "not a git repository", initialize:
244
+ git init
245
+
246
+ # Add all files
247
+ git add .
248
+
249
+ # Make first commit
250
+ git commit -m "Initial setup"
251
+ ```
252
+
253
+ ### Step 4: Add Hugging Face Remote
254
+
255
+ ```bash
256
+ # Add Hugging Face Space as remote
257
+ git remote add space https://huggingface.co/spaces/Distopia22/icd-cpt-coding-gradio
258
+
259
+ # Verify remote
260
+ git remote -v
261
+ ```
262
+
263
+ **Expected output:**
264
+
265
+ ```
266
+ space https://huggingface.co/spaces/Distopia22/icd-cpt-coding-gradio (fetch)
267
+ space https://huggingface.co/spaces/Distopia22/icd-cpt-coding-gradio (push)
268
+ ```
269
+
270
+ ### Step 5: Push Your Changes
271
+
272
+ ```bash
273
+ # Pull latest changes first (if working with team)
274
+ git pull space main --allow-unrelated-histories
275
+
276
+ # If conflicts, resolve them, then:
277
+ git add .
278
+ git commit -m "Merge remote changes"
279
+
280
+ # Push your changes
281
+ git push space main
282
+ ```
283
+
284
+ **If prompted for credentials:**
285
+
286
+ - **Username:** Your Hugging Face username
287
+ - **Password:** Your Hugging Face **Access Token** (not your password!)
288
+
289
+ ### Step 6: Monitor Deployment
290
+
291
+ 1. **Go to your Space:** `https://huggingface.co/spaces/Distopia22/icd-cpt-coding-gradio`
292
+ 2. **Click "Logs" tab** to see build progress
293
+ 3. **Wait 1-2 minutes** for deployment
294
+ 4. **Status changes to** 🟢 **Running**
295
+ 5. **Click on your Space URL** to test live version
296
+
297
+ ### Step 7: Verify Live Deployment
298
+
299
+ **Your live app will be at:**
300
+
301
+ ```
302
+ https://Distopia22-icd-cpt-coding-gradio.hf.space
303
+ ```
304
+
305
+ **Test the same workflow as local testing:**
306
+
307
+ 1. Check API Status ✅
308
+ 2. Load Example ✅
309
+ 3. Analyze Provider Notes ✅
310
+ 4. Verify results ✅
311
+
312
+ ---
313
+
314
+ ## 🔄 Making Updates (Workflow)
315
+
316
+ ### Daily Workflow:
317
+
318
+ ```bash
319
+ # 1. Activate virtual environment
320
+ venv\Scripts\activate # Windows
321
+ source venv/bin/activate # Mac/Linux
322
+
323
+ # 2. Pull latest changes
324
+ git pull space main
325
+
326
+ # 3. Make your code changes in app.py or other files
327
+
328
+ # 4. Test locally
329
+ python app.py
330
+ # Test in browser: http://localhost:7860
331
+
332
+ # 5. If tests pass, commit changes
333
+ git add .
334
+ git commit -m "Descriptive message about your changes"
335
+
336
+ # 6. Push to Hugging Face
337
+ git push space main
338
+
339
+ # 7. Monitor deployment in Logs tab
340
+ # 8. Test live version
341
+ ```
342
+
343
+ ---
344
+
345
+ ## 🐛 Troubleshooting
346
+
347
+ ### Issue 1: "ModuleNotFoundError: No module named 'gradio'"
348
+
349
+ **Solution:**
350
+
351
+ ```bash
352
+ # Make sure virtual environment is activated
353
+ # Look for (venv) in terminal prompt
354
+
355
+ # Reinstall dependencies
356
+ pip install -r requirements.txt
357
+ ```
358
+
359
+ ### Issue 2: "Port 7860 already in use"
360
+
361
+ **Solution:**
362
+
363
+ ```bash
364
+ # Find and kill the process using port 7860
365
+
366
+ # Windows:
367
+ netstat -ano | findstr :7860
368
+ taskkill /PID <PID_NUMBER> /F
369
+
370
+ # Mac/Linux:
371
+ lsof -ti:7860 | xargs kill -9
372
+
373
+ # Or change port in app.py:
374
+ # demo.launch(server_port=7861)
375
+ ```
376
+
377
+ ### Issue 3: Backend API not responding
378
+
379
+ **Solution:**
380
+
381
+ ```python
382
+ # In app.py, update the API URL (line 147):
383
+ value="https://YOUR-ACTUAL-BACKEND-URL.hf.space",
384
+
385
+ # Test backend URL in browser:
386
+ # Should open: https://YOUR-BACKEND-URL.hf.space/docs
387
+ ```
388
+
389
+ ### Issue 4: Git push fails - "Permission denied"
390
+
391
+ **Solution:**
392
+
393
+ ```bash
394
+ # Make sure you're using Access Token, not password
395
+ # Regenerate token if needed: https://huggingface.co/settings/tokens
396
+
397
+ # Or use SSH instead of HTTPS:
398
+ git remote set-url space git@hf.co:spaces/Distopia22/icd-cpt-coding-gradio
399
+ ```
400
+
401
+ ### Issue 5: Deployment fails on Hugging Face
402
+
403
+ **Check these:**
404
+
405
+ 1. **requirements.txt** has correct versions
406
+ 2. **README.md** has correct header with `sdk: gradio`
407
+ 3. **app.py** has no syntax errors
408
+ 4. Check **Logs** tab for specific error messages
409
+
410
+ ---
411
+
412
+ ## 📞 Getting Help
413
+
414
+ ### If you encounter issues:
415
+
416
+ 1. **Check Logs:**
417
+
418
+ - Local: Terminal output
419
+ - Hugging Face: Logs tab in Space
420
+
421
+ 2. **Common fixes:**
422
+
423
+ - Restart virtual environment
424
+ - Clear pip cache: `pip cache purge`
425
+ - Delete and recreate venv
426
+
427
+ 3. **Contact:**
428
+ - Team Lead: [Your contact]
429
+ - Hugging Face Docs: https://huggingface.co/docs/hub/spaces
430
+
431
+ ---
432
+
433
+ ## ✅ Quick Reference Commands
434
+
435
+ ```bash
436
+ # Activate virtual environment
437
+ venv\Scripts\activate # Windows
438
+ source venv/bin/activate # Mac/Linux
439
+
440
+ # Run locally
441
+ python app.py
442
+
443
+ # Git workflow
444
+ git add .
445
+ git commit -m "Your message"
446
+ git push space main
447
+
448
+ # Check status
449
+ git status
450
+ git log --oneline -5
451
+
452
+ # Pull updates
453
+ git pull space main
454
+ ```
455
+
456
+ ---
457
+
458
+ ## 📚 Additional Resources
459
+
460
+ - **Gradio Documentation:** https://gradio.app/docs
461
+ - **Hugging Face Spaces:** https://huggingface.co/docs/hub/spaces
462
+ - **Git Tutorial:** https://git-scm.com/docs/gittutorial
463
+ - **Python Virtual Environments:** https://docs.python.org/3/tutorial/venv.html
464
+
465
+ ---
466
+
467
+ **Good luck! 🚀**
468
+
469
+ If you follow this guide step-by-step, you'll have the frontend running locally and deployed to Hugging Face in under 30 minutes.
app.py CHANGED
@@ -10,7 +10,7 @@ def check_api_health(api_url):
10
  response = requests.get(f"{api_url}/api/v1/health", timeout=10)
11
  response.raise_for_status()
12
  health_data = response.json()
13
- return f"✅ API Status: {health_data.get('status', 'Unknown')}\n\nService: {health_data.get('service', 'N/A')}"
14
  except requests.exceptions.Timeout:
15
  return "❌ API Health Check Failed: Request timed out"
16
  except requests.exceptions.RequestException as e:
@@ -18,10 +18,10 @@ def check_api_health(api_url):
18
  except Exception as e:
19
  return f"❌ Unexpected Error: {str(e)}"
20
 
21
- def analyze_provider_notes(api_url, provider_notes, progress=gr.Progress()):
22
  """Send provider notes to backend API for analysis"""
23
  if not provider_notes or not provider_notes.strip():
24
- return "⚠️ Please enter provider notes before analyzing.", "", ""
25
 
26
  progress(0, desc="Starting analysis...")
27
 
@@ -44,211 +44,476 @@ def analyze_provider_notes(api_url, provider_notes, progress=gr.Progress()):
44
 
45
  progress(0.9, desc="Formatting results...")
46
 
47
- # Format ICD codes
48
- icd_output = format_icd_codes(result.get("icd_codes", []))
49
-
50
- # Format CPT codes
51
- cpt_output = format_cpt_codes(result.get("cpt_codes", []))
52
-
53
- # Overall summary
54
- summary = result.get("overall_summary", "No summary available")
55
- summary_output = f"### 📋 Overall Summary\n\n{summary}\n\n---\n"
56
 
57
  progress(1.0, desc="Complete!")
58
 
59
- return summary_output, icd_output, cpt_output
60
 
61
  except requests.exceptions.Timeout:
62
- return "❌ Request timed out. The API is taking too long to respond.", "", ""
63
  except requests.exceptions.HTTPError as e:
64
- return f"❌ HTTP Error: {e.response.status_code}\n\n{e.response.text}", "", ""
65
  except requests.exceptions.RequestException as e:
66
- return f"❌ Request Error: {str(e)}", "", ""
67
  except Exception as e:
68
- return f"❌ Unexpected Error: {str(e)}", "", ""
 
 
 
 
 
 
 
69
 
70
- def format_icd_codes(icd_codes):
71
- """Format ICD codes for display"""
72
- if not icd_codes:
73
- return "ℹ️ No ICD-10 codes identified from the provider notes."
 
 
 
 
 
 
 
 
 
74
 
75
- output = "### 🏥 ICD-10 Diagnostic Codes\n\n"
 
 
76
 
77
- for idx, icd in enumerate(icd_codes, 1):
78
- output += f"**{idx}. Code: `{icd.get('code', 'N/A')}`**\n\n"
79
- output += f"**Description:** {icd.get('description', 'N/A')}\n\n"
80
- output += f"**Explanation:**\n{icd.get('explanation', 'N/A')}\n\n"
81
- output += "---\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
  return output
84
 
85
- def format_cpt_codes(cpt_codes):
86
- """Format CPT codes for display"""
87
- if not cpt_codes:
88
- return "ℹ️ No CPT codes identified from the provider notes."
89
 
90
- output = "### 💼 CPT Procedure Codes\n\n"
91
 
92
- for idx, cpt in enumerate(cpt_codes, 1):
93
- output += f"**{idx}. Code: `{cpt.get('code', 'N/A')}`**\n\n"
94
- output += f"**Description:** {cpt.get('description', 'N/A')}\n\n"
95
- output += f"**Explanation:**\n{cpt.get('explanation', 'N/A')}\n\n"
96
- output += "---\n\n"
97
 
98
- return output
 
 
 
99
 
100
- def load_example():
101
  """Load example provider notes"""
102
- return """Patient presents with acute bronchitis. Cough for 5 days, productive with yellow sputum. Lung exam reveals diffuse wheezing. Prescribed azithromycin 500mg."""
103
 
104
- def clear_all():
105
- """Clear all fields"""
106
- return "", "", "", ""
107
 
108
- # ==================== Gradio Interface ====================
109
-
110
- # Custom CSS
111
  custom_css = """
 
112
  .gradio-container {
113
- font-family: 'Arial', sans-serif;
 
 
 
114
  }
115
- .header {
 
 
 
 
116
  text-align: center;
117
- padding: 20px;
118
- background: linear-gradient(90deg, #1f77b4 0%, #2ca02c 100%);
 
 
 
 
119
  color: white;
120
- border-radius: 10px;
121
- margin-bottom: 20px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  .footer {
124
  text-align: center;
125
- margin-top: 30px;
126
- padding: 15px;
127
- color: #666;
128
- font-size: 0.9em;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  }
130
  """
131
 
132
- # Create Gradio Interface
133
- with gr.Blocks(css=custom_css, title="ICD-10 & CPT Coding Assistant") as demo:
 
 
 
 
134
 
135
  # Header
136
  gr.HTML("""
137
- <div class="header">
138
  <h1>🏥 ICD-10 & CPT Coding Assistant</h1>
139
  <p>AI-Powered Medical Coding Analysis using Groq LLaMA 3.3 70B</p>
140
  </div>
141
  """)
142
 
143
- # API Configuration
144
- with gr.Accordion("⚙️ API Configuration", open=False):
145
- api_url_input = gr.Textbox(
146
- label="Backend API URL",
147
- value="https://Distopia22-icd-cpt-coding-api.hf.space",
148
- placeholder="https://your-backend-api.hf.space",
149
- info="Enter your FastAPI backend URL"
150
- )
151
-
152
- api_health_btn = gr.Button("🔍 Check API Status", variant="secondary", size="sm")
153
- api_health_output = gr.Textbox(label="API Status", lines=3, interactive=False)
154
-
155
- gr.Markdown("---")
156
-
157
- # Main Content - Two Columns
158
  with gr.Row():
159
- # Left Column - Input
160
- with gr.Column(scale=1):
161
- gr.Markdown("### 📝 Provider Notes Input")
162
 
163
- provider_notes_input = gr.Textbox(
164
- label="Enter Clinical Provider Notes",
165
- placeholder="Enter detailed clinical documentation here...",
166
- lines=15,
167
- max_lines=20,
168
- info="Provide comprehensive clinical notes for accurate coding"
169
- )
 
 
170
 
171
- with gr.Row():
172
- analyze_btn = gr.Button("🔬 Analyze & Generate Codes", variant="primary", size="lg")
173
- clear_btn = gr.Button("🗑️ Clear All", variant="secondary", size="lg")
174
- example_btn = gr.Button("📄 Load Example", variant="secondary", size="lg")
175
-
176
- # Right Column - Output
177
- with gr.Column(scale=1):
178
- gr.Markdown("### 📊 Analysis Results")
179
 
180
- summary_output = gr.Markdown(label="Summary", value="*Enter provider notes and click 'Analyze' to see results*")
181
-
182
- with gr.Tabs():
183
- with gr.Tab("🏥 ICD-10 Codes"):
184
- icd_output = gr.Markdown(value="*No results yet*")
 
 
 
185
 
186
- with gr.Tab("💼 CPT Codes"):
187
- cpt_output = gr.Markdown(value="*No results yet*")
188
-
189
- # Information Section
190
- gr.Markdown("---")
191
-
192
- with gr.Accordion("ℹ️ How to Use This Application", open=False):
193
- gr.Markdown("""
194
- ### 📖 Instructions:
195
-
196
- 1. **Configure API**: Ensure the backend API URL is correct (default is set)
197
- 2. **Check API Status**: Click 'Check API Status' to verify connection
198
- 3. **Enter Notes**: Type or paste clinical provider notes in the text area
199
- 4. **Load Example**: Click 'Load Example' to see a sample note
200
- 5. **Analyze**: Click 'Analyze & Generate Codes' to process the notes
201
- 6. **Review Results**: View ICD-10 and CPT codes in the tabs on the right
202
-
203
- ### 🔒 Privacy & Security:
204
- - All data is processed securely via encrypted API calls
205
- - No patient data is stored on servers
206
- - Compliant with healthcare data standards
207
 
208
- ### Features:
209
- - Real-time AI analysis using Groq LLaMA 3.3 70B
210
- - Detailed explanations for each code
211
- - Separate ICD-10 and CPT code categorization
212
- - Overall summary of coding decisions
213
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
 
215
  # Footer
216
  gr.HTML("""
217
  <div class="footer">
218
  <p>Powered by <strong>Groq LLaMA 3.3 70B</strong> | <strong>FastAPI</strong> | <strong>Gradio</strong></p>
219
- <p>© 2025 ICD-CPT Coding Assistant</p>
220
  </div>
221
  """)
222
 
223
  # ==================== Event Handlers ====================
224
 
225
- # Check API Health
226
- api_health_btn.click(
227
- fn=check_api_health,
228
- inputs=[api_url_input],
229
- outputs=[api_health_output]
230
- )
231
-
232
- # Analyze Provider Notes
233
- analyze_btn.click(
234
  fn=analyze_provider_notes,
235
- inputs=[api_url_input, provider_notes_input],
236
- outputs=[summary_output, icd_output, cpt_output]
237
- )
238
-
239
- # Load Example
240
- example_btn.click(
241
- fn=load_example,
242
- inputs=[],
243
- outputs=[provider_notes_input]
244
  )
245
 
246
- # Clear All
247
  clear_btn.click(
248
- fn=clear_all,
249
- inputs=[],
250
- outputs=[provider_notes_input, summary_output, icd_output, cpt_output]
251
  )
 
 
 
 
 
 
 
 
252
 
253
  # Launch the app
254
  if __name__ == "__main__":
 
10
  response = requests.get(f"{api_url}/api/v1/health", timeout=10)
11
  response.raise_for_status()
12
  health_data = response.json()
13
+ return f"✅ API is healthy and running!\n\nService: {health_data.get('service', 'ICD-CPT Coding API')}"
14
  except requests.exceptions.Timeout:
15
  return "❌ API Health Check Failed: Request timed out"
16
  except requests.exceptions.RequestException as e:
 
18
  except Exception as e:
19
  return f"❌ Unexpected Error: {str(e)}"
20
 
21
+ def analyze_provider_notes(provider_notes, api_url, progress=gr.Progress()):
22
  """Send provider notes to backend API for analysis"""
23
  if not provider_notes or not provider_notes.strip():
24
+ return generate_empty_response()
25
 
26
  progress(0, desc="Starting analysis...")
27
 
 
44
 
45
  progress(0.9, desc="Formatting results...")
46
 
47
+ # Format complete response
48
+ formatted_response = format_complete_response(result)
 
 
 
 
 
 
 
49
 
50
  progress(1.0, desc="Complete!")
51
 
52
+ return formatted_response
53
 
54
  except requests.exceptions.Timeout:
55
+ return "❌ **Request Timeout**\n\nThe API is taking too long to respond. Please try again."
56
  except requests.exceptions.HTTPError as e:
57
+ return f"❌ **HTTP Error {e.response.status_code}**\n\n{e.response.text}"
58
  except requests.exceptions.RequestException as e:
59
+ return f"❌ **Request Error**\n\n{str(e)}"
60
  except Exception as e:
61
+ return f"❌ **Unexpected Error**\n\n{str(e)}"
62
+
63
+ def generate_empty_response():
64
+ """Generate empty response message"""
65
+ return """
66
+ ### 💬 Welcome to ICD-10 & CPT Coding Assistant
67
+
68
+ Please enter provider notes in the chat box and click **Send** to analyze.
69
 
70
+ **Tips:**
71
+ - Provide detailed clinical documentation
72
+ - Include symptoms, diagnoses, and procedures
73
+ - Be specific about treatments and prescriptions
74
+ """
75
+
76
+ def format_complete_response(result):
77
+ """Format complete analysis response"""
78
+ output = "---\n\n"
79
+
80
+ # Overall Summary
81
+ if result.get("overall_summary"):
82
+ output += f"### 📋 Overall Summary\n\n{result['overall_summary']}\n\n---\n\n"
83
 
84
+ # ICD-10 Codes
85
+ output += "### 🏥 ICD-10 Diagnostic Codes\n\n"
86
+ icd_codes = result.get("icd_codes", [])
87
 
88
+ if icd_codes:
89
+ for idx, icd in enumerate(icd_codes, 1):
90
+ output += f"**{idx}. {icd.get('code', 'N/A')}** - {icd.get('description', 'N/A')}\n\n"
91
+ output += f"*Explanation:* {icd.get('explanation', 'N/A')}\n\n"
92
+ else:
93
+ output += "*No ICD-10 codes identified*\n\n"
94
+
95
+ output += "---\n\n"
96
+
97
+ # CPT Codes
98
+ output += "### 💼 CPT Procedure Codes\n\n"
99
+ cpt_codes = result.get("cpt_codes", [])
100
+
101
+ if cpt_codes:
102
+ for idx, cpt in enumerate(cpt_codes, 1):
103
+ output += f"**{idx}. {cpt.get('code', 'N/A')}** - {cpt.get('description', 'N/A')}\n\n"
104
+ output += f"*Explanation:* {cpt.get('explanation', 'N/A')}\n\n"
105
+ else:
106
+ output += "*No CPT codes identified*\n\n"
107
 
108
  return output
109
 
110
+ # ==================== Example Notes ====================
111
+
112
+ EXAMPLES = {
113
+ "Acute Bronchitis": """Patient presents with acute bronchitis. Cough for 5 days, productive with yellow sputum. Lung exam reveals diffuse wheezing. Prescribed azithromycin 500mg.""",
114
 
115
+ "Type 2 Diabetes": """Patient with type 2 diabetes mellitus, uncontrolled. HbA1c 9.2%. Discussed diet and medication compliance. Adjusted insulin dosing. Referred to diabetes educator.""",
116
 
117
+ "Hypertension Follow-up": """Follow-up visit for hypertension. Blood pressure 145/92. Patient reports good medication compliance. Continue current antihypertensive regimen. Return in 3 months.""",
 
 
 
 
118
 
119
+ "Annual Physical": """Annual physical examination for 45-year-old patient. Comprehensive metabolic panel ordered. Discussed preventive health measures. No acute concerns. Patient in good health.""",
120
+
121
+ "Acute Pharyngitis": """Patient with sore throat for 3 days, fever 101.5°F. Physical exam shows erythematous pharynx with exudate. Rapid strep test positive. Prescribed amoxicillin 500mg TID for 10 days.""",
122
+ }
123
 
124
+ def load_example(example_name):
125
  """Load example provider notes"""
126
+ return EXAMPLES.get(example_name, "")
127
 
128
+ # ==================== Custom CSS ====================
 
 
129
 
 
 
 
130
  custom_css = """
131
+ /* Global Styles */
132
  .gradio-container {
133
+ max-width: 100% !important;
134
+ padding: 0 !important;
135
+ background: linear-gradient(135deg, #0d1117 0%, #1a1f2e 100%) !important;
136
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
137
  }
138
+
139
+ /* Header Styling */
140
+ .header-container {
141
+ background: linear-gradient(90deg, #00d4aa 0%, #00a896 100%);
142
+ padding: 25px;
143
  text-align: center;
144
+ border-radius: 0;
145
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
146
+ margin-bottom: 0;
147
+ }
148
+
149
+ .header-container h1 {
150
  color: white;
151
+ font-size: 2rem;
152
+ font-weight: 700;
153
+ margin: 0;
154
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
155
+ }
156
+
157
+ .header-container p {
158
+ color: #e0f7f4;
159
+ font-size: 1rem;
160
+ margin: 8px 0 0 0;
161
+ }
162
+
163
+ /* Sidebar Styling */
164
+ .sidebar {
165
+ background: #1a1f2e !important;
166
+ border-right: 1px solid #00d4aa !important;
167
+ padding: 20px !important;
168
+ height: 100vh !important;
169
+ overflow-y: auto !important;
170
+ }
171
+
172
+ .sidebar-title {
173
+ color: #00d4aa !important;
174
+ font-size: 1.3rem !important;
175
+ font-weight: 600 !important;
176
+ margin-bottom: 20px !important;
177
+ padding-bottom: 10px !important;
178
+ border-bottom: 2px solid #00d4aa !important;
179
+ }
180
+
181
+ /* Example Buttons */
182
+ .example-btn {
183
+ background: linear-gradient(135deg, #00d4aa 0%, #00a896 100%) !important;
184
+ color: white !important;
185
+ border: none !important;
186
+ border-radius: 8px !important;
187
+ padding: 12px 16px !important;
188
+ margin: 8px 0 !important;
189
+ font-weight: 500 !important;
190
+ cursor: pointer !important;
191
+ transition: all 0.3s ease !important;
192
+ width: 100% !important;
193
+ text-align: left !important;
194
+ }
195
+
196
+ .example-btn:hover {
197
+ background: linear-gradient(135deg, #00ffcc 0%, #00d4aa 100%) !important;
198
+ transform: translateX(5px) !important;
199
+ box-shadow: 0 4px 12px rgba(0, 212, 170, 0.4) !important;
200
+ }
201
+
202
+ /* Chat Container */
203
+ .chat-container {
204
+ background: #0d1117 !important;
205
+ border-radius: 12px !important;
206
+ padding: 20px !important;
207
+ height: calc(100vh - 200px) !important;
208
+ display: flex !important;
209
+ flex-direction: column !important;
210
+ }
211
+
212
+ /* Input Area */
213
+ .input-row {
214
+ background: #1a1f2e !important;
215
+ border: 2px solid #00d4aa !important;
216
+ border-radius: 12px !important;
217
+ padding: 15px !important;
218
+ margin-top: 10px !important;
219
+ }
220
+
221
+ .input-row textarea {
222
+ background: #0d1117 !important;
223
+ color: #e6e6e6 !important;
224
+ border: 1px solid #2d3748 !important;
225
+ border-radius: 8px !important;
226
+ font-size: 1rem !important;
227
+ padding: 12px !important;
228
+ }
229
+
230
+ .input-row textarea:focus {
231
+ border-color: #00d4aa !important;
232
+ outline: none !important;
233
+ box-shadow: 0 0 0 3px rgba(0, 212, 170, 0.1) !important;
234
+ }
235
+
236
+ /* Send Button */
237
+ .send-button {
238
+ background: linear-gradient(135deg, #00d4aa 0%, #00a896 100%) !important;
239
+ color: white !important;
240
+ border: none !important;
241
+ border-radius: 8px !important;
242
+ padding: 12px 32px !important;
243
+ font-size: 1rem !important;
244
+ font-weight: 600 !important;
245
+ cursor: pointer !important;
246
+ transition: all 0.3s ease !important;
247
+ margin-top: 10px !important;
248
+ }
249
+
250
+ .send-button:hover {
251
+ background: linear-gradient(135deg, #00ffcc 0%, #00d4aa 100%) !important;
252
+ box-shadow: 0 6px 20px rgba(0, 212, 170, 0.4) !important;
253
+ transform: translateY(-2px) !important;
254
+ }
255
+
256
+ /* Clear Button */
257
+ .clear-button {
258
+ background: linear-gradient(135deg, #2d3748 0%, #1a202c 100%) !important;
259
+ color: white !important;
260
+ border: 1px solid #4a5568 !important;
261
+ border-radius: 8px !important;
262
+ padding: 12px 32px !important;
263
+ font-size: 1rem !important;
264
+ font-weight: 600 !important;
265
+ cursor: pointer !important;
266
+ transition: all 0.3s ease !important;
267
+ margin-top: 10px !important;
268
+ }
269
+
270
+ .clear-button:hover {
271
+ background: linear-gradient(135deg, #4a5568 0%, #2d3748 100%) !important;
272
+ border-color: #718096 !important;
273
+ transform: translateY(-2px) !important;
274
+ }
275
+
276
+ /* Output Area */
277
+ .output-container {
278
+ background: #1a1f2e !important;
279
+ border: 1px solid #2d3748 !important;
280
+ border-radius: 12px !important;
281
+ padding: 20px !important;
282
+ color: #e6e6e6 !important;
283
+ overflow-y: auto !important;
284
+ flex-grow: 1 !important;
285
+ margin-bottom: 15px !important;
286
+ }
287
+
288
+ .output-container h3 {
289
+ color: #00d4aa !important;
290
+ border-bottom: 2px solid #00d4aa !important;
291
+ padding-bottom: 8px !important;
292
+ margin-top: 20px !important;
293
+ }
294
+
295
+ .output-container strong {
296
+ color: #00ffcc !important;
297
+ }
298
+
299
+ .output-container hr {
300
+ border: none !important;
301
+ border-top: 1px solid #2d3748 !important;
302
+ margin: 20px 0 !important;
303
  }
304
+
305
+ /* API Config Section */
306
+ .api-config {
307
+ background: #1a1f2e !important;
308
+ border: 1px solid #2d3748 !important;
309
+ border-radius: 8px !important;
310
+ padding: 15px !important;
311
+ margin-bottom: 15px !important;
312
+ }
313
+
314
+ .api-config input {
315
+ background: #0d1117 !important;
316
+ color: #e6e6e6 !important;
317
+ border: 1px solid #2d3748 !important;
318
+ border-radius: 6px !important;
319
+ padding: 10px !important;
320
+ }
321
+
322
+ .api-config input:focus {
323
+ border-color: #00d4aa !important;
324
+ outline: none !important;
325
+ }
326
+
327
+ /* Check API Button */
328
+ .check-api-button {
329
+ background: linear-gradient(135deg, #00a896 0%, #008577 100%) !important;
330
+ color: white !important;
331
+ border: none !important;
332
+ border-radius: 6px !important;
333
+ padding: 10px 20px !important;
334
+ font-weight: 500 !important;
335
+ cursor: pointer !important;
336
+ transition: all 0.3s ease !important;
337
+ }
338
+
339
+ .check-api-button:hover {
340
+ background: linear-gradient(135deg, #00d4aa 0%, #00a896 100%) !important;
341
+ box-shadow: 0 4px 12px rgba(0, 168, 150, 0.4) !important;
342
+ }
343
+
344
+ /* Footer */
345
  .footer {
346
  text-align: center;
347
+ padding: 20px;
348
+ color: #718096;
349
+ font-size: 0.9rem;
350
+ background: #0d1117;
351
+ border-top: 1px solid #2d3748;
352
+ margin-top: 20px;
353
+ }
354
+
355
+ .footer strong {
356
+ color: #00d4aa;
357
+ }
358
+
359
+ /* Scrollbar Styling */
360
+ ::-webkit-scrollbar {
361
+ width: 8px;
362
+ }
363
+
364
+ ::-webkit-scrollbar-track {
365
+ background: #0d1117;
366
+ }
367
+
368
+ ::-webkit-scrollbar-thumb {
369
+ background: #00d4aa;
370
+ border-radius: 4px;
371
+ }
372
+
373
+ ::-webkit-scrollbar-thumb:hover {
374
+ background: #00ffcc;
375
+ }
376
+
377
+ /* Accordion Styling */
378
+ .accordion {
379
+ background: #1a1f2e !important;
380
+ border: 1px solid #2d3748 !important;
381
+ border-radius: 8px !important;
382
+ }
383
+
384
+ .accordion summary {
385
+ color: #00d4aa !important;
386
+ font-weight: 600 !important;
387
+ padding: 12px !important;
388
+ cursor: pointer !important;
389
+ }
390
+
391
+ /* Responsive */
392
+ @media (max-width: 768px) {
393
+ .header-container h1 {
394
+ font-size: 1.5rem;
395
+ }
396
+
397
+ .sidebar {
398
+ height: auto !important;
399
+ border-right: none !important;
400
+ border-bottom: 1px solid #00d4aa !important;
401
+ }
402
  }
403
  """
404
 
405
+ # ==================== Gradio Interface ====================
406
+
407
+ with gr.Blocks(css=custom_css, theme=gr.themes.Soft(), title="ICD-10 & CPT Coding Assistant") as demo:
408
+
409
+ # Hidden state for API URL
410
+ api_url_state = gr.State(value="https://Distopia22-icd-cpt-coding-api.hf.space")
411
 
412
  # Header
413
  gr.HTML("""
414
+ <div class="header-container">
415
  <h1>🏥 ICD-10 & CPT Coding Assistant</h1>
416
  <p>AI-Powered Medical Coding Analysis using Groq LLaMA 3.3 70B</p>
417
  </div>
418
  """)
419
 
420
+ # Main Layout
 
 
 
 
 
 
 
 
 
 
 
 
 
 
421
  with gr.Row():
422
+ # Left Sidebar
423
+ with gr.Column(scale=1, elem_classes="sidebar"):
424
+ gr.HTML('<div class="sidebar-title">📚 Example Cases</div>')
425
 
426
+ # Example buttons
427
+ for example_name in EXAMPLES.keys():
428
+ gr.Button(
429
+ f"📄 {example_name}",
430
+ elem_classes="example-btn"
431
+ ).click(
432
+ fn=lambda name=example_name: load_example(name),
433
+ outputs=gr.Textbox(elem_id="provider_notes_input", visible=False)
434
+ )
435
 
436
+ gr.Markdown("---")
 
 
 
 
 
 
 
437
 
438
+ # API Configuration
439
+ with gr.Accordion("⚙️ API Configuration", open=False, elem_classes="api-config"):
440
+ api_url_input = gr.Textbox(
441
+ label="Backend API URL",
442
+ value="https://Distopia22-icd-cpt-coding-api.hf.space",
443
+ placeholder="https://your-backend-api.hf.space",
444
+ interactive=True
445
+ )
446
 
447
+ check_api_btn = gr.Button("🔍 Check API Status", elem_classes="check-api-button", size="sm")
448
+ api_status_output = gr.Textbox(label="Status", lines=3, interactive=False)
449
+
450
+ check_api_btn.click(
451
+ fn=check_api_health,
452
+ inputs=[api_url_input],
453
+ outputs=[api_status_output]
454
+ )
455
+
456
+ # Update state when URL changes
457
+ api_url_input.change(
458
+ fn=lambda x: x,
459
+ inputs=[api_url_input],
460
+ outputs=[api_url_state]
461
+ )
 
 
 
 
 
 
462
 
463
+ # Right Chat Area
464
+ with gr.Column(scale=3, elem_classes="chat-container"):
465
+ # Output/Chat History
466
+ output_area = gr.Markdown(
467
+ value=generate_empty_response(),
468
+ elem_classes="output-container",
469
+ label="Analysis Results"
470
+ )
471
+
472
+ # Input Area
473
+ with gr.Row(elem_classes="input-row"):
474
+ with gr.Column(scale=5):
475
+ provider_notes_input = gr.Textbox(
476
+ label="",
477
+ placeholder="Enter clinical provider notes here...",
478
+ lines=4,
479
+ max_lines=8,
480
+ elem_id="provider_notes_input"
481
+ )
482
+
483
+ with gr.Column(scale=1):
484
+ send_btn = gr.Button("🚀 Send", elem_classes="send-button", size="lg")
485
+ clear_btn = gr.Button("🗑️ Clear", elem_classes="clear-button", size="lg")
486
 
487
  # Footer
488
  gr.HTML("""
489
  <div class="footer">
490
  <p>Powered by <strong>Groq LLaMA 3.3 70B</strong> | <strong>FastAPI</strong> | <strong>Gradio</strong></p>
491
+ <p>© 2025 ICD-CPT Coding Assistant - Secure & HIPAA Compliant</p>
492
  </div>
493
  """)
494
 
495
  # ==================== Event Handlers ====================
496
 
497
+ # Send button - Analyze notes
498
+ send_btn.click(
 
 
 
 
 
 
 
499
  fn=analyze_provider_notes,
500
+ inputs=[provider_notes_input, api_url_state],
501
+ outputs=[output_area]
 
 
 
 
 
 
 
502
  )
503
 
504
+ # Clear button
505
  clear_btn.click(
506
+ fn=lambda: ("", generate_empty_response()),
507
+ outputs=[provider_notes_input, output_area]
 
508
  )
509
+
510
+ # Example buttons - Load example into input
511
+ for example_name in EXAMPLES.keys():
512
+ example_btn = gr.Button(f"📄 {example_name}", visible=False)
513
+ example_btn.click(
514
+ fn=lambda name=example_name: load_example(name),
515
+ outputs=[provider_notes_input]
516
+ )
517
 
518
  # Launch the app
519
  if __name__ == "__main__":