paper-qa 詳細教學 — Agentic RAG for Scientific Literature
⚠️ 資安警示(讀者必看):本專案最新 OPEN issue #1325 揭露「pickle 反序列化遠端程式碼執行」風險。永遠不要載入第三方分享、來路不明、或從網路下載的 pre-built
pqaindex;index 是含 zlib-compressed pickle 的目錄,攻擊者可放毒。詳見 §6。
📌 本教學的雙重意義(meta-relevance):PaperQA2 在本知識庫扮演兩個角色——它是本專案
paper-qa-liteskill 的上游引擎(lite 版只是 thin wrapper),同時是 Ghareeb 等人 Robin 系統的 Crow / Falcon 自動文獻檢索組件。讀懂 paper-qa 等於同時讀懂這兩條工作流的核心。
1. 專案定位
1.1 解決什麼問題?
傳統 RAG 在科學文獻上有三大痛點:
- Metadata 缺失 — 一般 RAG 只切 chunk、嵌入、檢索,卻不知道這個 chunk 來自哪篇論文、被引用幾次、是否被撤稿。引文無法追溯。
- 單跳檢索不夠 — 真實的科學問題需要 agent 反覆「換關鍵字搜尋 → 取證 → 重排 → 補強搜尋」。一次 retrieve 太弱。
- Context 浪費 — 把 top-k chunk 整段塞進 prompt 會超出 context window,且包含大量不相關文字。
PaperQA2 用三個機制回應:
- Metadata-aware embeddings(從 Crossref / Semantic Scholar / Unpaywall 補齊資訊,含 retraction 檢查)
- Agentic loop with three tools(
paper_search/gather_evidence/gen_answer,由 LLM 自主切換) - Ranked Contextual Summarization(RCS)(每個 chunk 先被
summary_llm摘要+評分,再喂進llm生答)
1.2 雙重 meta-relevance(本知識庫角度)
| 角色 | 在本知識庫的對應 | 為什麼重要 |
|---|---|---|
| paper-qa-lite 的上游引擎 | .claude/skills/paper-qa-lite/ + scripts/paperqa-lite.sh | lite 版只是「安全 sandbox + 簡化 CLI」的薄殼,所有核心 retrieval / agentic 邏輯都在 paper-qa;想理解 lite 的行為必須先理解 paper-qa |
| Robin 的 Crow/Falcon 組件 | Ghareeb 2025 Robin paper(co-scientist 工作流) | Robin 把 paper-qa 包成兩個 agent:Crow(從文獻找候選假說 / 機制)、Falcon(驗證假說的引文支撐);本知識庫的 co-scientist tutorial 系列會反覆引用 |
讀懂這份教學等於同時掌握三層:paper-qa 本體 → paper-qa-lite skill → Robin 工作流。
1.3 與 LangChain / LlamaIndex 的差異
| 維度 | LangChain | LlamaIndex | paper-qa |
|---|---|---|---|
| 焦點 | 通用 LLM app | 通用 RAG | 科學文獻專屬 |
| Metadata | 自行處理 | 自行處理 | 內建 Semantic Scholar / Crossref / Unpaywall |
| Agent | 多種 | 部分 | 三 tool 固定迴圈 + LiteLLM |
| 依賴 | 龐大 | 龐大 | 僅 LiteLLM + Pydantic + tantivy |
| 引文追溯 | 需自行加 | 需自行加 | 強制每答案都有可追溯引文 |
2. 安裝指南
2.1 基本安裝(PyPI)
1# 建議 uv(本庫規範)
2uv venv .venv && source .venv/bin/activate
3uv pip install "paper-qa>=5"
4
5# 或 pip
6pip install "paper-qa>=5"
7
8# 驗證
9pqa --help
需求: Python 3.11+(v5 起強制)。
2.2 環境變數(最少要設一個 LLM key)
1export OPENAI_API_KEY=sk-... # 預設
2export ANTHROPIC_API_KEY=sk-ant-... # 用 Claude
3export GEMINI_API_KEY=... # 用 Gemini
4
5# Metadata 服務(強烈建議;否則公開 rate limit 會卡)
6export CROSSREF_API_KEY=...
7export SEMANTIC_SCHOLAR_API_KEY=...
🔐 本庫規範:API key 絕不寫在程式碼或 Discord,只走
.env/ 環境變數。
2.3 進階:本地 / OpenAI-compatible LLM
1from paperqa import Settings, ask
2
3# Ollama / llamafile / 自架 vLLM 等
4ans = ask(
5 "What is PaperQA2?",
6 settings=Settings(
7 llm="ollama/llama3.1",
8 summary_llm="ollama/llama3.1",
9 embedding="ollama/nomic-embed-text",
10 ),
11)
⚠️ 五個 LLM config point 任一缺失會 silently 回退 OpenAI(#1321 已記錄此 footgun):llm / summary_llm / embedding / agent.agent_llm / parsing.enrichment_llm。
2.4 進階:四套 PDF reader 的可選裝
1uv pip install paper-qa-pypdf # 預設、最相容
2uv pip install paper-qa-pymupdf # 最快,但有 CMYK 圖片邊角案例
3uv pip install paper-qa-docling # model-based,保留版面
4uv pip install paper-qa-nemotron # Nvidia model,最高精度
切換用 Settings(parsing.parse_pdf=...)。
3. 核心架構解析
3.1 三層架構圖(Mermaid)
flowchart TD
User[User Query] --> Agent[Agent Loop
agent_llm decides next tool]
Agent -->|"tool 1"| Search[paper_search
tantivy + metadata clients]
Agent -->|"tool 2"| Evidence[gather_evidence
vector retrieval + RCS]
Agent -->|"tool 3"| Answer[gen_answer
compose with citations]
Search --> Idx[(tantivy index
+ pickle metadata
⚠️ #1325)]
Search --> Meta[Metadata Clients
Crossref / S2 / Unpaywall]
Evidence --> Vec[(Vector Store
Numpy / Qdrant)]
Evidence --> SumLLM[summary_llm
Ranked Contextual
Summarization]
Answer --> MainLLM[llm
final synthesis]
MainLLM --> Out[Answer + In-text Citations]
Out --> Agent
Agent -->|"loop until done"| User
style Idx fill:#fee,stroke:#c33
style Search fill:#e7f3ff
style Evidence fill:#e7f3ff
style Answer fill:#e7f3ff
3.2 主要模組(src/paperqa/)
| 模組 | 行數 | 職責 |
|---|---|---|
docs.py | 721 | Docs class — 加文件、aadd、aquery、aget_evidence 三大入口 |
settings.py | 1290 | Settings Pydantic model — 全系統配置(最龐大、可調最多) |
agents/tools.py | 712 | 三個 tool 定義:paper_search / gather_evidence / gen_answer |
agents/main.py | 437 | Agent loop + agent_query 對外 entry |
agents/search.py | (含 pickle 路徑) | tantivy 索引讀寫 + ⚠️ pickle metadata persistence |
core.py | 400 | 底層 retrieval / scoring 邏輯 |
llms.py | 585 | Numpy / Qdrant vector store + LiteLLM wrapper |
readers.py | 557 | PDF / Office / 文字 parser + chunking |
clients/ | — | Crossref / S2 / Unpaywall / journal_quality |
3.3 預設工作流(README §What is PaperQA2 → Algorithm)
1Phase 1: Paper Search
2 - LLM 生 keyword query
3 - Crossref / S2 抓候選 → chunk + embed → 加入 state
4
5Phase 2: Gather Evidence
6 - query embed → 取 top-k chunk(answer.evidence_k=10)
7 - 每個 chunk 餵 summary_llm → contextual summary + score
8 - LLM 重排 → 取 answer.answer_max_sources=5
9
10Phase 3: Generate Answer
11 - 5 個摘要 + 原 chunk text → 主 LLM
12 - 回答含 in-text citation(如 "Qian2011Neural pages 1-2")
Agent 可不按順序,可重複呼叫任一 tool。
4. Helper Scripts 詳細用法
PaperQA2 沒有「scripts/」目錄;對外介面只有 pqa CLI 和 Python API。
4.1 pqa CLI
1# 最簡:cd 到 PDF 目錄問問題
2pqa ask 'What is PaperQA2?'
3
4# 切 bundled setting
5pqa --settings fast ask '...'
6pqa --settings high_quality ask '...'
7pqa --settings wikicrow ask '...'
8
9# 命名索引(重要!)
10pqa -i my_index index # 建索引
11pqa -i my_index search 'keyword' # 全文搜尋
12pqa -i my_index ask '...' # 在指定索引上問
13
14# 調 hyperparameter
15pqa --temperature 0.5 ask '...'
16pqa --parsing.chunk_size 5000 ask '...'
17
18# 存自訂 setting
19pqa -s my_settings --temperature 0.3 --llm gpt-4o save
20pqa -s my_settings ask '...'
21
22# 看現有 setting
23pqa view
24pqa -s fast view
PQA_HOME 預設 ~/.pqa/,所有索引和答案都存這裡。
4.2 Python API(最常用三條路徑)
1# 路徑 A:一行式 ask(agent + 全自動)
2from paperqa import Settings, ask
3ans = ask("What is PaperQA2?", settings=Settings(temperature=0.0))
4
5# 路徑 B:手動 Docs(無 agent,最快、最可控)
6from paperqa import Docs
7docs = Docs()
8for pdf in ["a.pdf", "b.pdf"]:
9 await docs.aadd(pdf)
10session = await docs.aquery("...")
11
12# 路徑 C:agent_query(要 agent loop 但自己給 docs)
13from paperqa.agents.main import agent_query
14result = await agent_query(query="...", settings=settings)
4.3 6 套 bundled config 的選用
| Config | 何時用 |
|---|---|
fast | 大量問題、可接受品質下降;evidence_k 較小 |
high_quality | 重要問題;evidence_k=15、用 ToolSelector agent |
wikicrow | 寫維基百科風格長文 |
contracrow | 找論文間矛盾(claim → 是否被反駁) |
debug | 開發 / 排錯 |
tier{1..5}_limits | OpenAI 各 tier 的 rate limit |
5. 應用場景
5.1 個人文獻問答(取代 NotebookLM)
1mkdir ~/papers/PD-L1 && cd ~/papers/PD-L1
2# 把 10–50 篇 PDF 丟進來
3pqa -i PD-L1 index
4pqa -i PD-L1 ask "What are the main mechanisms of PD-L1 resistance in NSCLC?"
優點:完全本地、可換任何 LLM、引文可追到頁碼。
5.2 系統性文獻回顧(systematic review)初篩
把 PRISMA 階段 1 收到的 200–500 篇 PDF 全丟給 paper-qa,用一組標準問題(PICO 框架)對每篇問同一題,匯出引文與 evidence summary。
5.3 Pre-IND / 法規盡職調查
⚠️ caveat:跨團隊分享索引時絕不要直接傳 pickle 索引(見 §6)。改傳:源 PDF + Settings JSON + 收件方自建索引。
5.4 整合進 AI scientist 系統(Robin / Crow / Falcon)
Robin paper(Ghareeb 2025)裡的:
- Crow agent = paper-qa + 「給定假說/機制 → 找文獻支撐」的 system prompt
- Falcon agent = paper-qa + 「給定候選分子 → 找實驗證據」的 system prompt
兩個 agent 共用同一個 paper-qa index,由 Robin 的 orchestrator 切換。
5.5 本知識庫的 paper-qa-lite skill
paperqa-lite.sh 是 paper-qa 的「安全薄殼」,差異:
| 維度 | paper-qa | paper-qa-lite |
|---|---|---|
| 介面 | pqa CLI + Python | bash paperqa-lite.sh ask |
| 索引位置 | ~/.pqa/ | inbox/Paper/<date>/<topic>/.paperqa-lite/ |
| 機密邊界 | 無 | patent-creator session 禁用 |
| 預設模型 | OpenAI | 透過 preset(quick / standard / precise)強制鎖定 |
6. 資安掃描報告
6.1 整體紅黃綠燈
| 等級 | 數量 | 摘要 |
|---|---|---|
| 🔴 高 | 1 | Pickle 反序列化 RCE(issue #1325, OPEN 未修) |
| 🟡 中 | 2 | LiteLLM 大量網路依賴(隱性流量); multimodal 預設啟用 → 圖會送外部 LLM |
| 🟢 低 | 3 | 無 eval() / os.system() / shell=True;API key 走標準環境變數;HTTPS-only metadata clients |
6.2 🔴 高風險詳述 — Pickle 反序列化
位置: src/paperqa/agents/search.py:67-93, 249, 378
1class SearchDocumentStorage(StrEnum):
2 JSON_MODEL_DUMP = "json_model_dump"
3 PICKLE_COMPRESSED = "pickle_compressed" # ⚠️ 預設值
4 PICKLE = "pickle"
5
6 def read_from_string(self, data):
7 if self == SearchDocumentStorage.PICKLE_COMPRESSED:
8 return pickle.loads(zlib.decompress(data)) # noqa: S301
9 return pickle.loads(data) # noqa: S301
威脅模型: 任何能寫入受害者 PQA_HOME/indexes/<name>/ 的攻擊者(或誘騙受害者解壓含中毒索引的 zip)可在 pqa ask 時取得受害者 Python 程序的任意程式碼執行權。
緩解(在 #1325 修復前):
- 永遠只用自建索引;不接受外部 pre-built index
- 改用
SearchDocumentStorage.JSON_MODEL_DUMP(需手動指定,未驗證所有 code path 都尊重此設定) - 不在多租戶機器跑
pqa(其他使用者寫入索引 → RCE) - 對於 tutorial / 分享情境:只分享 PDF 與設定,不分享 index
6.3 🟡 中風險
- LiteLLM 隱性網路流量:metadata 自動發 Crossref / S2 / Unpaywall 請求,並可能透過 retraction client 抓 PubMed。pre-IND 機密情境需手動關閉
parsing.use_doc_details=False - Multimodal 預設 ON:
parsing.multimodal=True預設把圖片送enrichment_llm(預設 gpt-4o)。處理機密圖表時請設parsing.multimodal=False
6.4 🟢 低風險(已驗證)
- 全 codebase grep:無
eval(/exec(/os.system/subprocess.call(... shell=True)(唯一一個ast.literal_eval在types.py:1176,安全變體) - API key 一律走環境變數(
OPENAI_API_KEY等),無硬編 - 所有 metadata client 用 HTTPS(
httpxlibrary)
6.5 給本知識庫的建議
- 在
paper-qa-liteskill 文件加上「禁止接受外部索引」一條 - patent-creator 既有禁用 paper-qa-lite 的規則應延伸到完整 paper-qa(CLAUDE.md 已記載)
7. FAQ
Q1: 為什麼我的答案跟你們 paper 對不上?
A: FutureHouse 內部用了未開源的 citation traversal + 商業論文 API;公開版的索引基底較小。
Q2: 可以完全離線跑嗎?
A: 部分可以——embedding、llm、summary_llm 都可換 Ollama / vLLM 本地。但 metadata 服務(Crossref / S2)需要連網;若全離線,設 parsing.use_doc_details=False,缺點是引文 metadata 變不完整。
Q3: 我有 1000+ PDFs,會爆嗎?
A: tantivy 處理 1000 篇沒問題。但 agent.index.concurrency=5 預設較保守;可調高。embedding cost 才是真痛點(每篇切 30+ chunk,每 chunk 一個 embedding 呼叫)。
Q4: Docs 物件可以存嗎?
A: 可以 pickle.dump,但僅限自己用、自己機器(見 §6 警告)。跨機器分享改存 PDF + Settings JSON。
Q5: 跟 NotebookLM 比?
A: NotebookLM 易用、有 audio overview;paper-qa 可完全本地、可換 LLM、引文更嚴謹、有 multimodal、可自動補 metadata(retraction check 是殺手鐧)。
Q6: 跟 LangChain RAG 比?
A: LangChain 給你樂高積木自己組;paper-qa 是「組好的、為科學文獻優化的成品」,調整空間透過 1290 行的 Settings 提供。
Q7: 為什麼預設 chunk_size 不能太小?
A: contextual summarization 需要足夠的 context 才能判斷 chunk 是否相關。太小(如 < 500 token)會導致 summary_llm 把所有 chunk 都評為相關。
8. 進階技巧
8.1 把 5 個 LLM config point 一次設好(避免回退 OpenAI)
1from paperqa import Settings
2from paperqa.settings import AgentSettings, ParsingSettings
3
4s = Settings(
5 llm="ollama/llama3.1",
6 summary_llm="ollama/llama3.1",
7 embedding="ollama/nomic-embed-text",
8 agent=AgentSettings(agent_llm="ollama/llama3.1"),
9 parsing=ParsingSettings(
10 enrichment_llm="ollama/llava",
11 multimodal=False, # 機密情境可關
12 use_doc_details=False, # 完全離線可關
13 ),
14)
8.2 自訂 prompt(pre / post)
1s = Settings(
2 prompts=PromptSettings(
3 pre="先 brainstorm 3 個關鍵 sub-question,再回答主問題:{question}",
4 post="幫我把以下答案改寫成 200 字摘要 + bullet list...",
5 ),
6)
8.3 換 vector store(Qdrant 持久化)
1from paperqa import Docs, QdrantVectorStore
2docs = Docs(texts_index=QdrantVectorStore(url="http://localhost:6333"))
8.4 用 4 套 PDF reader 的場景
- 一般論文 → PyPDF(預設、最相容)
- 大量論文要快 → PyMuPDF
- 表格 / 圖很重要(藥物臨床表)→ Docling
- 最高精度(給高品質 RAG)→ Nemotron-parse
8.5 把 paper-qa 嵌進 LangGraph / 自家 agent
1async def paperqa_tool(query: str, paper_dir: str) -> str:
2 from paperqa import Settings, ask
3 return (await ask(query, settings=Settings(...))).answer
4# 然後當作 LangGraph 的一個 node
這就是 Robin / Crow / Falcon 的本質做法。
9. 整合進其他工作流
9.1 與本知識庫既有 layer 的關係
1paper-search (學術檢索 + docling 全文)
2 │
3 ▼
4inbox/Paper/<date>/<topic>/ ← PDF + 全文 md
5 │
6 ├──→ paper-qa-lite (本庫 thin wrapper) ← upstream = paper-qa
7 │ │
8 │ ▼
9 │ 本地 RAG 問答
10 │
11 └──→ ai-notebooklm (NotebookLM 雲端) ← 雲端問答
12 │
13 ▼
14 audio overview / mindmap
paper-qa 在這條鏈中是 paper-qa-lite 的引擎;如果讀者直接用 paper-qa 而非 lite,會失去本庫的機密邊界(patent-creator session 禁用規則)。
9.2 與 Robin / co-scientist 工作流(meta-relevance 重點)
Ghareeb 2025 Robin paper 的 architecture:
1 ┌─────────────────────────────────────┐
2 │ Robin Orchestrator (claude/gpt) │
3 └──────────────┬──────────────────────┘
4 │
5 ┌───────────────┼───────────────┐
6 ▼ ▼ ▼
7 ┌─────────┐ ┌─────────┐ ┌─────────┐
8 │ Crow │ │ Falcon │ │ Owl │
9 │ (找假說)│ │(驗實驗) │ │ (規劃) │
10 └────┬────┘ └────┬────┘ └─────────┘
11 │ │
12 └──────┬───────┘
13 ▼
14 ┌──────────────────┐
15 │ paper-qa core │ ← 兩個 agent 共用同一個 retrieval engine
16 └──────────────────┘
→ 想 fork Robin、或想自己做 co-scientist:先把 paper-qa 玩熟,再包兩層 system prompt 就是 Crow 與 Falcon。本知識庫的 co-scientist tutorial 系列會把這條鏈拆解到「可自架重現」的程度。
9.3 與 graphify / gitnexus
gitnexus analyze /tmp/paper-qa→ 可看清 712 行的agents/tools.py與其他模組的呼叫鏈graphify update .→ 把本份 tutorial 與既有 paper-qa-lite skill 文件合成同一張知識圖
9.4 與 patent-creator
❌ 禁用。patent-creator session 為 pre-filing 機密,所有 RAG(含 paper-qa / paper-qa-lite)都不能在該 session 內呼叫,避免機密技術點外洩到 LLM 訓練回路或 metadata API 日誌。
10. 重點摘要 Checklist
- 確認用 Python 3.11+ 與
uv pip install "paper-qa>=5" - 設
OPENAI_API_KEY(或其他 LiteLLM 支援的 provider) - 強烈建議設
CROSSREF_API_KEY+SEMANTIC_SCHOLAR_API_KEY - 若用本地 LLM,五個 config point 全填(避免 silent fallback to OpenAI)
- 絕不載入外部 pre-built index(issue #1325 OPEN)
- 機密圖表處理時設
parsing.multimodal=False - 全離線需求設
parsing.use_doc_details=False - patent-creator session 內不呼叫 paper-qa
- 想加速:選
fastconfig;要高品質:選high_quality - 想做 Robin 風 agent:paper-qa 是基底,加 system prompt 即得 Crow / Falcon
11. 進一步閱讀
11.1 官方資源
- 📄 PaperQA1 paper — Lála et al., 2023, https://arxiv.org/abs/2312.07559
- 📄 PaperQA2 paper — Skarlinski et al., 2024, https://arxiv.org/abs/2409.13740
- 📄 Aviary paper(含 LitQA2) — Narayanan et al., 2024
- 🌐 FutureHouse Cookbook — https://futurehouse.gitbook.io/futurehouse-cookbook
- 🌐 GitHub — https://github.com/Future-House/paper-qa
- 🌐 Demo(WikiCrow) — https://paper.wikicrow.ai
11.2 本知識庫相關
inbox/2026-05-20-github-Future-House-paper-qa.md— gh-save 標準報告.claude/skills/paper-qa-lite/SKILL.md— 本庫薄殼層scripts/paperqa-lite.sh— bash 介面docs/superpowers/specs/2026-05-20-co-scientist-tutorial-design.md— Robin 系列教學設計docs/superpowers/plans/2026-05-20-co-scientist-tutorial-plan.md— 對應實作計畫
11.3 關鍵 issue 追蹤
- #1325 🔴 Pickle deserialization RCE(OPEN,必追)
- #1321 五個 LLM config point silent fallback footgun
- #1294 社群正在做 Claude skill 整合
- #1283 與 WFGY 16 Problem Map 的 RAG failure taxonomy 對映
Comments