Spaces:
Runtime error
Runtime error
| """ | |
| app.py | |
| Gradio UI for the RAG Document Q&A system. | |
| """ | |
| import os | |
| import shutil | |
| import tempfile | |
| import logging | |
| import gradio as gr | |
| from rag_pipeline import RAGPipeline | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| pipeline = RAGPipeline() | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Handlers | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| def handle_upload(file): | |
| if file is None: | |
| return "β οΈ No file uploaded.", gr.update(interactive=False) | |
| try: | |
| ext = os.path.splitext(file.name)[1].lower() | |
| tmp_path = tempfile.mktemp(suffix=ext) | |
| shutil.copy(file.name, tmp_path) | |
| stats = pipeline.ingest_document(tmp_path) | |
| status = ( | |
| f"β **Document ready!**\n\n" | |
| f"- π File: `{stats['document']}`\n" | |
| f"- π§© Chunks: `{stats['chunks']}`\n" | |
| f"- π Embedding dim: `{stats['embedding_dim']}`\n" | |
| f"- β‘ Ingestion time: `{stats['ingestion_time_s']}s`\n\n" | |
| f"You can now ask questions below." | |
| ) | |
| return status, gr.update(interactive=True) | |
| except Exception as e: | |
| logger.error(f"Upload error: {e}") | |
| return f"β Error processing document: {str(e)}", gr.update(interactive=False) | |
| def handle_query(question, history): | |
| if not pipeline.is_ready: | |
| history.append((question, "β οΈ Please upload a document first.")) | |
| return history, "", "" | |
| if not question.strip(): | |
| return history, "", "" | |
| try: | |
| result = pipeline.query(question) | |
| answer = result["answer"] | |
| latency = result["latency_s"] | |
| # β FIXED: use rank instead of score | |
| sources_md = "### π Retrieved Sources\n\n" | |
| for src in result["sources"]: | |
| rank = src["rank"] | |
| excerpt = src["chunk"][:300] + ("..." if len(src["chunk"]) > 300 else "") | |
| sources_md += f"**Source {rank}**\n\n> {excerpt}\n\n---\n\n" | |
| history.append((question, answer)) | |
| return history, sources_md, f"β‘ Response time: {latency}s" | |
| except Exception as e: | |
| logger.error(f"Query error: {e}") | |
| history.append((question, f"β Error: {str(e)}")) | |
| return history, "", "" | |
| def clear_all(): | |
| return [], "", "" | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| # UI | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Blocks( | |
| title="RAG Document Q&A", | |
| theme=gr.themes.Soft(primary_hue="blue"), | |
| css=""" | |
| .title { text-align: center; margin-bottom: 8px; } | |
| .subtitle { text-align: center; color: #64748b; margin-bottom: 24px; } | |
| footer { display: none !important; } | |
| """ | |
| ) as demo: | |
| gr.Markdown("# π RAG Document Q&A", elem_classes="title") | |
| gr.Markdown( | |
| "Upload a PDF or TXT document, then ask questions. " | |
| "Answers are grounded in your document β not hallucinated.", | |
| elem_classes="subtitle" | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Markdown("### π Upload Document") | |
| file_input = gr.File( | |
| label="Upload PDF or TXT (max 10 MB)", | |
| file_types=[".pdf", ".txt"], | |
| ) | |
| upload_status = gr.Markdown("_No document loaded yet._") | |
| with gr.Column(scale=2): | |
| gr.Markdown("### π¬ Ask a Question") | |
| chatbot = gr.Chatbot(height=380, label="Conversation") | |
| with gr.Row(): | |
| question_box = gr.Textbox( | |
| placeholder="e.g. What is the main topic of this document?", | |
| label="Your question", | |
| scale=4, | |
| interactive=False, | |
| ) | |
| submit_btn = gr.Button("Ask π", variant="primary", scale=1) | |
| latency_display = gr.Markdown("") | |
| clear_btn = gr.Button("ποΈ Clear conversation", variant="secondary") | |
| with gr.Accordion("π View Retrieved Sources", open=False): | |
| sources_display = gr.Markdown("_Ask a question to see retrieved sources._") | |
| gr.Markdown("### π‘ Example Questions") | |
| gr.Examples( | |
| examples=[ | |
| ["What is the main topic of this document?"], | |
| ["Summarize the key points."], | |
| ["What conclusions are drawn?"], | |
| ["What data or evidence is mentioned?"], | |
| ], | |
| inputs=question_box, | |
| ) | |
| # Events | |
| file_input.change( | |
| fn=handle_upload, | |
| inputs=file_input, | |
| outputs=[upload_status, question_box], | |
| ) | |
| submit_btn.click( | |
| fn=handle_query, | |
| inputs=[question_box, chatbot], | |
| outputs=[chatbot, sources_display, latency_display], | |
| ) | |
| question_box.submit( | |
| fn=handle_query, | |
| inputs=[question_box, chatbot], | |
| outputs=[chatbot, sources_display, latency_display], | |
| ) | |
| clear_btn.click( | |
| fn=clear_all, | |
| outputs=[chatbot, sources_display, latency_display], | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=True, | |
| ) |