parhamkhoshsolat's picture
StudyHub web β€” custom Docker frontend (FastAPI + SPA)
8db761b verified
Raw
History Blame Contribute Delete
5.39 kB
from __future__ import annotations
from .service import StudyService
def _sources_md(result) -> str:
return ("**Sources** (open the files below to verify at the exact slide/page)\n\n" + result.sources_md) \
if result.sources_md else ""
def build_app(service: StudyService, title: str = "StudyHub"):
import gradio as gr
with gr.Blocks(title=title) as demo:
gr.Markdown(
f"# {title}\nBrowse by topic or ask freely. Answers are grounded in the course materials, "
"cite the exact file + slide/page, and reply in your language β€” even when the source is in "
"Italian. Short snippets go to a no-training model provider to generate answers."
)
with gr.Tab("Topics"):
gr.Markdown("Pick a module β†’ a topic. Answers draw on **all** of that topic's sources "
"(slides, notes, transcripts), each cited.")
module_dd = gr.Dropdown(
choices=[(f"{m['title']} Β· {m['lecturer']}".strip(" Β·"), m["id"]) for m in service.modules()],
label="Module",
)
topic_dd = gr.Dropdown(choices=[], label="Topic")
t_sources = gr.Markdown()
sum_btn = gr.Button("Generate summary")
t_summary = gr.Markdown()
t_sum_files = gr.File(label="Summary sources β€” download the cited files", file_count="multiple")
gr.Markdown("β€”")
with gr.Row():
t_q = gr.Textbox(label="Ask about this topic (any language)", lines=1, scale=4)
t_ask = gr.Button("Ask", variant="primary", scale=1)
t_ans = gr.Markdown()
t_ans_src = gr.Markdown()
t_files = gr.File(label="Cited sources", file_count="multiple")
def _topic_src_md(tid):
srcs = service.topic_sources(tid) if tid else []
if not srcs:
return "_No sources linked to this topic yet._"
return "**Sources:** " + " Β· ".join(f"`{s['type']}` {s['file'].split('/')[-1]}" for s in srcs)
def _on_module(mid):
choices = [(t["title"], t["id"]) for t in service.topics(mid)] if mid else []
return gr.update(choices=choices, value=None), ""
def _summarize(tid):
if not tid:
return "Pick a topic first.", []
r = service.topic_summary(tid)
return (r.answer + (("\n\n" + _sources_md(r)) if r.sources_md else "")), service.cited_files(r)
def _topic_ask(tid, q):
if not tid:
return "Pick a topic first.", "", []
r = service.topic_ask(tid, q or "")
return r.answer, _sources_md(r), service.cited_files(r)
module_dd.change(_on_module, inputs=module_dd, outputs=[topic_dd, t_sources])
topic_dd.change(_topic_src_md, inputs=topic_dd, outputs=t_sources)
sum_btn.click(_summarize, inputs=topic_dd, outputs=[t_summary, t_sum_files])
t_ask.click(_topic_ask, inputs=[topic_dd, t_q], outputs=[t_ans, t_ans_src, t_files])
with gr.Tab("Ask"):
q = gr.Textbox(label="Your question (Italian or English)", lines=2)
ask = gr.Button("Ask", variant="primary")
a_ans = gr.Markdown()
a_src = gr.Markdown()
a_files = gr.File(label="Cited sources β€” click to open/download", file_count="multiple")
def _ask(query):
r = service.ask(query or "")
return r.answer, _sources_md(r), service.cited_files(r)
ask.click(_ask, inputs=q, outputs=[a_ans, a_src, a_files])
with gr.Tab("Summaries"):
doc = gr.Dropdown(choices=service.list_files(), label="Document")
sbtn = gr.Button("Summarize", variant="primary")
s_out = gr.Markdown()
s_src = gr.Markdown()
s_files = gr.File(label="Cited sources β€” click to open/download", file_count="multiple")
def _sum(file):
if not file:
return "Pick a document first.", "", []
r = service.summarize(file)
return r.answer, _sources_md(r), service.cited_files(r)
sbtn.click(_sum, inputs=doc, outputs=[s_out, s_src, s_files])
with gr.Tab("Quiz"):
topic = gr.Textbox(label="Topic")
n = gr.Slider(1, 10, value=5, step=1, label="Number of questions")
qbtn = gr.Button("Generate quiz", variant="primary")
q_out = gr.Markdown()
q_src = gr.Markdown()
q_files = gr.File(label="Cited sources β€” click to open/download", file_count="multiple")
def _quiz(t, num):
r = service.quiz(t or "", int(num))
return r.answer, _sources_md(r), service.cited_files(r)
qbtn.click(_quiz, inputs=[topic, n], outputs=[q_out, q_src, q_files])
with gr.Tab("Browse & Download"):
mat = gr.Dropdown(choices=service.list_files(), label="Material")
dbtn = gr.Button("Get file")
dfile = gr.File(label="Download")
def _dl(file):
return service.download_path(file) if file else None
dbtn.click(_dl, inputs=mat, outputs=dfile)
return demo