Spaces:
Build error
Build error
| import logging | |
| import gradio as gr | |
| from utils.document_utils import initialize_logging | |
| from globals import app_config | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
| initialize_logging() | |
| def load_sample_question(question): | |
| return question | |
| def clear_selection(): | |
| return gr.update(value=[]), "", "", gr.update(value=[]) # Reset doc_selector to empty list | |
| def process_uploaded_file(file, current_selection): | |
| """Process uploaded file using DocumentManager and update UI.""" | |
| try: | |
| if file is None: | |
| # When file input is cleared, preserve current selection and choices | |
| uploaded_docs = app_config.doc_manager.get_uploaded_documents() | |
| return ( | |
| "", | |
| gr.update(choices=uploaded_docs, value=current_selection or []), | |
| False, | |
| "" | |
| ) | |
| status, filename, doc_id = app_config.doc_manager.process_document(file.name if file else None) | |
| updated_selection = current_selection if current_selection else [] | |
| if filename and filename not in updated_selection: | |
| updated_selection.append(filename) | |
| trigger_summary = bool(filename) | |
| logging.info(f"Processed file: {filename}, Trigger summary: {trigger_summary}") | |
| return ( | |
| status, | |
| gr.update(choices=app_config.doc_manager.get_uploaded_documents(), value=updated_selection), | |
| trigger_summary, | |
| filename | |
| ) | |
| except Exception as e: | |
| logging.error(f"Error in process_uploaded_file: {e}") | |
| return "Error processing file", gr.update(choices=[]), False, '' | |
| def update_doc_selector(selected_docs): | |
| """Keep selected documents in sync.""" | |
| return selected_docs | |
| # UI Configuration | |
| models = [ "gemma2-9b-it", "llama3-70b-8192"] | |
| example_questions = [ | |
| "What is the architecture of the Communication Server?", | |
| "Show me an example of a configuration file.", | |
| "How to create Protected File Directories ?", | |
| "What functionalities are available in the Communication Server setups?", | |
| "What is Mediator help?", | |
| "Why AzureBlobStorage port is used?" | |
| ] | |
| with gr.Blocks(css=""" | |
| .chatbot .user { | |
| position: relative; | |
| background-color: #cfdcfd; | |
| padding: 12px 16px; | |
| border-radius: 20px; | |
| border-bottom-right-radius: 6px; | |
| display: inline-block; | |
| max-width: 80%; | |
| margin: 8px 0; | |
| } | |
| /* Tail effect */ | |
| .chatbot .user::after { | |
| content: ""; | |
| position: absolute; | |
| right: -10px; | |
| bottom: 10px; | |
| width: 0; | |
| height: 0; | |
| border: 10px solid transparent; | |
| border-left-color: #cfdcfd; | |
| border-right: 0; | |
| border-top: 0; | |
| margin-top: -5px; | |
| } | |
| .chatbot .bot { background-color: #f1f8e9; padding: 8px; border-radius: 10px; } /* Light green for bot responses */ | |
| """) as interface: | |
| interface.title = "π€ IntelliDoc: AI Document Explorer" | |
| gr.Markdown(""" | |
| # π€ IntelliDoc: AI Document Explorer | |
| **AI Document Explorer** allows you to upload PDF documents and interact with them using AI-powered analysis and summarization. Ask questions, extract key insights, and gain a deeper understanding of your documents effortlessly. | |
| """) | |
| summary_query_state = gr.State() # State to hold the summary query | |
| trigger_summary_state = gr.State() # State to hold trigger flag | |
| filename_state = gr.State() # State to hold file name | |
| chunks_state = gr.State() | |
| summary_text_state = gr.State() | |
| sample_questions_state = gr.State() | |
| with gr.Row(): | |
| # Left Sidebar | |
| with gr.Column(scale=2): | |
| gr.Markdown("## Upload and Select Document") | |
| upload_btn = gr.File(label="Upload PDF Document", file_types=[".pdf"]) | |
| doc_selector = gr.Dropdown( | |
| choices=app_config.doc_manager.get_uploaded_documents(), | |
| label="Documents", | |
| multiselect=True, | |
| value=[] # Initial value as empty list | |
| ) | |
| model_selector = gr.Dropdown(choices=models, label="Models", interactive=True) | |
| clear_btn = gr.Button("Clear Selection") | |
| upload_status = gr.Textbox(label="Upload Status", interactive=False) | |
| # Process uploaded file and update UI | |
| upload_event = upload_btn.change( | |
| process_uploaded_file, | |
| inputs=[upload_btn, doc_selector], | |
| outputs=[ | |
| upload_status, | |
| doc_selector, | |
| trigger_summary_state, # Store trigger_summary | |
| filename_state | |
| ] | |
| ) | |
| # Middle Section (Chat & LLM Response) | |
| with gr.Column(scale=6): | |
| gr.Markdown("## Chat with document(s)") | |
| chat_history = gr.Chatbot(label="Chat History", height= 650, bubble_full_width= False, type="messages") | |
| with gr.Row(): | |
| chat_input = gr.Textbox(label="Ask additional questions about the document...", show_label=False, placeholder="Ask additional questions about the document...", elem_id="chat-input", lines=3) | |
| chat_btn = gr.Button("π Send", variant="primary", elem_id="send-button", scale=0) | |
| chat_btn.click(app_config.chat_manager.generate_chat_response, inputs=[chat_input, doc_selector, chat_history], outputs=chat_history).then( | |
| lambda: "", # Return an empty string to clear the chat_input | |
| outputs=chat_input | |
| ) | |
| # Right Sidebar (Sample Questions & History) | |
| with gr.Column(scale=2): | |
| gr.Markdown("## Sample questions for this document:") | |
| with gr.Column(): | |
| sample_questions = gr.Dropdown( | |
| label="Select a sample question", | |
| choices=[], | |
| interactive=True, | |
| allow_custom_value=True # Allows users to type custom questions if needed | |
| ) | |
| clear_btn.click( | |
| clear_selection, | |
| outputs=[doc_selector, upload_status, filename_state, sample_questions] | |
| ) | |
| # Reinitialize LLM when the model changes | |
| model_selector.change( | |
| app_config.gen_llm.reinitialize_llm, | |
| inputs=[model_selector], | |
| outputs=[upload_status] | |
| ) | |
| # After upload, generate "Auto Summary" message only if trigger_summary is True | |
| upload_event.then( | |
| fn=lambda trigger, filename: "Can you provide summary of the document" if trigger and filename else None, | |
| inputs=[trigger_summary_state, filename_state], | |
| outputs=[summary_query_state] | |
| ).then( | |
| fn=lambda query, history: history + [{"role": "user", "content": ""}, {"role": "assistant", "content": "Generating summary of the document, please wait..."}] if query else history, | |
| inputs=[summary_query_state, chat_history], | |
| outputs=[chat_history] | |
| ).then( | |
| fn=lambda trigger, filename: app_config.doc_manager.get_chunks(filename) if trigger and filename else None, | |
| inputs=[trigger_summary_state, filename_state], | |
| outputs=[chunks_state] | |
| ).then( | |
| fn=lambda chunks: app_config.chat_manager.generate_summary(chunks) if chunks else None, | |
| inputs=[chunks_state], | |
| outputs=[summary_text_state] | |
| ).then( | |
| fn=lambda summary, history: history + [{"role": "assistant", "content": summary}] if summary else history, | |
| inputs=[summary_text_state, chat_history], | |
| outputs=[chat_history] | |
| ).then( | |
| fn=lambda chunks: app_config.chat_manager.generate_sample_questions(chunks) if chunks else [], | |
| inputs=[chunks_state], | |
| outputs=[sample_questions_state] | |
| ).then( | |
| fn=lambda questions: gr.update( | |
| choices=questions if questions else ["No questions available"], | |
| value=questions[0] if questions else None # Set the first question as default | |
| ), | |
| inputs=[sample_questions_state], | |
| outputs=[sample_questions] | |
| ) | |
| # Populate chat_input when a question is selected | |
| sample_questions.change( | |
| fn=lambda question: question, | |
| inputs=[sample_questions], | |
| outputs=[chat_input] | |
| ) | |
| #gr.Markdown("## Logs") | |
| #history = gr.Textbox(label="Previous Queries", interactive=False) | |
| if __name__ == "__main__": | |
| interface.launch() |