OR_Search / gradio.app
ambrosfitz's picture
Create gradio.app
d04fe9b verified
raw
history blame
7.46 kB
import gradio as gr
import requests
import json
import os
from typing import List, Tuple
# --- Configuration ---
API_URL = "https://monocopter.net"
API_TOKEN = os.getenv("API_TOKEN", "")
HEADERS = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json"
}
# --- Core API Functions ---
def query_rag_system(query: str, max_cards: int = 5) -> dict:
"""Query the RAG system with a historical question."""
try:
payload = {"query": query, "max_cards": max_cards, "include_sources": True}
response = requests.post(f"{API_URL}/query", json=payload, headers=HEADERS)
return response.json()
except Exception as e:
return {"error": str(e)}
def search_cards_semantic(query: str, max_cards: int = 5) -> dict:
"""Perform semantic search on cards."""
try:
payload = {"query": query, "max_cards": max_cards}
response = requests.post(f"{API_URL}/search", json=payload, headers=HEADERS)
return response.json()
except Exception as e:
return {"error": str(e)}
# --- Chatbot Functions ---
def format_rag_response(result: dict) -> str:
"""Format the RAG response for display in the chatbot."""
if "error" in result:
return f"❌ **Error**: {result['error']}"
answer = result.get("answer", "I couldn't generate an answer for your question.")
cards_used = result.get("cards_used", [])
sources = result.get("sources", [])
processing_time = result.get("processing_time", 0)
# Build formatted response
response = f"**Answer:**\n{answer}\n\n"
if sources:
response += f"**πŸ“š Sources ({len(sources)} documents):**\n"
for i, source in enumerate(sources[:3], 1): # Limit to top 3 sources
response += f"{i}. {source}\n"
if len(sources) > 3:
response += f"... and {len(sources) - 3} more sources\n"
response += "\n"
if cards_used:
response += f"**πŸ—ƒοΈ Retrieved {len(cards_used)} relevant cards** | "
response += f"**⏱️ {processing_time:.2f}s**"
return response
def format_search_response(result: dict) -> str:
"""Format the search response for display."""
if "error" in result:
return f"❌ **Error**: {result['error']}"
cards = result.get("cards", [])
if not cards:
return "πŸ” No relevant historical information found for your search."
response = f"πŸ” **Found {len(cards)} relevant historical entries:**\n\n"
for i, card in enumerate(cards[:3], 1): # Show top 3 results
title = card.get('title', 'Untitled')
summary = card.get('summary', 'No summary available')
relevance = card.get('relevance_score', 0)
# Truncate summary if too long
if len(summary) > 200:
summary = summary[:200] + "..."
response += f"**{i}. {title}** (Relevance: {relevance:.3f})\n{summary}\n\n"
if len(cards) > 3:
response += f"*... and {len(cards) - 3} more results*\n"
processing_time = result.get("processing_time", 0)
response += f"⏱️ Search completed in {processing_time:.2f}s"
return response
def chatbot_respond(message: str, history: List[Tuple[str, str]], search_mode: bool) -> Tuple[str, List[Tuple[str, str]]]:
"""Main chatbot response function."""
if not message.strip():
return "", history
# Determine max cards based on query complexity
max_cards = 3 if len(message.split()) < 5 else 5
if search_mode:
# Use semantic search for browsing/exploring
result = search_cards_semantic(message, max_cards)
response = format_search_response(result)
else:
# Use RAG for question-answering
result = query_rag_system(message, max_cards)
response = format_rag_response(result)
# Add to history
history.append((message, response))
return "", history
def clear_chat():
"""Clear the chat history."""
return [], ""
# --- Gradio Interface ---
def create_interface():
with gr.Blocks(
title="Historical Knowledge Assistant",
theme=gr.themes.Soft(),
css="""
.chat-container { max-height: 600px; overflow-y: auto; }
.examples { margin: 10px 0; }
"""
) as demo:
gr.Markdown("""
# πŸ›οΈ Historical Knowledge Assistant
Ask questions about historical events, people, and concepts. Powered by your Rolodex RAG database.
""")
with gr.Row():
with gr.Column(scale=4):
chatbot = gr.Chatbot(
label="Historical Q&A",
height=500,
show_copy_button=True,
container=True,
elem_classes=["chat-container"]
)
with gr.Row():
msg_input = gr.Textbox(
placeholder="Ask about historical events, people, or concepts...",
label="Your Question",
lines=2,
scale=4
)
with gr.Row():
send_btn = gr.Button("πŸ’¬ Ask", variant="primary", scale=1)
clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary", scale=1)
with gr.Column(scale=1):
search_mode = gr.Checkbox(
label="πŸ” Search Mode",
value=False,
info="Toggle between Q&A (off) and Search (on)"
)
gr.Markdown("""
### πŸ’‘ Example Questions
**Question & Answer Mode:**
- What caused the American Revolution?
- How did colonial resistance evolve?
- Who were key figures in Bacon's Rebellion?
**Search Mode:**
- colonial resistance
- Boston Massacre
- taxation without representation
### ℹ️ Tips
- **Q&A Mode**: Ask complete questions for detailed answers
- **Search Mode**: Use keywords to explore topics
- Sources and processing time shown with each response
""", elem_classes=["examples"])
# Event handlers
msg_input.submit(
chatbot_respond,
inputs=[msg_input, chatbot, search_mode],
outputs=[msg_input, chatbot]
)
send_btn.click(
chatbot_respond,
inputs=[msg_input, chatbot, search_mode],
outputs=[msg_input, chatbot]
)
clear_btn.click(
clear_chat,
outputs=[chatbot, msg_input]
)
return demo
# --- Launch Configuration ---
if __name__ == "__main__":
print("πŸš€ Launching Historical Knowledge Assistant...")
print(f"🌐 API URL: {API_URL}")
print(f"πŸ”‘ Using API token: {API_TOKEN[:10]}...")
demo = create_interface()
# For Hugging Face Spaces deployment
demo.launch(
share=False, # Set to True for temporary sharing
server_name="0.0.0.0", # Required for HF Spaces
server_port=7860, # Standard port for HF Spaces
show_error=True
)