用多模态大模型做合同关键信息抽取:从 OCR 到结构化 JSON 的落地实践
在企业数字化系统中,合同管理是一个非常典型但又容易被低估的场景。很多公司虽然已经上线了合同管理系统,但历史合同、供应商合同、扫描件合同仍然大量以 PDF、图片或 Word 文档形式存在。业务人员想要查询合同金额、付款节点、合同期限、违约条款时,往往还需要人工打开文件逐页查找。
随着 OCR、文档智能和多模态大模型的发展,合同信息抽取逐渐从“人工录入”变成“AI 自动识别 + 人工校验”。本文聚焦一个具体方向:如何使用 OCR + 多模态大模型实现合同关键信息结构化抽取。
一、合同信息抽取到底要解决什么问题?
合同信息抽取的目标不是简单地把 PDF 转成文字,而是把合同中的核心字段提取成结构化数据,方便后续检索、审批、预警和统计。
例如一份采购合同中,系统需要抽取:
json
{ "contract_name": "设备采购合同", "contract_no": "CG-2024-0018", "party_a": "上海某某科技有限公司", "party_b": "杭州某某设备有限公司", "amount": "¥580,000.00", "sign_date": "2024-03-12", "effective_date": "2024-03-12", "end_date": "2025-03-11", "payment_terms": [ "合同签订后7个工作日内支付30%", "设备验收合格后支付60%", "质保期满后支付10%" ], "termination_clause": "任何一方严重违约,守约方有权解除合同"}
这些字段一旦结构化,就可以用于:
- 合同到期提醒;
- 付款计划自动生成;
- 供应商合同金额统计;
- 法务风险条款检查;
- 审批系统自动回填。
因此,合同抽取的核心是:从非结构化文档中稳定提取业务字段。
二、为什么传统 OCR 不够?
传统 OCR 主要解决“看图识字”,把图片或扫描件转成文本。例如:
text
甲方:上海某某科技有限公司乙方:杭州某某设备有限公司合同总金额:人民币伍拾捌万元整(¥580,000.00)
但 OCR 本身并不知道这些文字分别代表什么字段。它也难以处理以下问题:
1. 合同格式不统一
不同供应商、不同业务部门使用的合同模板可能完全不同。有的写“甲方/乙方”,有的写“买方/卖方”,还有的写“委托方/受托方”。
2. 字段可能分散在多页
合同金额在第一页,付款方式在第三页,违约责任在第八页。仅靠正则表达式很难覆盖所有情况。
3. 条款语言复杂
付款条款、保密条款、解除条款通常是长文本,并不是一个固定格式的字段。
4. OCR 结果存在错误
扫描件质量不好时,OCR 可能把“580,000.00”识别成“58O,000.OO”,把“乙方”识别成“己方”。如果后续没有纠错机制,抽取结果会出现明显错误。
因此,合同智能抽取不能只依赖 OCR,而需要结合大模型的语义理解能力。
三、整体方案:OCR + 文档切分 + 大模型抽取
一个比较实用的合同抽取流程如下:
text
合同文件上传 ↓文件解析 ↓OCR 识别 / PDF 文本提取 ↓版面结构还原 ↓按章节切分文本 ↓大模型字段抽取 ↓JSON 格式校验 ↓规则校验与人工复核 ↓写入合同系统
如果合同是原生 PDF,可以优先直接提取文本;如果是扫描件或图片 PDF,则需要 OCR。对于表格较多的合同,还需要表格识别能力,否则付款计划、设备清单、报价明细很容易丢失结构。
四、字段定义要先明确
在调用大模型之前,必须先定义要抽取哪些字段。不要让模型自由总结,否则输出结果不可控。
可以把字段设计成配置化模板:
json
{ "contract_name": "合同名称", "contract_no": "合同编号", "party_a": "甲方名称", "party_b": "乙方名称", "amount": "合同金额,优先提取数字金额", "currency": "币种,如 CNY、USD", "sign_date": "签署日期", "effective_date": "生效日期", "end_date": "终止日期或合同到期日", "payment_terms": "付款条件,按条款数组输出", "liability_clause": "违约责任条款摘要", "termination_clause": "解除或终止条款摘要"}
字段定义越清晰,模型输出越稳定。特别是金额、日期、主体名称这类字段,需要明确抽取规则。例如金额要优先输出阿拉伯数字,日期统一为 YYYY-MM-DD 格式。
五、Prompt 设计:要求模型输出严格 JSON
合同抽取场景中,Prompt 的核心目标是让模型按指定格式输出,方便程序解析。
示例 Prompt:
text
你是合同信息抽取助手。请根据给定合同文本,抽取指定字段。
要求:1. 只能基于合同文本抽取,不要编造;2. 如果字段不存在,填 null;3. 日期统一输出为 YYYY-MM-DD;4. 金额字段输出阿拉伯数字,不要包含中文大写金额;5. payment_terms 输出数组;6. 只输出 JSON,不要输出解释文字。
需要抽取的字段:- contract_name- contract_no- party_a- party_b- amount- currency- sign_date- effective_date- end_date- payment_terms- termination_clause
合同文本:……
期望输出:
json
{ "contract_name": "设备采购合同", "contract_no": "CG-2024-0018", "party_a": "上海某某科技有限公司", "party_b": "杭州某某设备有限公司", "amount": 580000.00, "currency": "CNY", "sign_date": "2024-03-12", "effective_date": "2024-03-12", "end_date": "2025-03-11", "payment_terms": [ "合同签订后7个工作日内支付合同总金额的30%", "设备验收合格后支付合同总金额的60%", "质保期满后支付合同总金额的10%" ], "termination_clause": "任何一方严重违约,经催告后仍未改正的,守约方有权解除合同。"}
上线时一定要做 JSON 校验。如果模型输出了多余说明或格式错误,需要自动重试或走人工复核。
六、长合同如何处理?
很多合同动辄几十页,直接把全文塞进大模型会遇到两个问题:
- 超出上下文长度;
- 成本较高,且容易引入无关信息。
更合理的方式是按字段选择相关片段。
例如:
- 合同主体、编号、签署日期:通常在首页和末页;
- 金额:通常在合同标的、价款、费用章节;
- 付款条款:通常在“付款方式”“结算方式”章节;
- 解除条款:通常在“合同解除”“违约责任”“终止”章节。
可以先用规则或向量检索找相关片段,再让大模型抽取。
流程如下:
text
全文 OCR ↓章节标题识别 ↓根据字段召回相关段落 ↓分别抽取字段 ↓结果合并
例如抽取付款条款时,只传入包含以下关键词的段落:
text
付款、支付、结算、发票、验收、尾款、质保金
这样可以降低成本,也能提高抽取准确率。
七、金额和日期必须做规则校验
大模型可以理解语义,但不适合完全承担数值校验。合同抽取中,金额和日期是高风险字段,必须加规则校验。
1. 金额校验
合同中经常同时存在中文大写金额和阿拉伯数字:
text
人民币伍拾捌万元整(¥580,000.00)
系统可以用规则提取两种金额,并互相校验。如果模型输出金额为 58,000,就应该触发异常。
校验逻辑示例:
python
if model_amount not in regex_amount_candidates: mark_as_need_review("金额不在原文候选金额中")
2. 日期校验
日期需要统一格式:
text
2024年3月12日 → 2024-03-12二〇二四年三月十二日 → 2024-03-12
同时需要检查:
- 生效日期是否晚于终止日期;
- 签署日期是否为空;
- 合同期限是否合理。
如果出现 end_date < effective_date,就应进入人工复核。
八、表格合同的处理难点
很多采购合同、服务合同包含表格,例如设备清单:
| 序号 | 名称 | 数量 | 单价 | 总价 |
|---|---|---|---|---|
| 1 | 工控机 | 10 | 8000 | 80000 |
| 2 | 显示器 | 10 | 1200 | 12000 |
如果 OCR 只输出纯文本,表格结构可能变成:
text
1 工控机 10 8000 80000 2 显示器 10 1200 12000
这会严重影响抽取。比较好的做法是使用支持版面分析和表格识别的 OCR 工具,将表格转为 Markdown 或 JSON,再交给大模型处理。
例如转成 Markdown:
markdown
| 序号 | 名称 | 数量 | 单价 | 总价 || 1 | 工控机 | 10 | 8000 | 80000 || 2 | 显示器 | 10 | 1200 | 12000 |
大模型对 Markdown 表格的理解通常明显好于混乱文本。
九、人工复核不是失败,而是必要环节
合同属于高价值、强合规场景,不建议完全无人值守。更合理的方案是:
- 低风险字段自动入库;
- 高风险字段人工确认;
- 异常字段强制复核。
例如:
text
合同名称、主体名称:自动抽取 + 人工可修改合同金额、付款节点、终止日期:必须人工确认违约责任、解除条款:AI 摘要 + 法务复核
系统界面最好能展示字段来源位置,例如“该金额来自第 2 页第 3 段”。这样审核人员可以快速定位原文,而不是重新阅读整份合同。
十、效果评估指标
合同抽取效果不能只靠主观感受,需要建立评测集。可以选取 100 到 300 份历史合同,人工标注关键字段,然后计算指标。
常见指标包括:
- 字段准确率:字段值是否完全正确;
- 字段召回率:应该抽到的字段是否被抽出;
- 格式合规率:JSON、日期、金额格式是否符合要求;
- 人工修改率:上线后人工改动字段的比例;
- 高风险字段错误率:金额、日期、主体名称等关键字段错误比例。
例如:
| 字段 | 准确率 |
|---|---|
| 合同编号 | 92% |
| 甲方名称 | 95% |
| 乙方名称 | 94% |
| 合同金额 | 89% |
| 付款条款 | 82% |
| 解除条款 | 78% |
通常来说,主体名称、合同编号这类短字段效果较好,付款条款、违约条款这类长文本字段更依赖模型理解和人工复核。
总结
合同关键信息抽取是一个非常适合 AI 落地的细分场景,但它不是简单的 OCR,也不是简单调用一次大模型。一个稳定可用的方案通常包括:
- OCR 或 PDF 文本解析;
- 版面和表格结构还原;
- 明确字段模板;
- 基于 Prompt 的结构化抽取;
- JSON 格式校验;
- 金额、日期等规则校验;
- 人工复核闭环。
对于企业来说,合同抽取的价值不只是减少录入工作量,更重要的是让合同数据真正进入系统,支撑到期提醒、付款管理、风险审查和经营分析。只有把 OCR、大模型、规则校验和人工审核结合起来,合同智能化才能从演示效果走向真实生产环境。
更多推荐



所有评论(0)