在企业数字化系统中,合同管理是一个非常典型但又容易被低估的场景。很多公司虽然已经上线了合同管理系统,但历史合同、供应商合同、扫描件合同仍然大量以 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 校验。如果模型输出了多余说明或格式错误,需要自动重试或走人工复核。


六、长合同如何处理?

很多合同动辄几十页,直接把全文塞进大模型会遇到两个问题:

  1. 超出上下文长度;
  2. 成本较高,且容易引入无关信息。

更合理的方式是按字段选择相关片段。

例如:

  • 合同主体、编号、签署日期:通常在首页和末页;
  • 金额:通常在合同标的、价款、费用章节;
  • 付款条款:通常在“付款方式”“结算方式”章节;
  • 解除条款:通常在“合同解除”“违约责任”“终止”章节。

可以先用规则或向量检索找相关片段,再让大模型抽取。

流程如下:

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,也不是简单调用一次大模型。一个稳定可用的方案通常包括:

  1. OCR 或 PDF 文本解析;
  2. 版面和表格结构还原;
  3. 明确字段模板;
  4. 基于 Prompt 的结构化抽取;
  5. JSON 格式校验;
  6. 金额、日期等规则校验;
  7. 人工复核闭环。

对于企业来说,合同抽取的价值不只是减少录入工作量,更重要的是让合同数据真正进入系统,支撑到期提醒、付款管理、风险审查和经营分析。只有把 OCR、大模型、规则校验和人工审核结合起来,合同智能化才能从演示效果走向真实生产环境。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐