paper-qa 詳細教學 — Agentic RAG for Scientific Literature

⚠️ 資安警示(讀者必看):本專案最新 OPEN issue #1325 揭露「pickle 反序列化遠端程式碼執行」風險。永遠不要載入第三方分享、來路不明、或從網路下載的 pre-built pqa index;index 是含 zlib-compressed pickle 的目錄,攻擊者可放毒。詳見 §6。

📌 本教學的雙重意義(meta-relevance):PaperQA2 在本知識庫扮演兩個角色——它是本專案 paper-qa-lite skill 的上游引擎(lite 版只是 thin wrapper),同時是 Ghareeb 等人 Robin 系統的 Crow / Falcon 自動文獻檢索組件。讀懂 paper-qa 等於同時讀懂這兩條工作流的核心。


1. 專案定位

1.1 解決什麼問題?

傳統 RAG 在科學文獻上有三大痛點:

  1. Metadata 缺失 — 一般 RAG 只切 chunk、嵌入、檢索,卻不知道這個 chunk 來自哪篇論文、被引用幾次、是否被撤稿。引文無法追溯。
  2. 單跳檢索不夠 — 真實的科學問題需要 agent 反覆「換關鍵字搜尋 → 取證 → 重排 → 補強搜尋」。一次 retrieve 太弱。
  3. Context 浪費 — 把 top-k chunk 整段塞進 prompt 會超出 context window,且包含大量不相關文字。

PaperQA2 用三個機制回應:

  • Metadata-aware embeddings(從 Crossref / Semantic Scholar / Unpaywall 補齊資訊,含 retraction 檢查)
  • Agentic loop with three toolspaper_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.shlite 版只是「安全 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 的差異

維度LangChainLlamaIndexpaper-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.py721Docs class — 加文件、aaddaqueryaget_evidence 三大入口
settings.py1290Settings Pydantic model — 全系統配置(最龐大、可調最多)
agents/tools.py712三個 tool 定義:paper_search / gather_evidence / gen_answer
agents/main.py437Agent loop + agent_query 對外 entry
agents/search.py(含 pickle 路徑)tantivy 索引讀寫 + ⚠️ pickle metadata persistence
core.py400底層 retrieval / scoring 邏輯
llms.py585Numpy / Qdrant vector store + LiteLLM wrapper
readers.py557PDF / 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}_limitsOpenAI 各 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-qapaper-qa-lite
介面pqa CLI + Pythonbash paperqa-lite.sh ask
索引位置~/.pqa/inbox/Paper/<date>/<topic>/.paperqa-lite/
機密邊界patent-creator session 禁用
預設模型OpenAI透過 preset(quick / standard / precise)強制鎖定

6. 資安掃描報告

6.1 整體紅黃綠燈

等級數量摘要
🔴 1Pickle 反序列化 RCE(issue #1325, OPEN 未修)
🟡 2LiteLLM 大量網路依賴(隱性流量); multimodal 預設啟用 → 圖會送外部 LLM
🟢 3eval() / 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 修復前):

  1. 永遠只用自建索引;不接受外部 pre-built index
  2. 改用 SearchDocumentStorage.JSON_MODEL_DUMP(需手動指定,未驗證所有 code path 都尊重此設定)
  3. 不在多租戶機器跑 pqa(其他使用者寫入索引 → RCE)
  4. 對於 tutorial / 分享情境:只分享 PDF 與設定,不分享 index

6.3 🟡 中風險

  • LiteLLM 隱性網路流量:metadata 自動發 Crossref / S2 / Unpaywall 請求,並可能透過 retraction client 抓 PubMed。pre-IND 機密情境需手動關閉 parsing.use_doc_details=False
  • Multimodal 預設 ONparsing.multimodal=True 預設把圖片送 enrichment_llm(預設 gpt-4o)。處理機密圖表時請設 parsing.multimodal=False

6.4 🟢 低風險(已驗證)

  • 全 codebase grep: eval( / exec( / os.system / subprocess.call(... shell=True)(唯一一個 ast.literal_evaltypes.py:1176,安全變體)
  • API key 一律走環境變數(OPENAI_API_KEY 等),無硬編
  • 所有 metadata client 用 HTTPS(httpx library)

6.5 給本知識庫的建議

  • paper-qa-lite skill 文件加上「禁止接受外部索引」一條
  • patent-creator 既有禁用 paper-qa-lite 的規則應延伸到完整 paper-qa(CLAUDE.md 已記載)

7. FAQ

Q1: 為什麼我的答案跟你們 paper 對不上?

A: FutureHouse 內部用了未開源的 citation traversal + 商業論文 API;公開版的索引基底較小。

Q2: 可以完全離線跑嗎?

A: 部分可以——embeddingllmsummary_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 問答
1011       └──→ ai-notebooklm (NotebookLM 雲端)   ← 雲端問答
121314           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       └──────┬───────┘
1314     ┌──────────────────┐
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
  • 想加速:選 fast config;要高品質:選 high_quality
  • 想做 Robin 風 agent:paper-qa 是基底,加 system prompt 即得 Crow / Falcon

11. 進一步閱讀

11.1 官方資源

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 對映