uumerrr684 commited on
Commit
a8131ef
Β·
verified Β·
1 Parent(s): 7ae48d4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +293 -364
app.py CHANGED
@@ -1,7 +1,7 @@
1
  #!/usr/bin/env python3
2
  """
3
- Hybrid AI Assistant - ChatGPT Style Full Screen Interface
4
- A full-screen ChatGPT clone with healthcare billing expertise
5
  """
6
 
7
  import os
@@ -39,8 +39,6 @@ class ConversationContext:
39
  messages: List[Dict[str, str]] = field(default_factory=list)
40
  detected_codes: List[str] = field(default_factory=list)
41
  last_topic: Optional[str] = None
42
- chat_history: List[Dict] = field(default_factory=list)
43
- current_chat_id: str = "chat_1"
44
 
45
  # ============= Healthcare Billing Database =============
46
 
@@ -116,6 +114,41 @@ class BillingCodesDB:
116
  code_type='HCPCS',
117
  additional_info='Cyanocobalamin up to 1000 mcg.',
118
  category='Injections'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  )
120
  }
121
 
@@ -165,9 +198,14 @@ class HybridAIAssistant:
165
  def detect_intent(self, message: str) -> Dict[str, Any]:
166
  """Detect if the message is about billing codes or general conversation"""
167
  lower_msg = message.lower()
 
 
168
  codes = self.billing_db.search_codes(message)
169
 
170
- billing_keywords = ['code', 'cpt', 'hcpcs', 'icd', 'drg', 'billing', 'medical code']
 
 
 
171
  is_billing = any(keyword in lower_msg for keyword in billing_keywords) or len(codes) > 0
172
 
173
  return {
@@ -181,21 +219,21 @@ class HybridAIAssistant:
181
  responses = []
182
 
183
  if codes:
184
- for code in codes[:3]:
185
  info = self.billing_db.lookup(code)
186
  if info:
187
- response = f"### {info.code} ({info.code_type})\n\n"
188
- response += f"**Description:** {info.description}\n\n"
189
  if info.additional_info:
190
- response += f"**Details:** {info.additional_info}\n\n"
191
  if info.category:
192
- response += f"**Category:** {info.category}\n"
193
  responses.append(response)
194
 
195
  if responses:
196
  final_response = "I found information about the billing code(s) you mentioned:\n\n"
197
- final_response += "\n---\n\n".join(responses)
198
- final_response += "\n\nπŸ’‘ Need more details? Feel free to ask specific questions about these codes!"
199
  return final_response
200
  else:
201
  return self.get_general_response(message, billing_context=True)
@@ -203,20 +241,24 @@ class HybridAIAssistant:
203
  def get_general_response(self, message: str, billing_context: bool = False) -> str:
204
  """Get response from OpenRouter API for general queries"""
205
 
 
206
  system_prompt = """You are a helpful, friendly AI assistant with expertise in healthcare billing codes.
207
  You can assist with any topic - from casual conversation to complex questions.
208
  When discussing medical billing codes, you provide accurate, detailed information.
209
- Be conversational, helpful, and engaging. Format your responses with markdown for better readability.
210
- Use headers (###), bold (**text**), and bullet points where appropriate."""
211
 
212
  if billing_context:
213
  system_prompt += "\nThe user is asking about medical billing. Provide helpful information even if you don't have specific code details."
214
 
 
215
  messages = [{'role': 'system', 'content': system_prompt}]
216
 
 
217
  for msg in self.context.messages[-10:]:
218
  messages.append(msg)
219
 
 
220
  messages.append({'role': 'user', 'content': message})
221
 
222
  try:
@@ -236,9 +278,11 @@ class HybridAIAssistant:
236
  result = response.json()
237
  ai_response = result['choices'][0]['message']['content']
238
 
 
239
  self.context.messages.append({'role': 'user', 'content': message})
240
  self.context.messages.append({'role': 'assistant', 'content': ai_response})
241
 
 
242
  if len(self.context.messages) > 20:
243
  self.context.messages = self.context.messages[-20:]
244
 
@@ -256,7 +300,8 @@ class HybridAIAssistant:
256
  fallbacks = [
257
  "I'm having trouble connecting right now, but I'm still here to help! Could you rephrase your question?",
258
  "Let me think about that differently. What specific aspect would you like to know more about?",
259
- "That's an interesting question! While I process that, is there anything specific you'd like to explore?"
 
260
  ]
261
  return random.choice(fallbacks)
262
 
@@ -265,8 +310,10 @@ class HybridAIAssistant:
265
  if not message.strip():
266
  return "Feel free to ask me anything! I can help with general questions or healthcare billing codes. 😊"
267
 
 
268
  intent = self.detect_intent(message)
269
 
 
270
  if intent['is_billing'] and intent['codes_found']:
271
  return self.handle_billing_query(message, intent['codes_found'])
272
  else:
@@ -276,411 +323,273 @@ class HybridAIAssistant:
276
  """Reset conversation context"""
277
  self.context = ConversationContext()
278
 
279
- # ============= Create ChatGPT-Style Interface =============
280
 
281
  def create_interface():
282
  assistant = HybridAIAssistant()
283
 
284
- # Full-screen ChatGPT CSS
285
  custom_css = """
286
- /* Full screen layout */
287
  .gradio-container {
288
- margin: 0 !important;
289
- padding: 0 !important;
290
- width: 100vw !important;
291
- max-width: 100vw !important;
292
- height: 100vh !important;
293
- display: flex !important;
294
- flex-direction: column !important;
295
- font-family: 'SΓΆhne', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
296
- background: #f9f9f9 !important;
297
  }
298
 
299
- /* Remove all Gradio default spacing */
300
- .contain, .wrapper, .wrap, .block {
301
- border: none !important;
302
- background: transparent !important;
 
 
 
303
  }
304
 
305
- /* Main container layout */
306
- .main-container {
307
- display: flex;
308
- height: 100vh;
309
- width: 100vw;
310
- overflow: hidden;
311
- background: #fff;
312
- }
313
-
314
- /* Sidebar */
315
- .sidebar {
316
- width: 260px;
317
- background: #202123;
318
  color: white;
319
- padding: 0;
320
- display: flex;
321
- flex-direction: column;
322
- height: 100vh;
323
- overflow-y: auto;
324
- }
325
-
326
- .sidebar-header {
327
- padding: 12px;
328
- border-bottom: 1px solid rgba(255,255,255,0.1);
329
- }
330
-
331
- .new-chat-btn {
332
- width: 100%;
333
- padding: 12px 16px;
334
- background: transparent;
335
- border: 1px solid rgba(255,255,255,0.2);
336
- color: white;
337
- border-radius: 6px;
338
- cursor: pointer;
339
- font-size: 14px;
340
  display: flex;
341
  align-items: center;
342
- gap: 12px;
343
- transition: background 0.2s;
344
- }
345
-
346
- .new-chat-btn:hover {
347
- background: rgba(255,255,255,0.1);
348
- }
349
-
350
- .chat-history {
351
- flex: 1;
352
- padding: 8px;
353
- overflow-y: auto;
354
- }
355
-
356
- .chat-item {
357
- padding: 12px 16px;
358
- margin: 2px 0;
359
- border-radius: 6px;
360
- cursor: pointer;
361
- font-size: 14px;
362
- color: rgba(255,255,255,0.8);
363
- white-space: nowrap;
364
- overflow: hidden;
365
- text-overflow: ellipsis;
366
- transition: background 0.2s;
367
- }
368
-
369
- .chat-item:hover {
370
- background: rgba(255,255,255,0.05);
371
- }
372
-
373
- .chat-item.active {
374
- background: rgba(255,255,255,0.1);
375
- color: white;
376
  }
377
 
378
- /* Main chat area */
379
- .chat-container {
380
- flex: 1;
381
- display: flex;
382
- flex-direction: column;
383
- background: #fff;
384
- position: relative;
385
  }
386
 
387
- /* Chat messages area */
388
  #chatbot {
389
- flex: 1;
390
- overflow-y: auto;
391
- padding: 0;
392
- background: #fff;
393
- display: flex;
394
- flex-direction: column;
395
- }
396
-
397
- #chatbot > .wrap {
398
- max-width: 48rem;
399
- margin: 0 auto;
400
- width: 100%;
401
- padding: 2rem 1rem;
402
  }
403
 
404
  /* Message styling */
405
  .message {
406
- padding: 1.5rem 0;
407
- border-bottom: 1px solid #f0f0f0;
408
- }
409
-
410
- .message.user {
411
- background: #fff;
412
- }
413
-
414
- .message.assistant {
415
- background: #f7f7f8;
416
- }
417
-
418
- .message-content {
419
- max-width: 48rem;
420
- margin: 0 auto;
421
- display: flex;
422
- gap: 1.5rem;
423
- padding: 0 1rem;
424
- }
425
-
426
- .avatar {
427
- width: 32px;
428
- height: 32px;
429
- border-radius: 4px;
430
- background: #5436DA;
431
- display: flex;
432
- align-items: center;
433
- justify-content: center;
434
- color: white;
435
- font-weight: bold;
436
- font-size: 14px;
437
- flex-shrink: 0;
438
  }
439
 
440
- .avatar.assistant {
441
- background: #19c37d;
 
 
442
  }
443
 
444
- .message-text {
445
- flex: 1;
446
- line-height: 1.6;
447
- font-size: 15px;
448
- color: #2d2d2d;
449
  }
450
 
451
- .message-text h1 { font-size: 1.8em; margin: 1em 0 0.5em; }
452
- .message-text h2 { font-size: 1.5em; margin: 1em 0 0.5em; }
453
- .message-text h3 { font-size: 1.2em; margin: 1em 0 0.5em; font-weight: 600; }
454
- .message-text p { margin: 0.8em 0; }
455
- .message-text ul, .message-text ol { margin: 0.8em 0; padding-left: 1.5em; }
456
- .message-text li { margin: 0.4em 0; }
457
- .message-text code {
458
- background: #f3f4f6;
459
- padding: 2px 6px;
460
- border-radius: 4px;
461
- font-family: 'Consolas', monospace;
462
- font-size: 0.9em;
463
- }
464
- .message-text pre {
465
- background: #1e1e1e;
466
- color: #d4d4d4;
467
- padding: 1em;
468
- border-radius: 6px;
469
- overflow-x: auto;
470
- margin: 1em 0;
471
- }
472
- .message-text strong { font-weight: 600; }
473
-
474
  /* Input area */
475
- .input-container {
476
- border-top: 1px solid #e5e5e5;
477
- background: #fff;
478
- padding: 1rem 0;
479
- }
480
-
481
- .input-wrapper {
482
- max-width: 48rem;
483
- margin: 0 auto;
484
- padding: 0 1rem;
485
- }
486
-
487
  #input-box {
488
- width: 100%;
489
- border: 1px solid #d9d9e3;
490
- border-radius: 12px;
491
- padding: 12px 48px 12px 16px;
492
- font-size: 15px;
493
- resize: none;
494
- background: #fff;
495
- color: #2d2d2d;
496
- outline: none;
497
- box-shadow: 0 0 0 2px transparent;
498
- transition: all 0.2s;
499
  }
500
 
501
  #input-box:focus {
502
- border-color: #10a37f;
503
- box-shadow: 0 0 0 2px rgba(16,163,127,0.1);
504
- }
505
-
506
- .send-button {
507
- position: absolute;
508
- right: 12px;
509
- bottom: 12px;
510
- background: #10a37f;
511
- color: white;
512
- border: none;
513
- border-radius: 8px;
514
- padding: 8px 12px;
515
- cursor: pointer;
516
- font-size: 14px;
517
- font-weight: 500;
518
- transition: background 0.2s;
519
  }
520
 
521
- .send-button:hover {
522
- background: #0d8f6e;
523
- }
524
-
525
- .send-button:disabled {
526
- background: #e5e5e5;
527
- cursor: not-allowed;
528
- }
529
-
530
- /* Welcome screen */
531
- .welcome-screen {
532
- max-width: 48rem;
533
- margin: 0 auto;
534
- padding: 3rem 1rem;
535
- text-align: center;
536
- }
537
-
538
- .welcome-title {
539
- font-size: 2rem;
540
- font-weight: 600;
541
- color: #2d2d2d;
542
- margin-bottom: 1rem;
543
- }
544
-
545
- .welcome-subtitle {
546
- font-size: 1rem;
547
- color: #6e6e80;
548
- margin-bottom: 3rem;
549
- }
550
-
551
- .example-grid {
552
- display: grid;
553
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
554
- gap: 12px;
555
- margin-top: 2rem;
556
- }
557
-
558
- .example-card {
559
- background: #f7f7f8;
560
- border: 1px solid #e5e5e5;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
  border-radius: 12px;
562
- padding: 16px;
563
- cursor: pointer;
564
- transition: all 0.2s;
565
- text-align: left;
566
  }
567
 
568
- .example-card:hover {
569
- background: #ececf1;
570
- border-color: #d9d9e3;
571
- }
572
-
573
- .example-title {
574
- font-weight: 600;
575
- font-size: 14px;
576
- color: #2d2d2d;
577
- margin-bottom: 4px;
578
- }
579
-
580
- .example-text {
581
- font-size: 13px;
582
- color: #6e6e80;
583
- }
584
-
585
- /* Responsive */
586
  @media (max-width: 768px) {
587
- .sidebar {
588
- display: none;
589
  }
590
 
591
- .input-wrapper {
592
- padding: 0 0.5rem;
593
  }
594
 
595
- #chatbot > .wrap {
596
- padding: 1rem 0.5rem;
 
597
  }
598
  }
599
  """
600
 
601
- with gr.Blocks(css=custom_css, theme=gr.themes.Base(), title="AI Assistant") as app:
602
-
603
- # Welcome message formatted with markdown
604
- welcome_html = """
605
- <div class="welcome-screen">
606
- <h1 class="welcome-title">AI Assistant Plus</h1>
607
- <p class="welcome-subtitle">Your intelligent companion for any question + Healthcare Billing Expert</p>
608
-
609
- <div class="example-grid">
610
- <div class="example-card" onclick="document.querySelector('#input-box textarea').value='What is medical billing code A0429?'; document.querySelector('#input-box textarea').dispatchEvent(new Event('input'));">
611
- <div class="example-title">πŸ₯ Medical Billing</div>
612
- <div class="example-text">"Explain code A0429"</div>
613
- </div>
614
- <div class="example-card" onclick="document.querySelector('#input-box textarea').value='How does machine learning work?'; document.querySelector('#input-box textarea').dispatchEvent(new Event('input'));">
615
- <div class="example-title">πŸ€– Learn</div>
616
- <div class="example-text">"Explain ML simply"</div>
617
- </div>
618
- <div class="example-card" onclick="document.querySelector('#input-box textarea').value='Write a professional email template'; document.querySelector('#input-box textarea').dispatchEvent(new Event('input'));">
619
- <div class="example-title">✍️ Write</div>
620
- <div class="example-text">"Draft an email"</div>
621
- </div>
622
- <div class="example-card" onclick="document.querySelector('#input-box textarea').value='Give me a healthy recipe idea'; document.querySelector('#input-box textarea').dispatchEvent(new Event('input'));">
623
- <div class="example-title">🍳 Create</div>
624
- <div class="example-text">"Recipe ideas"</div>
625
- </div>
626
- </div>
627
- </div>
628
- """
629
-
630
- # Main layout with HTML structure
631
  gr.HTML("""
632
- <div class="main-container">
633
- <!-- Sidebar -->
634
- <div class="sidebar">
635
- <div class="sidebar-header">
636
- <button class="new-chat-btn">
637
- <span>+</span>
638
- <span>New chat</span>
639
- </button>
640
- </div>
641
- <div class="chat-history">
642
- <div class="chat-item active">Healthcare Billing Expert</div>
643
- <div class="chat-item">General Assistant</div>
644
- <div class="chat-item">Previous Chat</div>
645
- </div>
646
- </div>
647
-
648
- <!-- Main chat area -->
649
- <div class="chat-container">
650
  """)
651
 
652
- # Chat interface
653
  chatbot_ui = gr.Chatbot(
654
- value=[],
 
 
 
 
 
655
  elem_id="chatbot",
656
  show_label=False,
657
  type="messages",
658
- height=600,
659
- render_markdown=True,
660
- avatar_images=None
661
  )
662
 
663
- # Set initial welcome message
664
- chatbot_ui.value = [
665
- {
666
- "role": "assistant",
667
- "content": welcome_html
668
- }
669
- ]
 
 
 
 
 
 
 
 
 
 
 
 
670
 
671
- # Input area
672
- with gr.Row(elem_classes="input-container"):
673
- with gr.Column(elem_classes="input-wrapper"):
674
- msg = gr.Textbox(
675
- placeholder="Message AI Assistant...",
676
- show_label=False,
677
- elem_id="input-box",
678
- lines=1,
679
- max_lines=5,
680
- autofocus=True
681
- )
682
 
683
- gr.HTML("</div></div>")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
684
 
685
  # Event handlers
686
  def respond(message, chat_history):
@@ -696,8 +605,29 @@ def create_interface():
696
 
697
  return "", chat_history
698
 
 
 
 
 
 
 
 
 
699
  # Connect events
700
  msg.submit(respond, [msg, chatbot_ui], [msg, chatbot_ui])
 
 
 
 
 
 
 
 
 
 
 
 
 
701
 
702
  return app
703
 
@@ -707,6 +637,5 @@ if __name__ == "__main__":
707
  app.launch(
708
  server_name="0.0.0.0",
709
  server_port=7860,
710
- share=False,
711
- favicon_path=None
712
  )
 
1
  #!/usr/bin/env python3
2
  """
3
+ Hybrid AI Assistant - General Purpose + Healthcare Billing Expert
4
+ A ChatGPT-style assistant that can handle any conversation while specializing in healthcare billing codes
5
  """
6
 
7
  import os
 
39
  messages: List[Dict[str, str]] = field(default_factory=list)
40
  detected_codes: List[str] = field(default_factory=list)
41
  last_topic: Optional[str] = None
 
 
42
 
43
  # ============= Healthcare Billing Database =============
44
 
 
114
  code_type='HCPCS',
115
  additional_info='Cyanocobalamin up to 1000 mcg.',
116
  category='Injections'
117
+ ),
118
+ '80053': CodeInfo(
119
+ code='80053',
120
+ description='Comprehensive metabolic panel',
121
+ code_type='CPT',
122
+ additional_info='14 blood tests including glucose, kidney, and liver function.',
123
+ category='Laboratory'
124
+ ),
125
+ '70450': CodeInfo(
126
+ code='70450',
127
+ description='CT head/brain without contrast',
128
+ code_type='CPT',
129
+ additional_info='Computed tomography of head without contrast material.',
130
+ category='Radiology'
131
+ ),
132
+ '90837': CodeInfo(
133
+ code='90837',
134
+ description='Psychotherapy, 60 minutes',
135
+ code_type='CPT',
136
+ additional_info='Individual psychotherapy session.',
137
+ category='Mental Health'
138
+ ),
139
+ '36415': CodeInfo(
140
+ code='36415',
141
+ description='Venipuncture (blood draw)',
142
+ code_type='CPT',
143
+ additional_info='Collection of blood by needle.',
144
+ category='Laboratory'
145
+ ),
146
+ '99282': CodeInfo(
147
+ code='99282',
148
+ description='Emergency department visit, low-moderate severity',
149
+ code_type='CPT',
150
+ additional_info='ED visit for problems of low to moderate severity.',
151
+ category='Emergency'
152
  )
153
  }
154
 
 
198
  def detect_intent(self, message: str) -> Dict[str, Any]:
199
  """Detect if the message is about billing codes or general conversation"""
200
  lower_msg = message.lower()
201
+
202
+ # Check for billing codes in the message
203
  codes = self.billing_db.search_codes(message)
204
 
205
+ # Keywords that suggest billing/medical coding questions
206
+ billing_keywords = ['code', 'cpt', 'hcpcs', 'icd', 'drg', 'billing', 'medical code',
207
+ 'healthcare code', 'diagnosis code', 'procedure code']
208
+
209
  is_billing = any(keyword in lower_msg for keyword in billing_keywords) or len(codes) > 0
210
 
211
  return {
 
219
  responses = []
220
 
221
  if codes:
222
+ for code in codes[:3]: # Limit to first 3 codes
223
  info = self.billing_db.lookup(code)
224
  if info:
225
+ response = f"**{info.code} ({info.code_type})**\n"
226
+ response += f"πŸ“‹ **Description:** {info.description}\n"
227
  if info.additional_info:
228
+ response += f"ℹ️ **Details:** {info.additional_info}\n"
229
  if info.category:
230
+ response += f"🏷️ **Category:** {info.category}\n"
231
  responses.append(response)
232
 
233
  if responses:
234
  final_response = "I found information about the billing code(s) you mentioned:\n\n"
235
+ final_response += "\n---\n".join(responses)
236
+ final_response += "\n\nπŸ’‘ **Need more details?** Feel free to ask specific questions about these codes!"
237
  return final_response
238
  else:
239
  return self.get_general_response(message, billing_context=True)
 
241
  def get_general_response(self, message: str, billing_context: bool = False) -> str:
242
  """Get response from OpenRouter API for general queries"""
243
 
244
+ # Prepare system prompt
245
  system_prompt = """You are a helpful, friendly AI assistant with expertise in healthcare billing codes.
246
  You can assist with any topic - from casual conversation to complex questions.
247
  When discussing medical billing codes, you provide accurate, detailed information.
248
+ Be conversational, helpful, and engaging. Use emojis occasionally to be friendly.
249
+ Keep responses concise but informative."""
250
 
251
  if billing_context:
252
  system_prompt += "\nThe user is asking about medical billing. Provide helpful information even if you don't have specific code details."
253
 
254
+ # Build conversation history for context
255
  messages = [{'role': 'system', 'content': system_prompt}]
256
 
257
+ # Add recent conversation history (last 5 exchanges)
258
  for msg in self.context.messages[-10:]:
259
  messages.append(msg)
260
 
261
+ # Add current message
262
  messages.append({'role': 'user', 'content': message})
263
 
264
  try:
 
278
  result = response.json()
279
  ai_response = result['choices'][0]['message']['content']
280
 
281
+ # Update context
282
  self.context.messages.append({'role': 'user', 'content': message})
283
  self.context.messages.append({'role': 'assistant', 'content': ai_response})
284
 
285
+ # Keep only last 20 messages in context
286
  if len(self.context.messages) > 20:
287
  self.context.messages = self.context.messages[-20:]
288
 
 
300
  fallbacks = [
301
  "I'm having trouble connecting right now, but I'm still here to help! Could you rephrase your question?",
302
  "Let me think about that differently. What specific aspect would you like to know more about?",
303
+ "That's an interesting question! While I process that, is there anything specific you'd like to explore?",
304
+ "I'm here to help! Could you provide a bit more detail about what you're looking for?"
305
  ]
306
  return random.choice(fallbacks)
307
 
 
310
  if not message.strip():
311
  return "Feel free to ask me anything! I can help with general questions or healthcare billing codes. 😊"
312
 
313
+ # Detect intent
314
  intent = self.detect_intent(message)
315
 
316
+ # Route to appropriate handler
317
  if intent['is_billing'] and intent['codes_found']:
318
  return self.handle_billing_query(message, intent['codes_found'])
319
  else:
 
323
  """Reset conversation context"""
324
  self.context = ConversationContext()
325
 
326
+ # ============= Gradio Interface =============
327
 
328
  def create_interface():
329
  assistant = HybridAIAssistant()
330
 
331
+ # ChatGPT-style CSS
332
  custom_css = """
333
+ /* Main container */
334
  .gradio-container {
335
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif !important;
336
+ max-width: 900px !important;
337
+ margin: auto !important;
338
+ background: #ffffff !important;
 
 
 
 
 
339
  }
340
 
341
+ /* Header styling */
342
+ .header-container {
343
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
344
+ padding: 2rem;
345
+ border-radius: 15px 15px 0 0;
346
+ margin-bottom: 0;
347
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
348
  }
349
 
350
+ .header-title {
 
 
 
 
 
 
 
 
 
 
 
 
351
  color: white;
352
+ font-size: 2rem;
353
+ font-weight: 700;
354
+ margin: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
355
  display: flex;
356
  align-items: center;
357
+ justify-content: center;
358
+ gap: 0.5rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
359
  }
360
 
361
+ .header-subtitle {
362
+ color: rgba(255,255,255,0.9);
363
+ font-size: 1rem;
364
+ margin-top: 0.5rem;
365
+ text-align: center;
 
 
366
  }
367
 
368
+ /* Chat container */
369
  #chatbot {
370
+ height: 500px !important;
371
+ border: 1px solid #e5e7eb !important;
372
+ border-radius: 12px !important;
373
+ box-shadow: 0 2px 6px rgba(0,0,0,0.05) !important;
374
+ background: #ffffff !important;
 
 
 
 
 
 
 
 
375
  }
376
 
377
  /* Message styling */
378
  .message {
379
+ padding: 1rem !important;
380
+ margin: 0.5rem !important;
381
+ border-radius: 12px !important;
382
+ font-size: 15px !important;
383
+ line-height: 1.6 !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
384
  }
385
 
386
+ .user-message {
387
+ background: #f3f4f6 !important;
388
+ border: 1px solid #e5e7eb !important;
389
+ margin-left: 20% !important;
390
  }
391
 
392
+ .bot-message {
393
+ background: #ffffff !important;
394
+ border: 1px solid #e5e7eb !important;
395
+ margin-right: 20% !important;
 
396
  }
397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
398
  /* Input area */
 
 
 
 
 
 
 
 
 
 
 
 
399
  #input-box {
400
+ border: 2px solid #e5e7eb !important;
401
+ border-radius: 12px !important;
402
+ padding: 14px 16px !important;
403
+ font-size: 15px !important;
404
+ transition: all 0.3s ease !important;
405
+ background: #ffffff !important;
 
 
 
 
 
406
  }
407
 
408
  #input-box:focus {
409
+ border-color: #667eea !important;
410
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important;
411
+ outline: none !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
412
  }
413
 
414
+ /* Buttons */
415
+ .primary-btn {
416
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
417
+ color: white !important;
418
+ border: none !important;
419
+ border-radius: 10px !important;
420
+ padding: 12px 24px !important;
421
+ font-weight: 600 !important;
422
+ font-size: 15px !important;
423
+ cursor: pointer !important;
424
+ transition: transform 0.2s ease !important;
425
+ }
426
+
427
+ .primary-btn:hover {
428
+ transform: translateY(-1px) !important;
429
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3) !important;
430
+ }
431
+
432
+ .secondary-btn {
433
+ background: #f3f4f6 !important;
434
+ color: #374151 !important;
435
+ border: 1px solid #e5e7eb !important;
436
+ border-radius: 10px !important;
437
+ padding: 10px 20px !important;
438
+ font-weight: 500 !important;
439
+ cursor: pointer !important;
440
+ transition: all 0.2s ease !important;
441
+ }
442
+
443
+ .secondary-btn:hover {
444
+ background: #e5e7eb !important;
445
+ border-color: #d1d5db !important;
446
+ }
447
+
448
+ /* Example chips */
449
+ .example-chip {
450
+ display: inline-block !important;
451
+ background: #ffffff !important;
452
+ border: 1px solid #e5e7eb !important;
453
+ border-radius: 20px !important;
454
+ padding: 8px 16px !important;
455
+ margin: 4px !important;
456
+ font-size: 14px !important;
457
+ color: #4b5563 !important;
458
+ cursor: pointer !important;
459
+ transition: all 0.2s ease !important;
460
+ }
461
+
462
+ .example-chip:hover {
463
+ background: #f9fafb !important;
464
+ border-color: #667eea !important;
465
+ color: #667eea !important;
466
+ transform: translateY(-1px) !important;
467
+ }
468
+
469
+ /* Info cards */
470
+ .info-card {
471
+ background: linear-gradient(135deg, #f6f8fb 0%, #f1f5f9 100%);
472
+ border: 1px solid #e5e7eb;
473
  border-radius: 12px;
474
+ padding: 1rem;
475
+ margin: 1rem 0;
 
 
476
  }
477
 
478
+ /* Responsive design */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
  @media (max-width: 768px) {
480
+ .gradio-container {
481
+ padding: 0 !important;
482
  }
483
 
484
+ .header-title {
485
+ font-size: 1.5rem;
486
  }
487
 
488
+ .user-message, .bot-message {
489
+ margin-left: 5% !important;
490
+ margin-right: 5% !important;
491
  }
492
  }
493
  """
494
 
495
+ with gr.Blocks(css=custom_css, theme=gr.themes.Base()) as app:
496
+ # Header
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
497
  gr.HTML("""
498
+ <div class="header-container">
499
+ <h1 class="header-title">
500
+ <span>πŸ€–</span>
501
+ <span>AI Assistant</span>
502
+ <span style="font-size: 0.8em; background: rgba(255,255,255,0.2); padding: 2px 8px; border-radius: 12px;">PLUS</span>
503
+ </h1>
504
+ <p class="header-subtitle">Your intelligent companion for any question + Healthcare Billing Expert</p>
505
+ </div>
 
 
 
 
 
 
 
 
 
 
506
  """)
507
 
508
+ # Main chat interface
509
  chatbot_ui = gr.Chatbot(
510
+ value=[
511
+ {
512
+ "role": "assistant",
513
+ "content": "πŸ‘‹ **Hello! I'm your AI Assistant!**\n\nI can help you with:\n\nπŸ₯ **Healthcare Billing Codes** - I'm an expert in CPT, HCPCS, ICD-10, and DRG codes\nπŸ’¬ **General Conversation** - Ask me anything!\nπŸ“š **Learning & Education** - Help with various topics\n✍️ **Writing & Creation** - Stories, emails, ideas\nπŸ”§ **Problem Solving** - Let's work through challenges together\n\n**Try asking:**\nβ€’ 'What is billing code A0429?'\nβ€’ 'Help me write an email'\nβ€’ 'Explain quantum physics simply'\nβ€’ 'What's the weather like?'\n\nHow can I assist you today? 😊"
514
+ }
515
+ ],
516
  elem_id="chatbot",
517
  show_label=False,
518
  type="messages",
519
+ height=500
 
 
520
  )
521
 
522
+ # Input section
523
+ with gr.Row():
524
+ msg = gr.Textbox(
525
+ placeholder="Ask me anything... (e.g., 'Explain code 99213' or 'Help me write a story')",
526
+ show_label=False,
527
+ elem_id="input-box",
528
+ scale=5,
529
+ lines=1,
530
+ max_lines=5
531
+ )
532
+ send_btn = gr.Button("Send", elem_classes="primary-btn", scale=1)
533
+
534
+ # Quick examples
535
+ gr.HTML("<div style='text-align: center; margin: 1rem 0; color: #6b7280; font-size: 14px;'>Quick Examples</div>")
536
+
537
+ with gr.Row():
538
+ ex_col1 = gr.Column(scale=1)
539
+ ex_col2 = gr.Column(scale=1)
540
+ ex_col3 = gr.Column(scale=1)
541
 
542
+ with ex_col1:
543
+ gr.HTML("<div style='color: #667eea; font-weight: 600; font-size: 13px; margin-bottom: 8px;'>πŸ₯ Medical Billing</div>")
544
+ ex1 = gr.Button("What is code A0429?", elem_classes="example-chip", size="sm")
545
+ ex2 = gr.Button("Explain CPT 99213", elem_classes="example-chip", size="sm")
546
+ ex3 = gr.Button("DRG 470 details", elem_classes="example-chip", size="sm")
 
 
 
 
 
 
547
 
548
+ with ex_col2:
549
+ gr.HTML("<div style='color: #667eea; font-weight: 600; font-size: 13px; margin-bottom: 8px;'>πŸ’­ General Questions</div>")
550
+ ex4 = gr.Button("How does AI work?", elem_classes="example-chip", size="sm")
551
+ ex5 = gr.Button("Recipe for pasta", elem_classes="example-chip", size="sm")
552
+ ex6 = gr.Button("Python tutorial", elem_classes="example-chip", size="sm")
553
+
554
+ with ex_col3:
555
+ gr.HTML("<div style='color: #667eea; font-weight: 600; font-size: 13px; margin-bottom: 8px;'>✍️ Creative Help</div>")
556
+ ex7 = gr.Button("Write a poem", elem_classes="example-chip", size="sm")
557
+ ex8 = gr.Button("Email template", elem_classes="example-chip", size="sm")
558
+ ex9 = gr.Button("Story ideas", elem_classes="example-chip", size="sm")
559
+
560
+ # Control buttons
561
+ with gr.Row():
562
+ clear_btn = gr.Button("πŸ”„ New Chat", elem_classes="secondary-btn", size="sm")
563
+ gr.HTML("<div style='flex-grow: 1;'></div>")
564
+ gr.HTML("""
565
+ <div style='text-align: right; color: #6b7280; font-size: 12px;'>
566
+ Powered by GPT-3.5 β€’ Healthcare Billing Database
567
+ </div>
568
+ """)
569
+
570
+ # Footer info
571
+ gr.HTML("""
572
+ <div class="info-card" style="margin-top: 2rem;">
573
+ <div style="display: flex; justify-content: space-around; text-align: center;">
574
+ <div>
575
+ <div style="color: #667eea; font-size: 24px; font-weight: bold;">15+</div>
576
+ <div style="color: #6b7280; font-size: 12px;">Medical Codes</div>
577
+ </div>
578
+ <div>
579
+ <div style="color: #667eea; font-size: 24px; font-weight: bold;">∞</div>
580
+ <div style="color: #6b7280; font-size: 12px;">Topics</div>
581
+ </div>
582
+ <div>
583
+ <div style="color: #667eea; font-size: 24px; font-weight: bold;">24/7</div>
584
+ <div style="color: #6b7280; font-size: 12px;">Available</div>
585
+ </div>
586
+ <div>
587
+ <div style="color: #667eea; font-size: 24px; font-weight: bold;">Fast</div>
588
+ <div style="color: #6b7280; font-size: 12px;">Responses</div>
589
+ </div>
590
+ </div>
591
+ </div>
592
+ """)
593
 
594
  # Event handlers
595
  def respond(message, chat_history):
 
605
 
606
  return "", chat_history
607
 
608
+ def clear_chat():
609
+ assistant.reset_context()
610
+ welcome_msg = {
611
+ "role": "assistant",
612
+ "content": "πŸ‘‹ **Chat cleared! Ready for a new conversation.**\n\nI'm here to help with anything you need - from healthcare billing codes to general questions!\n\nWhat would you like to know? 😊"
613
+ }
614
+ return [welcome_msg]
615
+
616
  # Connect events
617
  msg.submit(respond, [msg, chatbot_ui], [msg, chatbot_ui])
618
+ send_btn.click(respond, [msg, chatbot_ui], [msg, chatbot_ui])
619
+ clear_btn.click(clear_chat, outputs=[chatbot_ui])
620
+
621
+ # Example button handlers
622
+ ex1.click(lambda: "What is healthcare billing code A0429?", outputs=msg)
623
+ ex2.click(lambda: "Can you explain CPT code 99213 in detail?", outputs=msg)
624
+ ex3.click(lambda: "Tell me about DRG 470", outputs=msg)
625
+ ex4.click(lambda: "How does artificial intelligence work?", outputs=msg)
626
+ ex5.click(lambda: "Give me a simple pasta recipe", outputs=msg)
627
+ ex6.click(lambda: "Teach me Python basics", outputs=msg)
628
+ ex7.click(lambda: "Write a short poem about nature", outputs=msg)
629
+ ex8.click(lambda: "Help me write a professional email template", outputs=msg)
630
+ ex9.click(lambda: "Give me creative story ideas", outputs=msg)
631
 
632
  return app
633
 
 
637
  app.launch(
638
  server_name="0.0.0.0",
639
  server_port=7860,
640
+ share=False
 
641
  )