File size: 8,530 Bytes
d7c0aa2
 
 
2101408
d7c0aa2
 
 
c953011
d7c0aa2
 
c953011
d7c0aa2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c953011
d7c0aa2
 
 
c953011
d7c0aa2
 
c953011
d7c0aa2
c953011
d7c0aa2
c953011
d7c0aa2
c953011
 
 
 
 
7d58419
c953011
2101408
d7c0aa2
c953011
 
 
 
2101408
 
08eb6be
 
 
 
 
c953011
 
 
 
 
 
 
 
d7c0aa2
c953011
 
d7c0aa2
c953011
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d7c0aa2
 
 
518996e
c953011
 
 
d7c0aa2
c953011
d7c0aa2
c953011
 
d7c0aa2
c953011
d7c0aa2
c953011
d7c0aa2
2101408
c953011
2101408
 
 
 
 
 
 
 
 
d7c0aa2
c953011
 
7d58419
c953011
 
d7c0aa2
 
 
c953011
7d58419
d7c0aa2
 
 
 
2101408
 
518996e
2101408
c953011
d7c0aa2
2101408
c953011
2101408
c953011
 
 
2101408
d7c0aa2
c953011
d7c0aa2
08eb6be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d7c0aa2
518996e
c953011
2101408
c953011
 
2101408
 
c953011
 
2101408
 
c953011
 
 
2101408
 
7d58419
 
c953011
 
2101408
 
 
d7c0aa2
 
 
 
 
7d58419
d7c0aa2
 
 
08eb6be
 
 
2101408
 
 
 
 
 
08eb6be
c953011
d7c0aa2
c953011
 
d7c0aa2
 
08eb6be
d7c0aa2
c953011
 
d7c0aa2
 
518996e
d7c0aa2
 
 
 
f2fd281
d7c0aa2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
import gradio as gr
import requests
import json
import os

# ==================== API Functions ====================

def analyze_provider_notes(provider_notes, api_url, progress=gr.Progress()):
    """Send provider notes to backend API for analysis"""
    if not provider_notes or not provider_notes.strip():
        return generate_empty_response()
    
    progress(0, desc="Starting analysis...")
    
    try:
        payload = {"provider_notes": provider_notes}
        
        progress(0.3, desc="Sending request to API...")
        
        response = requests.post(
            f"{api_url}/api/v1/analyze",
            json=payload,
            headers={"Content-Type": "application/json"},
            timeout=60
        )
        
        progress(0.6, desc="Processing response...")
        
        response.raise_for_status()
        result = response.json()
        
        progress(0.9, desc="Formatting results...")
        
        formatted_response = format_complete_response(result)
        
        progress(1.0, desc="Complete!")
        
        return formatted_response
        
    except requests.exceptions.Timeout:
        return "❌ **Request Timeout**\n\nThe API is taking too long to respond. Please try again."
    except requests.exceptions.HTTPError as e:
        return f"❌ **HTTP Error {e.response.status_code}**\n\n{e.response.text}"
    except requests.exceptions.RequestException as e:
        return f"❌ **Request Error**\n\n{str(e)}"
    except Exception as e:
        return f"❌ **Unexpected Error**\n\n{str(e)}"

def generate_empty_response():
    """Generate empty response message"""
    return """
### πŸ’¬ Welcome to Medical Coding (ICD-10) Assistant

Please enter provider notes in the text box below and click **Send** to analyze.

**Tips:**
- Provide detailed clinical documentation
- Include symptoms, diagnoses, and procedures
- Be specific about treatments and prescriptions

**How to use:**
1. Select an example from the sidebar, or
2. Upload documents via the Upload button
3. Type your own clinical notes below
4. Click the **Send** button
5. Review the ICD-10 and CPT codes generated
"""

def format_complete_response(result):
    """Format complete analysis response"""
    output = "---\n\n"
    
    if result.get("overall_summary"):
        output += f"### πŸ“‹ Overall Summary\n\n{result['overall_summary']}\n\n---\n\n"
    
    output += "### πŸ₯ ICD-10 Diagnostic Codes\n\n"
    icd_codes = result.get("icd_codes", [])
    
    if icd_codes:
        for idx, icd in enumerate(icd_codes, 1):
            output += f"**{idx}. {icd.get('code', 'N/A')}** - {icd.get('description', 'N/A')}\n\n"
            output += f"*Explanation:* {icd.get('explanation', 'N/A')}\n\n"
    else:
        output += "*No ICD-10 codes identified*\n\n"
    
    output += "---\n\n"
    
    output += "### πŸ’Ό CPT Procedure Codes\n\n"
    cpt_codes = result.get("cpt_codes", [])
    
    if cpt_codes:
        for idx, cpt in enumerate(cpt_codes, 1):
            output += f"**{idx}. {cpt.get('code', 'N/A')}** - {cpt.get('description', 'N/A')}\n\n"
            output += f"*Explanation:* {cpt.get('explanation', 'N/A')}\n\n"
    else:
        output += "*No CPT codes identified*\n\n"
    
    return output

# ==================== Example Notes ====================

EXAMPLES = {
    "Acute Bronchitis": """Patient presents with acute bronchitis. Cough for 5 days, productive with yellow sputum. Lung exam reveals diffuse wheezing. Prescribed azithromycin 500mg.""",
    
    "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.""",
    
    "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.""",
}

def load_example(example_name):
    """Load example provider notes"""
    return EXAMPLES.get(example_name, "")

# ==================== Load External CSS ====================

def load_css():
    """Load external CSS file"""
    css_path = os.path.join(os.path.dirname(__file__), "assets", "styles.css")
    try:
        with open(css_path, "r", encoding="utf-8") as f:
            return f.read()
    except FileNotFoundError:
        print("Warning: styles.css not found")
        return ""

# ==================== Gradio Interface ====================

with gr.Blocks(css=load_css(), theme=gr.themes.Soft(), title="Medical Coding (ICD-10) Assistant") as demo:
    
    api_url_state = gr.State(value="https://Distopia22-icd-cpt-coding-api.hf.space")
    
    # Header
    gr.HTML("""
        <div class="header-container">
            <h1>πŸ₯ Medical Coding (ICD-10) Assistant</h1>
            <p>AI-Powered Medical Coding Analysis using Groq LLaMA 3.3 70B</p>
        </div>
    """)
    
    with gr.Row(elem_classes="main-container"):
        
        # Left Sidebar
        with gr.Column(scale=1, min_width=280, elem_classes="sidebar"):
            gr.HTML('<div class="sidebar-title">πŸ“š Example Cases</div>')
            
            example_buttons = {}
            for example_name in EXAMPLES.keys():
                btn = gr.Button(
                    f"πŸ“„ {example_name}",
                    elem_classes="example-btn"
                )
                example_buttons[example_name] = btn
            
            gr.Markdown("---")
            
            # Upload Document Section - Redirects to API Docs
            gr.HTML('<div class="sidebar-title">πŸ“€ Upload Document</div>')
            
            gr.HTML("""
                <a href="https://distopia22-icd-cpt-coding-api-backend.hf.space/docs" target="_blank" style="text-decoration: none;">
                    <button class="upload-redirect-button">
                        πŸ“ Upload via API Docs
                    </button>
                </a>
                <div style="background: rgba(255,255,255,0.1); padding: 10px; border-radius: 8px; margin-top: 10px;">
                    <p style="color: #e0f7f4; font-size: 0.8rem; margin: 5px 0; text-align: center;">
                        πŸ“ Only .txt format allowed
                    </p>
                    <p style="color: #ffffff; font-size: 0.75rem; margin: 5px 0; text-align: center; opacity: 0.7;">
                        Click button to upload files
                    </p>
                </div>
            """)
        
        # Right Chat Area
        with gr.Column(scale=3, elem_classes="chat-container"):
            
            output_area = gr.Markdown(
                value=generate_empty_response(),
                elem_classes="output-area",
                label=""
            )
            
            with gr.Group(elem_classes="input-container"):
                with gr.Row():
                    provider_notes_input = gr.Textbox(
                        label="",
                        placeholder="Enter clinical provider notes here...",
                        lines=3,
                        max_lines=5,
                        show_label=False,
                        elem_classes="prompt-input"
                    )
                
                with gr.Row():
                    send_btn = gr.Button("πŸš€ Send", elem_classes="send-button", size="sm")
                    clear_btn = gr.Button("πŸ—‘οΈ Clear", elem_classes="clear-button", size="sm")
    
    # Footer
    gr.HTML("""
        <div class="footer">
            <p>Powered by <strong>Groq LLaMA 3.3 70B</strong> | <strong>FastAPI</strong> | <strong>Gradio</strong></p>
            <p>Β© 2025 Medical Coding Assistant - Secure & HIPAA Compliant</p>
        </div>
    """)
    
    # ==================== Event Handlers ====================
    
    # Example button clicks
    for example_name, btn in example_buttons.items():
        btn.click(
            fn=lambda name=example_name: load_example(name),
            outputs=[provider_notes_input]
        )
    
    # Send button - Analyze notes
    send_btn.click(
        fn=analyze_provider_notes,
        inputs=[provider_notes_input, api_url_state],
        outputs=[output_area]
    )
    
    # Clear button
    clear_btn.click(
        fn=lambda: ("", generate_empty_response()),
        outputs=[provider_notes_input, output_area]
    )

# Launch
if __name__ == "__main__":
    demo.launch(
        server_name="0.0.0.0",
        server_port=7860,
        show_error=True
    )