TilanB commited on
Commit
a30d34a
·
verified ·
1 Parent(s): 4b4e808
Files changed (1) hide show
  1. main.py +77 -29
main.py CHANGED
@@ -516,7 +516,7 @@ def main():
516
  border: 2px solid #d1d5db !important;
517
  margin-bottom: 16px !important;
518
  }
519
- """
520
 
521
 
522
  with gr.Blocks(theme=gr.themes.Soft(), title="SmartDoc AI", css=css) as demo:
@@ -535,7 +535,7 @@ def main():
535
 
536
  files = gr.Files(label="Upload your files", file_types=definitions.ALLOWED_TYPES)
537
  question = gr.Textbox(label="Ask a question", lines=2, placeholder="Type your question here...")
538
- chat = gr.Chatbot(label="Answers", elem_id="chat-history", type="messages")
539
  submit_btn = gr.Button("Get Answer", variant="primary")
540
  processing_message = gr.HTML("", elem_id="processing-message", visible=False)
541
  doc_context_display = gr.Markdown("*Submit a question to see which document sections were referenced*", elem_classes="doc-context", visible=False)
@@ -569,10 +569,8 @@ def main():
569
  )
570
  try:
571
  if not question_text.strip():
572
- chat_history.extend([
573
- {"role": "user", "content": question_text},
574
- {"role": "assistant", "content": "Please enter a question."}
575
- ])
576
  yield (
577
  chat_history,
578
  gr.update(visible=False),
@@ -585,10 +583,8 @@ def main():
585
  )
586
  return
587
  if not uploaded_files:
588
- chat_history.extend([
589
- {"role": "user", "content": question_text},
590
- {"role": "assistant", "content": "Please upload at least one document."}
591
- ])
592
  yield (
593
  chat_history,
594
  gr.update(visible=False),
@@ -643,7 +639,10 @@ def main():
643
  gr.update(interactive=False),
644
  gr.update(interactive=False),
645
  gr.update(interactive=False),
646
- gr.update(value='''<div style=\"background:#fff; border-radius:8px; padding:18px 24px; margin-top:32px; color:#1e293b; font-size:1.2em; font-weight:600; box-shadow:0 2px 8px rgba(0,0,0,0.04);\">\n <span id=\"processing-msg\"></span>\n <span id=\"processing-timer\" style=\"opacity:0.8; margin-left:8px;\"></span>\n</div>''', visible=True)
 
 
 
647
  )
648
  # After all chunks, show 100%
649
  yield (
@@ -654,7 +653,10 @@ def main():
654
  gr.update(interactive=False),
655
  gr.update(interactive=False),
656
  gr.update(interactive=False),
657
- gr.update(value='''<div style=\"background:#fff; border-radius:8px; padding:18px 24px; margin-top:32px; color:#1e293b; font-size:1.2em; font-weight:600; box-shadow:0 2px 8px rgba(0,0,0,0.04);">\n <span id=\"processing-msg\"></span>\n <span id=\"processing-timer\" style=\"opacity:0.8; margin-left:8px;\"></span>\n</div>''', visible=True)
 
 
 
658
  )
659
  # Stage 3: Building Retriever
660
  yield (
@@ -682,7 +684,10 @@ def main():
682
  gr.update(interactive=False),
683
  gr.update(interactive=False),
684
  gr.update(interactive=False),
685
- gr.update(value='''<div style=\"background:#fff; border-radius:8px; padding:18px 24px; margin-top:32px; color:#1e293b; font-size:1.2em; font-weight:600; box-shadow:0 2px 8px rgba(0,0,0,0.04);\">\n <span id=\"processing-msg\"></span>\n <span id=\"processing-timer\" style=\"opacity:0.8; margin-left:8px;\"></span>\n</div>''', visible=True)
 
 
 
686
  )
687
  result = orchestrator.run_workflow(question=question_text, retriever=retriever)
688
  answer = result["draft_answer"]
@@ -695,14 +700,16 @@ def main():
695
  gr.update(interactive=False),
696
  gr.update(interactive=False),
697
  gr.update(interactive=False),
698
- gr.update(value='''<div style=\"background:#fff; border-radius:8px; padding:18px 24px; margin-top:32px; color:#1e293b; font-size:1.2em; font-weight:600; box-shadow:0 2px 8px rgba(0,0,0,0.04);\">\n <span id=\"processing-msg\"></span>\n <span id=\"processing-timer\" style=\"opacity:0.8; margin-left:8px;\"></span>\n</div>''', visible=True)
 
 
 
699
  )
700
  verification = result.get("verification_report", "No verification details available.")
701
  logger.info(f"Verification (internal):\n{verification}")
702
- chat_history.extend([
703
- {"role": "user", "content": question_text},
704
- {"role": "assistant", "content": f"**Answer:**\n{answer}"}
705
- ])
706
  session_state.value["last_documents"] = retriever.invoke(question_text)
707
  yield (
708
  chat_history,
@@ -712,7 +719,10 @@ def main():
712
  gr.update(interactive=True),
713
  gr.update(interactive=True),
714
  gr.update(interactive=True),
715
- gr.update(value='''<div style=\"background:#fff; border-radius:8px; padding:18px 24px; margin-top:32px; color:#1e293b; font-size:1.2em; font-weight:600; box-shadow:0 2px 8px rgba(0,0,0,0.04);">\n <span id="processing-msg"></span>\n <span id="processing-timer" style="opacity:0.8; margin-left:8px;"></span>\n</div>''', visible=True)
 
 
 
716
  )
717
  yield (
718
  chat_history,
@@ -726,10 +736,8 @@ def main():
726
  )
727
  except Exception as e:
728
  logger.error(f"Processing error: {e}", exc_info=True)
729
- chat_history.extend([
730
- {"role": "user", "content": question_text},
731
- {"role": "assistant", "content": f"Error: {str(e)}"}
732
- ])
733
  yield (
734
  chat_history,
735
  gr.update(visible=False),
@@ -741,23 +749,63 @@ def main():
741
  gr.update(value="", visible=False)
742
  )
743
 
744
- def refresh_context(chat_history):
 
 
 
 
 
 
 
 
745
  docs = session_state.value.get("last_documents", [])
746
  last_question = ""
747
- for msg in reversed(chat_history or []):
748
- if msg.get("role") == "user":
749
- last_question = msg.get("content", "")
750
  break
751
  return format_document_context(docs, last_question)
752
 
753
  refresh_context_btn.click(
754
  fn=refresh_context,
755
- inputs=[chat],
756
  outputs=[doc_context_display]
757
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
758
  # Launch server - Compatible with both local and Hugging Face Spaces
759
  # HF Spaces sets SPACE_ID environment variable
760
  is_hf_space = os.environ.get("SPACE_ID") is not None
 
761
  demo.queue()
762
  if is_hf_space:
763
  # Hugging Face Spaces configuration
@@ -770,7 +818,7 @@ def main():
770
  logger.info(f"Launching Gradio on port {server_port}")
771
  logger.info(f"Access the app at: http://127.0.0.1:{server_port}")
772
  demo.launch(server_name="127.0.0.1", server_port=server_port, share=False)
773
-
774
 
775
  if __name__ == "__main__":
776
  main()
 
516
  border: 2px solid #d1d5db !important;
517
  margin-bottom: 16px !important;
518
  }
519
+ """
520
 
521
 
522
  with gr.Blocks(theme=gr.themes.Soft(), title="SmartDoc AI", css=css) as demo:
 
535
 
536
  files = gr.Files(label="Upload your files", file_types=definitions.ALLOWED_TYPES)
537
  question = gr.Textbox(label="Ask a question", lines=2, placeholder="Type your question here...")
538
+ chat = gr.Chatbot(label="Answers", elem_id="chat-history")
539
  submit_btn = gr.Button("Get Answer", variant="primary")
540
  processing_message = gr.HTML("", elem_id="processing-message", visible=False)
541
  doc_context_display = gr.Markdown("*Submit a question to see which document sections were referenced*", elem_classes="doc-context", visible=False)
 
569
  )
570
  try:
571
  if not question_text.strip():
572
+ chat_history.append({"role": "user", "content": question_text})
573
+ chat_history.append({"role": "assistant", "content": "Please enter a question."})
 
 
574
  yield (
575
  chat_history,
576
  gr.update(visible=False),
 
583
  )
584
  return
585
  if not uploaded_files:
586
+ chat_history.append({"role": "user", "content": question_text})
587
+ chat_history.append({"role": "assistant", "content": "Please upload at least one document."})
 
 
588
  yield (
589
  chat_history,
590
  gr.update(visible=False),
 
639
  gr.update(interactive=False),
640
  gr.update(interactive=False),
641
  gr.update(interactive=False),
642
+ gr.update(value='''<div style="background:#fff; border-radius:8px; padding:18px 24px; margin-top:32px; color:#1e293b; font-size:1.2em; font-weight:600; box-shadow:0 2px 8px rgba(0,0,0,0.04);">
643
+ <span id="processing-msg"></span>
644
+ <span id="processing-timer" style="opacity:0.8; margin-left:8px;"></span>
645
+ </div>''', visible=True)
646
  )
647
  # After all chunks, show 100%
648
  yield (
 
653
  gr.update(interactive=False),
654
  gr.update(interactive=False),
655
  gr.update(interactive=False),
656
+ gr.update(value='''<div style="background:#fff; border-radius:8px; padding:18px 24px; margin-top:32px; color:#1e293b; font-size:1.2em; font-weight:600; box-shadow:0 2px 8px rgba(0,0,0,0.04);">
657
+ <span id="processing-msg"></span>
658
+ <span id="processing-timer" style="opacity:0.8; margin-left:8px;"></span>
659
+ </div>''', visible=True)
660
  )
661
  # Stage 3: Building Retriever
662
  yield (
 
684
  gr.update(interactive=False),
685
  gr.update(interactive=False),
686
  gr.update(interactive=False),
687
+ gr.update(value='''<div style="background:#fff; border-radius:8px; padding:18px 24px; margin-top:32px; color:#1e293b; font-size:1.2em; font-weight:600; box-shadow:0 2px 8px rgba(0,0,0,0.04);">
688
+ <span id="processing-msg"></span>
689
+ <span id="processing-timer" style="opacity:0.8; margin-left:8px;"></span>
690
+ </div>''', visible=True)
691
  )
692
  result = orchestrator.run_workflow(question=question_text, retriever=retriever)
693
  answer = result["draft_answer"]
 
700
  gr.update(interactive=False),
701
  gr.update(interactive=False),
702
  gr.update(interactive=False),
703
+ gr.update(value='''<div style="background:#fff; border-radius:8px; padding:18px 24px; margin-top:32px; color:#1e293b; font-size:1.2em; font-weight:600; box-shadow:0 2px 8px rgba(0,0,0,0.04);">
704
+ <span id="processing-msg"></span>
705
+ <span id="processing-timer" style="opacity:0.8; margin-left:8px;"></span>
706
+ </div>''', visible=True)
707
  )
708
  verification = result.get("verification_report", "No verification details available.")
709
  logger.info(f"Verification (internal):\n{verification}")
710
+ # Do not display verification to user, only use internally
711
+ chat_history.append({"role": "user", "content": question_text})
712
+ chat_history.append({"role": "assistant", "content": f"**Answer:**\n{answer}"})
 
713
  session_state.value["last_documents"] = retriever.invoke(question_text)
714
  yield (
715
  chat_history,
 
719
  gr.update(interactive=True),
720
  gr.update(interactive=True),
721
  gr.update(interactive=True),
722
+ gr.update(value='''<div style="background:#fff; border-radius:8px; padding:18px 24px; margin-top:32px; color:#1e293b; font-size:1.2em; font-weight:600; box-shadow:0 2px 8px rgba(0,0,0,0.04);">
723
+ <span id="processing-msg"></span>
724
+ <span id="processing-timer" style="opacity:0.8; margin-left:8px;"></span>
725
+ </div>''', visible=True)
726
  )
727
  yield (
728
  chat_history,
 
736
  )
737
  except Exception as e:
738
  logger.error(f"Processing error: {e}", exc_info=True)
739
+ chat_history.append({"role": "user", "content": question_text})
740
+ chat_history.append({"role": "assistant", "content": f"Error: {str(e)}"})
 
 
741
  yield (
742
  chat_history,
743
  gr.update(visible=False),
 
749
  gr.update(value="", visible=False)
750
  )
751
 
752
+ submit_btn.click(
753
+ fn=process_question,
754
+ inputs=[question, files, chat],
755
+ outputs=[chat, doc_context_display, refresh_context_btn, submit_btn, question, files, example_dropdown, processing_message],
756
+ queue=True,
757
+ show_progress=True
758
+ )
759
+
760
+ def refresh_context():
761
  docs = session_state.value.get("last_documents", [])
762
  last_question = ""
763
+ for msg in reversed(chat.value or []):
764
+ if msg["role"] == "user":
765
+ last_question = msg["content"]
766
  break
767
  return format_document_context(docs, last_question)
768
 
769
  refresh_context_btn.click(
770
  fn=refresh_context,
771
+ inputs=[],
772
  outputs=[doc_context_display]
773
  )
774
+
775
+ def load_example(example_key):
776
+ if not example_key or example_key not in EXAMPLES:
777
+ return [], "", "Select a valid example from the dropdown above"
778
+ ex_data = EXAMPLES[example_key]
779
+ question_text = ex_data["question"]
780
+ file_paths = ex_data["file_paths"]
781
+ import tempfile
782
+ temp_dir = tempfile.mkdtemp()
783
+ copied_files = []
784
+ file_info_text = f"Loaded: {example_key}\n\n"
785
+ for source_file_path in file_paths:
786
+ abs_source = os.path.abspath(source_file_path)
787
+ if os.path.exists(abs_source):
788
+ filename = os.path.basename(abs_source)
789
+ temp_file_path = os.path.join(temp_dir, filename)
790
+ shutil.copy2(abs_source, temp_file_path)
791
+ copied_files.append(temp_file_path)
792
+ file_size_mb = os.path.getsize(temp_file_path) / (1024 * 1024)
793
+ file_info_text += f"{filename} ({file_size_mb:.2f} MB)\n"
794
+ else:
795
+ file_info_text += f"{source_file_path} not found\n"
796
+ if not copied_files:
797
+ return [], "", "Could not load example files"
798
+ return copied_files, question_text, file_info_text
799
+
800
+ example_dropdown.change(
801
+ fn=load_example,
802
+ inputs=[example_dropdown],
803
+ outputs=[files, question, loaded_file_info]
804
+ )
805
  # Launch server - Compatible with both local and Hugging Face Spaces
806
  # HF Spaces sets SPACE_ID environment variable
807
  is_hf_space = os.environ.get("SPACE_ID") is not None
808
+
809
  demo.queue()
810
  if is_hf_space:
811
  # Hugging Face Spaces configuration
 
818
  logger.info(f"Launching Gradio on port {server_port}")
819
  logger.info(f"Access the app at: http://127.0.0.1:{server_port}")
820
  demo.launch(server_name="127.0.0.1", server_port=server_port, share=False)
821
+
822
 
823
  if __name__ == "__main__":
824
  main()