WNP-ARAG / app.py
starfriend's picture
Upload 14 files
f6d1fb2 verified
Raw History Blame Contribute Delete
11.9 kB
import gradio as gr
from config import (
APP_SUBTITLE,
APP_TITLE,
DEFAULT_CONCURRENCY_LIMIT,
DEFAULT_JURISDICTION,
JURISDICTIONS,
MAX_RETRIEVAL_LOOPS,
TOP_K_RETRIEVAL,
UPLOAD_SESSION_ROOT,
)
from document_service import (
clear_document_session,
process_uploaded_document,
validate_document_session,
)
from pipeline import run_document_rag, run_rag_agent
from job_service import (
forget_rag_job,
get_rag_job_status,
start_document_processing_job,
start_document_rag_job,
start_rag_job,
)
from services import check_system_status
CUSTOM_CSS = """
.gradio-container {max-width:1280px!important;margin:0 auto!important;
font-family:"Segoe UI",Tahoma,Geneva,Verdana,sans-serif!important}
.app-header {text-align:center;padding:24px;
background:linear-gradient(135deg,#5f9eea 0%,#7bc5ef 100%);
color:white;border-radius:10px;margin-bottom:18px}
.app-header h1 {margin:0;font-size:2.35rem;font-weight:650}
.app-header p {margin:8px 0 0;font-size:1.05rem;opacity:.95}
.app-section {background:white;padding:18px;border-radius:10px;
box-shadow:0 3px 12px rgba(0,0,0,.07);margin-bottom:16px}
.answer-panel {border-left:4px solid #5f9eea}
.process-panel {border-left:4px solid #7a8ca5}
.source-panel {border-left:4px solid #65a97b}
.footer {text-align:center;padding:14px;margin-top:24px;color:#666;
font-size:.9rem;border-top:1px solid #e6e6e6}
"""
JURISDICTION_CHOICES = [
(str(details["name"]), code)
for code, details in JURISDICTIONS.items()
]
def clear_interface():
return "", "", "", "", "", "Status: Ready"
with gr.Blocks(title=APP_TITLE, fill_width=True) as demo:
with gr.Column(elem_classes="app-header"):
gr.Markdown(f"# {APP_TITLE}")
gr.Markdown(APP_SUBTITLE)
with gr.Column(elem_classes="app-section"):
gr.Markdown(
"Select a jurisdiction, then enter a nutrient-policy, "
"wastewater-management, or regulatory-compliance question. "
"The agent will search the corresponding regulatory vector "
"database and generate a grounded answer."
)
with gr.Row():
jurisdiction_dropdown = gr.Dropdown(
choices=JURISDICTION_CHOICES,
value=DEFAULT_JURISDICTION,
label="Jurisdiction",
interactive=True,
)
question_box = gr.Textbox(
label="Question",
placeholder=(
"Example: What phosphorus-related compliance requirements "
"apply to municipal wastewater treatment facilities?"
),
lines=4,
)
with gr.Row():
top_k_slider = gr.Slider(
1,
15,
value=TOP_K_RETRIEVAL,
step=1,
label="Passages retrieved per search",
)
max_loops_slider = gr.Slider(
1,
10,
value=min(MAX_RETRIEVAL_LOOPS, 10),
step=1,
label="Maximum retrieval steps",
)
with gr.Row():
run_button = gr.Button(
"Run RAG Agent",
variant="primary",
)
clear_button = gr.Button("Clear")
status_button = gr.Button("Check System")
system_status = gr.Textbox(
value="Status: Ready",
label="System status",
lines=20,
interactive=False,
)
with gr.Column(elem_classes="app-section"):
gr.Markdown("## Uploaded document mode")
gr.Markdown(
"Process one document independently from the Florida and New Jersey "
"regulatory databases. Supported formats are PDF, DOC, DOCX, PPTX, "
"HTML, and TXT. The temporary session expires after 30 minutes "
"of inactivity."
)
uploaded_document = gr.File(
label="Document",
file_types=[".pdf", ".doc", ".docx", ".pptx", ".html", ".txt"],
type="filepath",
)
process_document_button = gr.Button(
"Process document",
variant="secondary",
)
document_requested_session_id = gr.Textbox(
label="Requested document session ID",
visible=False,
)
document_session_id = gr.Textbox(
label="Document session ID",
visible=False,
)
document_ready = gr.Checkbox(
label="Document database ready",
value=False,
visible=False,
)
document_session_valid = gr.Checkbox(
label="Document session valid",
value=False,
visible=False,
)
document_session_validation_message = gr.Textbox(
label="Document session validation message",
visible=False,
)
validate_document_session_button = gr.Button(
"Validate Uploaded Document Session",
visible=False,
)
document_status = gr.Markdown(
"No document has been processed."
)
vector_download = gr.File(
label="Download temporary vector database",
interactive=False,
)
document_question = gr.Textbox(
label="Question about the uploaded document",
lines=3,
)
with gr.Row():
run_document_button = gr.Button(
"Ask Uploaded Document",
variant="primary",
)
clear_document_button = gr.Button(
"Clear Uploaded Document Session"
)
# Hidden components used by the resumable job API.
resumable_requested_job_id = gr.Textbox(
visible=False,
label="Requested resumable job ID",
)
resumable_job_id = gr.Textbox(
visible=False,
label="Resumable job ID",
)
resumable_job_status = gr.Textbox(
visible=False,
label="Resumable job status JSON",
)
resumable_start_button = gr.Button(
"Start resumable state RAG job",
visible=False,
)
resumable_start_document_button = gr.Button(
"Start resumable document RAG job",
visible=False,
)
resumable_start_document_processing_button = gr.Button(
"Start resumable document-processing job",
visible=False,
)
resumable_status_button = gr.Button(
"Get resumable RAG job status",
visible=False,
)
resumable_forget_button = gr.Button(
"Forget resumable RAG job",
visible=False,
)
with gr.Column(
elem_classes=["app-section", "answer-panel"]
):
gr.Markdown("## Grounded answer")
answer_output = gr.Markdown(
"The final grounded answer will appear here."
)
with gr.Accordion(
"Retrieval process",
open=True,
elem_classes=["app-section", "process-panel"],
):
process_output = gr.Markdown(
"No retrieval has been run."
)
with gr.Accordion(
"Retrieved source passages",
open=False,
elem_classes=["app-section", "source-panel"],
):
sources_output = gr.Markdown(
"No sources have been retrieved."
)
with gr.Accordion("Run diagnostics", open=False):
diagnostics_output = gr.Textbox(
label="Diagnostics",
lines=12,
interactive=False,
)
with gr.Column(elem_classes="footer"):
gr.Markdown(
"WNP-ARAG | Built with Gradio, FAISS, "
"LangChain, and Llama 3.1"
)
inputs = [
question_box,
jurisdiction_dropdown,
top_k_slider,
max_loops_slider,
]
outputs = [
answer_output,
process_output,
sources_output,
diagnostics_output,
]
run_button.click(
run_rag_agent,
inputs,
outputs,
api_name="run_rag_agent",
api_visibility="public",
)
resumable_start_button.click(
start_rag_job,
inputs=[
question_box,
jurisdiction_dropdown,
top_k_slider,
max_loops_slider,
resumable_requested_job_id,
],
outputs=resumable_job_id,
api_name="start_rag_job",
api_visibility="public",
queue=False,
)
resumable_start_document_processing_button.click(
start_document_processing_job,
inputs=[
uploaded_document,
document_requested_session_id,
resumable_requested_job_id,
],
outputs=resumable_job_id,
api_name="start_document_processing_job",
api_visibility="public",
queue=False,
)
resumable_start_document_button.click(
start_document_rag_job,
inputs=[
document_question,
document_session_id,
top_k_slider,
max_loops_slider,
resumable_requested_job_id,
],
outputs=resumable_job_id,
api_name="start_document_rag_job",
api_visibility="public",
queue=False,
)
resumable_status_button.click(
get_rag_job_status,
inputs=resumable_job_id,
outputs=resumable_job_status,
api_name="get_rag_job_status",
api_visibility="public",
queue=False,
)
resumable_forget_button.click(
forget_rag_job,
inputs=resumable_job_id,
outputs=resumable_job_status,
api_name="forget_rag_job",
api_visibility="public",
queue=False,
)
question_box.submit(
run_rag_agent,
inputs,
outputs,
api_visibility="private",
)
process_document_button.click(
process_uploaded_document,
inputs=[
uploaded_document,
document_requested_session_id,
],
outputs=[
document_session_id,
document_status,
vector_download,
document_ready,
],
api_name="process_uploaded_document",
api_visibility="public",
)
run_document_button.click(
run_document_rag,
inputs=[
document_question,
document_session_id,
top_k_slider,
max_loops_slider,
],
outputs=outputs,
api_name="run_document_rag",
api_visibility="public",
)
validate_document_session_button.click(
validate_document_session,
inputs=document_session_id,
outputs=[
document_session_valid,
document_session_validation_message,
],
api_name="validate_document_session",
api_visibility="public",
queue=False,
)
clear_document_button.click(
clear_document_session,
inputs=document_session_id,
outputs=document_status,
api_name="clear_document_session",
api_visibility="public",
queue=False,
)
clear_button.click(
clear_interface,
outputs=[
question_box,
answer_output,
process_output,
sources_output,
diagnostics_output,
system_status,
],
api_name="clear_interface",
queue=False,
)
status_button.click(
check_system_status,
outputs=system_status,
api_name="check_system_status",
queue=False,
)
if __name__ == "__main__":
demo.queue(
default_concurrency_limit=DEFAULT_CONCURRENCY_LIMIT
).launch(
debug=True,
show_error=True,
theme=gr.themes.Glass(primary_hue="blue"),
css=CUSTOM_CSS,
allowed_paths=[str(UPLOAD_SESSION_ROOT.resolve())],
ssr_mode=False,
)