学术论文参考文献核查与源头溯源
参考文件(执行前按需读取):
references/judgment-rubric.md— claim 分类与判断标准(Step C 前必读)references/entrez-api.md— 复用自 literature-search-omfs,PubMed Entrez API 规范references/prompt-templates.md— Step C 逐条判断的结构化 prompt 模板references/crossref-s2-api.md— CrossRef / Semantic Scholar API 调用规范(PubMed 回退路径)
依赖技能:
literature-search-omfs— Entrez API 指南和反幻觉规则literature-manager— 核查通过的文献可存入管理库
精度声明(用户必知)
本工具的验证精度上限是摘要级别。判断结果的含义:
| 判定 | 实际含义 | 不意味着 |
|---|---|---|
| PASS | claim 与摘要/全文内容不矛盾 | claim 被原文完整证实 |
| PARTIAL-A | 部分支持但存在需人工处理的问题(措辞过强、二手来源等) | claim 一定需要修改 |
| PARTIAL-B | 部分支持,仅为结构性限制(如复合引用) | claim 存在错误 |
| FAIL | claim 与摘要/全文矛盾,或内容完全无关 | 文献本身有问题 |
所有判定均附带 confidence 标记:confirmed(信息充分)或 preliminary(需全文确认,verdict 为基于摘要的最佳估计)。
PASS 率高不等于引用质量高。 摘要未提及的内容可能在全文中有 nuance 或 limitation 被论文忽略。本工具的定位是:把 ~80% 的机械核查劳动自动化,把 ~20% 的真正难题精准定位出来。
适用场景
- LLM 辅助写作后的引用验证(最刚需):LLM 推荐/撰写的参考文献可能含幻觉,本工具快速暴露问题
- 人工写作的保险性复查:人工引用一般质量较高,本工具做最终兜底
- 单条实时验证(inline 模式):写作过程中对单条引用即时核查
输入要求
| 输入 | 格式 | 必需 | 说明 |
|---|---|---|---|
| 论文正文 | .docx 或纯文本 | ✅ | 含 [N] 格式引用标记 |
| 参考文献列表 | .bib | ✅ | 每条须含 PMID 或 DOI(至少一项) |
| 全文 PDF | .pdf(多个) | ❌ | 用于补充摘要不足的文献 |
| 已有 verification_state.json | .json | ❌ | 断点续跑时加载,避免重复 fetch |
引用格式
当前版本支持 [N] 编号制(如 [1]、[29,30]、[1-5])。
扩展接口保留:未来版本可增加 author-year 格式解析器,Step A 的 regex 模块设计为可替换组件。
核心数据结构:verification_state.json
整个 pipeline 围绕单一 JSON 文件渐进增强。所有中间步骤向此文件追加字段,所有输出从此文件生成。
{
"meta": {
"source_file": "论文.docx",
"bib_file": "refs.bib",
"created": "2026-03-27T10:00:00",
"last_step": "A", // 当前完成到哪一步
"total_refs": 129,
"total_claims": 275
},
"refs": {
"29": {
// --- Step A 填充 ---
"bib_title": "...", // 从 .bib 解析
"bib_authors": "...",
"bib_year": 2023,
"bib_journal": "...",
"bib_pmid": "36XXXXX",
"bib_doi": "10.xxxx/...",
"claims": [
{
"claim_id": "C029_001",
"chapter": "前言",
"line": 162,
"context_raw": "某类治疗的缓解率报道从 10% 到 45% 不等[21,22,29]", // ±2句原文
"claim_summary": "Cites [29] as one of 3 refs supporting remission rate range → This ref reports 28%",
"severity": "Standard", // Strict | Standard | Lenient (see rubric §1)
"has_numeric": true,
"numeric_values": ["1%", "31%"],
"fulltext_likely": false, // Step A prediction
"method_needs_human_confirm": false
}
// ... 更多 claims
],
// --- Step B 填充 ---
"api_source": "pubmed", // pubmed | crossref | semantic_scholar
"api_title": "...",
"api_authors": ["Smith J", "..."],
"api_year": 2023,
"api_journal": "NEJM",
"api_article_type": "Review", // from PubMed PublicationType
"api_abstract": "...",
"abstract_source": "pubmed", // pubmed | crossref | semantic_scholar | full_text_pdf | none
"title_match_score": 0.95, // SequenceMatcher ratio
"title_match_ok": true,
"metadata_issues": [],
"fulltext_required_stepB": false, // true if abstract empty/short/missing
// --- Step C 填充 ---
"judgments": [
{
"claim_id": "C029_001",
"verdict": "PARTIAL-B", // PASS | PARTIAL-A | PARTIAL-B | FAIL
"confidence": "confirmed", // preliminary | confirmed
"fulltext_required": false, // independent of verdict
"reasoning": "Individual contribution confirmed (28% within 10-45%), composite structural limitation",
"numeric_check": "N/A", // NUM_OK | NUM_MISS | N/A
"cross_validated": false, // only FAIL and PARTIAL-A
"cv_verdict": null,
"cv_reasoning": null
}
]
}
// ... 更多 refs
}
}
单一数据源原则:禁止在 verification_state.json 之外维护任何并行的结构化数据。所有 .md 输出均从此文件生成。
Pipeline 总览
输入: docx + bib (+ 可选 PDF)
↓
Step A: 解析 + 引用上下文提取 + claim 摘要生成 + 严格度分配 + fulltext 预测
→ verification_state.json(首次创建)
→ citation_contexts.md(人读输出 ①)
✋ 用户检查点: claim 摘要 + 严格度 + 方法引用必要性
↓
Step B: API fetch + 元数据校验 + 标题模糊匹配
→ verification_state.json 追加字段
↓
Step C: 逐条 source tracing(分批 + 交叉验证)
→ verification_state.json 追加字段
↓
Step D: 报告生成
→ verification_report.md(人读输出 ②,三视图:by-ref + action-item + by-chapter)
→ backlog.md(人读输出 ③)
→ cross_validation_log.md(人读输出 ④)
→ fulltext_prediction_monitor.md(试运行监控 ⑤)
Step A:解析 + 引用上下文提取 + Claim 摘要 + 严格度分配 + Fulltext 预测
A1. 正文解析
- 读取 docx(python-docx)或纯文本
- 检测章节边界(基于标题格式或关键词匹配:"前言""第X章""引言""方法""结果""讨论""总结")
- 中文断句策略:以
。为主分割点,;作为次级分割点;不确定时宁可多取(±3句或整段) - 如果断句置信度低,在 claim 记录中标注
context_confidence: "low"
A2. 引用标记提取
正则提取所有 [N] 标记及其变体:
- 单引用:
[29] - 连续引用:
[21,22,29]→ 拆为三条,各自关联同一段 context - 范围引用:
[1-5]→ 展开为[1],[2],[3],[4],[5]
对每条引用记录:ref 编号、所在章节、行号、±2句上下文原文。
A3. Claim 摘要生成
对每条引用的上下文,生成 claim 摘要(两部分结构):
[Template phrase] → [Specific contribution]
模板短语(机器解析,自动映射严格度):
- "Cites [N] to provide data/evidence supporting {topic}" → Strict
- "Cites [N] to attribute the finding that {finding} to {author}" → Strict
- "Cites [N] as one of {k} refs supporting {general statement}" → Standard
- "Cites [N] to provide methodological provenance for {method}" → Standard
- "Cites [N] to provide definitional/standard provenance for {term}" → Lenient
- "Cites [N] as background reference for {topic}" → Lenient
具体贡献(人读,辅助 Step C 判断):
- 自由文本,描述该 ref 预期贡献什么。
此步骤是 LLM 推理步骤。目的是将 claim 含义显式化,让用户在检查点审核"Claude 理解的引用意图"是否与原意一致。
→ 执行前必须读取
references/judgment-rubric.md§1 和 §3
A4. 严格度分配
由 A3 的模板短语自动映射(见上表)。严格度决定 Step C 的判断标准。
方法/工具引用额外标记 method_needs_human_confirm: true,提示用户在检查点判断该方法是否非常规、是否值得引用。
A5. Fulltext 预测(双层触发)
# 代码兜底层(不依赖 LLM,永远执行)
if has_numeric and section in methods_sections:
fulltext_likely = True
# LLM 精判层(严格度分配之后执行)
if severity == "Strict" and has_numeric:
fulltext_likely = True
# 两层取 OR
fulltext_likely = true 的条目在 citation_contexts.md 中标注 📎,提醒用户提前准备 PDF。
A6. BIB 解析
解析 .bib 文件,提取每条的 title、author、year、journal、PMID、DOI。对缺少 PMID 和 DOI 的条目标记 needs_manual_id。
A7. 输出
- 更新
verification_state.json(meta.last_step = "A") - 生成
citation_contexts.md:按章节分组,逐条列出 context + claim 摘要 + 严格度 + fulltext_likely 标记
✋ 用户检查点(三项审核):
- Claim 摘要是否准确反映引用意图?
- 严格度分配是否合理?(特别关注 Strict 是否漏标、Standard 是否误标为 Lenient)
- 方法引用(
method_needs_human_confirm):该方法是否非常规、是否值得引用?
Step B:API Fetch + 元数据校验 + 标题模糊匹配
B1. API 调用策略(三级 fallback)
有 PMID → PubMed Entrez efetch(首选,结构化数据最可靠)
↓ 失败或无 PMID
有 DOI → CrossRef REST API(按 DOI 查询)
↓ 失败或无 DOI
标题 + 第一作者 → Semantic Scholar title search
↓ 全部失败
标记 API_FAIL,进入 backlog
B2. PubMed Entrez 批量 fetch
- 遵循
references/entrez-api.md中的规范 - 批量模式:每次 efetch 最多 200 个 PMID,sleep 0.35s
- 返回数据写入
verification_state.json的api_*字段 - Article type detection: 从 PubMed 的
PublicationType字段提取文献类型(Review / Meta-Analysis / Journal Article 等),写入api_article_type。此字段影响 Step C 的"一手 vs 二手"判断(见 rubric §2.4)
B3. CrossRef fallback
- REST API:
https://api.crossref.org/works/{DOI} - 无需认证,加
mailto参数进 polite pool - 提取 title、author、year、container-title
- 注意:CrossRef 通常不提供摘要(仅约 10% 的记录有),此路径获取的文献标记
abstract_source: "none"
B4. Semantic Scholar fallback
- REST API:
https://api.semanticscholar.org/graph/v1/paper/search?query={title}&fields=title,authors,year,abstract,externalIds - 无需认证,100 requests / 5 min
- 用返回的第一条结果做匹配
B5. 标题模糊匹配
对每条 ref,比较 bib 中的标题与 API 返回的标题:
from difflib import SequenceMatcher
def title_match(bib_title, api_title):
"""标题相似度,忽略大小写和标点"""
a = normalize(bib_title)
b = normalize(api_title)
score = SequenceMatcher(None, a, b).ratio()
return score
# 阈值
# ≥ 0.85: OK
# 0.60 - 0.85: WARNING(可能是缩写/截断导致)
# < 0.60: MISMATCH(可能是错误的 PMID/DOI)
不匹配(< 0.60)的条目立即标红,写入 metadata_issues,并在最终报告中醒目提示。此类 ref 跳过 Step C,标记为 METADATA_MISMATCH,进入 backlog。
B6. Fulltext requirement 检测(客观层)
对每条 ref,检测摘要可用性:
if api_abstract is None or len(api_abstract.split()) < 100 or abstract_source == "none":
fulltext_required_stepB = True # 摘要不足,所有关联 claim 标记
fulltext_required_stepB = true 的 ref 下属所有 claim 在 Step C 中将获得 confidence: "preliminary" 标记。
B7. PDF 解析(可选)
如果用户提供了全文 PDF:
- 使用 pymupdf (fitz) 提取文本
- 截取摘要 + 结果 + 结论段落(基于关键词匹配)
- 写入
api_abstract字段,标注abstract_source: "full_text_pdf" - 有全文的 ref,其
fulltext_required_stepB重置为 false
B8. 输出
- 更新
verification_state.json(meta.last_step = "B") - 终端汇报:N 条 PubMed 成功 / N 条 CrossRef fallback / N 条 S2 fallback / N 条失败 / N 条标题不匹配 / N 条摘要不足(fulltext_required)
Step C:逐条 Source Tracing(分批 + 交叉验证)
→ 执行前必须读取
references/judgment-rubric.md和references/prompt-templates.md
C1. 分批策略
- 按 ref 为单位分批,每批 ≤ 10 个 ref 或 ≤ 30 条 claim(取先触及的上限)
- 单个 ref 如有 > 15 条 claim,独占一批
- 按 severity 降序处理(Strict 先跑),同级内按 ref 被引总次数降序
METADATA_MISMATCH的 ref 跳过(已在 Step B 拦截)
C2. 逐条判断
对每条 claim,输入:
- claim 上下文原文 (
context_raw) - claim 摘要 (
claim_summary,含模板短语 + 具体贡献) - 严格度 (
severity) - 对应文献的摘要/全文 (
api_abstract) - 文献类型 (
api_article_type)
判断逻辑按严格度分层(详见 references/judgment-rubric.md §1–§5):
| 严格度 | PASS 标准 |
|---|---|
| Strict | 摘要/全文有明确对应内容,措辞不高于原文(见 rubric §5 强度阶梯) |
| Standard | 主题方向一致,该 ref 贡献了至少一个相关数据点或观点 |
| Lenient | 文献主题领域相关 |
四级判定:
| 判定 | 条件 |
|---|---|
| PASS | 满足该严格度的 PASS 标准 |
| PARTIAL-A | 部分支持但存在需行动的问题(措辞过强 / 二手来源 / 方法出处错配 / 内容缺口) |
| PARTIAL-B | 部分支持但仅为结构性限制(复合引用中个体贡献可确认但不能独立支撑整体) |
| FAIL | 摘要/全文与 claim 矛盾,或完全无关 |
Fulltext requirement(Step C 层):如果判断过程中发现摘要信息不足以覆盖 claim 的某个具体要素(如数字缺失、方法细节缺失),设 fulltext_required = true,verdict 给出基于现有信息的最佳估计,confidence = "preliminary"。
数字 claim 额外检查(Strict 级别 + has_numeric):
NUM_OK:数字在摘要/全文中找到(四舍五入优先 → ±5% 容差兜底,见 rubric §4)NUM_MISS:数字未找到 → 自动设fulltext_required = true
文献类型联动(见 rubric §2.4):
- Original article:结果/结论为一手
- SR/Meta-analysis:汇总结论为一手;转述纳入研究的具体发现为二手
- 二手来源检测仅在
abstract_source = "full_text_pdf"时触发
独立逐条判断:每条 claim 独立评估,不受同批次其他 claim 的判断结果影响。
C3. 交叉验证
仅对 FAIL 和 PARTIAL-A 条目执行(PARTIAL-B 和 PASS 不交叉验证):
- 第一轮 prompt 视角:"摘要是否支持此 claim?"
- 第二轮 prompt 视角:"此 claim 的哪些具体部分在摘要中找不到依据?"
两轮结果比对:
| 情况 | 处理 |
|---|---|
| 两轮一致 | 采纳,标注 cross_validated: true |
| 两轮不一致 | 标记 CONFLICT,verdict 保留第一轮结果但 confidence = "conflict",写入 cross_validation_log,等待人工裁决 |
C4. 输出
- 更新
verification_state.json(meta.last_step = "C") - 每批完成后向用户汇报进度:已完成 N/M 批,当前 PASS / PARTIAL-A / PARTIAL-B / FAIL 计数 + preliminary 条目数
Step D:报告生成
从 verification_state.json 生成以下文件(纯确定性 Python 脚本,零 LLM 推理,零幻觉风险):
D1. verification_report.md(主报告,三视图)
视图一:汇总表(报告顶部)
# 参考文献核查报告
生成时间: YYYY-MM-DD HH:MM
输入: {source_file} + {bib_file}
范围: {total_refs} 个引用 / {total_claims} 条 claim
API 来源: PubMed {N} / CrossRef {N} / Semantic Scholar {N}
## 精度声明
[复制本 SKILL.md 中"精度声明"段落]
## 汇总
| Severity \ Verdict | PASS | PARTIAL-A | PARTIAL-B | FAIL | Total |
|:-------------------|-----:|----------:|----------:|-----:|------:|
| Strict | | | | | |
| Standard | | | | | |
| Lenient | | | | | |
| **Total** | | | | | |
Preliminary (fulltext needed to confirm): X items (Strict: N, Standard: N)
CONFLICT (awaiting human decision): X items
METADATA_MISMATCH (skipped): X refs
> **Action required**: {FAIL} FAIL + {PARTIAL-A} PARTIAL-A = {total} items to review. {preliminary} items awaiting PDF upload.
视图二:By-ref 主体(报告正文)
## [29] Smith 2023 | PMID 37XXXXXX | NEJM | Review
**Metadata check**: ✅ Title match 0.97 | Year ✅ | Journal ✅
**Abstract source**: PubMed (structured, 420 words)
### C029_001 (Preface L162) — Standard → PARTIAL-B ✓
> Context: "某类治疗的缓解率报道从 10% 到 45% 不等[21,22,29]"
> Summary: Cites [29] as one of 3 refs supporting remission rate range → This ref reports 28%
> Verdict: PARTIAL-B — Individual contribution confirmed (28% within 10–45% range), composite structural limitation.
### C029_002 (Ch1 L305) — Strict → PASS ✓
> ...
Each claim line shows: severity → verdict confidence_symbol(✓ = confirmed, ⏳ = preliminary)
视图三:Action-item index + Chapter view(报告末尾)
## Action Required
### FAIL
(none — or listed items with → §ref links)
### PARTIAL-A
- [ref] Chapter Line: "excerpt..." — Reason (→ §ref)
### Preliminary (awaiting full text)
- [ref] Chapter Line: current verdict PASS ⏳ — Upload PDF (DOI: ...)
### CONFLICT
- [ref] Chapter Line: Round 1 vs Round 2 disagree (→ cross_validation_log.md)
## Record Only
### PARTIAL-B
- [ref] Chapter Line: composite structure (→ §ref)
---
## Chapter View: Preface
| Line | Ref(s) | Severity | Verdict | Conf. | Note |
|-----:|:-------|:---------|:--------|:------|:-----|
| 148 | [1,2] | Lenient | PASS | ✓ | |
| 162 | [21] | Strict | PASS | ✓ | |
| 162 | [22] | Strict | PASS | ✓ | |
| 162 | [29] | Standard | PARTIAL-B | ✓ | composite |
## Chapter View: Ch1
...
D2. backlog.md
列出所有需人工介入的条目:
METADATA_MISMATCH条目:标题匹配 < 0.60 的 ref,附 bib 标题 vs API 标题对比CONFLICT条目:附两轮判断的具体分歧API_FAIL条目:API 三级 fallback 均失败的 refneeds_manual_id条目:bib 中缺 PMID 和 DOI 的 ref- Preliminary 条目汇总:附 DOI 链接,提示用户上传 PDF
D3. cross_validation_log.md
记录所有经过交叉验证的条目(仅 FAIL + PARTIAL-A):
- 第一轮 verdict + reasoning
- 第二轮 verdict + reasoning
- 是否一致
- 最终状态(一致 → 采纳;不一致 → CONFLICT)
D4. fulltext_prediction_monitor.md(试运行阶段)
记录 Step A fulltext_likely 预测 vs Step C fulltext_required 实际结果:
| Ref | Claim | fulltext_likely | Trigger layer | fulltext_required (Step C) | Match? |
|:----|:------|:----------------|:--------------|:---------------------------|:-------|
| [168] | C168_001 | true | code_safeguard | true | ✅ TP |
| [29] | C029_003 | false | — | false | ✅ TN |
| [45] | C045_001 | true | code_safeguard | false | ❌ FP |
Summary: TP: N, TN: N, FP: N, FN: N → Code safeguard FP rate: XX%
D5. citation_contexts.md(Step A 已生成,此处不重复)
运行模式
批量模式(post-hoc,默认)
完整跑 Step A → B → C → D。适用于论文完稿后的系统性核查。 预计耗时:150 ref 的论文约 30-60 分钟,需用户在场处理 preliminary 条目和 CONFLICT。
单条模式(inline)
用户提供一条引用 + 对应的 claim context,跳过 Step A 的全文解析,直接走 B → C → D 的单条路径。适用于写作过程中的实时验证。
断点续跑模式
加载已有的 verification_state.json,从 meta.last_step 之后继续。适用于长论文分多次会话完成核查。
防护机制
反幻觉
- 禁止从训练数据记忆中补全摘要内容。API 返回什么就用什么。
- 禁止将 claim 摘要中的推理结论反写入判断理由。判断依据只能来自
api_abstract。 - 数字核查必须精确匹配。不允许"摘要没写但根据上下文可推断出此数字"。
元数据验证嵌入
Step B 的标题模糊匹配等同于独立的元数据验证层。如果一条 ref 的 PMID 指向了一篇完全不同的论文(标题匹配 < 0.60),后续 Step C 的任何判断都没有意义。此类 ref 直接跳过 Step C,标记为 METADATA_MISMATCH,进入 backlog。
交叉验证
Step C 对 FAIL 和 PARTIAL-A 自动重跑(不同 prompt 视角)。PARTIAL-B 和 PASS 不交叉验证。CONFLICT 标记要求人工介入而非自动裁决。
断句降级
Step A 中文断句不确定时,宁可多取。标注 context_confidence: "low" 的条目在 Step C 判断时需额外谨慎。
与其他 skill 的数据格式对齐
与 literature-search-omfs
- 共享
references/entrez-api.md - 共享信息可及度标签体系(📄📑📌):本工具在
abstract_source字段中标注来源,等效于 📄/📑/📌 - 共享置信度概念:本工具的 PASS / PARTIAL-A / PARTIAL-B / FAIL + confidence 是更细粒度的置信度评估
与 literature-manager
verification_state.json中的 ref 元数据字段(title, authors, year, journal, PMID, DOI)与 literature-manager 的 entry schema 对齐- 核查完成后可将 PASS 条目一键导入 literature-manager
与 dr-reconstruct
- dr-reconstruct 的第四步(Claim-摘要匹配)是本工具 Step C 的简化版
- 本工具可作为 dr-reconstruct 重构报告产出后的二次验证工具
输出文件清单
| 文件 | 生成步骤 | 性质 | 说明 |
|---|---|---|---|
verification_state.json |
A→B→C 渐进增强 | 内部数据 | 单一数据源,所有步骤读写此文件 |
citation_contexts.md |
Step A | 人读输出 | 按章节分组的引用上下文 + claim 摘要 + 严格度 |
verification_report.md |
Step D | 主交付物 | 三视图:汇总表 + by-ref 主体 + action-item/chapter 索引 |
backlog.md |
Step D | 人读输出 | METADATA_MISMATCH / CONFLICT / API_FAIL / preliminary 汇总 |
cross_validation_log.md |
Step D | 过程记录 | FAIL + PARTIAL-A 的交叉验证详情 |
fulltext_prediction_monitor.md |
Step D | 试运行监控 | fulltext_likely 预测 vs fulltext_required 实际的 TP/FP 统计 |
注意事项
- API 域名白名单:需要
eutils.ncbi.nlm.nih.gov(必须);api.crossref.org和api.semanticscholar.org为 fallback 路径,如未加入白名单则该路径不可用 - CrossRef 通常不提供摘要:走 CrossRef fallback 的 ref 关联的所有 claim 将标记
fulltext_required = true,verdict 为 preliminary - Semantic Scholar 速率限制较严:100 req / 5 min(未认证),大批量时注意 sleep
- 跨语言比对:英文论文为主要使用场景,中文论文为附录场景。跨语言时关注变量关系方向而非措辞强度(见 rubric §5)
- .bib 质量是隐含前提:如果 .bib 本身是 LLM 生成的,PMID/DOI 可能是错的——Step B 的标题匹配是唯一防线
- 本工具不做引用必要性判断:只验证"引用内容是否正确",不判断"这个地方该不该引这篇"(方法引用的必要性通过
method_needs_human_confirmflag 交给用户)