Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
-
Hybrid AI Assistant -
|
| 4 |
-
A
|
| 5 |
"""
|
| 6 |
|
| 7 |
import os
|
|
@@ -39,6 +39,8 @@ 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 |
|
| 43 |
# ============= Healthcare Billing Database =============
|
| 44 |
|
|
@@ -114,41 +116,6 @@ class BillingCodesDB:
|
|
| 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,14 +165,9 @@ class HybridAIAssistant:
|
|
| 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 |
-
|
| 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,21 +181,21 @@ class HybridAIAssistant:
|
|
| 219 |
responses = []
|
| 220 |
|
| 221 |
if codes:
|
| 222 |
-
for code in codes[:3]:
|
| 223 |
info = self.billing_db.lookup(code)
|
| 224 |
if info:
|
| 225 |
-
response = f"
|
| 226 |
-
response += f"
|
| 227 |
if info.additional_info:
|
| 228 |
-
response += f"
|
| 229 |
if info.category:
|
| 230 |
-
response += f"
|
| 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💡
|
| 237 |
return final_response
|
| 238 |
else:
|
| 239 |
return self.get_general_response(message, billing_context=True)
|
|
@@ -241,24 +203,20 @@ class HybridAIAssistant:
|
|
| 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.
|
| 249 |
-
|
| 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,11 +236,9 @@ class HybridAIAssistant:
|
|
| 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,8 +256,7 @@ class HybridAIAssistant:
|
|
| 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,10 +265,8 @@ class HybridAIAssistant:
|
|
| 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,273 +276,411 @@ class HybridAIAssistant:
|
|
| 323 |
"""Reset conversation context"""
|
| 324 |
self.context = ConversationContext()
|
| 325 |
|
| 326 |
-
# =============
|
| 327 |
|
| 328 |
def create_interface():
|
| 329 |
assistant = HybridAIAssistant()
|
| 330 |
|
| 331 |
-
#
|
| 332 |
custom_css = """
|
| 333 |
-
/*
|
| 334 |
.gradio-container {
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
| 338 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 339 |
}
|
| 340 |
|
| 341 |
-
/*
|
| 342 |
-
.
|
| 343 |
-
|
| 344 |
-
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 351 |
color: white;
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 355 |
display: flex;
|
| 356 |
align-items: center;
|
| 357 |
-
|
| 358 |
-
|
| 359 |
}
|
| 360 |
|
| 361 |
-
.
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 366 |
}
|
| 367 |
|
| 368 |
-
/* Chat
|
| 369 |
#chatbot {
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 375 |
}
|
| 376 |
|
| 377 |
/* Message styling */
|
| 378 |
.message {
|
| 379 |
-
padding:
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
|
| 383 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 384 |
}
|
| 385 |
|
| 386 |
-
.
|
| 387 |
-
background: #
|
| 388 |
-
border: 1px solid #e5e7eb !important;
|
| 389 |
-
margin-left: 20% !important;
|
| 390 |
}
|
| 391 |
|
| 392 |
-
.
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
|
|
|
|
| 396 |
}
|
| 397 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 398 |
/* Input area */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 399 |
#input-box {
|
| 400 |
-
|
| 401 |
-
border
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
|
| 405 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 406 |
}
|
| 407 |
|
| 408 |
#input-box:focus {
|
| 409 |
-
border-color: #
|
| 410 |
-
box-shadow: 0 0 0
|
| 411 |
-
outline: none !important;
|
| 412 |
}
|
| 413 |
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
cursor: pointer
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
|
| 460 |
-
|
| 461 |
-
|
| 462 |
-
|
| 463 |
-
|
| 464 |
-
|
| 465 |
-
|
| 466 |
-
|
| 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:
|
| 475 |
-
|
|
|
|
|
|
|
| 476 |
}
|
| 477 |
|
| 478 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 479 |
@media (max-width: 768px) {
|
| 480 |
-
.
|
| 481 |
-
|
| 482 |
}
|
| 483 |
|
| 484 |
-
.
|
| 485 |
-
|
| 486 |
}
|
| 487 |
|
| 488 |
-
|
| 489 |
-
|
| 490 |
-
margin-right: 5% !important;
|
| 491 |
}
|
| 492 |
}
|
| 493 |
"""
|
| 494 |
|
| 495 |
-
with gr.Blocks(css=custom_css, theme=gr.themes.Base()) as app:
|
| 496 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 497 |
gr.HTML("""
|
| 498 |
-
|
| 499 |
-
|
| 500 |
-
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
<
|
| 505 |
-
</
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
""")
|
| 507 |
|
| 508 |
-
#
|
| 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=
|
|
|
|
|
|
|
| 520 |
)
|
| 521 |
|
| 522 |
-
#
|
| 523 |
-
|
| 524 |
-
|
| 525 |
-
|
| 526 |
-
|
| 527 |
-
|
| 528 |
-
|
| 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 |
-
|
| 555 |
-
|
| 556 |
-
|
| 557 |
-
|
| 558 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 559 |
|
| 560 |
-
|
| 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,29 +696,8 @@ def create_interface():
|
|
| 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,5 +707,6 @@ if __name__ == "__main__":
|
|
| 637 |
app.launch(
|
| 638 |
server_name="0.0.0.0",
|
| 639 |
server_port=7860,
|
| 640 |
-
share=False
|
|
|
|
| 641 |
)
|
|
|
|
| 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 |
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 |
code_type='HCPCS',
|
| 117 |
additional_info='Cyanocobalamin up to 1000 mcg.',
|
| 118 |
category='Injections'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
)
|
| 120 |
}
|
| 121 |
|
|
|
|
| 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 |
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 |
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 |
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 |
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 |
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 |
"""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 |
|
| 697 |
return "", chat_history
|
| 698 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 699 |
# Connect events
|
| 700 |
msg.submit(respond, [msg, chatbot_ui], [msg, chatbot_ui])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 701 |
|
| 702 |
return app
|
| 703 |
|
|
|
|
| 707 |
app.launch(
|
| 708 |
server_name="0.0.0.0",
|
| 709 |
server_port=7860,
|
| 710 |
+
share=False,
|
| 711 |
+
favicon_path=None
|
| 712 |
)
|