From 898b52edcb47bcb3e9d6106e74ca73e74ea01e70 Mon Sep 17 00:00:00 2001 From: sillylaird Date: Thu, 3 Sep 2026 00:33:59 +0000 Subject: import live www.sillylaird.ca webroot --- .../citation-verification/references/README.md | 71 ++++ .../citation-verification/references/api-usage.md | 373 +++++++++++++++++++ .../references/common-errors.md | 385 ++++++++++++++++++++ .../references/verification-rules.md | 400 +++++++++++++++++++++ 4 files changed, 1229 insertions(+) create mode 100644 .agents/skills/citation-verification/references/README.md create mode 100644 .agents/skills/citation-verification/references/api-usage.md create mode 100644 .agents/skills/citation-verification/references/common-errors.md create mode 100644 .agents/skills/citation-verification/references/verification-rules.md (limited to '.agents/skills/citation-verification/references') diff --git a/.agents/skills/citation-verification/references/README.md b/.agents/skills/citation-verification/references/README.md new file mode 100644 index 0000000..10e8d6c --- /dev/null +++ b/.agents/skills/citation-verification/references/README.md @@ -0,0 +1,71 @@ +# Citation Verification Reference Files + +## 文件用途 + +本目录中的文件提供**背景知识和参考信息**,用于理解引用验证的原理和常见问题。 + +**重要**: 这些文件不是主要工作流的一部分。实际的引用验证使用 WebSearch 和 Google Scholar。 + +## 文件说明 + +### common-errors.md + +**内容**: 常见引用错误模式和修复方法 + +**用途**: +- 了解学术写作中常见的引用错误 +- 学习如何识别和修复这些错误 +- 理解为什么需要验证引用 + +**何时参考**: 当需要了解引用错误的类型和修复方法时 + +### verification-rules.md + +**内容**: 详细的验证规则和匹配算法 + +**用途**: +- 理解引用验证的完整逻辑 +- 了解如何匹配标题、作者、年份等信息 +- 学习验证的技术细节 + +**何时参考**: 当需要深入了解验证逻辑时 + +### api-usage.md + +**内容**: API 使用指南(CrossRef、arXiv、Semantic Scholar) + +**用途**: +- 了解学术API的使用方法 +- 理解API验证的原理 +- 参考高级用例的实现 + +**何时参考**: 当需要了解API验证方法时(注意:主要工作流使用 WebSearch) + +## 主要工作流 + +**实际的引用验证应该使用 `ml-paper-writing` skill 中的 Citation Workflow:** + +1. 使用 WebSearch 查找论文 +2. 在 Google Scholar 上验证 +3. 从 Google Scholar 获取 BibTeX +4. 验证声明(如需要) +5. 添加到 bibliography + +详见 `ml-paper-writing` skill 的 "Citation Workflow (Hallucination Prevention)" 部分。 + +## 使用建议 + +**对于日常论文写作**: +- ✅ 使用 `ml-paper-writing` skill 的 Citation Workflow +- ✅ 使用 WebSearch 和 Google Scholar +- ✅ 参考这些文件了解背景知识 +- ❌ 不要使用API方法作为主要工作流 + +**对于理解验证原理**: +- 阅读 `common-errors.md` 了解常见错误 +- 阅读 `verification-rules.md` 了解验证逻辑 +- 阅读 `api-usage.md` 了解API方法(参考用) + +## 更多信息 + +详见 `citation-verification` skill 的 SKILL.md 文件。 diff --git a/.agents/skills/citation-verification/references/api-usage.md b/.agents/skills/citation-verification/references/api-usage.md new file mode 100644 index 0000000..395f52a --- /dev/null +++ b/.agents/skills/citation-verification/references/api-usage.md @@ -0,0 +1,373 @@ +# API 使用指南 + +本文档详细说明如何使用三个主要 API 进行文献验证。 + +## Semantic Scholar API + +### 概述 + +Semantic Scholar 是一个免费的学术搜索引擎,提供强大的 API 用于论文检索和元数据获取。 + +**优势:** +- 免费使用,无需 API key +- 覆盖广泛的学科领域 +- 提供丰富的元数据 +- 支持模糊搜索 + +**限制:** +- 请求频率限制:100 requests/5min +- 部分论文可能缺失 + +### API 端点 + +**1. 通过 Paper ID 获取论文** +``` +GET https://api.semanticscholar.org/graph/v1/paper/{paper_id} +``` + +**2. 搜索论文** +``` +GET https://api.semanticscholar.org/graph/v1/paper/search?query={query} +``` + +### Python 示例 + +**安装:** +```bash +pip install semanticscholar +``` + +**基本用法:** +```python +from semanticscholar import SemanticScholar + +sch = SemanticScholar() + +# 通过标题搜索 +results = sch.search_paper("Attention is All You Need", limit=5) +for paper in results: + print(f"Title: {paper.title}") + print(f"Authors: {[a.name for a in paper.authors]}") + print(f"Year: {paper.year}") + print(f"DOI: {paper.externalIds.get('DOI', 'N/A')}") + print("---") +``` + +**通过 DOI 获取:** +```python +# DOI 格式: DOI:10.48550/arXiv.1706.03762 +paper = sch.get_paper("DOI:10.48550/arXiv.1706.03762") +print(f"Title: {paper.title}") +print(f"Citations: {paper.citationCount}") +``` + +### 字段说明 + +**返回的主要字段:** +- `paperId` - Semantic Scholar 内部 ID +- `title` - 论文标题 +- `authors` - 作者列表 +- `year` - 发表年份 +- `venue` - 发表场所(会议/期刊) +- `externalIds` - 外部标识符(DOI, arXiv, PubMed 等) +- `citationCount` - 引用次数 +- `abstract` - 摘要 + +### 错误处理 + +```python +try: + paper = sch.get_paper("invalid_id") +except Exception as e: + print(f"Error: {e}") + # 处理错误:标记需要人工验证 +``` + +## arXiv API + +### 概述 + +arXiv 是预印本论文库,提供免费的 API 用于访问论文元数据。 + +**优势:** +- 完全免费,无需认证 +- 覆盖物理、数学、计算机科学等领域 +- 提供完整的论文 PDF +- 更新及时 + +**限制:** +- 仅限预印本论文 +- 不包含已发表的期刊版本信息 + +### API 端点 + +**查询接口:** +``` +GET http://export.arxiv.org/api/query?search_query={query}&start={start}&max_results={max} +``` + +### Python 示例 + +**安装:** +```bash +pip install arxiv +``` + +**基本用法:** +```python +import arxiv + +# 通过 arXiv ID 获取 +paper = next(arxiv.Search(id_list=["1706.03762"]).results()) +print(f"Title: {paper.title}") +print(f"Authors: {[a.name for a in paper.authors]}") +print(f"Published: {paper.published}") +print(f"PDF URL: {paper.pdf_url}") + +# 通过标题搜索 +search = arxiv.Search( + query="Attention is All You Need", + max_results=5, + sort_by=arxiv.SortCriterion.Relevance +) + +for result in search.results(): + print(f"Title: {result.title}") + print(f"arXiv ID: {result.entry_id.split('/')[-1]}") + print("---") +``` + +### arXiv ID 格式 + +**识别 arXiv ID:** +- 新格式: `YYMM.NNNNN` (如 2301.12345) +- 旧格式: `arch-ive/YYMMNNN` (如 cs/0703001) + +**从 URL 提取:** +```python +import re + +def extract_arxiv_id(text): + # 匹配新格式 + match = re.search(r'\d{4}\.\d{4,5}', text) + if match: + return match.group() + # 匹配旧格式 + match = re.search(r'[a-z-]+/\d{7}', text) + if match: + return match.group() + return None +``` + +## CrossRef API + +### 概述 + +CrossRef 是 DOI 注册机构,提供权威的学术文献元数据。 + +**优势:** +- DOI 是最可靠的唯一标识符 +- 覆盖几乎所有正式发表的论文 +- 数据质量高,权威性强 +- 支持 BibTeX 格式直接获取 + +**限制:** +- 仅限有 DOI 的论文 +- 预印本通常没有 DOI + +### API 端点 + +**通过 DOI 获取元数据:** +``` +GET https://api.crossref.org/works/{doi} +``` + +**通过 DOI 获取 BibTeX:** +``` +GET https://doi.org/{doi} +Headers: Accept: application/x-bibtex +``` + +### Python 示例 + +**通过 DOI 获取元数据:** +```python +import requests + +def get_crossref_metadata(doi): + url = f"https://api.crossref.org/works/{doi}" + response = requests.get(url) + if response.status_code == 200: + data = response.json() + return data['message'] + return None + +# 示例 +doi = "10.48550/arXiv.1706.03762" +metadata = get_crossref_metadata(doi) +if metadata: + print(f"Title: {metadata['title'][0]}") + print(f"Authors: {[f\"{a['given']} {a['family']}\" for a in metadata['author']]}") + print(f"Published: {metadata['published']['date-parts'][0]}") +``` + +**通过 DOI 获取 BibTeX:** +```python +def doi_to_bibtex(doi): + url = f"https://doi.org/{doi}" + headers = {"Accept": "application/x-bibtex"} + response = requests.get(url, headers=headers) + if response.status_code == 200: + return response.text + return None + +# 示例 +bibtex = doi_to_bibtex("10.48550/arXiv.1706.03762") +print(bibtex) +``` + +### DOI 格式 + +**标准格式:** +- `10.XXXX/suffix` (如 10.1038/nature12345) +- 前缀 `10.` 是固定的 +- 中间是注册机构代码 +- 后缀是出版商定义的 + +**从文本中提取 DOI:** +```python +import re + +def extract_doi(text): + # 匹配 DOI 格式 + match = re.search(r'10\.\d{4,}/[^\s]+', text) + if match: + return match.group() + return None +``` + +## API 选择策略 + +根据引用信息选择最合适的 API: + +### 决策流程 + +``` +有 DOI? + ├─ 是 → CrossRef API (最可靠) + └─ 否 → 有 arXiv ID? + ├─ 是 → arXiv API + └─ 否 → Semantic Scholar API (通用搜索) +``` + +### 实现示例 + +```python +def verify_citation(citation_info): + """ + 根据引用信息选择合适的 API 进行验证 + + Args: + citation_info: dict with keys: doi, arxiv_id, title, authors + + Returns: + 验证结果字典 + """ + # 策略 1: DOI 优先 + if citation_info.get('doi'): + return verify_with_crossref(citation_info['doi']) + + # 策略 2: arXiv ID + if citation_info.get('arxiv_id'): + return verify_with_arxiv(citation_info['arxiv_id']) + + # 策略 3: 通用搜索 + if citation_info.get('title'): + return verify_with_semantic_scholar( + citation_info['title'], + citation_info.get('authors') + ) + + return {'status': 'insufficient_info'} +``` + +## 最佳实践 + +### 1. 错误处理 + +```python +import time +from requests.exceptions import RequestException + +def api_call_with_retry(func, max_retries=3): + """带重试的 API 调用""" + for i in range(max_retries): + try: + return func() + except RequestException as e: + if i == max_retries - 1: + raise + time.sleep(2 ** i) # 指数退避 +``` + +### 2. 速率限制 + +```python +import time + +class RateLimiter: + def __init__(self, calls_per_minute): + self.calls_per_minute = calls_per_minute + self.last_call = 0 + + def wait_if_needed(self): + elapsed = time.time() - self.last_call + min_interval = 60.0 / self.calls_per_minute + if elapsed < min_interval: + time.sleep(min_interval - elapsed) + self.last_call = time.time() + +# 使用示例 +limiter = RateLimiter(calls_per_minute=20) +limiter.wait_if_needed() +result = api_call() +``` + +### 3. 缓存结果 + +```python +import json +from pathlib import Path + +class APICache: + def __init__(self, cache_dir=".cache"): + self.cache_dir = Path(cache_dir) + self.cache_dir.mkdir(exist_ok=True) + + def get(self, key): + cache_file = self.cache_dir / f"{key}.json" + if cache_file.exists(): + return json.loads(cache_file.read_text()) + return None + + def set(self, key, value): + cache_file = self.cache_dir / f"{key}.json" + cache_file.write_text(json.dumps(value)) +``` + +## 总结 + +### API 对比 + +| API | 优势 | 限制 | 推荐场景 | +|-----|------|------|----------| +| **CrossRef** | 最权威,支持 BibTeX | 仅限有 DOI 的论文 | 有 DOI 时首选 | +| **arXiv** | 免费,更新快 | 仅限预印本 | arXiv 论文 | +| **Semantic Scholar** | 覆盖广,模糊搜索 | 部分论文缺失 | 通用搜索 | + +### 验证可靠性排序 + +1. **CrossRef (DOI)** - 最可靠 +2. **arXiv (arXiv ID)** - 可靠 +3. **Semantic Scholar (标题搜索)** - 较可靠,需要人工确认 + diff --git a/.agents/skills/citation-verification/references/common-errors.md b/.agents/skills/citation-verification/references/common-errors.md new file mode 100644 index 0000000..911bb8a --- /dev/null +++ b/.agents/skills/citation-verification/references/common-errors.md @@ -0,0 +1,385 @@ +# 常见引用错误模式 + +本文档总结常见的引用错误类型、识别方法和修复建议。 + +## 错误分类 + +### 1. 格式错误 (Format Errors) + +#### 1.1 缺少必填字段 + +**错误示例:** +```bibtex +@article{smith2020, + title={Deep Learning for NLP}, + year={2020} +} +``` + +**问题:** 缺少 `author` 和 `journal` 字段 + +**修复:** +```bibtex +@article{smith2020, + author={Smith, John and Doe, Jane}, + title={Deep Learning for NLP}, + journal={Nature}, + year={2020} +} +``` + +#### 1.2 年份格式错误 + +**错误示例:** +```bibtex +year={20} # 年份不完整 +year={2020-2021} # 年份范围格式错误 +year={circa 2020} # 包含非数字字符 +``` + +**修复:** +```bibtex +year={2020} # 使用四位数年份 +``` + +#### 1.3 DOI 格式错误 + +**错误示例:** +```bibtex +doi={doi:10.1038/nature12345} # 包含 "doi:" 前缀 +doi={https://doi.org/10.1038/...} # 包含完整 URL +doi={10.1038/nature12345.} # 末尾有句号 +``` + +**修复:** +```bibtex +doi={10.1038/nature12345} # 只保留 DOI 本身 +``` + +#### 1.4 作者名格式不一致 + +**错误示例:** +```bibtex +author={John Smith and Jane Doe and Bob} # 格式不一致 +author={Smith, J. and Doe, Jane} # 格式混用 +``` + +**修复:** +```bibtex +author={Smith, John and Doe, Jane and Brown, Bob} # 统一格式 +# 或 +author={Smith, J. and Doe, J. and Brown, B.} # 统一缩写 +``` + +### 2. 信息错误 (Information Errors) + +#### 2.1 作者名拼写错误 + +**错误示例:** +```bibtex +author={Vaswani, Ashish} # 正确 +author={Vaswani, Asish} # 拼写错误 +``` + +**识别方法:** +- API 验证时作者匹配度低 +- 通过 Google Scholar 搜索确认正确拼写 + +**修复建议:** +- 从可靠来源(Google Scholar, Semantic Scholar)获取 BibTeX +- 仔细核对作者名拼写 + +#### 2.2 标题错误 + +**错误示例:** +```bibtex +title={Attention is All You Need} # 正确 +title={Attention Is All You Need} # 大小写错误 +title={Attention is all you need} # 大小写错误 +title={Attention Mechanism for Transformers} # 标题完全错误 +``` + +**识别方法:** +- 标题匹配度低于阈值 +- API 返回的标题与 BibTeX 中的标题不一致 + +**修复建议:** +- 从原始论文或 DOI 获取准确标题 +- 保持原始大小写格式 + +#### 2.3 年份错误 + +**常见情况:** +- 使用预印本年份而非正式发表年份 +- 使用会议年份而非论文集出版年份 + +**错误示例:** +```bibtex +# 论文在 2017 年 arXiv 发布,2018 年 NIPS 正式发表 +year={2017} # 使用了预印本年份 +year={2018} # 正确:使用正式发表年份 +``` + +**修复建议:** +- 优先使用正式发表年份 +- 如果引用预印本,在 note 字段说明 + +#### 2.4 期刊/会议名称错误 + +**错误示例:** +```bibtex +booktitle={NeurIPS} # 缩写 +booktitle={Neural Information Processing Systems} # 完整名称 +booktitle={Advances in Neural Information Processing Systems} # 正确的完整名称 +``` + +**修复建议:** +- 使用官方全称或标准缩写 +- 保持整个文献列表的命名一致性 + +### 3. 虚假引用 (Fake Citations) + +#### 3.1 完全虚构的论文 + +**特征:** +- 论文不存在于任何数据库 +- API 验证全部失败 +- 无法通过 Google Scholar 找到 + +**识别方法:** +```python +# 所有 API 都返回 not_found +if not crossref_found and not arxiv_found and not semantic_scholar_found: + return "可能是虚假引用" +``` + +**修复建议:** +- 删除虚假引用 +- 如果确实需要引用,寻找真实的相关论文 + +#### 3.2 信息严重错误的引用 + +**特征:** +- 论文存在,但信息完全不匹配 +- 作者、标题、年份都不对 +- 可能是复制粘贴错误 + +**错误示例:** +```bibtex +@article{smith2020deep, + author={Smith, John}, + title={Deep Learning for NLP}, + journal={Nature}, + year={2020} +} +``` + +**实际论文:** +- 作者: Brown, Tom et al. +- 标题: Language Models are Few-Shot Learners +- 期刊: NeurIPS +- 年份: 2020 + +**修复建议:** +- 重新搜索正确的论文 +- 从可靠来源获取正确的 BibTeX + +#### 3.3 引用不存在的版本 + +**错误示例:** +```bibtex +# 引用了不存在的期刊版本 +@article{vaswani2017attention, + author={Vaswani, Ashish and others}, + title={Attention is All You Need}, + journal={Nature Machine Intelligence}, # 错误:这篇论文没有期刊版本 + year={2017} +} +``` + +**正确引用:** +```bibtex +@inproceedings{vaswani2017attention, + author={Vaswani, Ashish and others}, + title={Attention is All You Need}, + booktitle={Advances in Neural Information Processing Systems}, + year={2017} +} +``` + +### 4. 一致性错误 (Consistency Errors) + +#### 4.1 LaTeX 引用与 BibTeX 不一致 + +**错误示例:** + +LaTeX 文件中: +```latex +\cite{smith2020deep} +``` + +BibTeX 文件中: +```bibtex +@article{smith2020deeplearning, # Key 不匹配 + author={Smith, John}, + title={Deep Learning for NLP}, + year={2020} +} +``` + +**识别方法:** +```python +def check_citation_consistency(tex_keys, bib_keys): + """检查引用一致性""" + tex_set = set(tex_keys) + bib_set = set(bib_keys) + + # 未定义的引用 + undefined = tex_set - bib_set + + # 未使用的引用 + unused = bib_set - tex_set + + return { + 'undefined': list(undefined), + 'unused': list(unused) + } +``` + +**修复建议:** +- 确保 LaTeX 中的 citation key 与 BibTeX 中的 ID 完全一致 +- 删除未使用的 BibTeX 条目 +- 补充缺失的 BibTeX 条目 + +#### 4.2 引用格式不统一 + +**错误示例:** +```bibtex +# 同一文献列表中格式混乱 +@article{paper1, + author={Smith, John and Doe, Jane}, # 全名 + ... +} + +@article{paper2, + author={Brown, T. and Lee, S.}, # 缩写 + ... +} + +@article{paper3, + author={John Wilson and Mary Johnson}, # First Last 格式 + ... +} +``` + +**修复建议:** +- 统一作者名格式(全名或缩写) +- 统一期刊/会议名称格式(全称或标准缩写) +- 统一页码格式(1-10 或 1--10) + +#### 4.3 重复引用 + +**错误示例:** +```bibtex +@article{vaswani2017, + author={Vaswani, Ashish and others}, + title={Attention is All You Need}, + booktitle={NeurIPS}, + year={2017} +} + +@inproceedings{vaswani2017attention, + author={Vaswani, A. and others}, + title={Attention is All You Need}, + booktitle={Advances in Neural Information Processing Systems}, + year={2017} +} +``` + +**问题:** 同一篇论文被引用两次,使用不同的 citation key + +**识别方法:** +- 标题高度相似(相似度 > 0.9) +- 作者重叠度高 +- 年份相同 + +**修复建议:** +- 保留更完整准确的条目 +- 删除重复条目 +- 更新 LaTeX 文件中的引用 + +## 错误预防最佳实践 + +### 1. 使用可靠来源 + +✅ **推荐来源:** +- Google Scholar - 获取 BibTeX +- Semantic Scholar - 验证论文信息 +- 官方出版商网站 - 获取准确元数据 +- DOI 系统 - 最可靠的标识符 + +❌ **避免:** +- 手动输入 BibTeX +- 从不可靠网站复制 +- 使用过时的引用管理工具 + +### 2. 及时验证 + +**验证时机:** +- 添加引用后立即验证 +- 完成初稿后全面验证 +- 提交前最终验证 + +**验证内容:** +- 格式完整性 +- 信息准确性 +- 引用一致性 + +### 3. 保持一致性 + +**统一标准:** +- 作者名格式统一(全名或缩写) +- 期刊/会议名称统一(全称或标准缩写) +- 页码格式统一 +- 大小写规则统一 + +### 4. 使用工具辅助 + +**推荐工具:** +- BibTeX 格式检查器 +- LaTeX 编译器(检测未定义引用) +- Citation verification scripts +- 引用管理软件(Zotero, Mendeley) + +## 常见错误总结 + +| 错误类型 | 严重程度 | 检测难度 | 修复难度 | +|---------|---------|---------|---------| +| 缺少必填字段 | 高 | 低 | 低 | +| 年份格式错误 | 中 | 低 | 低 | +| DOI 格式错误 | 中 | 低 | 低 | +| 作者名拼写错误 | 高 | 中 | 中 | +| 标题错误 | 高 | 中 | 中 | +| 完全虚构论文 | 极高 | 高 | 高 | +| 信息严重错误 | 极高 | 中 | 高 | +| LaTeX-BibTeX 不一致 | 高 | 低 | 低 | +| 格式不统一 | 低 | 低 | 中 | +| 重复引用 | 中 | 中 | 中 | + +## 快速检查清单 + +提交论文前,确保完成以下检查: + +- [ ] 所有 BibTeX 条目包含必填字段 +- [ ] 年份格式正确(四位数字) +- [ ] DOI 格式正确(无前缀,无 URL) +- [ ] 作者名格式统一 +- [ ] 标题大小写正确 +- [ ] 所有引用通过 API 验证 +- [ ] LaTeX 引用与 BibTeX 一致 +- [ ] 无重复引用 +- [ ] 格式统一(作者名、期刊名、页码) +- [ ] 无虚假或严重错误的引用 + +遵循这些最佳实践可以有效避免常见的引用错误,提高论文质量和可信度。 + diff --git a/.agents/skills/citation-verification/references/verification-rules.md b/.agents/skills/citation-verification/references/verification-rules.md new file mode 100644 index 0000000..03d8a35 --- /dev/null +++ b/.agents/skills/citation-verification/references/verification-rules.md @@ -0,0 +1,400 @@ +# 验证规则 + +本文档详细说明四层验证机制的具体规则和匹配算法。 + +## Layer 1: Format Validation (格式验证) + +### BibTeX 格式检查 + +**必填字段验证:** + +不同类型的 BibTeX 条目有不同的必填字段要求: + +**@article (期刊论文):** +- 必填: `author`, `title`, `journal`, `year` +- 可选: `volume`, `number`, `pages`, `doi` + +**@inproceedings (会议论文):** +- 必填: `author`, `title`, `booktitle`, `year` +- 可选: `pages`, `organization`, `doi` + +**@book (书籍):** +- 必填: `author` 或 `editor`, `title`, `publisher`, `year` +- 可选: `volume`, `series`, `address` + +**@misc (其他):** +- 必填: `title` +- 可选: `author`, `howpublished`, `year`, `note` + +### 格式检查规则 + +**1. 条目结构检查** +```python +def check_bibtex_structure(entry): + """检查 BibTeX 条目结构""" + errors = [] + + # 检查是否有类型 + if not entry.get('ENTRYTYPE'): + errors.append("Missing entry type") + + # 检查是否有 ID + if not entry.get('ID'): + errors.append("Missing citation key") + + # 检查必填字段 + required = get_required_fields(entry.get('ENTRYTYPE')) + for field in required: + if not entry.get(field): + errors.append(f"Missing required field: {field}") + + return errors +``` + +**2. 字段格式检查** +```python +def check_field_format(entry): + """检查字段格式""" + errors = [] + + # 年份格式检查 + if 'year' in entry: + year = entry['year'] + if not year.isdigit() or len(year) != 4: + errors.append(f"Invalid year format: {year}") + if int(year) < 1900 or int(year) > 2030: + errors.append(f"Year out of reasonable range: {year}") + + # DOI 格式检查 + if 'doi' in entry: + doi = entry['doi'] + if not doi.startswith('10.'): + errors.append(f"Invalid DOI format: {doi}") + + return errors +``` + +### LaTeX 引用检查 + +**1. 引用命令检查** +```python +def check_latex_citations(tex_content): + """检查 LaTeX 引用命令""" + import re + + # 查找所有引用命令 + cite_pattern = r'\\cite(?:\[[^\]]*\])?\{([^}]+)\}' + citations = re.findall(cite_pattern, tex_content) + + # 展开多个引用 + all_keys = [] + for cite in citations: + keys = [k.strip() for k in cite.split(',')] + all_keys.extend(keys) + + return all_keys +``` + +**2. 引用一致性检查** +```python +def check_citation_consistency(tex_keys, bib_keys): + """检查引用一致性""" + tex_set = set(tex_keys) + bib_set = set(bib_keys) + + # 未定义的引用 + undefined = tex_set - bib_set + + # 未使用的引用 + unused = bib_set - tex_set + + return { + 'undefined': list(undefined), + 'unused': list(unused) + } +``` + +## Layer 2: Existence Verification (存在性验证) + +### API 验证流程 + +**验证步骤:** +1. 根据引用信息选择 API (DOI → CrossRef, arXiv ID → arXiv, 其他 → Semantic Scholar) +2. 调用 API 获取论文信息 +3. 判断论文是否存在 + +**验证结果:** +- `exists` - 论文存在 +- `not_found` - 论文不存在 +- `api_error` - API 调用失败,需要人工验证 + +### 验证代码示例 + +```python +def verify_existence(citation_info): + """验证论文存在性""" + # DOI 优先 + if citation_info.get('doi'): + result = verify_with_crossref(citation_info['doi']) + if result['status'] == 'success': + return {'exists': True, 'source': 'crossref', 'data': result['data']} + + # arXiv ID + if citation_info.get('arxiv_id'): + result = verify_with_arxiv(citation_info['arxiv_id']) + if result['status'] == 'success': + return {'exists': True, 'source': 'arxiv', 'data': result['data']} + + # 通用搜索 + if citation_info.get('title'): + result = verify_with_semantic_scholar(citation_info['title']) + if result['status'] == 'success' and result['data']: + return {'exists': True, 'source': 'semantic_scholar', 'data': result['data']} + + return {'exists': False, 'source': None} +``` + +## Layer 3: Information Matching (信息匹配) + +### 匹配算法 + +**1. 标题匹配** + +使用模糊匹配算法,允许轻微差异: + +```python +from difflib import SequenceMatcher + +def match_title(title1, title2, threshold=0.85): + """标题匹配""" + # 标准化:小写、去除标点 + def normalize(text): + import re + text = text.lower() + text = re.sub(r'[^\w\s]', '', text) + return ' '.join(text.split()) + + t1 = normalize(title1) + t2 = normalize(title2) + + # 计算相似度 + ratio = SequenceMatcher(None, t1, t2).ratio() + + return { + 'match': ratio >= threshold, + 'similarity': ratio + } +``` + +**2. 作者匹配** + +考虑作者顺序和名字格式差异: + +```python +def match_authors(authors1, authors2, threshold=0.7): + """作者匹配""" + def normalize_name(name): + # 处理 "Last, First" 和 "First Last" 格式 + parts = name.replace(',', '').split() + return ' '.join(sorted(parts)).lower() + + names1 = [normalize_name(a) for a in authors1] + names2 = [normalize_name(a) for a in authors2] + + # 计算交集比例 + set1 = set(names1) + set2 = set(names2) + intersection = len(set1 & set2) + union = len(set1 | set2) + + if union == 0: + return {'match': False, 'similarity': 0} + + ratio = intersection / union + + return { + 'match': ratio >= threshold, + 'similarity': ratio + } +``` + +**3. 年份匹配** + +允许 ±1 年的差异(考虑预印本和正式发表的时间差): + +```python +def match_year(year1, year2, tolerance=1): + """年份匹配""" + try: + y1 = int(year1) + y2 = int(year2) + diff = abs(y1 - y2) + return { + 'match': diff <= tolerance, + 'difference': diff + } + except (ValueError, TypeError): + return {'match': False, 'difference': None} +``` + +## Layer 4: Content Validation (内容验证) + +### 综合匹配评分 + +综合所有匹配结果,计算总体匹配分数: + +```python +def calculate_match_score(citation, api_data): + """计算综合匹配分数""" + scores = {} + weights = { + 'title': 0.4, + 'authors': 0.3, + 'year': 0.2, + 'venue': 0.1 + } + + # 标题匹配 + if citation.get('title') and api_data.get('title'): + result = match_title(citation['title'], api_data['title']) + scores['title'] = result['similarity'] + + # 作者匹配 + if citation.get('authors') and api_data.get('authors'): + result = match_authors(citation['authors'], api_data['authors']) + scores['authors'] = result['similarity'] + + # 年份匹配 + if citation.get('year') and api_data.get('year'): + result = match_year(citation['year'], api_data['year']) + scores['year'] = 1.0 if result['match'] else 0.0 + + # 计算加权总分 + total_score = 0 + total_weight = 0 + for key, weight in weights.items(): + if key in scores: + total_score += scores[key] * weight + total_weight += weight + + if total_weight == 0: + return 0 + + return total_score / total_weight +``` + +### 验证结果判定 + +根据匹配分数判定验证结果: + +```python +def judge_verification_result(match_score): + """判定验证结果""" + if match_score >= 0.9: + return { + 'status': 'verified', + 'level': 'high_confidence', + 'message': '✅ 验证通过 - 信息完全匹配' + } + elif match_score >= 0.7: + return { + 'status': 'partial_match', + 'level': 'medium_confidence', + 'message': '⚠️ 部分匹配 - 信息有轻微差异,建议人工确认' + } + elif match_score >= 0.5: + return { + 'status': 'low_match', + 'level': 'low_confidence', + 'message': '❌ 匹配度低 - 信息差异较大,需要人工验证' + } + else: + return { + 'status': 'failed', + 'level': 'no_confidence', + 'message': '❌ 验证失败 - 信息严重不匹配或论文不存在' + } +``` + +## 完整验证流程 + +### 主验证函数 + +```python +def verify_citation_complete(citation): + """完整的引用验证流程""" + result = { + 'citation_key': citation.get('ID'), + 'layers': {} + } + + # Layer 1: 格式验证 + format_errors = check_bibtex_structure(citation) + format_errors.extend(check_field_format(citation)) + result['layers']['format'] = { + 'passed': len(format_errors) == 0, + 'errors': format_errors + } + + # Layer 2: 存在性验证 + existence = verify_existence(citation) + result['layers']['existence'] = existence + + if not existence['exists']: + result['final_status'] = 'not_found' + return result + + # Layer 3 & 4: 信息匹配和内容验证 + api_data = existence['data'] + match_score = calculate_match_score(citation, api_data) + judgment = judge_verification_result(match_score) + + result['layers']['matching'] = { + 'score': match_score, + 'judgment': judgment + } + + result['final_status'] = judgment['status'] + result['confidence'] = judgment['level'] + + return result +``` + +## 验证阈值配置 + +### 可调整的阈值参数 + +```python +VERIFICATION_THRESHOLDS = { + # 匹配阈值 + 'title_similarity': 0.85, # 标题相似度阈值 + 'author_similarity': 0.70, # 作者相似度阈值 + 'year_tolerance': 1, # 年份容差 + + # 判定阈值 + 'high_confidence': 0.90, # 高置信度阈值 + 'medium_confidence': 0.70, # 中等置信度阈值 + 'low_confidence': 0.50, # 低置信度阈值 + + # 权重配置 + 'weights': { + 'title': 0.4, + 'authors': 0.3, + 'year': 0.2, + 'venue': 0.1 + } +} +``` + +### 阈值调整建议 + +**严格模式** (用于正式发表): +- title_similarity: 0.90 +- author_similarity: 0.80 +- high_confidence: 0.95 + +**宽松模式** (用于初稿): +- title_similarity: 0.80 +- author_similarity: 0.60 +- high_confidence: 0.85 + -- cgit v1.2.3