self-verify — 学术写作实时引用核查
定位
写作过程中的引用快速抽查。验证 Claude 输出的文献引用是否指向真实存在的 PubMed 文献。
不是什么:
- 不是通用幻觉抑制工具
- 不是 claim-摘要语义比对(那是 ref-verifier 的 Step C)
- 不验证引用的语义准确性("这篇文章是不是真的说了这个观点"),只验证引用的存在性("这篇文章是不是真的存在")
与 ref-verifier 的关系:ref-verifier 是论文完稿后的系统性体检(全量 bib、逐条 claim-摘要比对、生成报告)。self-verify 是写作中的随身血压计(几条引用、几秒出结果)。
触发条件
仅显式触发:
verify 一下/self-verify/self-check核查一下/查一下刚才的引用/check citations
半自动提示:当 Claude 输出的内容包含 ≥2 条来自训练知识(非本次对话中 API/工具调用返回)的文献引用时,在输出末尾追加一行提示:"本段包含 N 条来自训练知识的引用,建议 verify 核查。"仅提示,不自动执行。
不触发的情况:引用来自本次对话中的 Entrez 搜索结果或用户提供的文献列表时,不提示。
验证范围
能查的:
- 文献引用中的作者姓氏、发表年份、标题关键词 → Entrez 三重匹配
- 明确给出的 PMID → Entrez 直接查询
不查的(标 UNVERIFIABLE,附原因):
- 数值声明(样本量、p 值、百分比)
- 方法描述(统计方法、软件版本)
- 概念定义
- 非 PubMed 收录的文献(CS 会议论文、arXiv 预印本等)
工作流(三步)
Step 1: 引用提取
从目标文本中识别所有文献引用,提取结构化 anchor。
目标文本来源(按优先级):
- 用户指定的文本("verify 一下这段:……")
- 当前对话中 Claude 最近一条包含引用的输出
提取规则:
- 识别模式:
Author et al. (YYYY)、Author YYYY、Author and Author (YYYY)、PMID XXXXXXXX、[N]编号引用(如能从上下文推断对应文献) - 对每条引用生成 anchor:
{
"id": 1,
"citation_text": "Treece et al. (2010)",
"anchor": {
"author_surname": "Treece",
"year": "2010",
"title_keywords": "cortical bone mapping"
}
}
title_keywords从引用的上下文语境中推断(被引用时提到的方法名、主题词等),取 2-5 个实词- anchor 字段不完整时(如缺年份、缺作者),该条直接标 UNVERIFIABLE,reason 注明缺什么
- 非文献性质的事实声明不提取
提取质量自检:
- 作者姓氏是否为 last name(不是 first name,不是缩写)
- 年份是否为 4 位数字
- 关键词是否来自引用上下文(不是从训练知识中补全的)
- 如果无法从上下文推断关键词,标 UNVERIFIABLE 而不是猜
Step 2: Entrez 验证
对每条 anchor 调用验证脚本:
python skills/self-verify/scripts/entrez_verify.py --author <surname> --year <YYYY> --title-keywords "<kw1> <kw2> <kw3>"
脚本为确定性 Python,不依赖 LLM 判断。输出 JSON:
{
"verdict": "PASS",
"pmid": "20176027",
"matched_fields": ["author", "year", "title_full"],
"evidence": "https://pubmed.ncbi.nlm.nih.gov/20176027/",
"suggested_fix": null
}
四档判定:
| 档位 | 含义 | 条件 |
|---|---|---|
| PASS | 三重匹配全中 | author + year + 全部 title_keywords 命中同一 PMID |
| PARTIAL | 部分匹配 | author 对但年份偏差 ≤1,或标题关键词部分命中 |
| FAIL | 未找到匹配 | Entrez 无匹配,或匹配到的记录核心字段对不上 |
| UNVERIFIABLE | 无法核查 | anchor 不完整 / Entrez 不可达 / 非 PubMed 文献 |
关键约束:
- Entrez 不可达 → UNVERIFIABLE,不回退到训练知识猜测
- 查无结果 → 放宽关键词重试一次,仍无 → FAIL
- UNVERIFIABLE 不算失败
Step 3: 报告
输出 Markdown 表格:
## self-verify 报告
目标: <被核查文本的一句话描述>
引用总数: N | PASS X | PARTIAL Y | FAIL Z | UNVERIFIABLE W
| # | 引用 | verdict | PMID | evidence | suggested_fix |
|---|------|---------|------|----------|---------------|
| 1 | Treece et al. 2010 | PASS | 20176027 | [link] | — |
| 2 | Smith et al. 2023 | FAIL | — | — | 未找到匹配,检查作者拼写 |
- FAIL 和 PARTIAL 必须附
suggested_fix(基于 Entrez 实际返回的最近匹配) - UNVERIFIABLE 必须附
reason
错误处理
- 网络超时 → 该条标 UNVERIFIABLE,reason="entrez timeout"
- 脚本崩溃 → 报告错误信息,不静默跳过
- 目标文本中无引用 → 告知用户"未检测到文献引用",不生成空报告
局限性声明
每次使用时不需要主动声明,但如果用户对结果有疑问,说明:
- PASS 意味着"PubMed 上存在一篇匹配的文献",不意味着"引用内容语义正确"
- FAIL 可能是提取阶段关键词选取不准导致的假阴性,不一定是引用造假
- 非 PubMed 收录的文献(CS 会议、arXiv)会被标 UNVERIFIABLE