first commit
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
# Citation Verification Reference Files
|
||||
|
||||
## 文件用途
|
||||
|
||||
本目录中的文件提供**背景知识和参考信息**,用于理解引用验证的原理和常见问题。
|
||||
|
||||
**重要**: 这些文件不是主要工作流的一部分。实际的引用验证优先使用 arXiv、DOI/CrossRef、Semantic Scholar、publisher metadata 和 Zotero metadata。Google Scholar 只能作为人工发现或 fallback。
|
||||
|
||||
## 文件说明
|
||||
|
||||
### common-errors.md
|
||||
|
||||
**内容**: 常见引用错误模式和修复方法
|
||||
|
||||
**用途**:
|
||||
- 了解学术写作中常见的引用错误
|
||||
- 学习如何识别和修复这些错误
|
||||
- 理解为什么需要验证引用
|
||||
|
||||
**何时参考**: 当需要了解引用错误的类型和修复方法时
|
||||
|
||||
### verification-rules.md
|
||||
|
||||
**内容**: 详细的验证规则和匹配算法
|
||||
|
||||
**用途**:
|
||||
- 理解引用验证的完整逻辑
|
||||
- 了解如何匹配标题、作者、年份等信息
|
||||
- 学习验证的技术细节
|
||||
|
||||
**何时参考**: 当需要深入了解验证逻辑时
|
||||
|
||||
### api-usage.md
|
||||
|
||||
**内容**: API 使用指南(CrossRef、arXiv、Semantic Scholar)
|
||||
|
||||
**用途**:
|
||||
- 了解学术API的使用方法
|
||||
- 理解API验证的原理
|
||||
- 参考高级用例的实现
|
||||
|
||||
**何时参考**: 当需要了解API验证方法时。当前主要工作流应优先使用这些 programmatic / canonical sources。
|
||||
|
||||
## 主要工作流
|
||||
|
||||
**实际的引用验证应该使用 `ml-paper-writing` skill 中的 Citation Workflow:**
|
||||
|
||||
1. 查找 DOI、arXiv ID、publisher page 或 verified Zotero item
|
||||
2. 用 CrossRef、arXiv、Semantic Scholar、publisher metadata 或 Zotero metadata 验证
|
||||
3. 从 programmatic/canonical source 获取 BibTeX
|
||||
4. 验证声明(如需要)
|
||||
5. 添加到 bibliography
|
||||
|
||||
详见 `ml-paper-writing` skill 的 "Citation Workflow (Hallucination Prevention)" 部分。
|
||||
|
||||
## 使用建议
|
||||
|
||||
**对于日常论文写作**:
|
||||
- ✅ 使用 `ml-paper-writing` skill 的 Citation Workflow
|
||||
- ✅ 使用 arXiv、DOI/CrossRef、Semantic Scholar、publisher metadata 和 Zotero metadata
|
||||
- ✅ 必要时用 Google Scholar 做人工发现,但不要把它作为 canonical authority
|
||||
- ✅ 参考这些文件了解背景知识
|
||||
- ❌ 不要从记忆或未经验证的 Google Scholar 条目生成最终 BibTeX
|
||||
|
||||
**对于理解验证原理**:
|
||||
- 阅读 `common-errors.md` 了解常见错误
|
||||
- 阅读 `verification-rules.md` 了解验证逻辑
|
||||
- 阅读 `api-usage.md` 了解API方法(参考用)
|
||||
|
||||
## 更多信息
|
||||
|
||||
详见 `citation-verification` skill 的 SKILL.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 (标题搜索)** - 较可靠,需要人工确认
|
||||
|
||||
@@ -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 一致
|
||||
- [ ] 无重复引用
|
||||
- [ ] 格式统一(作者名、期刊名、页码)
|
||||
- [ ] 无虚假或严重错误的引用
|
||||
|
||||
遵循这些最佳实践可以有效避免常见的引用错误,提高论文质量和可信度。
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user