This release is a pre-release and may not be stable for production use.
Witnesses in the Margins — Gewita
简体中文 · English
展示名 Witnesses in the Margins 让每条引文都在页边留下可追索的见证;Gewita 是该项目的短名。
中文文献与引文核查工具。解析 GB/T 7714 参考文献、抽取正文引用、把引文与给定来源对齐,并可选查询文献记录。
为什么需要它 / Why
检查引用需要分开回答几个问题:参考文献能否解析、出版记录能否找到、引文能否在给定来源中定位,以及来源内容是否支持该表述。Gewita 帮助处理前几类可由规则和来源查询检查的问题;它不会把字符串相似误报成语义支持证明。
- 分级对齐结果:VERBATIM(逐字命中,带原文精确偏移)/ NEAR(近逐字,归一化相似度 ≥0.85)/ PARAPHRASE(字符 bigram 包含度 ≥0.5)/ NOT_FOUND——每条引用给证据和偏移,不给玄学分数
- 偏移不变量(招牌):VERBATIM 结果保证
source[start:end] == 引文原文,fuzz 测试永久守护,证据可回贴原文 - GB/T 7714 中文参考文献解析:
[J]/[M]/[C]/[D]/[P]/[S]/[EB/OL]/[DB/OL]类型标识定位标题边界、中文作者顿号分隔、电子文献日期/链接字段 - 诚实原则:离线模式永不输出"造假"结论,只说"未在给定来源中找到";只有在线核验(Crossref/arXiv)或 refstore 历史裁决才能给 EXISTS/SUSPECT/NOT_FOUND
- 引用透明库 refstore:本地追加式"已核验参考文献指纹库"(归一化标题 sha1 指纹 + 历史裁决),越用越强
- 零必装依赖:核心纯标准库(difflib/json/hashlib/urllib 够用);在线核验可注入 transport,测试绝不真联网
- 自带评测:内置 8 篇微文档 + 35 条金标,指标真实跑出(见 benchmarks/results.md)
核验流程
正文句子(含 [n] 标记)──┐
├─► ① 对齐裁决(对来源语料)
sources/ 目录 ──────────┘ │
VERBATIM 原文精确偏移 source[start:end]==引文(归一化抹平全角/引号/空白)
NEAR 句粒度 SequenceMatcher ratio≥0.85(证据=句窗)
PARAPHRASE 字符 bigram 包含度≥0.5(词面重叠,≠语义等价)
NOT_FOUND 未在给定来源中找到(≠内容有误)
参考文献表 ──► ② 解析(GB/T 7714 / 编号体 / APA-lite,覆盖率如实报告)
│
├─► ③ 存在性核验
LOCAL_ONLY refstore 历史(离线可判)
EXISTS 在线命中(标题包含度≥0.85 且年份/刊名不冲突)
SUSPECT 命中但年份差>1 或刊名不符(附差异说明)
NOT_FOUND Crossref+arXiv 均未找到(仅在线模式)
UNVERIFIED 未启用在线且无历史——诚实弃权,绝不推定造假
│
└─► ④ 合成裁决 + integrity score(credit_align × credit_exist 均值,权重写明)
安装 / Install
当前尚未发布到 PyPI;下方给出从 GitHub 获取并本地安装的命令。
git clone https://github.com/cloudydreamland/WitnessesInTheMargins.git
cd WitnessesInTheMargins
python -m pip install .
# PyPI 首发后:python -m pip install gewita
快速开始 / Quickstart
from gewita import judge_document, align_quote, parse_references, extract_citations
doc = open("报告.md", encoding="utf-8").read()
# 一次完整核验(离线;传入 transport=... 启用在线)
report = judge_document(doc, {"来源A": src_a_text, "来源B": src_b_text}, doc_name="报告")
print(render_markdown(report)) # Markdown 报告:逐条裁决 + integrity score + 异常清单
# 单独用各件
refs = parse_references(doc) # 参考文献表 → list[Reference]
cites = extract_citations(doc, refs) # 正文引用标记([1] [1,2] [1-3] (Smith, 2020))
a = align_quote("自注意力机制建模长距离依赖", src_a_text)
a.level, a.start, a.end # 'VERBATIM', 23, 35 —— src_a_text[23:35] 就是引文
命令行:
gewita check 报告.md --sources sources/ # 离线核验,退出码 0/1/2
gewita check 报告.md --sources sources/ --online # 启用 Crossref/arXiv 在线核验(真实联网)
gewita check 报告.md --sources sources/ --json # JSON 报告
gewita refs 参考文献.txt # 解析参考文献表(覆盖率如实报告)
gewita refs 参考文献.txt --verify # 逐条在线核验(真实联网,内置限速)
gewita bench # 内置评测(离线,mock transport)
gewita refstore stats refstore.jsonl # 引用透明库统计
退出码:0 干净 / 1 有可疑引用 / 2 输入错误。
偏移不变量(招牌)
align_quote 的 VERBATIM 结果保证证据可回贴原文:
a = align_quote(quote, source)
assert a.level == "VERBATIM"
assert source[a.start:a.end] == quote # 引文与来源逐字一致时
assert normalize(source[a.start:a.end]) == normalize(quote) # 全角/引号/空白变体抹平时
实现是归一化位置→原始位置 的索引映射(text.build_index):归一化串上 str.find 命中后,把区间两端映射回原文码点偏移。fuzz 测试(随机来源 × 随机逐字注入引文 × 多 seed)永久守护这条不变量。切句同理:"".join(s.text for s in split_sentences(text)) == text。
诚实边界(读这个再用)
- 离线不判造假。
transport=None时 existence 只会是UNVERIFIED/LOCAL_ONLY。对齐NOT_FOUND只表示"未在给定来源中找到"——来源给少了责任在使用者,报告会如实写"证据不足,不等于内容有误"。 - GB/T 7714 是启发式解析。内置语料实测覆盖率 94.3%(33/35,2 条故意无法解析的残卷条目如实标注
parsed=False)。解析不出的条目保留原文,绝不编造字段;更全的语料与 F1 报告在 ROADMAP iter3。 - PARAPHRASE ≠ 语义等价,只是字符 bigram 词面重叠 ≥0.5。语义相反但词面重叠的改写也会判 PARAPHRASE(测试里有这条断言);支持性判断留给 ROADMAP iter4 的可插拔 LLM judge。
- NEAR/PARAPHRASE 的证据 span 是句级窗,不是字符级精确区间(VERBATIM 才有精确区间)。
- 在线核验礼仪:默认关闭;开启后内置限速(相邻查询 ≥1s)与单次预算(
max_queries),网络失败如实记为UNVERIFIED而不是 NOT_FOUND。 - 内置评测是合成语料,数字(对齐四级 F1=1.000)是格式级能力上限,不外推到真实脏数据。
与现有方案的关系(如实)
| 方法类别 | 主要用途 | 与 Gewita 的关系 |
|---|---|---|
| 参考文献解析器 | 将引用字符串拆成作者、标题、年份等字段 | Gewita 聚焦中文 GB/T 7714 等格式,并保留未解析条目供人工检查 |
| 文献元数据服务 | 按 DOI、标题等查询出版记录 | Gewita 的在线查询为可选项,覆盖范围取决于 Crossref/arXiv 等来源 |
| 引文核验流程 | 对齐已有表述与用户提供的来源 | Gewita 可给出可回看的文本证据;语义蕴含仍需人工或单独评测的模型判断 |
- 在线查不到 ≠ 造假。带 DOI 的条目在 Crossref 无命中时,报告会明确说明:大量中文 DOI 注册于 ISTIC/CNKI 等非 Crossref 注册机构,注册机构级核验不在本工具能力内(详见 docs/competitors.md 对 anystyle 的同类分析)。
开发与测试
python -m pytest # 172 项测试,全离线(在线核验注入 mock transport)
python -m ruff check . # 0 error
python -m gewita bench # 内置评测,结果回填 benchmarks/results.md
完整英文说明与安装步骤见 README.en.md。当前 PyPI 首发尚未完成,请先按本页安装步骤从 GitHub 获取代码。
反馈与参与
使用问题和功能建议可以在 Discussions 交流;可复现缺陷请提交 Issue。请只附合成或脱敏后的最小样例,不要上传真实个人信息、API key 或业务原文。安全问题请按 SECURITY.md 私下报告。
许可
MIT。见 LICENSE。
Metadata
Release files for gewita 0.1.0rc1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gewita-0.1.0rc1.tar.gz | 56.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gewita-0.1.0rc1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 99.3 kB
Release files / gewita-0.1.0rc1.tar.gz
| Download URL | gewita-0.1.0rc1.tar.gz |
|---|---|
| Size | 56.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
efcc3db981e5e7c62adbc899ee30dfa067a5115709da858ffe7e3b6aa36fe07e
|
|
BLAKE2b-256 checksum How to use checksums |
d0117933749124d4462b7a35d12095184f8f8dacaa3c5dca5759984dd99908b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency logRelease files / gewita-0.1.0rc1-py3-none-any.whl
| Download URL | gewita-0.1.0rc1-py3-none-any.whl |
|---|---|
| Size | 43.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a0f5ddd9580061d2f58a828ae23a434d7a7237386185b34ffa3bf3fa73f85379
|
|
BLAKE2b-256 checksum How to use checksums |
077ffeeb013982ffe9f07986a9f9af7664d3a406c1258a727e8b1d54c06931bb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.
Transparency log