合同关键字段识别需分三阶段:先用ocr+布局分析实现结构化预处理,再以规则引导的小模型精准定位字段并抽取值,最后通过格式校验、互斥检查和空缺补偿进行业务逻辑兜底。

用python做合同关键字段识别,核心不是堆模型,而是分阶段设计:先精准定位字段位置,再提取对应文本内容。端到端大模型(如直接扔整份pdf进LLM)在实际合同场景中容易漏项、错位、混淆条款层级——尤其面对扫描件、多栏排版、盖章遮挡等情况。
一、结构化预处理:让非结构文本“可定位”
合同识别的成败,一半取决于前期是否把原始材料变成机器能“看懂”的结构化输入。
- OCR+布局分析双驱动:不用通用OCR(如Tesseract默认模式),改用支持版面检测的方案(如PaddleOCR的layout分析模块、DocTR或LayoutParser)。它能区分标题、表格、段落、印章、页眉页脚,输出带坐标和类型的区块列表。
- 字段锚点建模:不依赖关键词全文搜索。例如“甲方”字段,优先找左侧对齐、字体加粗、后接冒号或全角空格的文本块;“签约日期”则匹配“年|月|日”正则+附近含“签订”“签署”“本合同自……起生效”的上下文区块。
- 表格专项处理:合同中金额、产品清单、违约责任常藏于表格。用opencv或pdfplumber先检测表格线框,再按行列切分单元格,对每个单元格单独OCR+语义判断(如某列含“¥”“元”“小写”字样,即为金额列)。
二、轻量级字段定位模型:用规则+小模型协同
大模型做字段识别性价比低。推荐“规则引导 + 小型序列模型”组合,兼顾精度与部署成本。
- 字段位置分类器:把OCR后的每个文本块表示为[坐标、字体大小、是否加粗、行高比、前后词性、与已知锚点距离]等15维特征,用XGBoost或LightGBM训练二分类模型,判断该块是否为“乙方名称”“合同编号”等目标字段的标签行(而非值本身)。
- 值抽取采用指针网络:定位到标签行后,从其右侧/下一行连续文本中,用BiLSTM-CRF或TinyBERT微调模型预测“值起始-结束”位置(pointer network结构),避免NER的OOV和嵌套问题。例如“开户银行:中国XX银行股份有限公司深圳XX支行”,模型只标出“中国XX银行……支行”这一段。
- 动态上下文窗口:不同字段查找范围不同。“合同编号”通常紧邻标题,窗口设为±2行;“争议解决”条款可能跨页,需结合章节标题(如“第十二条”)做全局检索。
三、后处理校验:用业务逻辑兜底
模型会出错,但合同字段有强业务约束,可设计轻量校验层拦截明显错误。
立即学习“Python免费学习笔记(深入)”;
- 格式强制校验:身份证号必须18位含X,银行账号长度16–19位且全数字,日期必须符合yyYY年MM月DD日格式并真实存在(如2025年2月30日直接剔除)。
- 字段互斥检查:若同时抽到“固定总价”和“单价×数量”两种计价方式,触发人工复核;“甲方签字”和“乙方签字”在同一页面但Y坐标差<5mm,大概率是扫描重影,舍弃其一。
- 空缺补偿策略:未识别出“签约地点”,自动回退取“甲方地址”所在城市;“生效日期”为空时,取“签署日期”或“加盖公章日期”(从印章OCR结果中提取时间戳)。
基本上就这些。不复杂但容易忽略的是:别一上来就调LLM API,先把PDF怎么变坐标、坐标怎么变特征、特征怎么喂模型这三步理清楚。字段识别的本质是空间推理+语义对齐,不是纯文本问答。