PaperMate / README.md
ntphuc149's picture
docs: update README — guardrails, sign-in flow, new API endpoints + statuses
6d8a15b
|
Raw
History Blame
18.7 kB
---
title: PaperMate
emoji: 📝
colorFrom: yellow
colorTo: red
sdk: docker
app_port: 7860
pinned: false
---
# PaperMate — AI Research Paper Review System
A web application that automatically evaluates research paper manuscripts using AI. Sign in, upload a PDF, and receive a structured peer-review following the **ACL Rolling Review (ARR)** format with scores across all 7 ARR dimensions.
**Live demo:** [ntphuc149-papermate.hf.space](https://ntphuc149-papermate.hf.space/)
**Pages:** `/app/home.html` (landing) · `/app/upload.html` (submit paper) · `/app/review.html` (view results)
---
## Architecture
```mermaid
flowchart TD
User(["👤 User"])
subgraph Frontend["Frontend (Vanilla JS)"]
UI_Home["home.html\nLanding Page"]
UI_Upload["upload.html\nUpload Page"]
UI_Review["review.html\nReview Viewer"]
end
subgraph Backend["Backend (FastAPI)"]
API_Submit["POST /api/submit"]
API_Review["GET /api/review/{key}"]
API_Feedback["POST /api/feedback/{key}"]
Auth["Auth (Supabase GoTrue\n+ Google OAuth)"]
EmailSvc["Email Service\n(Resend)"]
end
subgraph Pipeline["Background Pipeline"]
G0["0. Guardrails\n(G1a: Abstract? G1b: NLP/CL? G2: ≤8 pages?)"]
P1["1. PDF → ParsedPaper\n(LandingAI / Docling + VLM enrichment)"]
P2["2. Extract Title"]
P3a["3a. Extract Contributions"]
P3b["3b. Extract Research Topic"]
P4["4. Generate Search Queries"]
P5["5. Search Related Papers\n(Tavily — ACL Anthology + arXiv)"]
P6["6. Fetch Paper Metadata\n(arXiv API)"]
P7["7. Summarize Related Work"]
P8["8. Multi-Agent ARR Review\n(LangGraph — ReAct + Gated Pipeline)"]
end
subgraph External["External Services"]
LLM["LLM Provider\nAnthropic / OpenAI\nGemini / OpenRouter"]
Tavily["Tavily Search API"]
ArXiv["arXiv API"]
LandingAI["LandingAI ADE"]
Docling["Kaggle Docling Server\n(GPU T4 + gpt-4o-mini VLM)"]
Resend["Resend Email"]
Supabase["Supabase\n(PostgreSQL + Storage + Auth)"]
end
User -->|"Browse"| UI_Home
UI_Home -->|"CTA"| UI_Upload
User -->|"Google Login (optional)"| Auth
User -->|"Upload PDF + Email"| UI_Upload
UI_Upload -->|"POST /api/submit"| API_Submit
API_Submit -->|"access_key"| UI_Upload
API_Submit -->|"create job"| Supabase
API_Submit -->|"trigger async"| G0
G0 -->|"PASS"| P1
G0 -->|"REJECT"| Supabase
API_Submit -->|"send key email"| EmailSvc
User -->|"Enter access key"| UI_Review
UI_Review -->|"poll status"| API_Review
API_Review -->|"read job"| Supabase
P1 --> P2 --> P3a & P3b --> P4 --> P5 --> P6 --> P7 --> P8
P8 -->|"save review"| Supabase
P8 -->|"notify user"| EmailSvc
P1 --> LandingAI
P1 --> Docling
P3a & P3b & P7 & P8 --> LLM
P5 --> Tavily
P6 --> ArXiv
EmailSvc --> Resend
Auth --> Supabase
```
---
## Submission Eligibility
Before the pipeline runs, three sequential **guardrails** screen every submission:
| # | Check | Logic | On Fail |
|---|---|---|---|
| G1a | Is it a research paper? | Parse page 1 via Docling; require `section_header` = "Abstract" | Desk-reject |
| G1b | Is it NLP/CL? | Feed abstract text to LLM → classify NLP/Computational Linguistics scope | Desk-reject |
| G2 | Does it follow the page limit? | Reuse full parse; find `section_header` = "References" — must be on page ≤ 9 (≤ 8 content pages) | Desk-reject |
Rejected submissions receive a `status: rejected` record in the database with a vague, non-reversible reason so users cannot infer the guardrail mechanism.
---
## How It Works
1. User signs in (Google OAuth) and uploads a PDF manuscript + email
2. System returns an **access key** immediately (also sent via email)
3. Three guardrails run before the main pipeline — ineligible papers are desk-rejected immediately
4. AI pipeline runs in the background (~5–15 minutes):
- PDF → **`ParsedPaper`** (structured JSON with labeled elements)
- Extract title, contributions & research topic from abstract + introduction
- Generate search queries → find related papers (Tavily: ACL Anthology + arXiv)
- Summarize related work
- **Multi-agent review** (LangGraph ReAct + Gated Pipeline — see below)
5. User enters access key on the review page to read results
6. Email notification sent when review is ready
---
## Multi-Agent Review Pipeline (Step 8)
Step 8 uses a **LangGraph StateGraph** combining a **Gated Sequential Pipeline** with a **ReAct orchestrator loop** — mirroring how a senior Area Chair reads a paper: classify first, map claims, then iteratively investigate the riskiest ones.
### Pattern: ReAct + Gated Pipeline (Orchestrator-Subagents)
```mermaid
flowchart TD
START(["📄 ParsedPaper\n+ Related Summaries"])
subgraph G1["Gate 1 — Desk Check"]
DC["Read abstract + intro + conclusion\nClassify paper type\nDetect fatal flaws"]
end
subgraph G2["Gate 2 — Claim Mapper"]
CM["Read results + tables + conclusion\nMap each claim → Table N / Section X.Y\nAssign risk: high / medium / low"]
end
DR(["🚫 DESK REJECT\n→ Synthesizer"])
subgraph G3["Gate 3 — ReAct Deep Dive (max 5 loops)"]
direction TB
PL["🧠 Planner — Orchestrator\nTHOUGHT: most important unresolved question?\nACTION: pick tools + focus areas\n─────────────────────────────\nLoop 1–2 · breadth: cover all dimensions\nLoop 3–4 · depth: re-examine weak findings\nLoop 5 · final: novelty deep-dive or presentation"]
subgraph TOOLS["Subagents — run in parallel via asyncio.gather"]
T1["AuditMethodologyTool"]
T2["CheckNoveltyTool"]
T3["CheckReproducibilityTool"]
T4["AuditClaimsTool"]
T5["CheckStatisticalRigorTool"]
T6["AuditPresentationTool"]
T7["ResourceQualityTool"]
end
PL -->|"tools_to_run"| TOOLS
TOOLS -->|"findings — OBSERVATION"| PL
end
subgraph CP["Compactor"]
CO["Deduplicate + rank: critical → major → minor\nPreserve verbatim quotes & evidence locations\nKeep ≤ 12 findings"]
end
subgraph G4["Gate 4 — Synthesizer"]
SY["Strengths: scientific judgement — WHY it matters\nWeaknesses: verbatim quote + exact citation\nScore all 7 ARR metrics"]
end
FB(["🔄 Fallback\nlegacy review.py"])
OUT(["✅ ARR Review\n7 metrics + strengths + weaknesses"])
START --> G1
DC -->|"DESK REJECT"| DR
DC -->|"PASS"| G2
G2 --> G3
PL -->|"is_last_loop or done"| CP
CP --> G4
G4 -->|"success"| OUT
G4 -->|"error"| FB
FB --> OUT
style G1 fill:#1a1208,stroke:#f5a623,color:#f5a623
style G2 fill:#1a1208,stroke:#f5a623,color:#f5a623
style G3 fill:#1a1208,stroke:#f5a623,color:#f5a623
style G4 fill:#1a1208,stroke:#f5a623,color:#f5a623
style CP fill:#1a1208,stroke:#888,color:#aaa
style TOOLS fill:#111,stroke:#555,color:#ccc
style OUT fill:#1a3010,stroke:#2dc653,color:#2dc653
style DR fill:#2a0a0a,stroke:#e63946,color:#e63946
style FB fill:#1a1208,stroke:#888,color:#888
```
### Tool Applicability by Paper Type
| Tool | empirical | theoretical | resource | survey/position | reproduction | demo |
|---|:---:|:---:|:---:|:---:|:---:|:---:|
| AuditMethodologyTool | ✅ | — | ✅ | — | ✅ | — |
| CheckNoveltyTool | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| CheckReproducibilityTool | ✅ | — | ✅ | — | ✅ | ✅ |
| AuditClaimsTool | ✅ | ✅ | ✅ | — | ✅ | — |
| CheckStatisticalRigorTool | ✅ | — | ✅ | — | ✅ | — |
| AuditPresentationTool | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| ResourceQualityTool | — | — | ✅ | — | — | — |
### Output: Full ACL ARR Review
Every review includes all 7 ARR metrics with correct scales:
| Metric | Scale | Half-points |
|---|---|:---:|
| Soundness | 1–5 | ✅ |
| Excitement | 1–5 | ✅ |
| Reproducibility | 1–5 | — |
| Datasets | 1–5 or N/A | — |
| Software | 1–5 or N/A | — |
| Confidence | 1–5 | — |
| Overall Assessment | 1.0–5.0 | ✅ |
**Overall Assessment labels:**
| Score | Label |
|---|---|
| 5.0 | Award Candidate (top 2.5%) |
| 4.5 | Strong Accept — Conference |
| 4.0 | Accept — Conference |
| 3.5 | Borderline Findings |
| 3.0 | Borderline Findings |
| 2.5 | Borderline Reject |
| 2.0 | Reject |
| 1.5 | Strong Reject |
| 1.0 | Reject — Out of Scope |
---
## Tech Stack
| Layer | Technology |
|---|---|
| Frontend | Plain HTML + Vanilla JS (dark/light theme) |
| Backend | Python FastAPI + BackgroundTasks |
| Database | Supabase (PostgreSQL) — submissions, reviews, pipeline steps, observability |
| File Storage | Supabase Storage — original PDFs + parsed markdown |
| Auth | Supabase GoTrue + Google OAuth (optional; anonymous submit still works) |
| PDF Parsing | LandingAI ADE (cloud) **or** Docling on Kaggle GPU T4 (self-hosted) |
| VLM Enrichment | OpenAI gpt-4o-mini — formulas → LaTeX, tables → markdown, figures → desc |
| LLM Review | Configurable: Anthropic / OpenAI / Gemini / OpenRouter |
| Multi-Agent | LangGraph StateGraph — ReAct + Gated Pipeline (Orchestrator-Subagents) |
| Paper Search | Tavily Search API (ACL Anthology priority + arXiv/Semantic Scholar) |
| Email | Resend (3,000 free/month) |
| Deploy | Hugging Face Docker Spaces |
---
## Project Structure
```
paper_review/
├── backend/
│ ├── main.py # FastAPI app & endpoints
│ ├── config.py # Settings from environment variables
│ ├── auth.py # Supabase GoTrue auth + RBAC (admin / user roles)
│ ├── observability.py # Pipeline step + LLM call tracking
│ ├── email_service.py # Resend email integration
│ ├── logger.py # Per-job stdout + file logger (uvicorn-routed)
│ ├── llm/
│ │ └── client.py # Unified LLM client (multi-provider)
│ ├── pipeline/
│ │ ├── guardrails.py # Pre-pipeline eligibility checks (G1a/G1b/G2)
│ │ ├── parsed_paper.py # ParsedPaper schema + helper functions
│ │ ├── pdf2md.py # PDF → ParsedPaper (LandingAI or Docling)
│ │ ├── extract.py # Extract title, contributions & topic
│ │ ├── search.py # Generate queries + Tavily 2-tier search
│ │ ├── paper_info.py # arXiv metadata fetching
│ │ ├── summarize.py # Summarize related papers
│ │ ├── review.py # Legacy single-pass ARR review (fallback only)
│ │ └── review_agent/ # Multi-agent LangGraph reviewer (primary)
│ │ ├── state.py # ReviewAgentState + ToolFinding TypedDicts
│ │ ├── prompts.py # System prompts for all gates, tools & synthesizer
│ │ ├── tools.py # 7 analysis tools (paper-type gated, parallel)
│ │ ├── nodes.py # LangGraph node functions (desk_check, planner, ...)
│ │ └── graph.py # StateGraph wiring + run_review_agent() entry point
│ ├── storage/
│ │ ├── jobs.py # Storage backend selector
│ │ └── supabase_store.py # Supabase persistence layer
│ └── requirements.txt
├── frontend/
│ ├── home.html # Landing page (7-metric ARR rubric showcase)
│ ├── upload.html # Upload page — drag-drop PDF + email
│ ├── login.html # Google OAuth login
│ ├── review.html # Review viewer — ARR scores, strengths, weaknesses
│ ├── admin.html # Admin dashboard
│ ├── css/style.css # Dark/gold theme, shared across all pages
│ └── js/
│ ├── auth.js # Supabase auth client
│ ├── upload.js # File drag-drop, submit, access key display
│ ├── review.js # Key lookup, poll status, render all 7 ARR chips
│ ├── feedback.js # Feedback form submission
│ └── theme.js # Dark/light theme toggle
├── docs/
│ ├── database/ # Supabase schema docs + Google OAuth setup guide
│ └── parser/ # PDF parser evaluation, OCR benchmarks, test outputs
│ ├── scripts/ # Evaluation scripts (run_mvp_eval.py, test_docling_ocr.py)
│ ├── test/ # Parsed PDF JSONs + review outputs for manual evaluation
│ └── vinuni20k-parser-serving.ipynb # Kaggle Docling server notebook
├── scripts/
│ └── apply_migration.py # One-time DB migration runner
├── Dockerfile # Hugging Face Docker Space
├── .env.example # Template for environment variables
└── run.py # Quick-start script (local dev)
```
---
## Setup
### 1. Prerequisites
- Python 3.10+
- Supabase project (free tier works)
- API keys (see below)
### 2. Install dependencies
```bash
cd paper_review
pip install -r backend/requirements.txt
```
### 3. Configure environment variables
```bash
cp .env.example .env
```
Fill in `.env` — minimum required to run:
```env
LLM_PROVIDER=openai
LLM_MODEL=gpt-4o-mini
OPENAI_API_KEY=sk-...
PDF_PARSER=landingai
LANDINGAI_API_KEY=...
TAVILY_API_KEY=tvly-...
RESEND_API_KEY=re_...
RESEND_FROM_EMAIL=onboarding@resend.dev
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJ...
SUPABASE_ANON_KEY=eyJ...
SUPABASE_STORAGE_BUCKET=paper-mate-artifacts
ADMIN_EMAILS=your@email.com
APP_BASE_URL=http://localhost:8000
```
### 4. Set up Supabase
1. Create a project at [supabase.com](https://supabase.com)
2. Run the SQL migrations in order via the Supabase SQL Editor:
- `scripts/migrations/` — baseline schema, auth/RBAC, RPC functions
- `supabase/migrations/` — guardrail columns (`rejection_reason`, `rejected` status)
3. Create a Storage bucket named `paper-mate-artifacts` (public)
4. Enable Google OAuth: Authentication → Providers → Google
5. Set Redirect URL: `https://<your-supabase-project>.supabase.co/auth/v1/callback`
### 5. API Keys — Where to Get Them
| Key | Where to get |
|---|---|
| `OPENAI_API_KEY` | [platform.openai.com](https://platform.openai.com) |
| `ANTHROPIC_API_KEY` | [console.anthropic.com](https://console.anthropic.com) |
| `GEMINI_API_KEY` | [aistudio.google.com](https://aistudio.google.com) |
| `OPENROUTER_API_KEY` | [openrouter.ai](https://openrouter.ai) |
| `LANDINGAI_API_KEY` | [va.landing.ai](https://va.landing.ai) |
| `TAVILY_API_KEY` | [tavily.com](https://tavily.com) — free tier available |
| `RESEND_API_KEY` | [resend.com](https://resend.com) — free 3,000 emails/month |
| `SUPABASE_*` | [supabase.com](https://supabase.com) → Project Settings → API |
### 6. Run locally
```bash
cd paper_review
python run.py
```
Or directly with uvicorn:
```bash
cd paper_review
python -m uvicorn backend.main:app --reload --host 0.0.0.0 --port 8000
```
| Page | URL |
|---|---|
| Landing page | http://localhost:8000/app/home.html |
| Login | http://localhost:8000/app/login.html |
| Upload page | http://localhost:8000/app/upload.html |
| Review page | http://localhost:8000/app/review.html |
| API docs | http://localhost:8000/docs |
> **Note:** If using `PDF_PARSER=docling`, start the Kaggle Docling server first (see [Docling on Kaggle](#docling-on-kaggle)), then submit a paper.
---
## Deploy to Hugging Face Spaces
1. Create a new Space (SDK: Docker, template: Blank)
2. Add all env vars as Secrets in Space Settings
3. Push the `deployment` branch:
```bash
git remote add hf https://huggingface.co/spaces/<username>/PaperMate
git push hf origin/deployment:refs/heads/main --force
```
---
## API Reference
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| `POST` | `/api/submit` | Optional | Upload PDF + email → returns `access_key` |
| `GET` | `/api/review/{access_key}` | — | Get job status and review result |
| `GET` | `/api/review/{key}/pdf` | — | Download original PDF |
| `GET` | `/api/review/{key}/markdown` | — | View parsed markdown |
| `POST` | `/api/feedback/{access_key}` | — | Submit feedback on a completed review |
| `GET` | `/api/me` | Required | Get current user profile |
| `GET` | `/api/me/submissions` | Required | List all submissions for the current user (includes `rejection_reason` on rejected submissions) |
| `GET` | `/api/public-config` | — | Supabase config for frontend |
| `GET` | `/health` | — | Health check (`reviewer: multi-agent-v1`) |
**Submission statuses:** `pending` · `processing` · `completed` · `failed` · `rejected`
---
## Switching LLM Provider
```env
LLM_PROVIDER=anthropic
LLM_MODEL=claude-sonnet-4-6
# or
LLM_PROVIDER=openai
LLM_MODEL=gpt-4o-mini
# or
LLM_PROVIDER=gemini
LLM_MODEL=gemini-1.5-flash
# or
LLM_PROVIDER=openrouter
LLM_MODEL=meta-llama/llama-3.1-8b-instruct
```
---
## Switching PDF Parser
```env
# LandingAI ADE (cloud, simpler setup)
PDF_PARSER=landingai
LANDINGAI_API_KEY=...
# Docling (self-hosted Kaggle notebook — higher quality, structured JSON)
PDF_PARSER=docling
NTFY_TOPIC=papermate_pdf2md
```
### Docling on Kaggle
The Kaggle server runs two stages:
1. **GPU parse** — Docling with `granite-docling-258M` extracts labeled elements (title, section, table, formula, figure...)
2. **VLM enrichment** — all formula/table/figure items enriched via gpt-4o-mini in parallel
**Kaggle secrets required:** `ngrok_auth_token` · `openai_api_key`
---
## GATE 2: First Working Agent (MVP)
| Criteria | Evidence |
|---|---|
| MVP Demo — video 3 phút show user flow end-to-end | [MVP Demo](https://drive.google.com/file/d/1kED_9sBtUXDFKtDzUgGYZK3Jwe_d-wTz/view?usp=drive_link) |
| Architecture diagram — sơ đồ components, data flow | [Arch Diagram](https://drive.google.com/file/d/1q0qt-HZBoXjCGY9jzKYSljUPtNoV6mBO) |
| Repo có >= 10 PR merged | [Proof](https://github.com/AI20K-Build-Cohort-2/C2-App-159/pulls?q=is%3Apr+is%3Aclosed) |
| README.md — setup instructions, env vars, sample queries | You reading this |
| Eval evidences — ít nhất 5 test case manual với output thực tế | [Click here](https://github.com/AI20K-Build-Cohort-2/C2-App-159/tree/main/paper_review/docs) |
| Live demo | [ntphuc149-papermate.hf.space](https://ntphuc149-papermate.hf.space/) |