--- name: literature-search-verify description: Search academic literature across arXiv, Semantic Scholar, Crossref, OpenAlex, and other connected paper-search MCP tools, and independently verify every candidate citation before it is treated as real. Use this whenever the user asks to find papers, search literature on a topic, build a reading list, compile related-work references, check whether a citation or bibliography entry actually exists, or prepare references to import into Zotero or a .bib file — especially in academic writing contexts where a fabricated citation would be a real problem. Also covers guiding the user to the Zotero Connector browser extension for Chinese-language sources (CNKI/知网, Wanfang/万方, VIP/维普) that have no public API and cannot be reached by search tools. --- # 文献检索 + 反幻觉引用核查 ## 为什么需要这个技能 大语言模型在编造论文引用这件事上非常擅长——生成的标题、作者、期刊名读起来都很像真的,但可能根本不存在,或者张冠李戴(把A论文的结论安在B论文头上)。这在正式学术写作里是不可接受的:一篇论文只要有一条编造的引用被发现,审稿人对全篇的信任都会崩塌。 所以这个技能的核心不是"搜索",而是"搜索之后不轻信"——每一条打算真正拿去引用的文献,都必须经过独立交叉验证,验证不通过的必须明确标出来,而不是悄悄丢弃或者悄悄当作真的用。 ## 工作流程 ### 第一步:明确检索范围 在开始搜索前,搞清楚(不确定就直接问,一句话就够): - 核心关键词/研究方向(可以中英文混合,比如"UAV磁补偿 Tolles-Lawson"这类) - 大致的时间范围(比如"近5年"还是不限) - 是否需要限定顶会/顶刊,还是什么来源都要 ### 第二步:检索——直接调用脚本,不要自己现编API调用 `scripts/` 目录下已经写好了能直接跑的检索脚本,不依赖任何第三方Python包,也不需要装MCP工具: ```bash # 始终从项目根目录调用(脚本本身不关心cwd,但--bib-out等输出路径按项目根目录约定拼)。 # 一次性搞定:检索 arXiv + Semantic Scholar + Crossref,自动去重、逐条验证, # 并把通过验证的条目写成BibTeX文件——这是应该默认调用的入口 mkdir -p output/literature-search-verify/uav_aeromagnetic_compensation python3 .claude/skills/literature-search-verify/scripts/literature_search.py \ "UAV magnetic compensation Tolles-Lawson" \ --max-per-source 8 \ --bib-out output/literature-search-verify/uav_aeromagnetic_compensation/refs.bib ``` 草稿路径(检索报告JSON、下载的PDF、中间生成的bib)统一落在项目根目录下的 `output/literature-search-verify/`,不要写回技能自己的目录里(`.claude/skills/` 应该只放技能代码,不放运行时产生的草稿数据)。如果项目里以后还有别的技能也 需要草稿区,各自建 `output//` 子目录,互不混放。 **同一个技能内部也要按主题分开,不要所有检索会话都堆在同一层**:开始一个新 主题的检索时,先按"和第六步归档时同样的规则"把主题名转成 slug(小写、非 字母数字换成下划线,比如"UAV aeromagnetic compensation" → `uav_aeromagnetic_compensation`), 建 `output/literature-search-verify//` 子目录,这一整个主题下 不管跑多少轮检索、多少条不同的query,原始JSON/bib草稿都写进这一个子目录里 (文件名可以随意区分轮次,比如`q1.json`/`q2.json`),不要用不带主题区分的 通用文件名散落在`output/literature-search-verify/`根下。这样同一个主题的 草稿和第六步归档产出的`references//`目录能通过同一个slug对上号, 之后回来补充检索同一主题时也知道去哪个子目录续。 正常情况下**只需要跑这一条命令**,它内部会依次调用 `search_arxiv.py`、`search_semantic_scholar.py`、`search_crossref.py`、`search_openalex.py` 做检索,再对每条合并后的候选文献跑 `verify_citation.py` 做交叉验证,输出一份JSON报告(每条候选都带`verdict`字段)。如果只是想单独查一个来源,或者针对某一条文献单独复核,再分别调用对应的单个脚本(用法见每个脚本文件开头的docstring)。OpenAlex(`search_openalex.py`)是在 arXiv/Semantic Scholar/Crossref 之外新增的第四个源,免费、无需API key,覆盖面比单独的 Crossref 更广(聚合了包括 IEEE 在内的绝大多数出版商元数据),还能拿到开放获取PDF直链;可以设置`OPENALEX_MAILTO`环境变量为一个邮箱地址进入OpenAlex的"polite pool"换取更稳的限额,不设置也能正常用。 所有脚本的网络请求都经过 `http_utils.py` 统一封装:遇到 429(限流)或 5xx 会按指数退避自动重试几次(优先遵守服务端返回的`Retry-After`),不需要每次手动重试;`verify_citation.py`的跨源标题核查更是同时查 Semantic Scholar 和 OpenAlex 两个独立源、任一命中即算通过,不会再出现"S2一限流,整批候选的跨源核查全部退化成skipped"的情况(这是实际发生过的问题,现在已经用两个源+重试解决)。即便如此,如果这些脚本因为网络原因跑不动(比如内网/代理限制导致连不上这几个学术API域名),`literature_search.py` 会把每个来源的报错单独记在`search_errors`里而不是直接崩溃——这时候老实告诉用户"检索脚本连不上网络,以下是报错信息",不要退回去凭记忆编文献。如果用户这边确实连不上这几个学术API域名,才退回到 web_search 工具,并在结果里明确标注"来自通用网络搜索的补充结果,未经过脚本的交叉验证流程,置信度较低"。 如果用户已经连了 paper-search-mcp / scholar_mcp_server 这类MCP工具,可以补充用来扩大覆盖面(比如它们能覆盖PubMed、能直接下载PDF),但**不能替代**`verify_citation.py`的交叉验证这一步——MCP搜到的候选一样要过一遍验证,不能因为是工具搜出来的就默认可信。 ### 第三步:理解验证结果——这是最关键的一步 `literature_search.py`(或单独调用`verify_citation.py`)对每条候选文献做的核查是: 1. **arXiv ID 独立核实**:如果有 arXiv ID,反查一次 arXiv API,确认这个ID真的存在且标题对得上——一个编造的ID在这一步会直接暴露。 2. **DOI 独立核实**:如果有 DOI,反查一次 Crossref,确认这个 DOI 真的能解析出对应文献。 3. **跨源标题复核(双源)**:不管有没有ID,单独拿标题分别去 Semantic Scholar 和 OpenAlex 各搜一次,要求返回的标题跟候选标题高度相似(相似度≥0.9)——这一步专门用来抓"标题作者读起来很像真的,但其实是编出来的"这种情况。两个源里任一个命中相似度达标就算通过;只有当两个源都明确没找到匹配(不是因为网络问题被跳过)时才算这一项核查失败——避免某个源覆盖不全(比如论文太新还没被其中一个索引收录)被误判成"编造"。 每条候选最后会带一个`verdict`: - **verified**:至少一项独立核查通过,而且没有任何一项核查明确失败 - **suspect**:至少一项核查明确失败(比如DOI查不到、跨源标题对不上)——**这种情况下不要用这条文献,即使标题看起来很合适** - **unverified**:所有核查项都因为网络等原因被跳过(`skipped`),不代表验证通过,只代表"没能验证"——**同样不能当成已核实的文献直接使用**,要跟用户说清楚原因 呈现给用户时按这三档分组说明,`suspect`和`unverified`都要明确标出来,不要因为报告里有个"看起来还行"的标题就含糊地当真的用。 **原则**:找不到真实存在的相关文献时,直接说"没找到符合条件的文献",不要为了凑数编一条出来。这条原则没有例外。 ### 第四步:输出 按 verified / suspect / unverified 分组呈现结果,每条包含标题、作者年份、venue、标识符、一句话相关性说明。 `literature_search.py` 传了 `--bib-out` 参数时,会自动把所有 `verified` 的条目写成BibTeX文件,citation key 用"姓氏+年份"约定,可以直接导入 Zotero(配合 Better BibTeX 插件)。这些 key 也是后续`paper-writing-grounded`技能里`\cite{}`要用到的,两个技能之间通过这些key保持一致,不需要额外对照。 ### 第五步:提醒中文文献的检索缺口 MCP 检索工具覆盖的是 arXiv/Semantic Scholar/Crossref 这类有公开 API 的英文为主的库,**知网、万方、维普这类中文数据库没有公开 API,搜不到很正常,不是技能出错**。遇到用户明显需要中文文献的场景,主动提醒:装好 Zotero Connector 浏览器插件,在浏览器里正常登录学校账号搜索、打开文献页面,点一下 Connector 图标就能把元数据和 PDF 存进 Zotero——这部分需要用户手动完成,不要尝试用检索工具"模拟"或"猜测"中文文献的存在。 ### 第六步:归档 `/output/literature-search-verify/` 只是脚本运行时的草稿区——里面 混着每一轮探索性检索的原始JSON(包括被过滤掉的噪声,比如"Tolles""Lawson"被当成 人名匹配出的无关文献),不适合作为最终交付物,而且随着会话增多会越堆越乱、也不 方便下次会话或用户直接翻阅。 所以每次整理出一份**稳定可信的参考文献列表**(不管是第一轮检索还是后续多轮补充检索合并后的结果)之后,调用归档脚本把它固化到项目级目录,而不是留在草稿区里: ```bash python3 .claude/skills/literature-search-verify/scripts/archive_references.py \ "UAV aeromagnetic compensation" \ --bib output/literature-search-verify/uav_aeromagnetic_compensation/uav_aeromagnetic_compensation_final.bib \ --project-root . \ --pdfs-dir output/literature-search-verify/uav_aeromagnetic_compensation/pdfs \ --suspect "某条可疑文献标题|不建议引用的具体原因" \ --notes "检索覆盖了哪些方向、哪些方向搜了但没结果、中文文献缺口提醒等" ``` 这会在 `/references/<按主题自动生成的slug>/` 下生成: - `references.bib` —— 传入的bib文件原样拷贝过去 - `pdfs/`(如果传了`--pdfs-dir`且里面有PDF)—— 一并拷贝过去 - `README.md` —— 自动从bib里解析出条目列表(标题/年份/venue/DOI/note)生成索引,`--suspect`和`--notes`里的内容会分别整理进"不要引用"和"检索覆盖说明"两个小节 几个要点: - `--bib` 传的必须是**已经过滤掉无关噪声、只保留verified条目**的干净bib文件,不要把`literature_search.py`直接吐出来的、可能夹杂噪声的原始bib不加甄别地拿去归档。 - 同一个`topic`名字多次调用会往同一个归档目录里覆盖更新(bib和README会被覆盖,pdfs按文件名去重合并),所以后续检索到更多文献后可以直接对同一个topic重新跑一遍归档脚本来更新,不需要手动合并。 - 这一步做完之后可以明确告诉用户归档目录的路径,方便他们后续在`paper-writing-grounded`阶段直接引用。 ## 维护者备注:单元测试 `scripts/tests/` 下有针对核心正确性逻辑的单元测试(不发真实网络请求,全部用 mock):`verify_citation.py` 的三档判定和双源标题核查合并逻辑、 `archive_references.py` 的 bib 解析(含嵌套花括号、中文主题名slugify等边界 情况)、`literature_search.py` 的候选去重合并与BibTeX生成、`http_utils.py` 的限流重试。改动这几个脚本后应该跑一遍: ```bash python3 -m unittest discover -s .claude/skills/literature-search-verify/scripts/tests -t .claude/skills/literature-search-verify/scripts ``` 只用标准库`unittest`,不引入pytest等第三方测试框架,和脚本本身"不依赖第三方 包"的原则保持一致。 ## 和 paper-writing-grounded 技能的配合 这个技能负责把"真实存在、经过核实的文献"整理好并生成 BibTeX;写作阶段的 paper-writing-grounded 技能会直接消费这里产出的 citation key,正文引用只能来自这里核实过的条目,不会凭空生成新的引用。两个技能配合使用时,建议先跑完这个技能、拿到稳定的参考文献列表,再进入写作。