""" app.py — Topic Modelling Agentic AI | Gradio UI ═══════════════════════════════════════════════════ Version: 3.0.0 | April 2026 Stack: Gradio 5.x + LangGraph + Mistral + BERTopic Deploy: HuggingFace Spaces (sdk: gradio) Rules: Zero gr.HTML(). All UI via native Gradio components. See GRADIO_UI_GUIDELINES_v2.docx for full standards. ARCHITECTURE — 20 Blocks in 5 Sections ───────────────────────────────────────── Section 1: Setup (B1–B3) Imports, agent, theme Section 2: Helpers (B4–B10) Pure Python functions, no UI Section 3: UI Layout (B11–B17) gr.Blocks with native components Section 4: Event Wiring (B18–B19) Connect UI to functions Section 5: Launch (B20) Start server BLOCK COMMUNICATION MAP ───────────────────────── B6 (respond) ←→ B2 (agent) : invokes agent for chat B6 (respond) → B4 (output) : scans for download files B7 (chart) → B17a (display) : loads Plotly JSON → gr.Plot B8 (table) → B16 (review) : builds rows → gr.Dataframe B9 (papers) ← B16 (review) : triggered by row click B10 (submit) → B2 (agent) : sends review edits to agent B18 (wiring) → B5,B7,B8 : refreshes progress, charts, table """ import os import glob import json import plotly.io as pio import gradio as gr from langchain_mistralai import ChatMistralAI from langgraph.prebuilt import create_react_agent from langgraph.checkpoint.memory import MemorySaver from agent import SYSTEM_PROMPT, get_local_tools print(">>> app.py: imports complete") # ╔═══════════════════════════════════════════════════════════════╗ # ║ SECTION 1 — SETUP ║ # ║ One-time initialization: agent creation and visual theme. ║ # ║ Nothing here renders UI — it prepares the backend brain ║ # ║ and the visual identity for the entire application. ║ # ╚═══════════════════════════════════════════════════════════════╝ # ── B2: Agent setup ───────────────────────────────────────────── # PURPOSE: Create the LangGraph ReAct agent that powers all chat. # Connects Mistral LLM to BERTopic tools with memory so # the agent remembers context across conversation turns. # PRODUCES: `agent` — used by B6 (respond) and B10 (_submit_review) # IMPORTS: SYSTEM_PROMPT, get_local_tools from agent.py # NOTE: MemorySaver keeps conversation in RAM (resets on restart). # For persistent memory, swap to SQLite checkpointer. # ──────────────────────────────────────────────────────────────── llm = ChatMistralAI(model="mistral-small-latest", temperature=0, timeout=300) tools = get_local_tools() agent = create_react_agent( model=llm, tools=tools, prompt=SYSTEM_PROMPT, checkpointer=MemorySaver() ) print(f">>> app.py: agent ready ({len(tools)} tools)") _msg_count = 0 # Global message counter (shared across users) _uploaded = {"path": ""} # Last uploaded CSV path (shared session) # ── end B2: Agent setup ──────────────────────────────────────── # ── B3: Theme ─────────────────────────────────────────────────── # PURPOSE: Define the visual identity of the entire application. # Replaces ALL custom CSS that was previously in HEADER_HTML: # - DM Sans font (was @import url in