采购合同审核 Skill
规则驱动、可插拔规则包的合同签约前风险审核引擎。AI 只出意见,采纳权在人;本工具不替代律师/法务最终判断,不构成法律意见,不直接改写合同正文。
何时使用
- 用户上传/粘贴一份采购合同(货物采购、软件与系统开发、服务外包、工程建设等),要求签约前风险自查或复核。
- 用户要求维护/新增/修改审核规则,或对规则包做回归测试、自检。
- 用户要求把同一引擎换规则包复用到其他合同类型(劳动、租赁、保密、SaaS、营销合规等)。
不适用于:代写合同、直接代签、出具法律意见书。
核心设计原则(不可妥协)
- 规则是数据,不是代码:引擎与规则包解耦。规则以 md/json 文本存在,每次审核前重载(热更新),改规则不碰引擎。
- 确定性归代码,语义归模型:字符级可判定的(失效法规、违禁表述、必备要素关键词、阈值验算)走脚本,结果确定、零漏报;需理解语义的走 LLM。
- 可溯源、防幻觉:每条问题必须给出【章节定位 + 原文摘录 + 命中规则 + 修改建议】;
quote必须能在合同原文中检索到,检索不到一律丢弃。原文无依据不输出。 - 未命中也透明:每条规则在报告中体现"已检查 / 未发现问题"。
- 人机协同:建议可接受 / 拒绝 / 编辑,采纳权在人。
- 规则可运营:规则包带版本号、生效日期、来源依据;改完能回归测试、能回滚。
资产结构
procurement-contract-review/
├── SKILL.md # 本文件:定位 + 编排流程 + 硬性不变量
├── package.json
├── references/
│ ├── LLM_SEMANTIC_PROMPT.md # 语义/要件规则的 LLM 评审提示词与 JSON 出参规范
│ ├── OPS_REPORT_SPEC.md # 命中项 Ops JSON 标准 + HTML 报告字段约定
│ └── RULE_PACK_AUTHORING.md # 如何新增/修改规则、写回归测试、换规则包
├── scripts/ # 纯 Python 标准库(除 docx/pdf 可选解析外,见下)
│ ├── parse_contract.py # F1/F2 解析 docx/pdf/txt + 章节切块
│ ├── hard_check.py # F4 硬规则:hard_match / value_check,字符级零漏报
│ ├── validate_rules.py # F9 规则包自检 + tests/ 回归测试
│ ├── render_report.py # F7 汇总去重 + 交互式 HTML 报告
│ └── contract_review.py # 编排入口(parse → hard → [LLM] → render)
├── rules-pack-企业采购合同/ # 首发规则包(可插拔)
│ ├── manifest.yaml # 包名/版本/生效日期/规则清单/来源/更新记录
│ ├── hard_terms.json # 硬规则词表:失效法规/违禁表述/必备要素/阈值
│ ├── rules/R-*.md # 一条规则一个文件(12 条)
│ └── tests/*.json # 回归测试集(正例应命中 / 反例不误报)
└── examples/ # 演示合同 + 生成的示例报告
执行流程(F1→F7 最小闭环)
所有脚本用托管 Python 运行:
C:\Users\About\.workbuddy\binaries\python\envs\default\Scripts\python.exe(无该 venv 时用...\versions\3.13.12\python.exe)。脚本仅依赖标准库;.docx解析优先用标准库读 zip 内 XML,无需第三方包。
第 0 步(每次审核前)· 规则包自检 + 热加载
- 运行
python scripts/validate_rules.py --pack <规则包目录> --lint校验规则格式;缺字段时报错并定位到具体文件。 - 引擎每次审核都重新扫描规则目录(不过夜缓存),新增/改规则下一份合同即生效。规则状态
draft仅提示、不计入正式问题(灰度用)。
第 1 步 · F1/F2 解析与切块
python scripts/parse_contract.py <合同文件> --out contract.json- 支持 .docx/.pdf/.txt;文件类型读内容首段判断,不靠后缀。按"第 X 章/条/节/附件"切分并保留章节路径;单块超阈值(默认 800 字)按行二次切分;保留章节编号用于定位。
第 2 步 · F4 硬规则审核(代码,零漏报)
python scripts/hard_check.py contract.json --pack <规则包目录> --out hard_hits.json- 词表来自
hard_terms.json:失效法规(如援引已被《民法典》替代的原《合同法》等)、违禁表述、必备要素关键词缺失、阈值验算(账期/尾款比例/违约金上限)。字符级精确匹配,不调 LLM、可重复。隐性规则(失效法规)未命中不展示、命中置顶。
第 3 步 · F5 语义/要件规则审核(LLM)
- 读取
rules/中判定方式为rule_check/semantic且状态active的规则,按references/LLM_SEMANTIC_PROMPT.md的提示词,逐规则(或按章节批量)让模型评审。 - 强制 JSON 出参:
{rule_id, hit, severity, location, quote, problem, suggestion};低温、关思考保稳定。 - 防幻觉硬约束:模型返回的每个
quote必须能在contract.json原文中检索到(去空白后子串匹配),检索不到则丢弃该条;超出规则范围的复杂情形输出hit=false+need_human=true(建议人工复核),不强行判定。 - 单条规则失败/超时/JSON 异常 → 兜底重试一次,仍失败则该规则标记"评审失败-建议人工",不阻断整体。
第 4 步 · F6 汇总去重
- 合并硬规则 hits 与 LLM hits;同一定位(章节 + 近似 quote)的问题归并;硬规则置顶,其余按严重度(高>中>低)排序。
第 5 步 · F7 交互式 HTML 报告
python scripts/render_report.py hard_hits.json llm_hits.json --pack <规则包目录> --contract contract.json --out 报告.html- 顶部汇总:合同名、审核时间、规则包名+版本+生效日期、命中数/未命中数;命中卡片含严重度、规则编码+名称、章节定位(原文高亮)、问题、可一键复制的修改建议、接受/拒绝复选框 + 可编辑;未命中规则折叠为"已检查 N 项未发现问题"。
- 报告为单文件、内联 CSS/JS、无外部依赖,可直接双击在浏览器打开。
第 6 步 · 交付
- 用
present_files打开 HTML 报告;同时可导出 markdown 审核意见(报告页内含"导出意见"按钮,或脚本--format md)。 - 提醒用户:AI 意见仅供参考,采纳前请法务复核;命中失效法规等硬规则项建议优先处理。
规则包判定方式
| 方式 | 判定方 | 适用 | 漏报要求 |
|---|---|---|---|
hard_match |
代码字符匹配 | 援引失效法规、违禁表述 | 0 漏报 |
value_check |
代码/简单验算 | 比例、期限、金额逻辑异常(阈值在词表,可配) | 0 漏报 |
rule_check |
LLM 按明确要件核验 | 必备条款要素是否齐全、表述是否可执行 | ≤5% |
semantic |
LLM 语义理解 | 权责对等、归属清晰、约定有效 | ≤5% |
阈值类(尾款比例、违约金上限、账期天数)不写死在引擎里,放在 hard_terms.json 的 thresholds,企业按自身采购政策调整;默认值仅行业常见参考,不构成硬性法律标准。
硬性不变量(违反即返工)
- 任何命中项四要素不全(定位/原文摘录/问题/建议)或
quote在原文检索不到 → 不得进入报告。 - 硬规则不得走 LLM;语义规则不得用字符匹配假装判定。
- 规则包每次审核前必须重新加载;不得缓存旧规则。
- 报告必须包含"未命中规则"清单项(透明),不得只报命中。
- 不修改用户原始合同文件;所有产出写入新文件。
- 报告/导出件须带规则包名称 + 版本 + 生效日期水印,保证"当时按哪版规则审的"可追溯。
复用与扩展
- 换场景 = 换规则包:复制
rules-pack-企业采购合同/为新包,改 manifest 与规则/词表/测试,引擎不动。详见references/RULE_PACK_AUTHORING.md。 - 新增规则后务必在
tests/加正例(应命中)与反例(不应误报),跑validate_rules.py --test回归。