文章
金融合同解析与交易日历规则引擎实践
金融合同解析不能只看字段是否抽出,还要处理分档表、隐含条件、开放日规则、节假日顺延和字段级评测,适合做合同抽取和金融文档自动化的人参考。
金融合同解析与交易日历规则引擎,是把资管合同里的费用、业绩报酬和申赎开放条款抽成标准规则,再生成逐日开放状态的一套工程系统。它的难点不在「让模型读懂合同」,而在让输出能被业务系统接住。
我之前做过一版合同抽取文章,重点讲评测。这次的素材更完整,也更接近真实问题:合同抽取如果只停在字段 JSON,后面还是会出错。因为真正进入生产的不是 JSON,而是标准规则、交易日历、缓存、人工复核和每一次版本改动后的回归判断。
合同里最危险的,经常不是没写清楚的部分
头部券商资管业务里的合同通常是十万字量级。费用、业绩报酬、申购赎回开放日、确认方式、封闭期、锁定期散落在正文、附件和表格里。业务最后要的不是一段摘要,而是一组能落到系统里的规则。
一个很典型的坑是业绩报酬分档。
合同可以写成:「8% 到 15% 收取 5% 的超额收益,15% 以上收取 10%」。这句话没有明说「8% 以下收取 0%」,但业务规则里必须有这一档。第一版系统准确率低的时候,这类隐含条件经常漏掉;有的版本又会反过来,把分档门槛过度推断到不该填的触发字段里。
这不是简单的「模型不够聪明」。它暴露的是另一个问题:合同抽取的输出必须被放进字段定义、标准规则和评测框架里看,不能只看模型有没有吐出一段看起来像答案的 JSON。
一个 prompt 装不下这类业务
我最后没有把所有字段塞进一个大 prompt。合同解析侧被拆成 5 个模块:费用、业绩报酬、申购流动性、赎回流动性和其他。费用、业绩报酬、申购流动性这几个重点模块会各跑两套不同风格的 prompt,单个 case 最多并发 8 路 LLM 调用。
这样做的原因很现实。单提示词便宜,但分档表和数字规则容易漏。双提示词成本更高,实测比单提示词约 +3pp。这个数字不算夸张,甚至有点朴素,但在合同抽取这种场景里,关键字段多进一次复核范围,比省一点 token 更重要。
双提示词也不是万能药。它只是让候选变多,后面还要有融合和清洗。
清洗层做的是更脏、更工程化的工作:把 T+2、T+2日、N+2 归一到同一个枚举,把「顺延」映射成 sy,把「工作日」映射成 gzr,把「千分之五」「百分之二十五」「正收益」转成数值语义。模型负责把候选找出来,代码负责把候选拉回业务系统能接受的形状。
我越来越觉得,合同抽取里最容易被低估的不是 prompt,而是这层无聊的确定性清洗。它没那么酷,但它决定结果能不能落库。
开放日规则不是日期抽取
开放日看起来像日期问题,其实是规则问题。
合同里有一种表达是:「每年 9 月第三个周五下一周的周二及此后两个工作日,遇非工作日顺延」。这句话要变成系统能跑的规则,至少要拆出周期类型、月份、周序、星期、工作日偏移和假期处理方式。
日历引擎支持 9 种周期类型,包括每月第 X 日、每季第 X 日、每周周 N、每月第 M 周周 N、按月倒数第 X 日、按季倒数第 X 日、每年 Y 月第 X 日、每年 Y 月第 M 周周 N、每年 Y 月倒数第 X 日。openDay=32 这种值还要解释成「当月最后一日」,按月份动态换成 28、29、30 或 31。
这里我做了一个拆分:所有周期先按自然日取号,不急着判断是不是交易日;再与交易日历取交集,或者进入假期对齐;落在休市日的候选,再按顺延、提前或不操作处理。
这个拆分有个好处:9 种周期只需要各自解决「怎么取号」,假期对齐全局只写一套。
顺延和提前要对称,不然节后会挤成一天
假期对齐里有个小细节,很容易被忽略。
如果同一个连续休市块里有多个候选开放日,不能把它们都顺延到节后第一个交易日。这样会把几个开放日压扁成一天,业务上是不对的。
我的处理方式是先识别最大连续休市块,再对同一休市块里的候选日按日期升序编号。顺延时,第 1 个候选取假期后第 1 个交易日,第 2 个候选取假期后第 2 个交易日;提前时方向相反,取假期前第 i 个交易日。
这个逻辑看起来像小修小补,但它影响的是交易日历上每天能不能申赎。合同解析如果只抽出「顺延」两个字,后面没有这套日历逻辑,仍然不能用。
我还给假期前后游走设了 400 天上界。极端边界下找不到交易日,就丢弃候选,而不是硬画一个日期。这个取舍偏保守,但金融规则里,画错通常比漏出异常更糟。
EDD 的价值不是分数,是告诉你该怪谁
第一版功能准确率低,映射标准规则经常出 bug。后来补 EDD 评测之后,问题才开始变得可讨论。
评测不是只跑一个总分。它有 L0-single、L1-dual、L2-dual-chunk 三档消融,逐级只改变一个变量;也会做 expected null 和 spurious 输出校验,专门抓「合同没写,模型却补了一个值」这种问题。
更有用的是多模型一致性归因。同一个字段错了,如果几个模型都错成同一个非空值,问题可能在 prompt 或金标定义;如果只有某个模型错,可能是模型差异;如果上下文没有被召回,那该改分块或定位,不该继续往 prompt 里塞规则。
这个机制让团队从「我感觉新 prompt 好一点」变成「这一版在哪些字段变好,哪些字段回归,错误更像模型问题还是规则定义问题」。
结果和边界
这套系统把合同处理耗时从数小时缩短到约 2 分钟,字段级结果从 60% 多提升到 90% 左右。更重要的是,它把合同自然语言条款变成了标准规则,再由交易日历引擎生成逐日开放状态。
但我不会把它写成完全自动化。高风险字段、冲突字段、隐含条件和业务定义未完全收口的字段,仍然需要人工复核。金融合同自动化最有价值的地方,不是把人拿掉,而是把人从「从头读十万字」挪到「检查系统给出的候选、证据和冲突」。
如果现在重新做,我会更早把 EDD 放进第一版,而不是等准确率低到影响标准规则映射时再补。合同抽取这种项目,早一点承认模型会错,反而能更快做出能用的系统。
相关链接
如果你正在做合同抽取、文档解析、交易日历规则或金融场景的大模型应用,可以通过页面下方微信二维码或邮件沟通,邮箱:contact@aildnc.com。