FaithSift
中文 | English
本项目原名 CiteCheck (renamed to FaithSift) —— 因名称冲突于 2026-10-27 更名, 缘由与证据见 CHANGELOG。旧
CITECHECK_*环境变量仍作回退。
RAG 回答的句子级引用忠实性检测器 —— 逐句判定 LLM 的回答是「有据 / 无据 / 与源冲突」, 并给出结论所依赖的证据定位。
给定一份回答(md/txt)和一组源文档,FaithSift 会把回答拆成句级论断,对每条:
- 检索:BM25 词法 + 数值不变性 + 中英概念词表(可选再接向量通道),找出最相关的证据片段;
- 判定三分类:supported(证据明确包含)/ contradicted(与同一事实的取值冲突)/ unsupported(证据沉默,既不支持也不冲突);
- 出报告:逐条证据摘录、理由、整体忠实性得分,渲染 md / html / json。
unsupported 被单列出来是整套设计的核心:把「说错了」和「编了一个语料没覆盖的话题」分开,
工程上才能判断问题出在检索召回还是生成篡改。
实测成绩(诚实声明)
v0.3 更新:困难金标从 49 条扩到 150 条(13 个类别,新增「量级错误 / 时间错配 / 情态篡改」),并接入本地离线向量通道(
--embedder local,fastembed + 多语 MiniLM, 中↔英跨语言,零 API)。下表的「启发式(词法)」是零依赖默认档;「启发式(+向量)」 指--retriever hybrid --embedder local,判官在词法之外多一条语义余弦证据。
| 数据集 | 条数 | 启发式(词法) | 启发式(+向量) | LLM 判官 | 说明 |
|---|---|---|---|---|---|
gold/gold.jsonl(合成) |
178 | 100.0% | — | 99.44% | 词法友好,只作回归下限 |
gold/hard_gold.jsonl(人工) |
150 | 88.7% | 88.7% | 99.33% | 改写/跨语言/多跳/方向/实体/量级/时态/情态;产物 results/baseline_v03_hard_heuristic.json / results/v03_hard_heuristic_hybrid150.json / results/v03_hard_llm.json |
困难金标的原 49 条子集:纯词法 91.8%(45/49)、词法+向量 100%。向量通道专门补回 纯词法漏判的「字面几乎不重合的重度同义改写」(如「四到六个周期、每个九十分钟」 ↔ 源文「4 至 6 个周期,每个约 90 分钟」),这正是 README 早先预告的向量通道用武之地。
困难金标(150 条)按类别准确率:
| 能力 | 词法 | +向量 | LLM | 能力 | 词法 | +向量 | LLM | |
|---|---|---|---|---|---|---|---|---|
| 逐字抽取 | 100% | 100% | 100% | 数字篡改 | 100% | 100% | 100% | |
| 单位错误 | 100% | 100% | 100% | 量级错误(新) | 100% | 100% | 100% | |
| 貌似合理缺失 | 100% | 92% | 100% | 中文同义改写 | 94% | 100% | 100% | |
| 跨语言(无数字) | 94% | 94% | 100% | 多跳证据 | 93% | 93% | 100% | |
| 实体错配 | 92% | 92% | 100% | 方向反转 | 86% | 86% | 100% | |
| 时间错配(新) | 83% | 83% | 100% | 相邻话题 vs 冲突 | 64% | 64% | 100% | |
| 情态篡改(新) | 0% | 0% | 83% |
多跳证据召回:词法 13/14、LLM 14/14。
必须说清楚的几件事:
- 合成金标 100% 不代表真实水平。它由「原文抽取 / 数字篡改 / 模板套话」三类规则生成, 天然对词法友好,只保证重构不会把做对的事弄坏。真实能力看困难金标。
- 困难金标现为人工撰写的 150 条,每条带标注理由(
rationale),且确定性可重建 (python -m faithsift gold幂等,固定 seed)。但它仍是一人判断,不是多人标注的工业集。 - 情态篡改(modal)是词法引擎的彻底盲区(0%):把「可能 / 学界存疑 / 多因素」说成 「确定 / 已有定论 / 唯一原因」,词法层没有任何语义情态信号可抓,只能靠 LLM 判官(83%)。 这是本轮扩充暴露出的最大新缺口——如实计入,没有为了好看去改金标答案。 「相邻话题 vs 冲突」词法档 64% 也是同类硬骨头(见已知局限)。
- LLM 判官 v0.3 全量复测(2026-10-28):合成 178 条 99.44%、困难 150 条 99.33%
(唯一错分是一条「蜜蜂是唯一授粉者」的情态/唯一性边界用例),两轮合计成本约 ¥0.54
(DeepSeek,逐调用记进
results/cost_ledger.jsonl),产物results/v03_{gold,hard}_llm.json。 v0.2 的历史结果(gold/validation_*_llm_v0.2.json,49 条旧困难金标)保留作对照。
双引擎 × 三检索通道
| 维度 | 选项 | 依赖 | 用途 |
|---|---|---|---|
| 判官 | heuristic |
零 API、纯本地规则 | CI 门禁、离线快检、批量回归 |
| 判官 | llm |
DeepSeek 结构化 JSON 判官 | 语义级判定:改写、蕴含陷阱、跨语言 |
| 检索 | lexical |
零依赖(BM25 + 数值 + 概念词表) | 默认通道 |
| 检索 | hybrid |
需嵌入后端,BM25+数值+向量融合 | 开放领域、重度改写 |
| 检索 | dense |
需嵌入后端,纯向量 + 数值 | 语义召回为主 |
向量通道永远不是必需品:核心包不装向量依赖也能 import、也能跑词法引擎(依赖隔离)。
--embedder local 走本地离线 ONNX 多语模型(fastembed,不含 torch),首次经
HF 国内镜像下载、之后完全离线并复用磁盘缓存;缺依赖或下载失败时打印中文提示并
自动退回 lexical,不会崩(与"没配 embedder 时 hybrid 退回 lexical"同一套降级哲学)。
纯离线替身 --embedder hashing 可把整条链路接线跑通(但它不跨语言)。
pip install -e ".[semantic]" # 装本地向量后端(fastembed)
export HF_ENDPOINT=https://hf-mirror.com # 国内镜像(可选,首次下载用)
python -m faithsift check answer.md --sources gold/sources \
--retriever hybrid --embedder local # 词法+数值+向量融合
快速开始
python -m venv .venv && .venv/Scripts/pip install -e ".[dev]"
python -m pytest tests/ -q # 89 项离线测试,零 API(向量用例无模型时自动 skip)
python -m faithsift gold # 重建两套金标(确定性)
python -m faithsift validate --dataset gold # 合成金标:回归下限
python -m faithsift validate --dataset hard # 困难金标:能力缺口
# 核查一份回答
python -m faithsift check demo/sample_answer.md --sources gold/sources \
--mode heuristic --out results/check
# -> results/check.{md,html,json}
demo/report_multihop.md 是多跳 + 跨语言召回的示例(3 条论断全对)。
CLI
faithsift check <answer> --sources <dir>
--mode heuristic|llm|both 判官
--retriever lexical|hybrid|dense 检索通道
--embedder hashing|local|<模型名> 向量后端(local=本地离线 ONNX 多语)
--top-k N --out results/check
--fail-under 0.9 忠实性低于阈值 -> 退出码 3
--fail-on-contradicted 出现与源冲突 -> 退出码 4
--json 机器可读输出
faithsift gold 重建 gold.jsonl 与 hard_gold.jsonl
faithsift validate --dataset gold|hard --mode heuristic|llm
--min-accuracy 0.85 准确率低于阈值 -> 退出码 5
退出码:0 成功 · 2 用法错误 · 3 忠实性不达标 · 4 存在冲突论断
· 5 准确率不达标 · 6 缺少密钥。
--fail-under / --fail-on-contradicted / --min-accuracy 就是挂在 CI 上的那道门禁。
判定标准(与 LLM 提示词一致)
- supported:证据明确包含论断的核心事实(实体与关系一致;非数值事实的同义改写、 跨语言翻译算支持);需要多段证据才能成立时,把用到的片段编号全部列出。
- contradicted:证据就同一事实给出不同取值 —— 数字不符、方向相反(升高/降低、 高于/低于)、实体张冠李戴、单位不同。
- unsupported:证据对论断主题保持沉默 —— 既不支持也不冲突。
三条硬规则:
- 禁止数值逻辑蕴含。证据说「200 度以上」、论断说「180 度以上」⇒
contradicted, 哪怕逻辑上能推出来。改一个数字就是篡改。 - 相邻话题不等于冲突。语料讨论了邻近话题但没给论断所说的这个事实 ⇒
unsupported。 - 声称支持必须给证据。每条判定带
evidence_idx(多跳时为数组)。
几个值得一提的设计
数字跨语言不变。 数字不随翻译改变,所以「一爆 196 至 205 摄氏度」的中文论断能命中 英文段落。这一条把 LLM 引擎的 demo 从 5/8 提到 8/8。
中文数词归一化。 「两千」「四到六」「一成」「10 万」「1.9 million」「2,000」
都会先归一化成阿拉伯数字再比对,否则中文回答里的数词既进不了检索、也进不了数值校验。
数百 这类约数不会被误转成 100。
概念词表补跨语言。 只靠数字的话,一条不含数字的中文论断永远召回不到英文证据。
faithsift/lexicon.py 把中英表面形式映射到共享概念词元
(茶树/tea → tea,一爆/first crack → first_crack),
约 250 个表面形式、120 个概念,覆盖随附的六个领域。
实体名录防张冠李戴。 论断点名阿姆斯特丹,而「2005 年起投资 20 亿丹麦克朗」讲的是
哥本哈根 —— 数字全对、主题全对,但结论是错的。判官会把「只讲别的实体」的片段划为旁证,
数字全部落在旁证里就判 contradicted(实体错配)。
多跳真的需要两段。 判官不满足于「某段沾边」,只有在第二段证据带来足够新增覆盖、 并且合并后达到阈值时才判多跳支持;否则一篇主题相关但不含该事实的段落就会被当成证据。
成本保险丝。 results/cost_ledger.jsonl 逐调用记账,硬顶 ¥12(FAITHSIFT_CAP 可调,旧名 CITECHECK_CAP 仍作回退),
到顶抛 BudgetStop,防止批量跑测试时超支。
结构
faithsift/claims.py 中英句级论断拆分
faithsift/evidence.py 源加载 / 分块 / 分词
faithsift/lexicon.py 中英概念词表 + 实体名录
faithsift/numbers.py 中文数词与量级归一化
faithsift/retrieval.py BM25 + 数值不变性 + 可选向量的混合检索
faithsift/embed.py 可选向量后端(OpenAI 兼容 / 本地离线 ONNX 多语 / 哈希替身 / 磁盘缓存)
faithsift/judge.py 双引擎判官(LLM JSON 判官 + 启发式,含多跳)
faithsift/pipeline.py 端到端流水线 + 金标验证 + CI 门禁
faithsift/report.py md / html / json 报告渲染
gold/ 两套金标 + 6 篇双语语料 + 验证产物
demo/ 示例回答与渲染好的报告
scripts/gap_report.py 按类别列出错分样本的开发脚本
tests/ 89 项离线测试(向量端到端无 fastembed/模型时 skip)
密钥与安全
真实密钥不放进仓库。加载顺序:
- 环境变量
DEEPSEEK_API_KEY FAITHSIFT_ENV_FILE指向的文件(可以在仓库外;旧名CITECHECK_ENV_FILE仍作回退).env.local(已 gitignore,本地私有).env(只有占位符)
tests/test_security.py 会扫描仓库内文件是否出现真实密钥形态,并校验 .env 未被 git 跟踪。
CI 里单独跑这个文件。
如果真实密钥曾经出现在文件里,请到控制台轮换它,而不是只删文件 —— 已经分发出去的副本不受你控制。
与已发表工作的关系(诚实定位)
系统调研(40+ 条目,逐条带核实状态与链接)见 docs/survey_faithfulness_landscape.md。要点:
- 不宣称首创的部分:拆句→取证→判定的管道是 2023 年起的成熟范式(FActScore、SAFE、RAGAS、DeepEval、ALCE 等);三分类中"证据沉默"单列有 FEVER(NotEnoughInfo)与 NLI(neutral)先例;改名前的旧名 CiteCheck 与北大 2025 同名工作(arXiv:2502.10881,中文引用忠实性数据集)撞车——这正是本项目改名 FaithSift 的原因,并与该工作无任何代码/数据继承关系。
- 站得住的差异点(调研核实范围内):①纯词法零 API 判官——现有低成本方案均为神经小模型,词法+数值一致性的可审计判官未找到对标物;②seed 固定的确定性金标用于审计判官本身(arXiv:2607.20527 恰好证明神经判官之间严重不一致,支持该设计动机);③中文论断→英文源的跨语言词法检索管道(数字不变性+概念词表,未找到相同设计);④多跳证据链的工程化判官(学术脉络引 FEVEROUS)。
- 引用纪律: survey 中 4 条【未核实:仅训练记忆】条目(如 FacTool venue)在正式引用前必须人工复核。
已知局限(v0.3 现状)
v0.2 的这几条已修复(移出局限):
同语言重度改写→ 接入向量通道(--embedder local)后,困难金标「中文同义改写」类 从词法档 94% 升到 100%;「低估自己有多困」这类字面不重合的改写由语义余弦兜底。相邻话题被判成冲突→ 「荷兰头盔立法始于 2010 年」(源文实为澳大利亚 1990 年代) 现判unsupported:缺失数字必须在同一事实槽 + 同一实体里找到竞争取值才算冲突。无数字的语义方向(Agtron)→ 新增烘焙「深/浅」定性刻度反义词识别, 「Agtron 数值越大越深」对源文「higher numbers indicate lighter roasts」现判contradicted。
仍未解决(如实列出):
- 情态篡改是词法盲区(0%):把「可能 / 学界存疑 / 多因素」拔高成「确定 / 已有定论 / 唯一原因」,词法与向量都没有可靠的语义情态信号,只能交给 LLM 判官(83%)。
- 隐蔽的相邻话题仍会被"多跳"凑成支持(词法 64%):当两段各沾一半主题词的片段
联合起来把论断的概念覆盖满(如「新加坡屋顶绿化覆盖率全球第一」),词法档会误判
supported。它与"忠实的多跳"在词法层结构相同,区分需要语义蕴含,LLM 档 100%。 - 跨语言稀疏概念:中文论断对英文源、且可映射的概念词太少时(如「一个蜂群在温带 地区有 20 万至 80 万只个体」),词法覆盖过低会漏召;向量通道能补一部分,但判官的 覆盖度仍以词法/概念为主。
- 概念词表只覆盖随附六个领域:开放语料请用
--retriever hybrid --embedder local或--mode llm;词表外的词平滑退化为原始词法词元。 - 方向词表有限:方向词与其修饰的数字/概念在源文里隔得较远,或用「低 / 高」这类 未登记的裸方向词时,反转会漏判(150 条 direction 词法 86%)。
- 金标仍是一人标注:150 条困难样本足以暴露缺口、给出按类别的相对强弱, 但仍不足以给出置信区间,也没有第二标注者做一致性(Kappa)检验。
License
MIT。
Metadata
Release files for faithsift 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| faithsift-0.3.0.tar.gz | 74.5 kB | Without provenance | Details for faithsift-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| faithsift-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for faithsift-0.3.0-py3-none-any.whl |
Total release size: 132.9 kB
Release files / faithsift-0.3.0.tar.gz
| Download URL | faithsift-0.3.0.tar.gz |
|---|---|
| Size | 74.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5be0fd0f4ae074f49d02c1b8b1cd4ff425102206a8dca693a0b1d8f8d108a241
|
|
BLAKE2b-256 checksum How to use checksums |
1d4d484c99a7c797924a1364c6a9bdf80f9652587fe5c3416fae081c1c7c48e0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.15
|
Release files / faithsift-0.3.0-py3-none-any.whl
| Download URL | faithsift-0.3.0-py3-none-any.whl |
|---|---|
| Size | 58.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b18fbddf7d6c28b9e8326590fed1d2678aa5ee691068bb804140b139b87f3c25
|
|
BLAKE2b-256 checksum How to use checksums |
76f3838bf9ddb0241348fd8dd4531463cab5d0fd85703f78936bdf4ee321a3fa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.15
|
Security for faithsift 0.3.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.