关于 scholar-deep-research
Scholar Deep Research 是一项技能,可根据问题生成带引用的结构化学术研究报告。其脚本化、可恢复的八阶段工作流整合学术来源,追踪证据与引用,并在生成报告前执行必需的对抗性自我评议。
主要功能
- 01八阶段研究工作流
- 02联合搜索多个学术来源
- 03脚本化去重与论文排序
- 04持久且可恢复的研究状态
- 05以引用锚定的证据综合
- 06必需的自我评议与报告导出
适用场景
- 01撰写文献综述
- 02比较多篇论文中的研究方法
- 03为研究提案整理背景
- 04依据既有研究评估新颖性
MCP 相关
MCP 补充检索为可选功能:条件允许时,技能可使用 Asta MCP 工具进行论文相关性搜索和片段检索。MCP 调用不在关键路径上,失败时研究流程仍会继续。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ agents365-ai/ 365-skills --skill scholar-deep-research安装后在 Claude Code 中输入/scholar-deep-research确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
CHANGELOG.mdrequirements.txtassets/prompts/self_critique.mdassets/templates/comparative_analysis.mdgrant_background.mdliterature_review.mdscoping_review.mdsystematic_review.mdchangelog.d/README.mdreferences/cli_contract.mdenv_vars.mdexample_run.mdpitfalls.mdquality_assessment.mdreport_templates.mdsearch_strategies.mdsource_selection.mdstate_schema.mdreferences/agent_prompts/phase3_deep_read.mdscripts/_common.py_gates.py_locking.py_pdf_fetch.py_s2_citations.py_search_meta.pybuild_citation_graph.pydedupe_papers.pyexport_bibtex.pyextract_pdf.pylist_sources.py详细介绍
学术深度研究
端到端学术研究工作流,将一个问题转化为有引文支撑、结构清晰的报告。专为深入研究而打造:整合多个来源、透明排序、追踪引文,并在发布报告前强制进行自我批判。
适用场景
明确触发条件:“文献综述”“研究报告”“研究现状”“梳理该领域”“关于 X 有哪些已知信息”“深入研究 Y”“系统综述”“范围综述”“比较关于 Z 的论文”。
主动触发条件(无需用户明确提出):
- 用户提出一个事实性问题,诚实的答案是“这取决于现有文献”
- 用户拟定研究计划,需要撰写背景部分
- 用户正在起草论文的引言或相关工作部分,但尚未梳理既有研究
- 用户提出一种方法,并询问它是否具有新颖性
**不适用场景:**有一篇已知论文就能回答问题;用户需要的是教程(而非综述);或用户正在调试代码。
指导原则
- 依靠脚本,而非感觉。 每个搜索、去重、排序和导出步骤都通过
scripts/中的脚本运行。相同的输入应产生相同的输出。不要凭目测臆断排序或计数。 - 整合多个来源,而非依赖单一来源。 OpenAlex 是主要基础数据源(免费,收录超过 2.4 亿篇作品,无需密钥)。arXiv(CS/ML/物理预印本)、Crossref(DOI 元数据)、PubMed(生物医学)、DBLP(CS 会议和期刊)、bioRxiv(通过 Europe PMC 获取生命科学预印本)和 Exa(开放网络,需要
EXA_API_KEY)用于补足缺口。Semantic Scholar 也由脚本驱动——Phase 4 的核心路径是build_citation_graph.py --source s2|both,其 CS / arXiv / 跨学科覆盖范围优于 OpenAlex;两者的图谱差异比你预想的更大。asta MCP 工具(mcp__asta__*)和 Brave Search 属于辅助层——仅按需用于相关性排序或非学术背景信息,绝不用于关键路径。如果 MCP 超时,研究仍会继续。 - 状态持久保存。 所有内容都通过
research_state.json管理,包括运行过的查询、看过的论文、作出的决定和各阶段进度。研究因此可以恢复,也便于审计。 - 引文是锚点,而非装饰。 草稿中的每项重要主张都必须附带
[^id],其中id与状态中的论文对应。没有锚点的主张将被视为幻觉,无法通过检查。 - 以饱和度为停止信号,而非穷尽搜索。 新一轮搜索新增论文少于 20%,且没有任何新论文的引用数超过 100 次时,该阶段结束。
- 自我批判是一个阶段,而非勾选项。 Phase 6 会以对抗性视角审阅草稿。审阅结果会纳入报告附录。
8 阶段工作流(Phase 0..7)
Phase 0: Scope → decompose question, pick archetype, init state
Phase 1: Discovery → multi-source search, dedupe
Phase 2: Triage → rank, select top-N for deep read
Phase 3: Deep read → extract evidence per paper
Phase 4: Chasing → citation graph (forward + backward)
Phase 5: Synthesis → cluster by theme, map tensions
Phase 6: Self-critique → adversarial review, gap finding
Phase 7: Report → render archetype template, export bibliography
每个阶段都会在进入下一阶段前将内容写入 research_state.json。如果用户暂停或会话崩溃,下次运行会读取状态,并从上一个已完成的阶段继续。
阶段 0 — 范围
搜索之前,先拆解问题。
- 用一句话重述问题。指出其中的歧义。
- 按 PICO 风格拆解(或针对非生物医学领域采用等效方法):
- Population / Problem(人群 / 问题)——涉及什么系统、物种、情境或现象?
- Intervention / Independent var(干预 / 自变量)——采用什么方法、因素或操控?
- Comparison(比较)——以什么基线或替代方案为参照?
- Outcome(结果)——要测量或论证什么?
- 选择符合用户意图的类型(参见
references/report_templates.md):literature_review— 关于 X 已有哪些研究(默认)systematic_review— 严谨的 PRISMA-lite,比较针对某个狭窄问题的多项研究scoping_review— 研究过什么以及如何研究(广度优先于深度)comparative_analysis— X 与 Y 的正面对比grant_background— 叙述性背景 + 提案的研究空白
- 起草关键词组——拟定 3–5 个布尔关键词组,涵盖同义词、缩写和不同拼写形式。加入一个“排除”关键词组。
- 初始化状态:
(python scripts/research_state.py --state research_state.json init \ --question "<restated question>" \ --archetype literature_review--state是顶层参数,适用于所有子命令;init本身接受--question、--archetype,以及可选的--force。)
不确定类型时,请询问用户。这个选择会影响后续所有步骤。
阶段 1——发现
并行搜索所有可用来源(如果来源支持并行)。OpenAlex 是主要来源;其他来源用于填补空缺。
并行最能发挥作用的地方。 最适合并行展开的是阶段 3(每篇论文分配一个 Agent 并发阅读 PDF——参见 references/agent_prompts/phase3_deep_read.md)。阶段 1 的瓶颈在上游 API,而非本地计算;在同一来源上并行展开,大多只会带来 429 错误和持续的冷却时间。此技能的原则应是:不同来源之间并行,单一来源内部串行。具体来说:
- 适合并行:OpenAlex(礼貌池,容忍度很高)、Crossref(礼貌池)、Exa(付费配额)、bioRxiv(Europe PMC)。
- 自动串行(使用文件锁):arXiv(每次请求间隔 ≥3s)、PubMed(不使用
NCBI_API_KEY时每次请求间隔 ≥0.34s,使用时 ≥0.10s)、DBLP(间隔 1s,以避免 SSL EOF 偶发错误)。
串行来源会在 ${SCHOLAR_CACHE_DIR:-.scholar_cache}/rate/<source>.lock 下使用每个来源独立的文件锁,因此,即使同一个 Agent 并行调用 N 次 search_arxiv.py,也会自动排队并等待适当的间隔——无需 Agent 端协调,但并行调用也不会加快这些来源的处理速度,只是不会报错。
# Primary (no API key, always available)
python scripts/search_openalex.py --query "<cluster 1>" --limit 50 --state research_state.json
python scripts/search_openalex.py --query "<cluster 2>" --limit 50 --state research_state.json
# Domain-specific (use when relevant)
python scripts/search_arxiv.py --query "<cluster>" --limit 50 --state research_state.json # CS/ML/physics preprints
python scripts/search_dblp.py --query "<cluster>" --limit 50 --state research_state.json # CS gold-standard bibliography (no abstracts)
python scripts/search_pubmed.py --query "<cluster>" --limit 50 --state research_state.json # biomedical (PubMed)
python scripts/search_biorxiv.py --query "<cluster>" --limit 50 --state research_state.json # life-sci preprints (bioRxiv + medRxiv via Europe PMC)
python scripts/search_crossref.py --query "<cluster>" --limit 50 --state research_state.json # DOI-backed metadata
# Open-web coverage (optional, requires EXA_API_KEY) — finds material the
# scholarly APIs miss: lab sites, institutional PDFs, conference mirrors,
# preprints parked outside arXiv, NGO/government reports.
python scripts/search_exa.py --query "<cluster>" --limit 50 --state research_state.json
# Dedupe across sources (DOI-first, title-similarity fallback)
python scripts/dedupe_papers.py --state research_state.json
**MCP 补充信息(可选,有条件时运行):**调用 mcp__asta__search_papers_by_relevance 和 mcp__asta__snippet_search,并通过 scripts/research_state.py ingest 导入结果。如果 MCP 调用出错或超时,不要重试——继续后续步骤。
**迭代。**读取状态文件。是否存在关键词缺口?是否有作者出现 3 次或更多,而你还未检索其其他作品?再进行一轮搜索。达到饱和时停止——检查所有来源,而不只是最后查询的来源:
python scripts/research_state.py saturation --state research_state.json
# Returns { "per_source": {...}, "overall_saturated": true/false, ... }
只有当每个已查询来源都至少完成 --min-rounds 轮(默认值为 2),且各自新增论文百分比和新增引用数均低于阈值时,overall_saturated 才为 true。只查询过一次的来源不能被判定为饱和,这样可以避免单个平静的来源错误地终止发现流程。使用 --source openalex 可单独检查某个来源。
预算上限与广泛主题的应对方式。 阶段 1 设有两个硬性上限,以防 Agent 无休止地运行:SCHOLAR_PHASE1_MAX_ROUNDS(每个来源默认最多 10 轮)和 SCHOLAR_PHASE1_MAX_REQUESTS_PER_SOURCE(每个来源默认最多导入 20 次)。达到任一上限时,会返回 phase1_budget_exhausted,并附带 next: 提示。对于跨越多个子领域的真正广泛主题(例如包含多个关键词簇的 CS-ML 主题),在默认设置下也可能无法达到饱和阈值——可使用 SCHOLAR_SATURATION_NEW_PCT(默认值为 20.0)、SCHOLAR_SATURATION_MAX_CITATIONS(默认值为 100)和 SCHOLAR_SATURATION_NEW_AUTHORS_PCT / SCHOLAR_SATURATION_NEW_VENUES_PCT 放宽阈值。这些环境变量在 python scripts/research_state.py saturation 和 G2 门控检查中都会生效,因此提高阈值后,门控检查就能接受那些无法达到默认阈值的主题的“足够好”覆盖度。
阶段 2 — 筛选
对去重后的文献库排序,并选出排名前 N 的文献进行深入阅读。
python scripts/rank_papers.py \
--state research_state.json \
--question "<phase 0 question>" \
--alpha 0.4 --beta 0.3 --gamma 0.2 --delta 0.1 \
--top 20
公式公开透明——脚本会打印公式,并将各组成部分写入状态,以便报告引用自身的方法:
score = α·relevance + β·log10(citations+1)/3 + γ·recency_decay(half-life=5yr) + δ·venue_prior
默认设置面向文献综述。对于范围综述,建议提高 α(相关性)并降低 β(引用数)。对于针对狭窄问题的系统综述,则建议降低 α 并提高 β。
将排名前 N 的文献写入状态:
python scripts/research_state.py select --state research_state.json --top 20
继续之前,请将筛选结果划分为深入阅读、略读和暂缓三个层级。 阶段 3 的扇出是工作流中成本最高的环节;并非每篇入选论文都值得完整派发给 Agent:
python scripts/skim_papers.py --state research_state.json \
--deep-ratio 0.5 --skim-ratio 0.5
默认将排名前 N 的文献平均分配:前半部分 → deep(在阶段 3 派发给 Agent),后半部分 → skim(自动填入基于摘要的证据占位内容,depth=shallow)。预算较紧时,可使用 --deep-ratio 0.3 --skim-ratio 0.5——剩余的 20% 会获得 tier=defer,并从 selected_ids 中移除(仍可作为候选文献用于引用追溯)。
脚本会生成 data.deep_tier_preview,按 triage_score 列出深入阅读层级的论文。继续之前,请向用户展示此列表,以便用户在 Agent 扇出前手动调整(重新运行并使用不同的比例,或在状态中手动重新排序)。通过 G3 前必须完成筛选——否则关卡的 triage_applied 检查会拒绝继续。
可选但推荐——在 Agent 扇出前预取深入阅读层级论文的 PDF:
python scripts/prefetch_pdfs.py --state research_state.json \
--tier deep --concurrency 4
通过 paper-fetch(并在必要时回退到 Unpaywall),以并行批次将每篇深入阅读层级论文的 PDF 下载到 ${SCHOLAR_CACHE_DIR:-.scholar_cache}/pdfs/<id-hash>/,并为每篇论文写入 pdf_path / pdf_status / pdf_source / pdf_bytes。这样,阶段 3 的 Agent 就能直接读取本地文件,而不必各自下载——Agent 可专注于阅读和推理,而不是反复尝试绕过付费墙。
下载失败的论文会标记为 pdf_status='failed',并附带 pdf_failure_code(paper_fetch_error、no_open_access_pdf、pdf_download_failed 等);没有 DOI 的论文会标记为 pdf_status='no_doi'。阶段 3 的 Agent 会先检查 pdf_path,只有在预取路径不存在时才会回退到 extract_pdf.py --doi。重新运行预取的成本很低:磁盘上已有 pdf_path 的论文会被跳过(pdf_status='cached')。
需要人工参与的付费墙处理流程。 自动获取失败时(遇到付费墙、开放获取渠道已全部尝试仍失败,或没有 DOI),可通过 --emit-manifest 向用户提供手动获取清单(只读):
python scripts/prefetch_pdfs.py --state research_state.json --emit-manifest
# Returns { needs_user_download: [{id, doi, title, drop_at, alt_urls}, ...] }
用户下载每篇 PDF(可通过机构 VPN、ResearchGate 等),并将文件放到清单中列出的 drop_at 路径(该子目录中的任意 *.pdf 文件名均可)。下次正常运行 prefetch_pdfs.py 时,放入的文件会自动纳入,标记为 pdf_source='user_provided',且不会重新获取。
如果未安装 paper-fetch,且不希望产生 Unpaywall 流量,可完全跳过预取——阶段 3 的 Agent 会在各自的上下文中逐篇下载(速度较慢、过程更杂,但功能相同)。
阶段 3 — 深度阅读(并行 Agent 扇出)
阶段 3 按层级拆分:
tier=skim—apply_triage()已基于摘要写入一条depth=shallow的证据记录。无需进一步操作。tier=deep— 每篇论文分派一个 Agent,以 8–10 篇为一波并行处理。每个 Agent 阅读 PDF,将结构化证据写回状态,并返回一行 JSON。宿主的主上下文不会看到完整的 PDF 文本。
Agent 提示词模板位于 references/agent_prompts/phase3_deep_read.md。加载一次后,为每篇论文实例化,并在单条消息中分派所有 N 个 tool_use 调用,使其并发扇出。每个 Agent 的约定:
- 输入:
paper_id、doi、pdf_url、abstract、question、state_path - 操作:
extract_pdf.py --doi <doi> --output <tmp>→ 读取文本 → 写入evidence --depth full - 输出: 一行
{"paper_id": "...", "status": "ok"|"evidence_unavailable", ...}
状态 CLI 使用独占锁,因此 N 个 Agent 并发调用 evidence 写入时会自动串行化——无需协调。
# After all wave(s) complete, verify deep-tier coverage:
python scripts/research_state.py advance --state research_state.json \
--to 4 --check-only
如果 deep_tier_full_evidence 失败,只需针对缺失的 id 分派后续一波。如果某篇论文的全文确实无法获取(付费墙、开放获取链路已耗尽),Agent 应按照提示词故障模式部分的说明,写入一条 depth=shallow 记录,并将 method 设置为以 evidence_unavailable: 开头——这条记录可满足 depth_marks_valid,且不会虚增深度阅读层级的覆盖数量。
手动回退(无可用 Agent)。 无法分派并行 Agent 的宿主(某些非 CC 平台)可以在主会话中按顺序运行阶段 3:对每篇 tier=deep 论文,先运行 extract_pdf.py --doi <doi>,再运行 research_state.py evidence --id <pid> --depth full ...。速度较慢且会消耗更多上下文,但门控逻辑相同。
阶段 4 — 引文追踪
选取排名最高的 5–10 篇论文,扩展图谱。
# Preview the request count first — this is the most expensive command
python scripts/build_citation_graph.py \
--state research_state.json \
--seed-top 8 --direction both --depth 1 --dry-run
# Run with an idempotency key so a retry after a network blip is free
python scripts/build_citation_graph.py \
--state research_state.json \
--seed-top 8 --direction both --depth 1 \
--idempotency-key "chase-$(date -u +%Y%m%dT%H%M)"
脚本会获取后向参考文献(这篇论文引用了什么?)和前向引文(哪些论文引用了这篇论文?),与现有状态去重,并将新的候选论文写入 discovered_via: citation_chase。对任何新增的高分论文再次运行排名和深度阅读。
双后端。 --source openalex|s2|both(默认值为 both)。OpenAlex 对大多数学科的覆盖良好;Semantic Scholar(S2)在计算机科学、arXiv 和跨学科领域的覆盖更好。两个图谱之间的差异比预期更大——同时运行两者并按 id 去重,可以发现实际的覆盖缺口。每个种子都需要提供 DOI、arXiv id 或 PMID,S2 不接受 OpenAlex id;没有这些信息的种子会跳过 S2 后端。设置 S2_API_KEY 环境变量可提高 S2 配额;否则适用约 1 req/s 的公共配额。
幂等性。 设置 --idempotency-key <k> 后,首次成功运行会将 {response, signature} 写入 .scholar_cache/<hash>.json。使用相同键重试时,会重放缓存的响应,不会再次请求 OpenAlex,也不会再次修改状态。使用相同键但参数不同,会返回 idempotency_key_mismatch,而非悄然提供过时数据。缓存目录:SCHOLAR_CACHE_DIR 环境变量,默认值为 .scholar_cache/。
特殊情况 — 一篇高被引论文从未受到质疑。 如果排名结果显示某篇论文的引用数位居前三,但语料中没有出现任何批评,请明确搜索 "<first author> <year>" critique OR limitations OR reanalysis OR failed replication。这是防止确认偏误的兜底措施。
阶段 5 — 综合分析
这里不需要编写脚本——这正是 Agent 发挥作用的地方。对论文进行归类和组织:
- 主题聚类。 将排名靠前的 N 篇论文归入 3–6 个主题,并使其与报告大纲对应。主题应互不重叠:一篇论文只能是一个主题的主要论文,最多还能作为另一个主题的次要论文。
- 矛盾关系图。 哪些论文存在分歧?对于每处分歧,注明涉及哪些论文、分歧内容,以及分歧属于实证层面(数据不同)、方法论层面(工具不同)还是理论层面(框架不同)。
- 时间线。 适用时,按时间顺序梳理发展脉络:开创性论文 → 研究整合 → 进一步完善 → 当前前沿。
- 维恩图/研究空白。 哪些内容已得到充分研究、哪些只得到部分研究、哪些尚未研究?研究空白是阶段 7 的切入点。
阶段 6 — 自我批评
这一步不可省略。 加载 assets/prompts/self_critique.md,按照完整清单检查你的草稿(尚未发布)。清单包括:
- 单一来源的论断(有没有只由一篇论文支持的论断?)
- 引用/时效性偏差(是否涵盖了最近 2 年?)
- 发表渠道偏差(文献集是否由某个期刊/发表渠道主导?)
- 作者偏差(引用是否由某个实验室主导?)
- 未经检验的高引用论文(有没有引用某篇论文却未阅读对其的批评?)
- 被掩盖的矛盾(阶段 5 中是否有哪处矛盾被一笔带过?)
- 类型适配(结构是否符合所选类型?)
- 缺乏依据的论断(有没有未用
[^id]标注出处的陈述?)
将发现写入 research_state.json 的 self_critique 下,并在进入阶段 7 前修复阻碍项。发现内容将原样放入报告附录——读者有权了解研究过程对自身提出了哪些质疑。
阶段 7 — 报告
根据状态数据生成类型模板框架,然后填充由 Agent 撰写的内容,并验证出处标记:
# Generate the scaffold — fills header, themes, tensions, methodology
# appendix, self-critique appendix, and bibliography anchor index from
# state. Leaves `` placeholders for prose.
python scripts/render_report.py --state research_state.json
# → reports/<slug>_<YYYYMMDD>.md by default; pass --output PATH to override.
# After filling in the prose, lint every [^id] anchor against
# state.papers. Catches typo'd anchors before the report ships.
python scripts/render_report.py --state research_state.json \
--lint reports/<slug>_<YYYYMMDD>.md
# Export bibliography in the user's preferred format
python scripts/export_bibtex.py --state research_state.json --format bibtex --output refs.bib
python scripts/export_bibtex.py --state research_state.json --format csl-json --output refs.json
模板框架正文使用 [^id] 标记(来自状态数据的论文 id)。底部的参考文献部分为每篇选定论文各定义一条注释。lint 模式会标记 unknown_anchors_used(拼写错误)和 undefined_in_text(文中有标记但没有对应脚注定义);二者都是阻碍项。unused_definitions 是一个软性提示——表示某些选定论文最终未在正文中引用。
保存路径约定: reports/<slug>_<YYYYMMDD>.md。除非用户指定路径,否则此技能不会在工作目录之外写入文件。
HTML/PDF 交付。 该流程按设计输出 Markdown——这是 render_report.py --lint 验证的约定格式,也是下游 Agent 可以重新处理的格式。若要制作精致、面向读者的成品,可将 reports/<slug>_<YYYYMMDD>.md 和 .bib 交给宿主编码 Agent,并使用类似这样的提示词:“将其渲染为适合分享给我的 PI 的精致 HTML 页面:正文使用衬线字体,栏宽约为 70 个字符,带侧边目录,将阶段 6 的批评内容放入 <details> 块,悬停引用时显示对应的参考文献条目。” 视觉样式不属于此技能的正确性约定范围。
报告类型选择
| 类型 | 适用场景 | 主要输出形式 |
|---|---|---|
literature_review | 用户想了解某个主题已取得哪些共识 | 主题章节 + 综合分析 + 研究空白 |
systematic_review | 问题范围狭窄、研究数量多,需要严谨比较 | 精简版 PRISMA 流程 + 提取表 + 汇总结果 |
scoping_review | 主题广泛,想了解“哪些内容已得到研究?” | 覆盖范围图 + 方法清单 + 研究空白 |
comparative_analysis | “A 与 B”——比较方法、模型、方案 | 比较维度 + 各维度结论 + 建议 |
grant_background | 为提案引言撰写背景叙述 | 问题的重要性 + 已知内容 + 尚缺内容 + 我们方案的理由 |
模板位于 assets/templates/<archetype>.md。只加载所需的模板。
脚本参考
| 脚本 | 用途 |
|---|---|
research_state.py | 初始化、读取、写入和查询状态文件。贯穿每个阶段的核心。 |
search_openalex.py | 主要搜索(无需密钥,覆盖 2.4 亿篇文献,提供引用次数)。 |
search_arxiv.py | arXiv API——预印本以及计算机科学、机器学习和物理学文献。 |
search_crossref.py | Crossref REST——权威 DOI 元数据。 |
search_pubmed.py | NCBI E-utilities——带有 MeSH 主题词的生物医学文献库。 |
search_dblp.py | DBLP——权威的计算机科学文献目录(会议和期刊,作者消歧准确)。可作为 OpenAlex/arXiv 的补充,用于计算机科学综述。不提供摘要或引用次数。 |
search_biorxiv.py | 通过 Europe PMC 网关获取 bioRxiv 和 medRxiv 预印本(CSHL DOI 前缀 10.1101/)。可捕获比 PubMed 建立索引早数周至数月的生命科学预印本。 |
search_exa.py | Exa 神经网络网页搜索(可选,需密钥)——覆盖学术 API 遗漏的开放网络内容。 |
list_sources.py | 列出所有 search_*.py 来源及其能力(领域、索引类型、更新延迟、身份验证要求等)。可按 --domain、--auth、--index-type 或 --needs-relevance-filter 筛选,以便编排器为问题选择合适的来源。架构定义在 _search_meta.py 中。 |
dedupe_papers.py | 规范化 DOI,并跨来源合并标题相似的文献。 |
rank_papers.py | 透明的评分公式。输出公式和每篇文献的评分组成项。 |
skim_papers.py | 第 3 阶段的初步筛选。根据低成本的确定性信号,将选中的文献分为 deep / skim / defer 三个层级,优化 selected_ids,并为 skim 层级自动填充证据占位项。在第 2 阶段结束、G3 之前运行。 |
prefetch_pdfs.py | 可选。在第 3 阶段 Agent 扇出之前,通过 paper-fetch(失败时回退到 Unpaywall)将 deep 层级的 PDF 下载到稳定缓存中。支持并发(--concurrency),重复运行时保持幂等,并针对单篇文献采用失败软处理。为每篇文献写入 pdf_path / pdf_status,使 Agent 读取本地文件,而无需重新下载。 |
build_citation_graph.py | 通过 OpenAlex 进行前向/后向滚雪球检索。 |
extract_pdf.py | 全文提取。--engine auto(默认)先尝试 pypdf;如果 pypdf 的结果看起来是扫描件或内容稀疏,则自动升级为 docling(输出 Markdown,感知版面,并对扫描区域执行 OCR)——通过 pip install docling 安装。可使用 --engine pypdf|docling 强制指定引擎。使用 --ocr-backend {auto,rapidocr,ocrmac,easyocr,tesseract,none} 和 --ocr-lang <list> 调整 docling 的 OCR(各后端的语言词表不同,详见 --help)。接受 --input、--url 或 --doi。DOI 模式会在已安装 paper-fetch 技能时通过它解析,否则回退到 Unpaywall。--idempotency-key 会缓存提取的文本,使重试时跳过重复提取。 |
export_bibtex.py | 从状态文件导出 BibTeX / CSL-JSON / RIS。 |
render_report.py | 第 7 阶段——根据 state.themes / state.tensions / state.queries / state.ranking / state.self_critique 渲染原型脚手架,并用 `` 作为行文占位符。--lint <report.md> 会根据 state.papers 验证每个 [^id] 锚点。 |
所有脚本均接受 --help、--schema,在标准输出中输出结构化 JSON 封装,并将 research_state.json 作为唯一真实数据源。所有脚本对状态文件的操作均具幂等性(网络层幂等性属于 P1 工作)。
CLI 合约、环境变量和状态架构
有三个细节需要 Agent 通过运行脚本并读取 JSON 信封来了解——为节省上下文,这些内容未放入正文。按需加载:
references/cli_contract.md— 成功/失败信封结构、退出代码、--schema内省,以及幂等缓存语义。references/env_vars.md— 信任边界环境变量(SCHOLAR_*、NCBI_API_KEY、EXA_API_KEY、S2_API_KEY、PAPER_FETCH_SCRIPT)。Agent 绝不应设置这些变量——如果脚本报告缺少某个变量,应告知用户。references/state_schema.md—research_state.json的结构。建议使用python scripts/research_state.py --schema获取实时的机器可读版本。
完成关卡
每次阶段转换都有一个关卡(G1..G7)。只能通过以下方式推进:
python scripts/research_state.py --state <path> advance # advance by 1
python scripts/research_state.py --state <path> advance --check-only # preview only
关卡判定条件由 scripts/_gates.py 强制执行。直接设置 set --field phase 会被拒绝——phase 字段已不可设置。如果关卡未通过,信封会按名称列出未通过的检查,让你清楚了解缺少什么。
| 目标 | 关卡(强制执行) |
|---|---|
| G1(→ 1) | 问题集、有效的类型,以及已初始化的状态。≥3 个关键词簇由宿主端检查。 |
| G2(→ 2) | 所有已查询来源的 overall_saturated == true,并且 state.queries 中至少有 3 个不同来源。 |
| G3(→ 3) | 已记录 state.ranking;selected_ids 非空;每篇入选论文都有 score_components;state.triage_complete=true(运行 skim_papers.py)。 |
| G4(→ 4) | 所有入选论文的 depth ∈ {full, shallow},并且每篇 tier=deep 的论文都满足以下条件之一:(a) depth=full,或 (b) depth=shallow 且 evidence.method 以两个已记录的例外前缀之一开头:evidence_unavailable:(无法访问 PDF——付费墙、开放获取来源链耗尽或扫描件),或 topic_mismatch:(已完整阅读 PDF,但与主题不符——Phase 2 排名误报)。按设计,depth=shallow 的粗读层论文不会阻碍推进。 |
| G5(→ 5) | 至少有 1 个查询的 source 包含 citation_chase(任意后端布局——openalex_citation_chase、s2_citation_chase 或默认的双后端 openalex_s2_citation_chase),且 hits > 0。 |
| G6(→ 6) | len(themes) ≥ 3,并且(len(tensions) ≥ 1 或某条批判性发现提到“没有张力”)。 |
| G7(→ 7) | state.self_critique.appendix 非空;len(resolved) ≥ len(findings)。 |
使用 MCP 工具进行补充
Semantic Scholar 覆盖并不属于这些补充内容——它通过脚本路径(build_citation_graph.py --source s2|both)实现,是 Phase 4 的一等后端,而非补充层。以下 MCP 工具才是真正的表层工具:它们可能超时、被重命名,或完全不可用,而且任何阶段的输出都不依赖它们。
如果会话中有 asta 或 Brave Search MCP 工具可用,可将其用于补充:
mcp__asta__search_papers_by_relevance— 在脚本搜索结果基础上进行高密度相关性排序mcp__asta__get_citations— 用于抽查单篇种子论文,比build_citation_graph.py更轻量mcp__asta__snippet_search— 类似 grep 的摘要搜索- Brave Search — 非学术来源(博客文章、新闻稿、预印本讨论)
请将 MCP 工具视为本质上不可靠——它们可能超时或不可用。绝不要将阶段关键步骤置于 MCP 调用之后。脚本是骨干;MCP 是表层。
使用主机原生 Web 工具进行补充
有些主机运行时自带开箱即用的 Web 工具,无需配置——不需要 MCP 服务、API 密钥或环境变量。**可将它们作为补充,与上述 MCP 工具配合使用或替代它们。**遵循与 MCP 相同的原则:仅作为辅助输入,绝不置于关键路径上。
已知工具(请确认主机实际提供哪些工具——工具名称可能变化):
| 主机 | Web 搜索 | Web 抓取 | 备注 |
|---|---|---|---|
| Claude Code | WebSearch | WebFetch | 无需配置,也不需要 API 密钥 |
| OpenCode | webfetch | webfetch | 单个工具即可抓取;搜索可能需要 MCP |
| Codex CLI | 因版本而异 | 因版本而异 | 工具集取决于 Codex 配置文件和插件 |
| OpenClaw / Hermes / pi-mono / Manus | 因情况而异 | 因情况而异 | 这些主机通常通过已配置的 MCP 服务进行路由——参见上文的 asta/Brave |
如果看不到这些工具,请改用 MCP 选项。如果两者都不可用,工作流仍可继续——仅使用脚本搜索也足以完成任务。
它们在 8 阶段工作流中最有价值的用法:
- 阶段 1——补充时效性信息。 对于答案在过去 30 天内发生变化的主题,可并行使用主机原生 Web 搜索和学术来源。arXiv/bioRxiv 延迟 1-3 天;OpenAlex/PubMed 约 1 周。WebSearch 能捕捉尚未出现在预印本中的博客、Twitter 帖子和新闻稿等最新信息。
- 阶段 3——最后手段:抓取 PDF。 在写入
evidence_unavailable前,如果extract_pdf.py --doi/--url均失败,可尝试使用WebFetch(landing_url_for_paper)从出版商的 HTML 页面提取摘要或研究发现。参见references/agent_prompts/phase3_deep_read.md中的步骤 (d)。 - 阶段 6——检查时效性。 自我批评时,使用 WebSearch 搜索论文标题,查找论文发表后出现的撤稿、更正或重复验证失败等信息。
**不要将 Web 搜索结果传入 apply_ingest。**主机原生搜索结果是非结构化的(没有 DOI、作者、发表场所或来源归属信息),因此应将其用于文本上下文或事实核查,而不是写入 research_state.json 的论文记录。这样可以确保语料库始终可审计。
常见陷阱(简要列表;详情见 references/pitfalls.md)
- 将搜索结果的第一页当作“文献综述”——使用多个关键词组合,并追踪引用。
- 缺少依据的论断——报告中的每项重要陈述都需要用
[^id]指向状态文件中的一篇论文。 - 确认偏误——主动搜索对高引用论文的批评;参见阶段 4 的特殊情况。
- 混淆预印本——arXiv/bioRxiv 上的内容属于预印本;在报告中将其标明为预印本,并相应调整证据权重。符合 Lint 规则的写法:将锚点与标记分开——
[^id] *(preprint)*,而非[^id, preprint](脚注方括号内的逗号会破坏 Markdown 解析和render_report.py --lint检查)。 - 发表来源单一——如果排名前 N 的论文中 >60% 来自同一期刊或发表场所,请扩大来源范围。
- 作者来源单一——单一实验室或作者的情况也一样。
- 忽视时效性——对于“最新进展”类表述,过去 2 年的研究很重要;请明确检查覆盖情况。
- MCP 工具名称过时——MCP 服务可能会重命名工具;请始终先列出可用工具,再确认名称。脚本路径稳定;MCP 工具名称则不然。
- 只搜索一次——每个关键词组合至少安排 ≥3 轮搜索,而不是只搜一次。
- 跳过自我批评——越是想提交一份看似完善的草稿,越是需要阶段 6 来发现问题。
交互示例
完整演示流程(DMD 的 CRISPR 碱基编辑——从阶段 0 重述问题,到阶段 7 生成报告和参考文献)见 references/example_run.md。想了解完整流程的理想效果时,可读一遍;日常使用时并非必需。
参考资料
模块化文档,仅在需要时加载:
references/search_strategies.md— 布尔检索组、PICO、滚雪球法、饱和度计算references/source_selection.md— 不同问题应使用哪个数据库references/quality_assessment.md— CRAAP、期刊等级、撤稿核查、预印本处理references/report_templates.md— 5 种报告类型及各章节指南references/pitfalls.md— 附带示例的完整陷阱清单references/cli_contract.md— JSON 封装格式、退出码、--schema内省、幂等性缓存references/env_vars.md— 信任边界配置(SCHOLAR_*、NCBI_API_KEY、EXA_API_KEY、S2_API_KEY、PAPER_FETCH_SCRIPT)references/state_schema.md—research_state.json格式和 ID 规范化规则references/example_run.md— 完整端到端示例(DMD 的 CRISPR 碱基编辑)references/agent_prompts/phase3_deep_read.md— Phase 3 中用于并行 Agent 扇出的逐篇论文提示词