import gradio as gr import os class GradioUI: def __init__(self, agent): self.agent = agent def process_input(self, query: str, pdf_file: gr.File = None): """ Processes user input, which can include a text query and optionally a PDF file. If a PDF is uploaded, it assumes the query is a question about it and calls the Document Q&A tool directly. Otherwise, it sends the query to the agent.run() method. Args: query (str): The text query from the user. pdf_file (gr.File, optional): The uploaded PDF file object provided by Gradio. Defaults to None. Returns: str: The response from the agent or tool. """ # Check if a PDF file is uploaded AND there is a text query (assumed to be the question) if pdf_file is not None and query and query.strip(): print(f"PDF file uploaded: {pdf_file.name}") print(f"Query (assumed question for PDF): {query}") try: # --- Call the Document Q&A tool directly --- # We assume the document_qna_tool is at index 4 as per your app.py initialization # Gradio's gr.File object has a .name attribute which is the file path # The document_qna_tool expects a file path string. print("Detected PDF upload and query. Calling document_qna_tool...") # The tool signature is document_qna_tool(pdf_path: str, question: str) response = self.agent.tools["document_qna_tool"](pdf_file.name, query) print("Document Q&A tool finished.") # Optional: Clean up the uploaded file after processing # import os # try: # if os.path.exists(pdf_file.name): # os.remove(pdf_file.name) # print(f"Cleaned up file: {pdf_file.name}") # except Exception as e: # print(f"Error cleaning up file {pdf_file.name}: {e}") return response except IndexError: return "Error: Document Q&A tool not found at the expected index (4). Check agent tool setup in app.py." except Exception as e: import traceback # Add this import if it's not already at the top of the file print(f"Error during Document Q&A tool execution: {e}") print("Full Traceback:") print(traceback.format_exc()) # <--- ADD THIS LINE return f"An error occurred during Document Q&A: {str(e)}" # If no PDF file, or query is empty when file is present, handle as a general agent query elif query and query.strip(): print(f"No PDF file or query is for general task. Processing with agent.run(): {query}") try: # --- Call the agent's run method for general queries --- response = self.agent.run(query) print("Agent.run finished for general query.") return response except Exception as e: print(f"Error during agent.run: {e}") return f"An error occurred while processing your request: {str(e)}" # Handle cases where only a PDF is uploaded without a question, or no input at all elif pdf_file is not None: # Optional: Clean up the uploaded file if no question was provided # import os # try: # if os.path.exists(pdf_file.name): # os.remove(pdf_file.name) # print(f"Cleaned up file: {pdf_file.name}") # except Exception as e: # print(f"Error cleaning up file {pdf_file.name}: {e}") return "Please enter a question in the textbox to ask about the uploaded PDF." else: return "Please enter a request or upload a document for analysis." def launch(self): """ Launches the Gradio user interface with input components stacked vertically. """ with gr.Blocks() as demo: gr.Markdown("# Multi-Tool AI Agent with Document Upload") gr.Markdown( "Enter your request and optionally upload a PDF document. " "If you upload a PDF, the text box should contain your question about the document. " "Otherwise, use the text box for general requests (weather, search, etc.)." ) # Stack components vertically by default within gr.Blocks # Text input for the user's query or question query_input = gr.Textbox( label="Enter your request or question:", placeholder="e.g., What is the weather in London? Search for the latest news about AI. What does this document say about [topic]? Summarize the document.", lines=3, # Gives height to the textbox interactive=True ) # File upload component for PDF documents - placed below the textbox pdf_upload = gr.File( label="Upload PDF (Optional - for Document Q&A)", file_types=[".pdf"], # Restrict file types to PDF interactive=True, # The vertical size of this component is somewhat fixed by Gradio ) # Button to trigger the processing function - placed below the file upload submit_btn = gr.Button("Submit") # Output field below the button agent_output = gr.Textbox( label="Agent's Response:", interactive=False, lines=10, autoscroll=True ) # Link the button click to the process_input function # Pass both query_input (text) and pdf_upload (file) as inputs submit_btn.click( fn=self.process_input, inputs=[query_input, pdf_upload], # This list specifies all inputs outputs=agent_output # This specifies the output where the return value goes ) # Optional examples - adjust these based on your tools and whether you have default files # examples = [ # ["What is the time in Berlin?", None], # Example with only text # ["Generate an image of a robot cooking pasta.", None], # Example with only text # # Example for document Q&A - requires a default file path accessible by the tool # # and needs to be in the same directory or accessible path # # ["Summarize the introduction section", "sample_document.pdf"] # Example with text and file # ] # gr.Examples(examples=examples, inputs=[query_input, pdf_upload]) # Examples take same inputs as function # Launch the Gradio interface # Setting share=True creates a public URL (useful for demos, be mindful of security/costs) # Setting inline=False opens the app in a new browser tab demo.launch(share=False, inline=False)