Skip to content

whats2000/PaperHub

PaperHub logo

PaperHub

A paper-aware chat client where every cited sentence traces back to its source.

Multi-agent tool routing · in-repo RAG knowledge base · agentic per-paper retrieval · a Citation Canvas that links every [chunk] back to the exact passage in the paper · a conference-grade Beamer slide pipeline with decoupled, editable speaker notes.

Python TypeScript FastAPI Vite Lint Types Tests Status License

English · 日本語 · 繁體中文 · 简体中文


PaperHub is built UX-first. Every retrieved chunk has a clickable provenance trail, every generation step writes an audit row, and every chat turn is reconstructible from SQLite alone. A single chat interface routes each turn to the right specialist agent — paper search, paper Q&A, NL→SQL library stats, memory curation, or slide generation.

✨ What it does

  • 🔎 Agentic paper retrieval. A per-paper subagent navigates each paper by its section table-of-contents (not blind top-k); a flagship model synthesises across papers over the raw cited chunks.
  • 🧷 Citation Canvas. Inline [chunk:N] markers link back to the exact passage — click to highlight it in both the rendered HTML and the source PDF. No ungrounded claims.
  • 🌍 Answers in your language. Ask in Chinese, get Chinese — citations preserved. A remembered "always reply in X" preference overrides per-turn detection.
  • 📊 Library stats in plain language. "How many papers do I have?" → a library_stats agent runs read-only SQL over a table allowlist, self-repairs, and answers with the numbers and the SQL it ran.
  • 🧠 Session + global memory. Remembered facts/preferences persist per-chat or everywhere — with a safety gate (refuses secrets), LLM conflict-supersede, and a Memory Manager panel to view/edit/(de)activate.
  • 🧭 Visible routing + tracing. A badge shows which agent + model handled each turn; an expandable trace panel replays every model/MCP/pipeline step from SQLite.
  • 🌐 Discovery via web + Semantic Scholar. paper_search resolves even vague references ("that diffusion paper everyone cites") to a citable hit.
  • 📎 Bring your own papers. Attach by arXiv ID, URL, or PDF upload — deduplicated + cached; a background Marker worker upgrades PDFs to real figures + captions + equations→LaTeX.
  • 🖼️ Conference-grade slides. Generate a grounded Beamer deck that never cites a figure that doesn't exist. Speaker notes are an opt-in, any-language follow-up; diff-edit a single slide by chat ("make slide 3 more concise") — never a full regen. Ask about the on-screen slide ("explain this diagram") and it's answered from the paper without mutating the deck.
  • 🔱 Fork & rewind. Branch a new chat from any of your past messages — the original is left intact. The forked message is prefilled, editable, not auto-sent: edit it to re-prompt, or send as-is to retry. Forks carry over the enabled references, session memories, and the deck, and nest under their parent in the sidebar.
  • ➗ Math renders. LaTeX in answers ($…$, $$…$$) renders as real equations via KaTeX.
  • 💾 Pick up on any device. Sessions and their full chat record live in the backend, not the browser — open the app anywhere. Deleting a chat removes it everywhere (with Undo).
  • 🔌 MCP-native. The agent's own tools are served over MCP (/mcp); external clients (Claude Desktop, Cursor) reach the same surface.

📸 Screenshots

Grounded answers — every claim traces back to the source.

Citation Canvas → rendered HTML Citation Canvas → source PDF
Citation Canvas highlighting a cited chunk in the rendered paper HTML Same citation highlighted in the source PDF via a geometry overlay
Click any [chunk] → scroll to + highlight the exact passage in the LaTeX-rendered HTML. …and the same passage in the original PDF. No ungrounded claims.

Conference-grade slides — decoupled, opt-in notes.

Generate (slides only) Speaker notes added on request
Deck chip with a Generate-notes button and the Slides panel open Slides panel with the speaker-note pane filled in
A Beamer deck with real figures (no hallucinated graphics) — slides first, no notes. Notes are an opt-in follow-up, authored separately (and in any language).

Library intelligence + memory.

NL→SQL library stats Session + global memory
A stats answer showing the numbers and the read-only SQL it ran Memory Manager with session/global groups and supersede badges
"How many papers do I have?" → answered with the numbers and the exact SQL. Remembered facts/preferences with a safety gate + conflict-supersede history.

Routing + observability.

Routing badge Trace panel (replayable DAG)
A chat turn tagged with the routing badge showing intent and model Expanded trace panel listing each step with latency and status
Every turn shows which agent + model handled it. Each model/MCP/pipeline step is an audit row — the full DAG replays from SQLite.

Discovery + bringing your own papers.

Paper search cards Reference Sources drawer
Paper-search result cards with Add-as-reference buttons Reference Sources drawer listing the session's enabled papers
Discovery via web + Semantic Scholar; the agent auto-adds its best picks. Session-scoped reference set with per-paper enable/remove.
More — app overview & answering in your language
The shell Answers in your language
Full PaperHub window: sidebar, chat, composer A Chinese question answered in Chinese with citation markers preserved
One chat shell; every turn routed to a specialist agent. Ask in any language — the answer follows, citations preserved.

🧱 Tech stack

Area Choice
Backend Python 3.11 · FastAPI · LangGraph · LiteLLM · SQLite (aiosqlite) · Pydantic v2
Frontend TypeScript · React 19 · Vite · Tailwind · Zustand · react-markdown + KaTeX
Retrieval SQLite chunks table — agentic section navigation via list_sections/read_section (no vector store)
Slides Beamer + pdflatex (metropolis theme) · datalab-to/marker PDF ingestion as a docker-compose service (optional, GPU-aware)
LLM Gemini by default (any LiteLLM provider — small-tier subagents, flagship finalizer)
Tooling uv · pytest · ruff · mypy --strict · Vitest · ESLint · Conventional Commits

Local-only, single-user. No auth surface — point it at your own LLM key and run it on your machine.


🚀 Quick start

🐳 Run with Docker (recommended — just use the app)

If you want to run PaperHub rather than develop it, the whole stack runs in containers — no Python, Node, or LaTeX to install. You only need Docker and an LLM key. One docker compose up brings up all five services (backend, model-server, Marker PDF ingestion, web-search, and the web UI), so slides (incl. Chinese/CJK), RAG, and web discovery all work out of the box.

git clone https://github.com/whats2000/PaperHub.git
cd PaperHub
cp backend/.env.example backend/.env   # then fill in GEMINI_API_KEY (or your provider's key)

docker compose up -d --build           # CPU; first build downloads TeX Live + Marker weights (a few GB, once)

Open http://localhost:8080.

GPU (optional, NVIDIA + Container Toolkit): faster Marker PDF ingestion. Layer the GPU override:

docker compose -f docker-compose.yml -f docker-compose.gpu.yml up -d --build

Data persists in named volumes (paperhub-workspace = DB + caches, model weights, Marker weights). docker compose down stops it; add -v to wipe the data too.


🛠️ Run from source (for development)

Prerequisites: Python 3.11 + uv, Node 18+, and an LLM API key (Gemini by default). Slide generation additionally needs a LaTeX distribution on PATH (pdflatex — e.g. winget install MiKTeX.MiKTeX); without it, only the slides intent is affected (it returns an "install a LaTeX distribution" message). PDF figure/equation extraction can optionally use the Dockerized marker service (docker compose up -d marker).

git clone https://github.com/whats2000/PaperHub.git
cd PaperHub

# Install both halves
cd backend && uv sync          # Python deps from uv.lock
cd ../frontend && npm install  # JS deps from package-lock.json

Configure your LLM key:

cd backend
cp .env.example .env           # then fill in GEMINI_API_KEY (or your provider's key)

Run the dev stack

Recommended (Windows, one command): scripts/start.ps1 orchestrates all the sibling processes — it brings up the external MCP daemons (open-websearch) via paperhub-mcp-up, then the backend with hot-reload:

# Terminal 1 — backend stack (MCP daemons + FastAPI on :8000)
cd backend
.\scripts\start.ps1
# Terminal 2 — frontend (Vite + React, hot-reload, :5173)
cd frontend
npm run dev

Open http://localhost:5173 and start chatting.

Lower-level: run uvicorn directly
cd backend
uv run uvicorn paperhub.app:app --reload --reload-dir src --port 8000

Note: this path does not start the web-search daemon for you. On Windows, uvicorn --reload runs on a SelectorEventLoop, so the in-worker autostart falls back gracefully (papers-only) — bring web search up yourself with uv run paperhub-mcp-up (or use scripts/start.ps1, which does it). See the web-search note under Configuration.

No API key handy? Exercise the chat plumbing with mocked LLMs (PowerShell):

$env:PAPERHUB_ROUTER_MOCK   = '{"intent":"chitchat","model_tier":"small","confidence":0.9,"reasoning":"dev"}'
$env:PAPERHUB_CHITCHAT_MOCK = "Hello from PaperHub!"
uv run uvicorn paperhub.app:app --reload --reload-dir src --port 8000

⚙️ Configuration

All settings live in backend/.env (grouped by function in .env.example). The ones you'll likely touch:

Variable Purpose Default
GEMINI_API_KEY LLM provider credential (or OPENAI_API_KEY / ANTHROPIC_API_KEY)
PAPERHUB_PAPER_QA_MODEL Flagship finalizer (cross-paper synthesis) gemini/gemini-2.5-pro
PAPERHUB_PAPER_QA_SUBAGENT_MODEL Per-paper section navigator (lightweight) gemini/gemini-3.1-flash-lite
PAPERHUB_SEMANTIC_SCHOLAR_API_KEY Higher Semantic Scholar rate limit (optional)

Web-search discovery (optional). paper_search / paper_suggest gain a no-key multi-engine discovery step when an open-websearch daemon is reachable on :3000. You don't install it by hand — scripts/start.ps1 (or uv run paperhub-mcp-up) reads mcp_servers.toml and launches every launch-declaring MCP server for you via npx -y, which fetches the package on first run (~25s, one-time):

cd backend
uv run paperhub-mcp-up          # launches open-websearch on :3000 (skips if already up)

When it's up, the backend's MCP registry auto-exposes web.search / web.fetch. When it's down, the agent falls back to a papers-only flow — no config needed. Spawned daemons are detached so they survive backend --reload; explicit teardown is start.ps1's job (otherwise they clear at reboot). Requires Node 18+ on PATH. (The paperhub-papers MCP surface ships in-process at /mcp; no install required.)


🗺️ Architecture (one screen)

┌─────────────────┐       SSE      ┌───────────────────────────────────────────┐
│  React shell    │ ◄───────────── │ FastAPI · POST /chat                      │
│  - Composer     │                │  ┌─────────────────────────────────────┐  │
│  - Routing badge│                │  │ LangGraph turn                      │  │
│  - Trace panel  │                │  │  Router ─► chitchat | paper_qa |    │  │
│  - Citation     │                │  │           paper_search | slides |   │  │
│    Canvas       │                │  │           library_stats             │  │
└─────────────────┘                │  └─────────────────────────────────────┘  │
                                   │     │                                     │
                                   │     ▼  paper_qa: fan out one subagent     │
                                   │        per paper → section nav →          │
                                   │        flagship finalizer over raw chunks │
                                   │  ┌─────────┐ ┌────────────────────────┐   │
                                   │  │ LiteLLM │ │ SQLite (chunks + audit │   │
                                   │  │ adapter │ │ + schema)              │   │
                                   │  └─────────┘ └────────────────────────┘   │
                                   └───────────────────────────────────────────┘

Every model call, MCP call, and pipeline step writes a tool_calls row before returning — enough state to reconstruct the full agent context from SELECT * FROM tool_calls WHERE run_id = ? alone. Paper content is deduplicated: one paper_content row + one cache dir + one set of chunks per unique paper, regardless of how many sessions reference it.

Full architecture lives in the SRS.


📍 Status

Plan Scope State
A Backend foundation + Router-only chat ✅ complete
B Frontend foundation (React shell, SSE, routing badge, trace panel) ✅ complete
C Paper Pipeline + Research Agent (ingest, paper_search, agentic paper_qa, MCP layer, PDF upload) ✅ complete — merged (SRS v2.10)
D Search results + Reference Sources + Citation Canvas (HTML + PDF passage highlighting) ✅ complete — merged (SRS v2.13)
E SQL Agent + library_stats (sqlite MCP) + session/global memory governance (gate, conflict-supersede, Memory Manager UI) ✅ complete — merged (SRS v2.17)
F Slide Pipeline + Report Agent — Marker ingestion (F2/F2.1), PhD-grade slide agent (F3), decoupled opt-in notes + diff-editing + length budget (F4), conference-grade metadata title page + title/style customization (F4.2) ✅ complete — merged (SRS v2.22)
F5 Slide presentation mode (audience pop-up window + BroadcastChannel sync + presenter cockpit) + Q&A-during-talk + composer voice input ✅ complete — merged (SRS v2.26)
G Frontend UI internationalization (i18n: en / zh-TW / zh-CN / ja) + account menu (language / theme switcher, About) + DB-backed runtime Settings panel ✅ complete — merged (SRS v2.31)
H Compare view + filesystem / paperhub.* MCP 🔜 planned

Each plan ships working, testable software on its own. Plans live under docs/superpowers/plans/.


🧑‍💻 Development

PaperHub is built spec → plan → TDD, with subagent-driven implementation and per-task spec-compliance + code-quality review.

Backend gates (from backend/):

uv run pytest          # 1104 tests, hermetic
uv run ruff check src tests
uv run mypy src        # --strict

Frontend gates (from frontend/):

npm test               # Vitest + RTL + MSW (386 tests)
npm run typecheck      # tsc --strict
npm run lint           # ESLint flat config
npm run build          # Vite production build

Replay any past chat turn from SQLite (debugging the agent flow):

cd backend
uv run paperhub-replay --run-id 1

End-to-end benchmarkpytest proves the wiring; the backend/benchmark/ harness proves the behaviour. It drives the live backend as a simulated user (attach cached papers → route prompts through /chat), collects grounding evidence (cited chunk text + agent trace), and scores each case 0/1 on correctness + grounding — by hand or via an LLM-as-Judge (fixed temperature, strict grounding). Cases are config-driven (TOML), so you can write your own:

# with the backend running (scripts/start.ps1), from backend/:
scripts/run-benchmark.ps1 -Judge            # 20-case eval (16 paper_qa + 4 slides) + LLM judge
scripts/run-benchmark.ps1 -Resume <prior.json>   # retry only failed cases after a drop

Contributing AI agents: read CLAUDE.md first — it carries the conventions, the fix-now policy, and the agent-flow observability rules.


📂 Repository layout

.
├── backend/
│   ├── src/paperhub/         # FastAPI app · agents · pipelines · mcp · tracer
│   ├── tests/                # pytest suite (1104 tests, hermetic)
│   ├── benchmark/            # config-driven real-API e2e benchmark + LLM-as-Judge
│   └── pyproject.toml        # uv project · mypy --strict · ruff
├── frontend/                 # React 19 + Vite + Tailwind + Zustand
├── docs/superpowers/
│   ├── specs/                # SRS — authoritative architecture document
│   └── plans/                # implementation plans, one per sub-project
├── reference/                # copied source from paper2slides-plus + Intro2GenAI-hw1
├── CLAUDE.md                 # AI-agent orientation for this repo
└── README.md

workspace/ (gitignored) holds runtime state — the SQLite database and the papers cache.


📖 Documentation


📚 Citation

If you use PaperHub in your research or build on it, please cite it:

@software{paperhub,
  author  = {Ren-Di, Wu},
  title   = {{PaperHub: A Provenance-First Multi-Agent Research Assistant for Grounded Paper Q\&A and Slide Generation}},
  year    = {2026},
  url     = {https://github.com/whats2000/PaperHub},
  version = {2.31.2}
}

📄 License

Apache License 2.0 — © PaperHub contributors. You may use, modify, and distribute this software under the terms of the license, which includes an express grant of patent rights from contributors.

About

A paper-aware chat client where every cited sentence traces back to its source.

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors