"""数值事实守卫回归测试(不依赖 pytest) python tests/test_fidelity_guard.py 背景:LLM 校对(qwen)曾把 ASR 原文的事实改错——实测样例: `自2027年1月1日起施行` -> `自2024年1月1日起施行` `第十一届东方经济论坛` -> `第九届东方经济论坛` `十五五` -> `十四五` 因此校对结果在落库前必须通过数值事实守卫:数值被改动则回退 ASR 原文。 注意守卫的取向是「宁可保留原文,也不接受 LLM 改数」: - 书写形式差异(7 ↔ 七、2026 ↔ 二零二六)必须放行,否则会误伤大量正常校对; - 任何真实数值变化必须拦下。 """ import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from audioRead import _number_drift, _number_signature # noqa: E402 # (原文, 校对后, 说明, 是否应拦下) CASES = [ # 应当放行:仅书写形式/切分差异 ('7月23号', '七月二十三号', '阿拉伯数字 ↔ 中文数字', False), ('2026年', '二零二六年', '阿拉伯 ↔ 逐年读法', False), ('2027年1月1日', '2027年1月1日', '完全相同', False), ('第十五届', '第十五届', '序数未变', False), ('增长55%', '增长百分之五十五', '百分比写法差异', False), ('他3日在莫斯科', '他三日在莫斯科', '日期写法差异', False), # 应当拦下:真实数值改动 ('自2027年1月1日起施行', '自2024年1月1日起施行', '年份篡改(实测样例)', True), ('第十一届东方经济论坛', '第九届东方经济论坛', '届次篡改(实测样例)', True), ('十五五规划', '十四五规划', '规划期篡改(实测样例)', True), ('增长5.3%', '增长5.31%', '小数点篡改', True), ('55个', '60个', '数量篡改', True), ('2025年', '2023年', '年份篡改', True), ('300亿元', '30亿元', '量级篡改', True), ] def main(): failed = 0 for raw, corrected, desc, expect_flag in CASES: only_raw, only_new = _number_drift(raw, corrected) flagged = bool(only_raw or only_new) if flagged == expect_flag: tag = '拦下' if flagged else '放行' print(f" ✓ {desc:20} -> {tag} {only_raw}{only_new}") else: failed += 1 expect = '拦下' if expect_flag else '放行' print(f" ✗ {desc:20} -> 期望{expect},实际{'拦下' if flagged else '放行'} {only_raw}{only_new}") # 签名函数自检:十五五/十四五 必须解析为不同的数值序列 c1, s1 = _number_signature('十五五规划') c2, s2 = _number_signature('十四五规划') if c1 != c2: print(f" ✓ 缩写解析 十五五={c1} 十四五={c2}(不同)") else: failed += 1 print(f" ✗ 缩写解析失败:十五五与十四五都被解析为 {c1}") print(f"\n结果: {'全部通过' if failed == 0 else f'{failed} 项失败'}") return 1 if failed else 0 if __name__ == '__main__': sys.exit(main())