Lab B · 合同条款审查
本章你会学到:如何做一个「每条结论都能回到原文」的文档审查助手,以及为什么这类系统的核心是引用、缺失检查和人工复核,而不是模型本身。
一句话:目标不是让 AI 替你审合同,而是把法务 45 分钟的通读,变成 20 分钟的核对——每条提示都带原文位置,且最终判断永远由人做。
这不是法律意见
本 Lab 的产出仅用于技术学习与流程演示,不构成法律意见,不能替代执业律师或企业法务的审查。真实合同必须由具备资质的人复核。不得使用真实客户合同、未脱敏合同或受保密协议约束的文件。
一个现场片段
以下为合成场景,用于说明典型情境,不对应任何真实客户或合同。
一家 200 人的软件公司(合成),采购与法务只有两人。每月过 40-60 份合同:采购协议、NDA、SaaS 订阅、数据处理协议。法务平均 45 分钟看一份,旺季积压一周,销售天天来催。
上个月,一份供应商合同有「自动续约、提前 60 天通知才能终止」的条款,采购没注意,自动续了一年。老板问:「能不能让机器先把有风险的地方标出来,你只看重点?」
法务主管的顾虑很具体:「漏一些不重要的可以接受,但高风险条款漏一条,我就得从头再读一遍,那还不如不用。还有,它不能瞎编条款原文,我要能点到那一页自己看。」
背景与用户故事
任务:输入一份合同(PDF / DOCX / 文本),输出一份「条款审查清单」。每条包含:
- 条款类型(责任限制、赔偿、自动续约、终止权、数据与隐私、知识产权、付款、管辖);
- 风险等级(高 / 中 / 低);
- 原文引用(逐字,含页码或段落号);
- 为什么值得关注(一句话,不是法律结论);
- 是否需要人工复核。
三个用户故事:法务要核对清单、不要替我下结论;采购只想知道卡在哪、要不要找法务;业务负责人要风险等级和影响范围,不要「建议咨询律师」这种废话。
明确不做:不自动修改合同、不给「签 / 不签」结论、不做最终法律判断、不覆盖劳动法与诉讼等专业领域。
成功指标
下面数字是教学示例,不是行业标准;用你自己的数据重设。
| 指标 | 定义与口径 | 目标(示例) | 为什么这样定 |
|---|---|---|---|
| 高风险条款召回率 | 金标中高风险条款被找出的比例 | ≥ 90% | 首要指标,漏检代价最高 |
| 高风险漏检率 | 金标高风险条款完全未提示的比例 | ≤ 2% | 漏一条就可能让法务重读全文 |
| 条款级精确率 | 提示中真正有问题的比例 | ≥ 70% | 允许误报,但误报不能淹没重点 |
| 引用正确率 | quote 能在原文逐字找到且定位正确 | ≥ 95% | 编造原文一次就失去信任 |
| 单份复核时间 | 法务从打开清单到确认完的时间 | 45 → ≤ 25 分钟 | 业务价值的直接度量 |
| 单份成本 | 解析 + 检索 + 模型调用总成本 | ≤ 0.30 美元 | 决定能否规模化 |
| 护栏:越界输出 | 出现法律结论、修改建议、无引用结论 | 0 | 合规红线 |
指标取舍:召回优先
合同审查和客服分流不同:漏检的代价远大于误报。所以主指标是高风险召回率,不是精确率;控制误报靠「分级 + 排序 + 折叠低风险」,而不是降低敏感度。
数据与合规
- 自己撰写的合成合同:写 10-20 份,覆盖 8 类条款的高、中、低风险写法,以及「故意不写某条款」的情况;
- 公开合同模板:政府、行业协会、开源项目公开的示范文本,确认许可证允许使用;
- 公开合同数据集:确认许可证与用途限制,只用于学习。
绝对不能用:真实客户合同、未脱敏文件、NDA 约束下的文档。也不要把合同上传到无法控制的数据处理方;用云 API 前先确认数据处理条款与留存策略,能用本地模型或企业网关更好。
标注格式建议按「条款实例」组织:
| 字段 | 说明 |
|---|---|
doc_id | 合同编号 |
clause_type | 8 类之一,或 other |
severity | high / medium / low |
quote | 逐字原文,至少 20 字,能唯一定位 |
is_missing | 布尔值,表示「应有关键条款但全文缺失」 |
先标 20 份、约 120 个条款实例。至少抽 8 份做双人标注,算一致率;低于 80% 先改标注规范,别急着上模型。
审查标准:先写 playbook,再写提示词
模型不该自己发明「什么是高风险」。先和法务(或扮演法务的人)把标准写成 playbook,再让模型按 playbook 判断。这是这个 Lab 和普通 RAG 问答最大的区别。
| 条款类型 | 高风险(红线)示例 | 中风险(黄线)示例 |
|---|---|---|
| 责任限制 | 责任上限缺失,或低于合同金额;排除全部间接损失 | 上限存在但低于年度合同额 2 倍 |
| 赔偿义务 | 单方赔偿、无上限、含第三方知识产权索赔 | 双向但范围宽泛 |
| 自动续约 | 自动续约且无提前通知机制;续约涨价无上限 | 有通知机制但窗口很短(如 15 天) |
| 终止权 | 对方可无条件单方终止,我方没有对等权利 | 终止需提前 90 天通知 |
| 数据与隐私 | 数据可用于训练、可跨境、保留期不明确 | 保留期明确但删除流程不清 |
| 知识产权 | 我方成果归对方;背景 IP 被永久授权 | 共同开发归属不明 |
| 付款与验收 | 无条件验收、账期超过 90 天、违约金过高 | 账期 60 天 |
| 管辖与争议 | 境外管辖、约定仲裁地成本极高 | 异地管辖但境内 |
这不是法律标准
上表是教学用的「关注点清单」,帮你看懂产品逻辑,不是法律判断标准。真实红线由企业法务按公司政策、行业监管和谈判地位来定;FDE 的工作是把规则变成可执行的检查项,而不是替法务做决定。
playbook 用结构化文件维护(YAML / JSON),每条规则包含:条款类型、触发条件、严重度、检查方式、提示语。升级标准不用改代码。
方案:RAG + 强制引用 + 缺失检查 + 人工复核
合同 PDF/DOCX
│
├─ 解析:抽文本、保留页码与段落号、按章节/条款切块(chunk)
│
├─ 通道 1:规则扫描(关键词/正则)
│ 责任限制、自动续约、终止、管辖……命中即生成候选
│
├─ 通道 2:playbook 检索(BM25 + 向量)
│ 对每个条款类型,找出「该看什么」的审查标准
│
├─ 通道 3:LLM 分析(按条款类型逐项检查)
│ 输出 findings[]:类型 / 等级 / 原文引用 / 位置 / 理由 / 待复核
│ 同时检查「应有但缺失」的条款
│
├─ 校验器(硬门槛)
│ quote 必须逐字出现在原文;定位必须存在;类型必须在枚举内
│ 校验失败 → 丢弃或转人工,绝不带着编造引用输出
│
└─ 排序与分级 → 人工复核界面 → 复核结果回流评测集与 playbook为什么还要「缺失检查」
最危险的问题常常不是「写了什么」,而是**「该写的没写」**——比如全文没有责任上限条款。纯 RAG 检索不到「不存在的东西」,所以要加一条独立检查路径:对每个高风险条款类型判断是否出现相关章节;全文检索不到时生成 is_missing: true 的 finding,风险等级为高并附检索范围;缺失结论必须人工复核,不允许自动结案。
输出契约
{
"doc_id": "synthetic-nda-007",
"findings": [
{
"clause_type": "auto_renewal",
"severity": "high",
"quote": "本合同到期后自动续展一年,除非提前六十(60)日书面通知不再续展。",
"location": {"page": 3, "paragraph": 2},
"rationale": "自动续约 + 通知窗口仅 60 天。",
"is_missing": false,
"needs_human": true
}
],
"missing_checks": [
{"clause_type": "limitation_of_liability", "searched_scope": "全文", "is_missing": true}
],
"disclaimer": "本结果由机器生成,仅供复核参考,不构成法律意见。"
}引用校验(必做)
PLAYBOOK_TYPES = {"liability", "indemnity", "auto_renewal", "termination",
"data_privacy", "ip", "payment", "governing_law"}
def validate_findings(findings: list[dict], doc_text: str) -> list[dict]:
valid = []
for f in findings:
quote = (f.get("quote") or "").strip()
if f.get("clause_type") not in PLAYBOOK_TYPES:
continue
if f.get("is_missing"):
# 缺失类无引文,必须人工复核
f["needs_human"] = True
valid.append(f)
continue
if len(quote) < 10 or quote not in doc_text: # 编造引用直接丢弃
continue
valid.append(f)
return valid模型调用用 OpenAI 兼容接口即可。提示词里写清四句话:只基于给定文本、逐字引用、找不到就说找不到、不输出法律结论。
system = """你是合同条款审查助手,只做信息提取与风险提示,不提供法律意见。
规则:
1. 只依据用户提供的合同文本,不得补充外部法律知识。
2. 每条 finding 必须包含逐字引用 quote 和位置 location;无法引用就不要输出。
3. 按 playbook 判断严重度,不要自行发明标准。
4. 关键条款缺失时输出 is_missing=true;不确定时 needs_human=true,不要猜测。
"""评测
黄金集结构
用 20 份合成合同,约 120 个条款实例,分层如下:
| 分层 | 数量 | 目的 |
|---|---|---|
| 高风险条款实例 | 40 | 主指标:召回率 |
| 中风险条款实例 | 40 | 考察分级是否合理 |
| 低风险 / 正常条款 | 20 | 考察误报 |
| 应判定为缺失的条款 | 20 | 考察缺失检查路径 |
| 干净合同(无问题) | 2 份 | 考察「不硬凑问题」 |
怎么评
条款级按「类型 + 位置重叠」匹配,算 precision / recall / F1;高风险召回、引用正确率、缺失识别率各自单列给业务方看;人工复核时间找 2-3 位同事计时,别自己估。
错误分析按「漏检 / 误报 / 引用错误 / 分级错误」归因。漏检逐条看:是解析切断了条款、playbook 没覆盖,还是模型读到了没输出?原因不同,修法完全不同。
阈值与展示策略
高风险全部展示、按位置排序、默认展开;中风险按分数排序,默认折叠前 10 条;低风险只显示数量;缺失类单独置顶,必须人工处理。这样即使误报不少,法务的注意力也不会被淹没。
防漂移
合同模板、法规、供应商条款都会变,评测集放三个月就可能过时。三个动作:漏检回流(法务标「漏了」的样本进入待标注队列,据 Foundation Capital 2025 年一篇分析(单一来源),有法律科技产品把漏检转成标注样本、每晚迭代,关键条款召回率一个月从 92% 升到 98%,数字不可套用但思路值得借鉴);playbook 版本化(版本号 + 变更说明 + 回归结果);季度重评(补新合同类型,重跑全量黄金集)。
上线检查
- 法务负责人书面确认使用范围、免责声明与人工复核流程
- 每条 finding 都能回到原文页码/段落,引用校验器默认开启
- 高风险与缺失类结论强制人工复核,不能自动结案
- 输出固定携带「不构成法律意见」声明
- 真实合同数据不出域、不进第三方不可控服务,已脱敏
- 审计日志记录 playbook、模型与提示词版本
- 一键退回纯人工流程,已演练
- 评测报告含高风险召回率与漏检分析,不只是平均分
- 法务参与黄金集标注与抽查,不只由工程师定义对错
交付清单
- README:场景、边界、免责声明、如何运行
- 数据说明:合同来源、合成方法、许可证、标注规范
- 解析与切分代码(保留页码与段落号)
- playbook 文件(8 类条款 + 版本记录)
- 检索 + LLM 分析流程、提示词版本、引用校验器
- 缺失检查逻辑
- 评测报告:总表、高风险召回、引用正确率、漏检分析
- 复核界面说明或截图(可用命令行/表格代替)
- 5 分钟演示脚本(强调「人做最终判断」)与复盘
常见误区
- 把「AI 审合同」当卖点:法律风险远大于技术收益;正确说法是「辅助审查 / 信息提取」。
- 只做 RAG 找条款,不做缺失检查:真正危险的是「没写的条款」。
- 引用不校验:模型会编造原文,一次就毁掉信任。
- 只看精确率不看漏检:法务宁可多看误报,也不能漏高风险。
- 用真实合同做 demo:合规事故的常见起点。
- 让模型自由发挥严重度:严重度由 playbook 定义。
本章小结
- 合同审查的第一原则是「可核对」:每条结论都能回到原文,否则没有使用价值。
- 先写 playbook,再写提示词;风险标准由人定,模型只执行。
- 缺失检查是与 RAG 并列的独立路径,不能省。
- 指标以高风险召回为优先,用分级展示控制误报。
- 法律边界要写进产品:辅助而非替代,人工复核不可绕过。
练习
- 写 8 份合成合同:覆盖 8 类条款的高、中、低风险,其中 2 份故意缺失责任上限。判断标准:能列出每份合同的金标条款清单。
- 做一次漏检分析:跑 20 份黄金集,逐条分析高风险漏检的原因。判断标准:每类漏检有明确修复动作(解析、playbook、提示词、模型)。
- 设计复核界面:画一屏(ASCII 即可),说明三类风险分别怎么展示。判断标准:法务能在 25 分钟内核对完一份合同。