Ali2206 commited on
Commit
2e5b8b2
Β·
verified Β·
1 Parent(s): 94b553f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +124 -36
app.py CHANGED
@@ -16,6 +16,7 @@ import torch
16
  import gc
17
  from diskcache import Cache
18
  from transformers import AutoTokenizer
 
19
 
20
  # ==================== CONFIGURATION ====================
21
  # Configure logging
@@ -313,12 +314,18 @@ class ClinicalOversightApp:
313
  cleaned = self.text_processor.clean_response(message.content)
314
  if cleaned:
315
  full_response += cleaned + " "
316
- yield {"role": "assistant", "content": full_response}
 
 
 
317
  elif isinstance(chunk, str) and chunk.strip():
318
  cleaned = self.text_processor.clean_response(chunk)
319
  if cleaned:
320
  full_response += cleaned + " "
321
- yield {"role": "assistant", "content": full_response}
 
 
 
322
 
323
  def analyze(self, message: str, history: List[dict], files: List) -> Generator[tuple, None, None]:
324
  """Main analysis pipeline with proper output formatting"""
@@ -329,11 +336,13 @@ class ClinicalOversightApp:
329
 
330
  try:
331
  # Add user message to history
332
- chatbot_output.append({"role": "user", "content": message})
 
 
 
333
  yield (chatbot_output, download_output, final_summary, progress_text)
334
 
335
  # Process uploaded files
336
- .ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 0
337
  extracted = []
338
  file_hash_value = ""
339
 
@@ -354,7 +363,10 @@ class ClinicalOversightApp:
354
  extracted.append({"error": f"Error processing file: {str(e)}"})
355
 
356
  file_hash_value = get_file_hash(files[0].name) if files else ""
357
- chatbot_output.append({"role": "assistant", "content": "βœ… File processing complete"})
 
 
 
358
  progress_text = self._update_progress(len(files), len(files), "Files processed")
359
  yield (chatbot_output, download_output, final_summary, progress_text)
360
 
@@ -373,7 +385,7 @@ are found, state 'No missed diagnoses identified'.
373
  Patient Record (Chunk {chunk_idx}/{len(chunks)}):
374
  {chunk[:1200]}
375
  """
376
- chatbot_output.append({"role": "assistant", "content": ""})
377
  progress_text = self._update_progress(chunk_idx, len(chunks), "Analyzing")
378
  yield (chatbot_output, download_output, final_summary, progress_text)
379
 
@@ -403,10 +415,16 @@ Patient Record (Chunk {chunk_idx}/{len(chunks)}):
403
 
404
  except Exception as e:
405
  logger.error(f"Analysis error: {e}")
406
- chatbot_output.append({"role": "assistant", "content": f"❌ Error: {str(e)}"})
 
 
 
407
  final_summary = f"Error occurred: {str(e)}"
408
  progress_text = {"visible": False}
409
  yield (chatbot_output, download_output, final_summary, progress_text)
 
 
 
410
 
411
  def _update_progress(self, current: int, total: int, stage: str = "") -> Dict[str, Any]:
412
  """Format progress update for UI"""
@@ -414,7 +432,7 @@ Patient Record (Chunk {chunk_idx}/{len(chunks)}):
414
  return {"value": progress, "visible": True}
415
 
416
  def create_interface(self):
417
- """Create Gradio interface with ChatGPT-like design"""
418
  css = """
419
  body, .gradio-container {
420
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
@@ -428,18 +446,23 @@ Patient Record (Chunk {chunk_idx}/{len(chunks)}):
428
  }
429
  .chat-container {
430
  background: var(--chat-bg);
431
- border-radius: 12px;
432
- padding: 20px;
433
  height: 80vh;
434
  overflow-y: auto;
435
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
 
436
  }
437
  .message {
438
- margin: 10px 0;
439
  padding: 12px 16px;
440
  border-radius: 12px;
441
  max-width: 80%;
442
- transition: all 0.2s ease;
 
 
 
 
443
  }
444
  .message.user {
445
  background: #007bff;
@@ -450,14 +473,22 @@ Patient Record (Chunk {chunk_idx}/{len(chunks)}):
450
  background: var(--message-bg);
451
  color: var(--text-color);
452
  }
 
 
 
 
 
 
453
  .input-container {
454
  display: flex;
455
  align-items: center;
456
  margin-top: 20px;
457
  background: var(--chat-bg);
458
- padding: 10px 20px;
459
- border-radius: 25px;
460
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
 
 
461
  }
462
  .input-textbox {
463
  flex-grow: 1;
@@ -465,31 +496,39 @@ Patient Record (Chunk {chunk_idx}/{len(chunks)}):
465
  background: transparent;
466
  color: var(--text-color);
467
  outline: none;
 
468
  }
469
  .send-btn {
470
  background: #007bff;
471
  color: white;
472
  border: none;
473
  border-radius: 20px;
474
- padding: 8px 16px;
475
- margin-left: 10px;
 
476
  }
477
  .send-btn:hover {
478
  background: #0056b3;
479
  }
480
  .sidebar {
481
  background: var(--sidebar-bg);
482
- padding: 20px;
483
- border-radius: 12px;
484
  margin-top: 20px;
485
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
 
 
486
  }
487
  .sidebar-hidden {
488
- display: none;
 
 
 
 
489
  }
490
  .header {
491
  text-align: center;
492
- margin-bottom: 20px;
493
  }
494
  .theme-toggle {
495
  position: absolute;
@@ -500,13 +539,28 @@ Patient Record (Chunk {chunk_idx}/{len(chunks)}):
500
  border: none;
501
  border-radius: 20px;
502
  padding: 8px 16px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
503
  }
504
  :root {
505
  --background: #ffffff;
506
  --text-color: #333333;
507
- --chat-bg: #f7f7f8;
508
  --message-bg: #e5e5ea;
509
- --sidebar-bg: #f1f1f1;
510
  }
511
  @media (prefers-color-scheme: dark) {
512
  :root {
@@ -519,19 +573,26 @@ Patient Record (Chunk {chunk_idx}/{len(chunks)}):
519
  }
520
  @media (max-width: 600px) {
521
  .gradio-container {
522
- padding: 10px;
523
  }
524
  .chat-container {
525
  height: 70vh;
526
  }
527
  .input-container {
528
  flex-direction: column;
529
- gap: 10px;
 
530
  }
531
  .send-btn {
532
  width: 100%;
533
  margin-left: 0;
534
  }
 
 
 
 
 
 
535
  }
536
  """
537
 
@@ -541,10 +602,11 @@ Patient Record (Chunk {chunk_idx}/{len(chunks)}):
541
  const isDark = root.style.getPropertyValue('--background') === '#1e2a44';
542
  root.style.setProperty('--background', isDark ? '#ffffff' : '#1e2a44');
543
  root.style.setProperty('--text-color', isDark ? '#333333' : '#ffffff');
544
- root.style.setProperty('--chat-bg', isDark ? '#f7f7f8' : '#2d3b55');
545
  root.style.setProperty('--message-bg', isDark ? '#e5e5ea' : '#3e4c6a');
546
- root.style.setProperty('--sidebar-bg', isDark ? '#f1f1f1' : '#2a3650');
547
  localStorage.setItem('theme', isDark ? 'light' : 'dark');
 
548
  }
549
 
550
  function toggleSidebar() {
@@ -556,6 +618,7 @@ Patient Record (Chunk {chunk_idx}/{len(chunks)}):
556
  const savedTheme = localStorage.getItem('theme');
557
  if (savedTheme === 'dark') toggleTheme();
558
  document.querySelector('.sidebar').classList.add('sidebar-hidden');
 
559
  });
560
  """
561
 
@@ -568,7 +631,7 @@ Patient Record (Chunk {chunk_idx}/{len(chunks)}):
568
  </p>
569
  </div>
570
  """)
571
- gr.Button("Toggle Light/Dark Mode", elem_classes="theme-toggle").click(
572
  None, None, None, _js="toggleTheme"
573
  )
574
 
@@ -578,27 +641,30 @@ Patient Record (Chunk {chunk_idx}/{len(chunks)}):
578
  height="100%",
579
  show_copy_button=True,
580
  type="messages",
581
- elem_classes="chatbot"
 
582
  )
 
583
 
584
  with gr.Row():
585
- gr.Button("Show/Hide Tools", variant="secondary").click(
586
  None, None, None, _js="toggleSidebar"
587
  )
588
 
589
  with gr.Column(elem_classes="sidebar"):
 
590
  file_upload = gr.File(
591
  file_types=[".pdf", ".csv", ".xls", ".xlsx"],
592
  file_count="multiple",
593
- label="Upload Patient Records"
594
  )
595
- gr.Markdown("### πŸ“ Summary of Findings")
596
  final_summary = gr.Markdown(
597
  "Analysis results will appear here..."
598
  )
599
- gr.Markdown("### πŸ“‚ Report Download")
600
  download_output = gr.File(
601
- label="Full Report",
602
  visible=False,
603
  interactive=False
604
  )
@@ -623,18 +689,40 @@ Patient Record (Chunk {chunk_idx}/{len(chunks)}):
623
  interactive=False
624
  )
625
 
 
 
 
 
 
 
626
  send_btn.click(
 
 
 
 
627
  self.analyze,
628
  inputs=[msg_input, chatbot, file_upload],
629
  outputs=[chatbot, download_output, final_summary, progress_text],
630
  show_progress="hidden"
 
 
 
 
631
  )
632
 
633
  msg_input.submit(
 
 
 
 
634
  self.analyze,
635
  inputs=[msg_input, chatbot, file_upload],
636
  outputs=[chatbot, download_output, final_summary, progress_text],
637
  show_progress="hidden"
 
 
 
 
638
  )
639
 
640
  app.load(
 
16
  import gc
17
  from diskcache import Cache
18
  from transformers import AutoTokenizer
19
+ from datetime import datetime
20
 
21
  # ==================== CONFIGURATION ====================
22
  # Configure logging
 
314
  cleaned = self.text_processor.clean_response(message.content)
315
  if cleaned:
316
  full_response += cleaned + " "
317
+ yield {
318
+ "role": "assistant",
319
+ "content": f"βœ… {cleaned} [{datetime.now().strftime('%H:%M:%S')}]"
320
+ }
321
  elif isinstance(chunk, str) and chunk.strip():
322
  cleaned = self.text_processor.clean_response(chunk)
323
  if cleaned:
324
  full_response += cleaned + " "
325
+ yield {
326
+ "role": "assistant",
327
+ "content": f"βœ… {cleaned} [{datetime.now().strftime('%H:%M:%S')}]"
328
+ }
329
 
330
  def analyze(self, message: str, history: List[dict], files: List) -> Generator[tuple, None, None]:
331
  """Main analysis pipeline with proper output formatting"""
 
336
 
337
  try:
338
  # Add user message to history
339
+ chatbot_output.append({
340
+ "role": "user",
341
+ "content": f"{message} [{datetime.now().strftime('%H:%M:%S')}]"
342
+ })
343
  yield (chatbot_output, download_output, final_summary, progress_text)
344
 
345
  # Process uploaded files
 
346
  extracted = []
347
  file_hash_value = ""
348
 
 
363
  extracted.append({"error": f"Error processing file: {str(e)}"})
364
 
365
  file_hash_value = get_file_hash(files[0].name) if files else ""
366
+ chatbot_output.append({
367
+ "role": "assistant",
368
+ "content": f"βœ… File processing complete [{datetime.now().strftime('%H:%M:%S')}]"
369
+ })
370
  progress_text = self._update_progress(len(files), len(files), "Files processed")
371
  yield (chatbot_output, download_output, final_summary, progress_text)
372
 
 
385
  Patient Record (Chunk {chunk_idx}/{len(chunks)}):
386
  {chunk[:1200]}
387
  """
388
+ chatbot_output.append({"role": "assistant", "content": "⏳ Analyzing..."})
389
  progress_text = self._update_progress(chunk_idx, len(chunks), "Analyzing")
390
  yield (chatbot_output, download_output, final_summary, progress_text)
391
 
 
415
 
416
  except Exception as e:
417
  logger.error(f"Analysis error: {e}")
418
+ chatbot_output.append({
419
+ "role": "assistant",
420
+ "content": f"❌ Error: {str(e)} [{datetime.now().strftime('%H:%M:%S')}]"
421
+ })
422
  final_summary = f"Error occurred: {str(e)}"
423
  progress_text = {"visible": False}
424
  yield (chatbot_output, download_output, final_summary, progress_text)
425
+ finally:
426
+ torch.cuda.empty_cache()
427
+ gc.collect()
428
 
429
  def _update_progress(self, current: int, total: int, stage: str = "") -> Dict[str, Any]:
430
  """Format progress update for UI"""
 
432
  return {"value": progress, "visible": True}
433
 
434
  def create_interface(self):
435
+ """Create Gradio interface with refined ChatGPT-like design"""
436
  css = """
437
  body, .gradio-container {
438
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 
446
  }
447
  .chat-container {
448
  background: var(--chat-bg);
449
+ border-radius: 16px;
450
+ padding: 24px;
451
  height: 80vh;
452
  overflow-y: auto;
453
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
454
+ position: relative;
455
  }
456
  .message {
457
+ margin: 12px 0;
458
  padding: 12px 16px;
459
  border-radius: 12px;
460
  max-width: 80%;
461
+ transition: all 0.3s ease;
462
+ position: relative;
463
+ }
464
+ .message:hover {
465
+ transform: translateY(-2px);
466
  }
467
  .message.user {
468
  background: #007bff;
 
473
  background: var(--message-bg);
474
  color: var(--text-color);
475
  }
476
+ .message-timestamp {
477
+ font-size: 0.75em;
478
+ opacity: 0.7;
479
+ margin-top: 4px;
480
+ text-align: right;
481
+ }
482
  .input-container {
483
  display: flex;
484
  align-items: center;
485
  margin-top: 20px;
486
  background: var(--chat-bg);
487
+ padding: 12px 24px;
488
+ border-radius: 30px;
489
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
490
+ position: sticky;
491
+ bottom: 0;
492
  }
493
  .input-textbox {
494
  flex-grow: 1;
 
496
  background: transparent;
497
  color: var(--text-color);
498
  outline: none;
499
+ font-size: 1em;
500
  }
501
  .send-btn {
502
  background: #007bff;
503
  color: white;
504
  border: none;
505
  border-radius: 20px;
506
+ padding: 10px 20px;
507
+ margin-left: 12px;
508
+ transition: background 0.2s ease;
509
  }
510
  .send-btn:hover {
511
  background: #0056b3;
512
  }
513
  .sidebar {
514
  background: var(--sidebar-bg);
515
+ padding: 24px;
516
+ border-radius: 16px;
517
  margin-top: 20px;
518
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
519
+ transition: transform 0.3s ease;
520
+ transform: translateX(0);
521
  }
522
  .sidebar-hidden {
523
+ transform: translateX(100%);
524
+ position: absolute;
525
+ right: 0;
526
+ top: 100px;
527
+ width: 300px;
528
  }
529
  .header {
530
  text-align: center;
531
+ margin-bottom: 24px;
532
  }
533
  .theme-toggle {
534
  position: absolute;
 
539
  border: none;
540
  border-radius: 20px;
541
  padding: 8px 16px;
542
+ display: flex;
543
+ align-items: center;
544
+ gap: 8px;
545
+ }
546
+ .loading-spinner {
547
+ position: absolute;
548
+ bottom: 80px;
549
+ left: 50%;
550
+ transform: translateX(-50%);
551
+ font-size: 1.2em;
552
+ animation: spin 1s linear infinite;
553
+ }
554
+ @keyframes spin {
555
+ 0% { transform: translateX(-50%) rotate(0deg); }
556
+ 100% { transform: translateX(-50%) rotate(360deg); }
557
  }
558
  :root {
559
  --background: #ffffff;
560
  --text-color: #333333;
561
+ --chat-bg: #f9fafb;
562
  --message-bg: #e5e5ea;
563
+ --sidebar-bg: #f1f3f5;
564
  }
565
  @media (prefers-color-scheme: dark) {
566
  :root {
 
573
  }
574
  @media (max-width: 600px) {
575
  .gradio-container {
576
+ padding: 12px;
577
  }
578
  .chat-container {
579
  height: 70vh;
580
  }
581
  .input-container {
582
  flex-direction: column;
583
+ gap: 12px;
584
+ padding: 12px;
585
  }
586
  .send-btn {
587
  width: 100%;
588
  margin-left: 0;
589
  }
590
+ .sidebar {
591
+ width: 100%;
592
+ }
593
+ .sidebar-hidden {
594
+ transform: translateX(100%);
595
+ }
596
  }
597
  """
598
 
 
602
  const isDark = root.style.getPropertyValue('--background') === '#1e2a44';
603
  root.style.setProperty('--background', isDark ? '#ffffff' : '#1e2a44');
604
  root.style.setProperty('--text-color', isDark ? '#333333' : '#ffffff');
605
+ root.style.setProperty('--chat-bg', isDark ? '#f9fafb' : '#2d3b55');
606
  root.style.setProperty('--message-bg', isDark ? '#e5e5ea' : '#3e4c6a');
607
+ root.style.setProperty('--sidebar-bg', isDark ? '#f1f3f5' : '#2a3650');
608
  localStorage.setItem('theme', isDark ? 'light' : 'dark');
609
+ document.querySelector('.theme-toggle').innerHTML = isDark ? 'πŸŒ™ Dark Mode' : 'β˜€οΈ Light Mode';
610
  }
611
 
612
  function toggleSidebar() {
 
618
  const savedTheme = localStorage.getItem('theme');
619
  if (savedTheme === 'dark') toggleTheme();
620
  document.querySelector('.sidebar').classList.add('sidebar-hidden');
621
+ document.querySelector('.theme-toggle').innerHTML = savedTheme === 'dark' ? 'β˜€οΈ Light Mode' : 'πŸŒ™ Dark Mode';
622
  });
623
  """
624
 
 
631
  </p>
632
  </div>
633
  """)
634
+ gr.Button("πŸŒ™ Dark Mode", elem_classes="theme-toggle").click(
635
  None, None, None, _js="toggleTheme"
636
  )
637
 
 
641
  height="100%",
642
  show_copy_button=True,
643
  type="messages",
644
+ elem_classes="chatbot",
645
+ render_markdown=True
646
  )
647
+ gr.HTML("<div class='loading-spinner' style='display: none;'>⏳</div>")
648
 
649
  with gr.Row():
650
+ gr.Button("πŸ“‚ Tools", variant="secondary").click(
651
  None, None, None, _js="toggleSidebar"
652
  )
653
 
654
  with gr.Column(elem_classes="sidebar"):
655
+ gr.Markdown("### πŸ“Ž Upload Records")
656
  file_upload = gr.File(
657
  file_types=[".pdf", ".csv", ".xls", ".xlsx"],
658
  file_count="multiple",
659
+ label="Patient Records"
660
  )
661
+ gr.Markdown("### πŸ“ Analysis Summary")
662
  final_summary = gr.Markdown(
663
  "Analysis results will appear here..."
664
  )
665
+ gr.Markdown("### πŸ“„ Full Report")
666
  download_output = gr.File(
667
+ label="Download Report",
668
  visible=False,
669
  interactive=False
670
  )
 
689
  interactive=False
690
  )
691
 
692
+ def show_loading_spinner():
693
+ return gr.update(value="<div class='loading-spinner'>⏳</div>", visible=True)
694
+
695
+ def hide_loading_spinner():
696
+ return gr.update(value="<div class='loading-spinner' style='display: none;'>⏳</div>", visible=False)
697
+
698
  send_btn.click(
699
+ show_loading_spinner,
700
+ outputs=[chatbot],
701
+ _js="() => { document.querySelector('.loading-spinner').style.display = 'block'; }"
702
+ ).then(
703
  self.analyze,
704
  inputs=[msg_input, chatbot, file_upload],
705
  outputs=[chatbot, download_output, final_summary, progress_text],
706
  show_progress="hidden"
707
+ ).then(
708
+ hide_loading_spinner,
709
+ outputs=[chatbot],
710
+ _js="() => { document.querySelector('.loading-spinner').style.display = 'none'; }"
711
  )
712
 
713
  msg_input.submit(
714
+ show_loading_spinner,
715
+ outputs=[chatbot],
716
+ _js="() => { document.querySelector('.loading-spinner').style.display = 'block'; }"
717
+ ).then(
718
  self.analyze,
719
  inputs=[msg_input, chatbot, file_upload],
720
  outputs=[chatbot, download_output, final_summary, progress_text],
721
  show_progress="hidden"
722
+ ).then(
723
+ hide_loading_spinner,
724
+ outputs=[chatbot],
725
+ _js="() => { document.querySelector('.loading-spinner').style.display = 'none'; }"
726
  )
727
 
728
  app.load(