lit-search

GitHub

用于系统综述、开题报告等场景的高召回文献检索,通过构建检索协议和自动化流水线获取分层 DOI 及参考文献列表。

lit-search/SKILL.md luwill/research-skills

Trigger Scenarios

需要查全某方向近 N 年文献 系统综述或 SLR 调研 开题报告文献梳理 挑战赛背景调研

Install

npx skills add luwill/research-skills --skill lit-search -g -y
More Options

Non-standard path

npx skills add https://github.com/luwill/research-skills/tree/main/lit-search -g -y

Use without installing

npx skills use luwill/research-skills@lit-search

指定 Agent (Claude Code)

npx skills add luwill/research-skills --skill lit-search -a claude-code -g -y

安装 repo 全部 skill

npx skills add luwill/research-skills --all -g -y

预览 repo 内 skill

npx skills add luwill/research-skills --list

SKILL.md

Frontmatter
{
    "name": "lit-search",
    "description": "Runs an exhaustive time-windowed literature search over a research topic and delivers a quality-tiered DOI list plus a matching formatted reference list, with measurable recall (gold-set recall, PRISMA counts, citation-closure saturation). Use for systematic reviews \/ SLR, 开题报告, 挑战赛调研, or any \"把某方向近 N 年文献检索全\/理一遍\/梳理一遍\/查全\" request. Builds the corpus — not for reading or summarizing the papers themselves, and not for writing the review text. Not for casual \"find me a few papers\" lookups."
}

时间窗受限的高召回文献检索

驱动 literature-search/ 这条流水线。核心前提:召回率不是提示词问题,是检索工程问题。 反复 WebSearch 得到的是"相关度排序的前若干条",既不可复现,也无法说明漏了什么。

工具位置与产物去向(第一步,别跳过)

CLI 就装在本 skill 目录里src/litsearch/ + pyproject.toml)。 所有命令都要在这个目录下执行——它是 uv 找得到项目的地方:

SKILL_DIR=~/.claude/skills/lit-search     # 本 SKILL.md 所在目录
cd "$SKILL_DIR" && uv run lit --help      # 跑不通就先跑一次 ./install.sh

$LITSEARCH_HOME 若已设置则优先用它(把工具装在别处的人靠这个覆盖)。 两处都找不到 src/litsearch/cli.py问用户,不要猜

产物必须写到用户的项目里,不是 skill 目录里。 --runs-root 默认是相对路径 runs/,而命令的工作目录是 skill 目录—— 不显式指定的话,几百 MB 的采集结果会堆进 ~/.claude/skills/lit-search/runs/, 用户既找不到,也想不到要去那里清理。每一条命令都要带上绝对路径

PROJ=/abs/path/to/用户的项目            # 开工前先跟用户确认这个位置
cd "$SKILL_DIR" && uv run lit harvest --topic "$PROJ/topics/<id>.yaml" \
                                      --runs-root "$PROJ/runs" --depth standard

协议 YAML 同理——写在用户项目的 topics/ 下,不要写进 skill 目录。 本目录的 examples/ 有两份真实协议(生物医学、纯 CS 各一份)可以照抄。 下文命令块为了可读省略了这两个路径参数,实际执行时必须补上

判断要不要用

:系统综述、开题报告、挑战赛调研——需要说得清召回边界的场合。 不用:用户只想快速看几篇代表作。那种情况直接 WebSearch 更快,别拖他走完整条流水线。

契约

输入:一句话研究主题 + 可选时间范围(不给就默认近 5 年)。 输出

文件 内容
dois.md 全量 DOI 清单,按质量层分节,每条带证据标记
references.md 参考文献列表,顺序与 dois.md 一致
references.bib BibTeX(--bibtex,需额外一遍抓取)
PRISMA.md / coverage_report.md 计数与召回率证据

全量交付,分层只决定顺序,不决定去留。

两份参考文件,按需读,不要预先读: references/topic-template.yaml(写协议用)、 references/evidence.md(下面每条规则背后的实测数字,用户追问或排查时才需要)。


阶段 0|写协议(这一步是模型的核心工作)

没有 lit init 命令——把主题变成协议需要判断力,不是代码。模板在 references/topic-template.yaml,复制到 topics/<id>.yaml 后按四步填。

① 拆概念块。 3–5 块,标出哪些 required

第一个 required 块会成为无布尔检索能力源(CVF/OpenReview/Zenodo)的锚点短语。 把区分度最高的概念放第一位——通常是疾病/对象/材料。放成 "segmentation" 这类泛词, 会把整届 CVPR(约 9,200 篇)拉回本地过滤。

② 提名金标准——5–10 篇,DOI 必须先验证再写入。

gold_set 是整条流水线里唯一能证伪的东西。所以:

curl -sI -o /dev/null -w "%{http_code}\n" -L "https://doi.org/<doi>"   # 200 才许写进协议

走 doi.org,不要走 Crossref。 arXiv 的 10.48550/arXiv.* 注册在 DataCite, api.crossref.org 对它一律 404——用 Crossref 验证会把真实存在的预印本当成编造的 DOI 拒掉, 而 CS/AI 主题的金标准几乎全是 arXiv

编一个格式合法但不存在的 DOI,代价不是"少一篇文献",是验证链条整个失效—— 你会看到 8/9 的召回,然后花半天排查一个根本不存在的漏检。

数量不能凑合。 少于 5 条时 coverage_report.md 会自己标注"证据偏弱": 3/3 和 9/9 印出来一模一样,但前者能证伪的检索缺陷少得多。

同时提名 1–2 篇窗口外的真实论文当 out_of_window_controls,验证日期过滤真的生效。

③ 干跑校准量级。

uv run lit strategies --topic topics/<id>.yaml    # 只看检索式,不发请求
uv run lit plan       --topic topics/<id>.yaml    # 各源预计命中数
命中量级 判断 动作
> 50,000 概念太宽 加 required 块,或收紧通配符
200 – 20,000 合适 冻结
< 200 太窄 补同义词;检查英美拼写变体(ischemic/ischaemic)

这是唯一允许调参的窗口。 一旦开始采集,改术语会变更语义指纹,作废整轮。

④ 领域判断。 生物医学之外的主题(纯 CS / 工程 / 材料)要主动提醒用户两件事

  1. 摘要覆盖会下降。 这条流水线对闭源出版商的摘要覆盖实质上是 PubMed 撑起来的 (实测 Elsevier 95.6%、Springer 80.4%,而 Crossref 上这些条目根本没有摘要)。 PubMed 用不上时初筛退化成只看标题。Semantic Scholar 本该补这个位,但当前版本尚未实现 ——协议里写 semantic_scholar: enabled 会被丢弃(CLI 会红字提示)。不要向用户 声称补上了覆盖面。
  2. 捕获-再捕获会结构性不可得。 它需要 PubMed × OpenAlex 两个源同时在场。 关掉 PubMed 后,召回证据就只剩金标准一个点位——所以这类主题的 gold_set 更要提满 5–10 条。

阶段 1–7|流水线

每一步跑完都要把数字念给用户听,不要静默推进。

先让用户选深度——代价必须先于执行可见

uv run lit depths     # 三档的规模、耗时、成本对照
滚雪球 规模 耗时 API 成本
quick 主干四源 不跑 ≤2,000 ~10 min $0.1–0.3
standard(默认) 全源 1 轮 2k–8k ~40 min $0.3–1.2
systematic 全源 至饱和 10k+ 2–4 h $3.4–10.4

三档的差别只在跑多少源、滚几轮雪球。判定规则、去重、时间窗、召回率证据 三档完全一致——降档降的是覆盖面,不是严谨度systematic 必须显式指定并等用户确认。

<run> 从哪来lit harvest 跑完第一行会打印 run 目录,那就是它。 后续命令也接受 <topic>/<run_id>,或只给协议里的 topic id 自动取最新一次—— 后者最省事。忘了跑到哪一步用 lit show <run>

# 1 采集
uv run lit harvest    --topic topics/<id>.yaml --depth standard
uv run lit proceedings <run> --topic ...   # 仅 MICCAI/LNCS 类主题;语料里没有 LNCS 会自动跳过

# 2 筛选(三级放量,见下)
uv run lit screen      <run> --topic ... --limit 4
uv run lit screen      <run> --topic ... --limit 100
uv run lit screen      <run> --topic ...
# 在 human_queue.csv 填 decision/reviewer/reason 后导回(可分批)
uv run lit adjudicate  <run> --topic ... --kind screening --input human_queue.csv
# 在 boundary_cases.csv 填 decision/reviewer/reason 后导回
uv run lit adjudicate  <run> --topic ... --kind date --input boundary_cases.csv

# 3 引文闭包(必须在筛选之后)
uv run lit snowball    <run> --topic ... --seeds included
uv run lit screen      <run> --topic ... --resume     # 只补新增记录,不重判已判过的

# 4 证据与报告
uv run lit validate    <run> --topic ...
uv run lit report      <run> --topic ...
uv run lit verify      <run> --strict

# 5 分层与交付(--ccf 可选,先问用户要目录路径)
uv run lit rank        <run> --ccf CCF.pdf --included
uv run lit deliver     <run> --topic ... --ccf CCF.pdf --style gbt7714 --bibtex

滚雪球循环怎么收。 snowballscreen --resumesnowball → …,交替进行。 三种终止,只有第一种能宣称闭包完成:

CLI 打印 含义 动作
「已达饱和」 连续 2 轮新纳入 < 5% 停,可以说闭包完成
「没有新的合格种子」 自然枯竭 停,可以说闭包完成
「已达最大轮数但尚未饱和」 撞上限了 不能说闭包完成——要么加 --max-rounds,要么在报告里写明

--depth quick 不跑滚雪球,standard 只滚 1 轮;要滚到饱和用 systematic 或显式 --max-rounds不要照全量重跑 screen——那会把几千条已判定的再判一遍, 钱翻倍,还可能触发"新一轮判定数少于上一轮"的护栏而拒绝写入。

补源不能靠续跑。 harvest --resume 只重跑上一轮未完成的检索式,它没有能力 覆盖一个从没跑过的源。先跑了 quick、之后想补顶会源,用:

uv run lit harvest --topic ... --into <run> --phase stage3 --sources cvf,openreview,grey

放量前必须先冒烟、再校准

不要直接对上万条跑筛选。三级放量,每级只花上一级十倍的钱,发现的却是完全不同的问题:

  • --limit 4(约 $0.003)验 API 契约。 假客户端测得了你的代码,测不了服务端约束。 实测就是在这一步撞到 Thinking mode does not support this tool_choice

  • --limit 100(约 $0.02)验任务设计。 两根轴都要看,缺一根都会放过问题:

    成因——大量 unclear 且理由雷同 = 把全文阶段的标准用在了标题摘要阶段, 该改提示词而不是改协议(改协议会变更语义指纹,挡住后续滚雪球并入)。 健康的队列应以"通道分歧"和"低置信度"为主。

    体量——队列占比超过 15% 就要停下来改标准,不管成因分布多"健康"。 实测一次 4,000 条的运行队列率 24.6%(973 条),成因分布完全正常, 但 973 条没有人会真去看lit adjudicate 能把裁定结果导回, 可它是给几十条用的;上千条时正确动作是回来改判定标准,不是把队列丢给用户。 在裁定导回之前,这些记录不进 included,也不进交付物。

  • 放量。

--limit 的结果写 screening_trial.json不占正式轮次——否则一次校准会盖掉全量结果。

不能跳过的顺序

筛选必须在滚雪球之前。 实测:从未筛选的 13,920 条种子出发,后向候选是 134,317 条; 而最终会纳入的只有几百条。跳过筛选去滚雪球 = 把噪声放大一个数量级,还要为此付十倍筛选费。 用户催的时候也不要改成 --seeds in_window——先把成本讲清楚,让他自己决定。

滚雪球与筛选必须交替。 种子是"已纳入",不筛就没有种子。 实测饱和曲线 34.7% → 4.1% → 0.4%,而 snowball 独有贡献占 92%—— 这是纯关键词检索会漏成什么样的直接证据。

成本必须先于执行可见。 lit screen --dry-run 给出 token 数与美元金额。 无凭据时是字符粗估并明确标注。不要替用户跳过这一步。


分层与交付

只标注与排序,绝不过滤。 阈值会把"没被评价过"和"质量低"变成同一个动作—— 实测以 4.0 切,1,487 条只剩 390 条,其中被删的 340 条是没有指标而非指标低。

分层取所有可用尺子里最好的那个

判据
S 顶会顶刊 CCF-A,或论文引用进入同领域前 1%
A 高水平 CCF-B,或期刊指标 ≥ 8.0,或引用前 10%
B 优质 CCF-C,或期刊指标 4.0–8.0
C 最新预印本 预印本 / 仓库,≤ 18 个月
D 会议(未评级) CCF 目录里没有——未评级,不是低等级
E 其它期刊 期刊指标 < 4.0
F 其余 无任何评价依据——未被评价,不是低质量

四条必须讲清楚的事:

  1. CCF 与影响力指标测的不是同一件事,取较优。 实测 Medical Image Analysis 是 CCF-C,而它的 OpenAlex 指标 10.14 全语料最高。
  2. OpenAlex 2yr_mean_citedness 不是 JIF。 JIF 分母只算 citable items, OpenAlex 分母算全部条目;发大量学会年会摘要的刊被系统性低估三到五倍 (实测 Stroke 1.81、Neurology 1.11)。阈值不能跨标度搬运。
  3. 排行榜数据由用户提供,不随仓库分发。 CCF 目录是公开文档但仍走 --ccf 槽位; JCR / 中科院分区是商业授权数据,绝对不能打包进仓库
  4. 没有目录就不猜等级。 目录里没有的会议标"未评级"。 编出来的 CCF-A 和真的长得一模一样,这是最危险的地方。

引文格式化免 keylit deliver 走 doi.org 内容协商,支持 apa / ieee / gbt7714 / nature / ama / bibtex

(期刊匹配走 ISSN 而非刊名、样式名发请求前先校验——这两条是 lit rank / lit deliver 内部的护栏,你没有对应操作。想知道为什么见 references/evidence.md。)


凭据

.env 或环境变量读(真实环境变量优先)。缺哪个的后果各不相同,要说清楚:

后果
LITSEARCH_LLM_API_KEY 不致命——用 --model host 走宿主模型,零配置
OPENALEX_API 采集中途 QuotaExhausted;捕获-再捕获算不出,召回证据只剩金标准一个点
CONTACT_EMAIL lit fulltext 直接拒绝跑——Unpaywall 与 Crossref 都要求声明身份

筛选后端:两条路

API 后端(默认):任何 OpenAI 兼容端点。三个环境变量 LITSEARCH_LLM_MODEL / _BASE_URL / _API_KEY。内置 DeepSeek 的实测价目, 其它厂商的价目由 LITSEARCH_PRICING 提供——没有价目时 --dry-run 会如实报 「无法估算」,不会报一个假的 $0.00

宿主后端--model host):调本机 claude -p不需要任何 key。 clone 完就能跑,这是给社区用户的零配置入口。三件事要说清楚:

  • 每次调用有约 20,000 token 的框架开销,所以批次自动放大到 60 条
  • 不是免费的:实测 60 条记录约 $0.30 API 等价成本(haiku;用 opus 是 $1.44)。 订阅用户不额外付费,但会消耗额度——别说成 "$0"
  • --host-model 默认 haiku。上万条规模请改用 API 后端

OpenAlex 有日配额。 lit deliver 默认复用 ranked.jsonl,不重取元数据; 要刷新加 --refresh。配额耗尽时 QuotaExhausted 会带上重置秒数——降速无效,别重试。


报数字的纪律

  • "本次没执行的部分"必须念给用户听。 lit report 会把它算出来写进 coverage_report.md 的第一节,终端也会黄字列出来。不要跳过这一段去讲纳入数: 「跑了没成功」有 partial 告警管着,「压根没跑」曾经在整套产物里没有任何痕迹—— 实测一次交付的 manifest 声明了 4 个源、实际只访问了 2 个,而当时没有一份产物提到。
  • partial/failed 的源要点名。 它的召回数字是下界,不是实际值。
  • 标题摘要初筛通过也不是最终纳入。 尚未筛选时,窗口内记录数不是相关文献数; 初筛完成后,include 也只是进入全文资格审查的候选报告。lit report 在没有全文 获取、排除理由与最终资格记录时会止于 Eligibility input,你也不要在话里补上终局。
  • 被测出来的零要说出来。 "CVPR/ICCV/WACV 2021–2026 共 9,200 篇里一篇都没有" 是有价值的结论,和"我觉得那里没有"完全不同。
  • 金标准漏检必须逐条归因到具体检索式或源缺陷,不能笼统说"召回率不错"。
  • Chapman 只用于两源重叠诊断。 PubMed 与 OpenAlex 不独立,正相关会使两源并集 覆盖度偏乐观;它没有验证主题相关性,也不是多源流水线召回率。

三条硬规则

① 200 不代表拿到的是你要的东西。 枚举源"200 但解析出 0 条"必须报失败; 内容协商拿回 HTML 必须判定为失败。实测这两种都真实发生过, 而且第二次是我只挡了"见过的坏样本"(JSON 错误)导致的复发。 校验要写成"确认它是我要的",不是"排除我见过的坏样本"。

② 跑砸的一轮不能覆盖跑成的一轮。 新一轮判定数少于上一轮 = 拒绝写入、非零退出。 断点续跑所需的信息(如通道号)必须在第一次跑的时候就存下来——事后要么补不出来, 要么只能靠猜,而猜出来的和真的长得一样。

撞到这个护栏时(退出码 1 + "不写入新轮次"):不要重试全量。先看失败样例定位 原因(配额耗尽 / 网络 / 端点变更),修好之后用 screen --resume 只补缺的判定。

③ 规则演进后不要重采。 lit reclassify 用当前规则从 records*.jsonl 重新去重 与判定窗口,一次请求都不发。某个源的解析缺陷修好后,用 lit harvest --into <run> --phase fix --labels <那几条> 定点补跑。 采集是昂贵的一次性动作,判定不是。

两个人工队列怎么交代

human_queue.csv(判定分歧 / 低置信度)和 boundary_cases.csv(日期精度不足) 现在都能经 lit adjudicate 回流,并保留裁定人、时间、理由与原判定。

所以跑完必须做两件事,都不能替用户代劳:

  1. 把两个文件的路径和条数报给用户,并说明 decision 允许值;不要替用户裁定。 --kind screeninginclude / exclude(不接受仍为 unclear); --kind datein_window / out_of_window,且只受理 boundary / undated 的记录 ——裁定是用来消解不确定的,不是用来盖掉已有判定的。已确定的日期判错了, 该修日期证据或 date_priority 再跑 lit reclassify
  2. 用户填写 reviewerreason 后运行相应的 lit adjudicate --kind ...。导回后报告 剩余队列,并运行 lit reportlit verify。队列大到不现实(>15%)时,先校准标准。

--kind date 把边界记录改判进严格窗口后,这些记录还没被筛选过lit verify 会报 screening-corpus-mismatch。这是正确的提醒:补跑 lit screen <run> --topic ... --resume 之后再出报告。

推送 Zotero

lit report 生成 zotero_dois.txt。逐条调 zotero_add_by_doi推送前先确认 collection 名称——这是对外部系统的写操作,不要默认执行。 该清单是标题摘要初筛通过的全文候选集,不是最终纳入研究。没有 DOI 的候选不在 清单里,不要凭空造标识符;推完要把这件事告诉用户。

产物

runs/<topic>/<timestamp>/

文件 内容
raw/<阶段>/<attempt-id>/ 每次 attempt 的 gzip 逐页原始响应,修复重跑不复用旧页
records*.jsonl 逐源记录,按采集阶段分文件,只追加不改写
corpus.jsonl 去重后的规范语料(派生产物,可随时重算)
manifest.json 协议指纹 + 每条检索式的结局与状态
boundary_cases.csv 日期精度不足,需人工裁定
human_queue.csv 双通道分歧或低置信度,需人工裁定
PRISMA.md 各环节计数(不自洽会拒绝生成)
coverage_report.md 本次未执行的部分、严格窗口金标准召回、窗口外泄漏、独有贡献、两源重叠诊断、饱和曲线
artifacts.json 派生产物内容哈希与输入依赖哈希;由 lit verify 检查过期
ranked.jsonl / ranked.csv 分层标注(ranked.jsonl 是元数据缓存)
tier_report.md 分层构成与逐级匹配率
dois.md / references.md / references.bib 交付物

Version History

  • 45ce78d Current 2026-08-19 23:52

Same Skill Collection

medical-imaging-review/SKILL.md
research-proposal/SKILL.md
scholar-slides/SKILL.md
paper-slide-deck/SKILL.md

Metadata

Files
0
Version
45ce78d
Hash
d5ef041f
Indexed
2026-08-19 23:52

inicio - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-22 06:51
浙ICP备14020137号-1 $mapa de visitantes$