File size: 4,667 Bytes
4b31891 2b1fa3f 4b31891 2b1fa3f 4b31891 3df1b71 4b31891 3df1b71 4b31891 2b1fa3f 4b31891 2b1fa3f 4b31891 2b1fa3f 3df1b71 4b31891 3df1b71 2b1fa3f 4b31891 3df1b71 2b1fa3f 4b31891 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | #!/usr/bin/env python3
"""
Usage: python scripts/launch_ui.py
Gradio web UI for the RAG system.
Provides a user-friendly interface for asking questions.
"""
import gradio as gr
from query.retriever import retrieve
from query.prompt_builder import build_prompt
from query.generator import generate
def answer_question_generator(question: str, show_sources: bool = False, tutor_mode: bool = False):
"""
Answer a question using the RAG system with streaming status updates.
Args:
question: The user's question
show_sources: Whether to display retrieved sources
tutor_mode: If True, use Socratic tutor mode; if False, use direct answer mode
Yields:
Tuples of (answer_markdown, sources_markdown) for progressive UI updates
"""
if not question.strip():
yield "Please enter a question.", ""
return
# Step 1: Retrieving sources
yield "π **Retrieving relevant sources...**\n\n*(This may take 5-10 seconds)*", ""
try:
chunks = retrieve(question)
count = len(chunks)
mode_label = "π **Tutor Mode**" if tutor_mode else "π **Regular Mode**"
yield f"β **Retrieved {count} relevant sources**\n\nβ³ **Generating response ({mode_label})...**\n\n*(This may take 15-30 seconds with local Ollama. Please wait.)*", ""
# Build prompt with context, passing tutor_mode
prompt = build_prompt(question, chunks, tutor_mode=tutor_mode)
# Generate response (this is the long operation)
response = generate(prompt)
# Format sources
sources_text = ""
if show_sources and chunks:
sources_text = "## Retrieved Sources\n\n"
for i, chunk in enumerate(chunks, 1):
source = chunk["metadata"].get("source", "unknown")
page = chunk["metadata"].get("page", chunk["metadata"].get("slide", "?"))
category = chunk["metadata"].get("category", "unknown")
distance = chunk.get("distance", "?")
sources_text += f"### Source {i}\n"
sources_text += f"**Category:** {category}\n"
sources_text += f"**Location:** {source} (page/slide {page})\n"
sources_text += f"**Relevance:** {distance:.4f}\n"
sources_text += f"**Excerpt:** {chunk['text'][:200]}...\n\n"
# Final: Show answer
yield response, sources_text
except Exception as e:
yield f"β **Error:** {str(e)}", ""
def main():
"""Launch the Gradio interface."""
with gr.Blocks(title="ENGR 445 RAG Assistant") as demo:
gr.Markdown("# ENGR 445 Course Assistant")
gr.Markdown("Ask questions about ENGR 445 course material β lectures, datasheets, application notes, and source code.")
with gr.Row():
question_input = gr.Textbox(
label="Your Question",
placeholder="E.g., How do I configure GPIO pins as push-pull?",
lines=2
)
with gr.Row():
submit_btn = gr.Button("Ask", scale=1)
show_sources_cb = gr.Checkbox(label="Show Retrieved Sources", value=False)
tutor_mode_cb = gr.Checkbox(label="π Tutor Mode (hints instead of answers)", value=False)
with gr.Row():
answer_output = gr.Markdown(label="Answer", value="*Ask a question to get started...*")
with gr.Row():
sources_output = gr.Markdown(label="Sources")
with gr.Row():
gr.Markdown("""
**Mode Explanation:**
- **Regular Mode**: Provides direct answers with citations
- **Tutor Mode**: Acts as a Socratic tutor, providing hints and guiding you to resources instead of answers
""")
# Connect the submit button to the function with streaming updates
submit_btn.click(
fn=answer_question_generator,
inputs=[question_input, show_sources_cb, tutor_mode_cb],
outputs=[answer_output, sources_output]
)
# Also support Enter key
question_input.submit(
fn=answer_question_generator,
inputs=[question_input, show_sources_cb, tutor_mode_cb],
outputs=[answer_output, sources_output]
)
gr.Markdown("---")
gr.Markdown("**Note:** All inference runs locally via Ollama. Ensure Ollama is running before using this interface.")
demo.launch(server_name="127.0.0.1", server_port=7860, share=False)
if __name__ == "__main__":
main() |