router-ui / app.py
GodRad's picture
Upload 3 files
8165105 verified
Raw History Blame Contribute Delete
5.66 kB
import gradio as gr
import requests
import os
import json
import tempfile
from fpdf import FPDF
from docx import Document
# Backend URLs (should be set via Environment Variables in HF Spaces)
CPU_BACKEND_URL = os.getenv("CPU_BACKEND_URL", "http://localhost:7860")
GPU_BACKEND_URL = os.getenv("GPU_BACKEND_URL", "http://localhost:7861")
API_KEY = os.getenv("API_KEY", "")
def get_backend_url(mode):
return GPU_BACKEND_URL if mode == "GPU (Faster)" else CPU_BACKEND_URL
def health_check(mode):
url = get_backend_url(mode)
try:
resp = requests.get(f"{url}/health", timeout=5)
return resp.json()
except Exception as e:
return {"error": str(e)}
def upload_files(mode, files):
if not files:
return "No files selected."
if len(files) > 3:
return "Error: Maximum 3 files allowed."
url = get_backend_url(mode)
headers = {"X-API-Key": API_KEY} if API_KEY else {}
results = []
for file in files:
with open(file.name, "rb") as f:
file_payload = {"file": (os.path.basename(file.name), f)}
try:
resp = requests.post(f"{url}/ingest", files=file_payload, headers=headers)
results.append(f"{os.path.basename(file.name)}: {resp.json()}")
except Exception as e:
results.append(f"{os.path.basename(file.name)}: Error - {str(e)}")
return "\n".join(results)
def generate_files(content):
# 1. TXT
txt_fd, txt_path = tempfile.mkstemp(suffix=".txt")
with os.fdopen(txt_fd, 'w', encoding='utf-8') as f:
f.write(content)
# 2. DOCX
doc = Document()
doc.add_heading('Course Syllabus', 0)
# Simple split by lines to add as paragraphs
for line in content.split('\n'):
doc.add_paragraph(line)
docx_fd, docx_path = tempfile.mkstemp(suffix=".docx")
os.close(docx_fd)
doc.save(docx_path)
# 3. PDF
pdf = FPDF()
pdf.add_page()
pdf.set_font("Arial", size=12)
# Replace unsupported characters for basic FPDF
safe_content = content.encode('latin-1', 'replace').decode('latin-1')
pdf.multi_cell(0, 10, txt=safe_content)
pdf_fd, pdf_path = tempfile.mkstemp(suffix=".pdf")
os.close(pdf_fd)
pdf.output(pdf_path)
return [txt_path, docx_path, pdf_path]
def generate_syllabus(mode, course_name, description, constraints):
url = get_backend_url(mode)
headers = {"X-API-Key": API_KEY} if API_KEY else {}
payload = {
"course_name": course_name,
"description": description,
"constraints": constraints
}
try:
resp = requests.post(f"{url}/generate_syllabus", json=payload, headers=headers)
data = resp.json()
syllabus_text = ""
if "syllabus" in data:
syllabus_text = data["syllabus"]
else:
syllabus_text = json.dumps(data, indent=2)
# Generate downloadable files
files = generate_files(syllabus_text)
return syllabus_text, files, None # Success
except Exception as e:
return f"Error: {str(e)}", [], f"Error details: {str(e)}"
# UI Layout
with gr.Blocks(title="Open Source Syllabus Engine") as demo:
gr.Markdown("# 🎓 Open Source Syllabus Engine")
gr.Markdown("Ingest your documents and generate a production-grade syllabus using RAG.")
with gr.Row():
mode_radio = gr.Radio(
choices=["CPU (Free)", "GPU (Faster)"],
value="CPU (Free)",
label="Select Backend"
)
health_btn = gr.Button("Check Connection")
health_output = gr.JSON(label="Backend Status")
health_btn.click(health_check, inputs=[mode_radio], outputs=[health_output])
with gr.Tab("1. Ingest Documents"):
gr.Markdown("Upload up to 3 documents (PDF, DOCX, TXT) to provide context for the syllabus.")
file_input = gr.File(label="Upload Documents", file_count="multiple")
ingest_btn = gr.Button("Ingest Files")
ingest_output = gr.Text(label="Ingestion Result")
ingest_btn.click(upload_files, inputs=[mode_radio, file_input], outputs=[ingest_output])
with gr.Tab("2. Generate Syllabus"):
with gr.Row():
course_name = gr.Textbox(label="Course Name", placeholder="e.g. Advanced Machine Learning")
course_desc = gr.Textbox(label="Description", placeholder="Describe what the course covers...")
constraints = gr.Textbox(label="Optional Constraints", placeholder="e.g. 10 weeks, include a final project")
gen_btn = gr.Button("Generate Syllabus", variant="primary")
with gr.Row():
gen_output = gr.Markdown(label="Generated Syllabus Preview")
with gr.Column():
gen_files = gr.File(label="Download Formats (.txt, .docx, .pdf)")
error_box = gr.Text(label="Debug Info", visible=True)
gen_btn.click(
generate_syllabus,
inputs=[mode_radio, course_name, course_desc, constraints],
outputs=[gen_output, gen_files, error_box]
)
gr.Markdown("---")
gr.Markdown("### Ops Notes")
gr.Markdown("- Ensure `CPU_BACKEND_URL` and `GPU_BACKEND_URL` are set correctly.")
gr.Markdown("- Use the API Key if authentication is enabled on the backends.")
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)