Spaces:
Sleeping
Sleeping
| """Gradio UI for the Lab Assistant. | |
| Run locally: py -3.12 app.py | |
| On Hugging Face: this file is the Space entry point (sdk: gradio). | |
| """ | |
| from __future__ import annotations | |
| import gradio as gr | |
| import config | |
| # Build the knowledge base on first boot if the artifacts are missing, so a fresh | |
| # clone or a freshly-pushed Space works without a manual ingest step. | |
| if not (config.CHUNKS_FILE.exists() and config.EMBEDDINGS_FILE.exists()): | |
| print("[app] knowledge base not found — running ingest at startup ...") | |
| try: | |
| import ingest | |
| ingest.main() | |
| except Exception as exc: # pragma: no cover | |
| print(f"[app] startup ingest failed: {exc}") | |
| import agent # noqa: E402 (import after potential ingest) | |
| import leads # noqa: E402 | |
| EXAMPLES = [ | |
| "What is Spatial-RAG and what problem does it solve?", | |
| "Summarize Prof. Zhao's work on graph retrieval-augmented generation.", | |
| "Is Prof. Zhao taking new PhD students, and what does he look for?", | |
| "What has the lab done on GNN explainability?", | |
| "How does the lab reduce LLM API costs?", | |
| ] | |
| HEADER = f""" | |
| # 🤖 {config.LAB_NAME} — Research Assistant | |
| **{config.PROFESSOR_NAME}** · {config.PROFESSOR_TITLE} | |
| Ask about the lab's research, publications, and opportunities. Answers are | |
| **grounded in the lab's publications with inline citations** — and the assistant | |
| will tell you when something is outside its knowledge rather than guess. | |
| [Homepage]({config.HOMEPAGE_URL}) · [Google Scholar]({config.SCHOLAR_URL}) | |
| """ | |
| ABOUT = """ | |
| **Prof. Liang Zhao** is an award-winning AI researcher at Emory University (Winship | |
| Distinguished Research Professor of Computer Science, with a joint appointment at the | |
| Winship Cancer Institute). He builds **scalable and trustworthy machine learning for | |
| structured, spatial, and scientific problems** — graph neural networks, | |
| spatio-temporal/geospatial reasoning, retrieval-augmented and agentic LLMs, AI for | |
| science, and efficient/trustworthy AI. | |
| His work spans a decade-long arc: from the deployed **EMBERS** civil-unrest forecasting | |
| system, through foundational **graph neural network** and **deep graph generation** | |
| research, to today's frontier of **graph & spatial RAG**, **agentic systems**, and | |
| **"world models" for science** (epidemiology, molecules, power grids). He is among | |
| **Stanford's "Top 2%" most-cited scientists** — **~12,200 citations, h-index 52** — | |
| with funding from **NSF (CAREER), NIH, Amazon, Meta, and NVIDIA**. | |
| _Ask below for a cited summary of any topic, e.g. graph RAG, Spatial-RAG, GNN | |
| explainability, LLM cost reduction, or his work on AI for science._ | |
| """ | |
| DISCLAIMER = ( | |
| "_This is an AI assistant prototype. Responses are generated automatically from " | |
| "the lab's public research and may be incomplete; they are not official " | |
| "statements from Prof. Zhao or Emory University. Verify deadlines, admissions, " | |
| "and funding through official channels._" | |
| ) | |
| def respond(message: str, chat_history: list): | |
| """Stream the assistant's reply into the chat history.""" | |
| message = (message or "").strip() | |
| if not message: | |
| yield "", chat_history | |
| return | |
| chat_history = (chat_history or []) + [{"role": "user", "content": message}] | |
| chat_history.append({"role": "assistant", "content": ""}) | |
| prior = chat_history[:-2] # history excluding the in-flight turn | |
| for partial in agent.stream_answer(message, prior): | |
| chat_history[-1]["content"] = partial | |
| yield "", chat_history | |
| # If they look like a prospective student/collaborator, nudge the lead form. | |
| if agent.wants_to_connect(message): | |
| chat_history[-1]["content"] += ( | |
| "\n\n👉 *Want the lab to reach out? Open **“📬 Connect with the lab”** " | |
| "below and leave your details.*" | |
| ) | |
| yield "", chat_history | |
| def submit_lead(name, email, role, interest): | |
| ok, msg = leads.save_lead(name, email, role, interest) | |
| prefix = "✅ " if ok else "⚠️ " | |
| return prefix + msg | |
| with gr.Blocks(title=f"{config.LAB_NAME} — Assistant") as demo: | |
| gr.Markdown(HEADER) | |
| with gr.Accordion("ℹ️ About Prof. Zhao", open=False): | |
| gr.Markdown(ABOUT) | |
| chatbot = gr.Chatbot(height=460, label="Lab Assistant", avatar_images=(None, None)) | |
| with gr.Row(): | |
| msg = gr.Textbox(placeholder="Ask about the lab's research or opportunities…", | |
| scale=8, show_label=False, autofocus=True) | |
| send = gr.Button("Send", variant="primary", scale=1) | |
| clear = gr.Button("Clear", scale=1) | |
| gr.Examples(examples=[[e] for e in EXAMPLES], inputs=[msg], label="Try asking") | |
| with gr.Accordion("📬 Connect with the lab (prospective students & collaborators)", open=False): | |
| gr.Markdown( | |
| "Leave your details and a note about your interest; they'll be passed to the lab." | |
| ) | |
| with gr.Row(): | |
| lead_name = gr.Textbox(label="Name", scale=1) | |
| lead_email = gr.Textbox(label="Email", scale=1) | |
| lead_role = gr.Dropdown( | |
| ["Prospective PhD student", "Prospective MS/undergrad", "Collaborator (academia)", | |
| "Collaborator (industry)", "Other"], | |
| label="I am a…", scale=1, | |
| ) | |
| lead_interest = gr.Textbox(label="Your interest / message", lines=2) | |
| lead_submit = gr.Button("Send to the lab", variant="primary") | |
| lead_status = gr.Markdown() | |
| footer = config.BUILT_BY and f"Prototype built by **{config.BUILT_BY}**. " | |
| gr.Markdown((footer or "") + DISCLAIMER) | |
| # wiring | |
| msg.submit(respond, [msg, chatbot], [msg, chatbot]) | |
| send.click(respond, [msg, chatbot], [msg, chatbot]) | |
| clear.click(lambda: [], None, chatbot, queue=False) | |
| lead_submit.click( | |
| submit_lead, [lead_name, lead_email, lead_role, lead_interest], [lead_status] | |
| ) | |
| if __name__ == "__main__": | |
| demo.queue().launch(theme=gr.themes.Soft()) | |