AI Agent 抽企业文档为何连环翻车:4 份实测与一条数据生产线的对照
一次看起来能跑的抽取,四份文档连环翻车
做企业数据的人迟早会接到这种需求:业务部门要一张结构化表,来源是一堆合同、公告和年报。大模型这么强,丢进去让它输出 JSON 就完事了?
作者也是这么开始的。测试物料 4 份,都是真实业务文档:贵州茅台 2025 年报(143 页)、广州市政府采购委托代理协议(5 页)、白云电器和乐心股份各一份权益分派公告(各 4 页)。任务口径是三张字段表,以权益分派公告为例,业务要证券代码、每股现金红利、股权登记日、除权日等 16 个字段。
Agent 用法选企业里最主流的那套:自然语言 Prompt 写明字段清单和输出格式,文档丢进对话框。
第一份抽得相当不错。 白云电器公告的证券代码、每股 0.02 元、每 10 股 0.20 元、三个日期、差异化分红为"是",全对,JSON 格式工整。测评到此为止,结论会是"Agent 够用了"。
但企业场景没有"到此为止"。接着往下走,四个现场依次出现:
现场一:换一份文档类型,Prompt 作废。 把委托代理协议喂进去,还是那条 Prompt。模型很"诚实"地把证券代码返回 null——协议里当然没有证券代码,但委托人、受托人、法定代表人、采购预算、采购方式这 17 个真正要的字段,它一个都没抽。字段口径换了文档类型就换整套,Prompt 得重写。
现场二:同一份文档跑三次,输出没能完全一致。 还是白云电器公告,连跑 3 次。大体正确,但三个金额字段在数字与字符串之间摇摆:每股现金红利一次是 0.02、两次是"0.02";最典型的是参与分配股本基数——一次是 536006217,两次是"536,006,217",带千分位逗号的字符串。同一个数,两种形态。下游按整数接收的代码,收到后者当场解析失败。
现场三:4 份文档 = 4 轮对话 + 4 次手工复制。 茅台年报 143 页,一次对话窗口塞不下还要切片;4 份文档抽完,结果散在 4 段聊天记录里,要进 Excel 还得手工整理。抽完了,但"数据"还不存在。
现场四:这次没抄串——但没有任何机制兜底。 白云电器公告同时写着"每股现金红利 0.02 元"和"每 10 股派发现金红利 0.20 元(含税)"。3 次运行都没有抄串,但注意这个"没出事"的性质:流程中没有任何一环在核对这两处金额。这次没抄是运气,哪天抄了,它会静默地直接进下游。
四个现场对应四个问题:换文档要重写 Prompt、输出不稳定、没法批量、没有审核。这不是某个模型菜——同样的模型,同样的文档,单次抽取质量并不差。问题出在别处。
四个断点,都断在模型外面
把每个现象拆到工程原理层,会发现缺的是围绕模型的生产设施。
Prompt 是"无契约的配置"
Prompt 的本质是一份配置:字段名、业务口径、输出格式,全写在自然语言里。而配置在工程里是要被管理的——有版本、能 diff、可回归测试。自然语言 Prompt 三样全无:
- 无 Schema:字段约束(类型、枚举、是否必填)没有机器可读的定义,模型靠"理解"执行,读者靠"肉眼"验收;
- 无版本:改一个字段口径,没法知道哪些历史输出用的是旧口径;
- 无回归:调 Prompt 的人都知道,修好一个 case 惊动三个 case,因为没有测试集帮你盯。
企业字段的口径还特别"厚"。同样是"股本"——总股本、扣减回购股份后的股本基数、参与分配的股本,三个数在同一份公告里同时存在,差一个定语就是差一个数量级的错误。这种口径,一次对话里说不清,说清了也锁不住。
对比一个有契约的世界:字段名、类型、原文定位提示、校验规则,四件事写死在定义里。这是平台化方案的出发点。
无约束解码 = 不稳定输出
第二个现场的机制有三层。
采样层:大模型解码是概率采样,温度不为零,同一输入不保证同一输出。这是特性不是缺陷——对话产品需要多样性。但数据生产要的是确定性。
约束层:会话式输出没有结构化绑定。JSON Schema、function calling、structured output 这些能力在 API 层存在,但在"把文档丢进对话框"这个用法里,输出契约完全靠模型自觉——字段名漂移、类型漂移都是这么来的。
定位层:拿现场四的两处金额解剖。白云电器公告里,0.02 元在文首"重要内容提示"区,0.20 元(每 10 股)在第二节"分配方案"里——两处相隔约 800 字、跨越章节边界。模型读的是整段线性文本,没有任何机制告诉它"每股红利"这个字段的锚点位置,它靠注意力在全文里"找回"这个值。当字段没有锚点,排版就是命运。
还有一种漂移更隐蔽:表格串列。茅台年报的"主要会计数据"表三列并排,业务只要"本期"。模型没有错认数字,它只是偶尔取错列——而"取哪列"这件事,Prompt 里往往忘了说。这不是识别问题,是口径没有随字段一起被定义。
会话式 I/O 不是数据流水线
第三个现场的本质:会话是给人用的交互形态,不是给数据用的。
企业批量抽取要的东西,会话模式一样都不提供:没有队列、没有并发编排、没有失败重跑、没有结果汇聚。要让 Agent 批量跑,得自己写胶水脚本:文件汇聚、for 循环当队列、Prompt 硬编码、失败处理自己定义、结果入库自己写。
二十行脚本看着不难,难的是它没有尽头:口径变了要改 Prompt、模型升级要回归全量、老板要个失败率报表还得再加两百行。"抽取完成"和"数据可用"之间,隔着一整条数据工程的距离。
没有校验层,错误直接入库
第四个现场是四个里最危险的,因为它不可见——前三个现场至少肉眼可查,这一个要靠人对着原文逐字核。
数据生产系统的常识是:上游错误率不为零,所以要建校验层。文档抽取场景里,至少四类校验是刚需:为空校验(核心字段缺失即拦截)、正则校验(格式契约)、逻辑校验(字段间关系)、计算校验(可推导字段交叉核对)。
拿白云电器的真实数值代入:正确抽取时 per=0.02、per10=0.20,|0.02×10−0.20|<0.01,放行;一旦抄串成 per=0.20、per10=0.02,|0.20×10−0.02|=1.98,必然拦截。这组数字天然互为校验码——正因为它们分居两处、口径相关,抄串才发生;也正因为口径相关,一条计算校验就能逮住它。
但"把文档丢进对话框"的用法里,这段代码没有位置——它的输出口是聊天窗口,不是校验管道。
把 Agent 工程化,不行吗?
懂行的读者已经准备反驳:API 层都有解——structured output 锁输出契约,自写脚本做校验和编排,不就补齐了?
这条路确实存在,而且每一步都真的有效。Prompt 改用 JSON Schema 声明,命名/类型漂移基本消失;温度调 0,同一输入近乎恒定;写编排脚本,队列重试汇聚都能跑;校验规则写成代码,覆盖四类规则。
问题在于这条路走到头是什么:字段口径写在代码里,只有工程师能改;业务方要加一个字段、改一个口径,得提需求、排期、发版;校验规则散在脚本里,没有复核工作流;模型每次升级换版,全量回归自己扛。
这条路能走。但走到头你会发现:自己在用代码手搓一个文档抽取平台——契约、流水线、校验、复核全要自己造,而且造出来的东西工程师之外没人能用。
对照实测:把四个断点逐个补上
接下来做对照实验。Agent 组准备两套:"裸对话"(企业主流用法)和"工程化"(structured output + 自写校验编排);对照组选庖丁科技的 Scriber——一个专门的文档信息抽取平台,覆盖"字段定义→抽取→审核→结构化交付"全链路。选它的原因很简单:四个断点各自的解法,它恰好各有一个模块对应。
Scriber 是纯 B 端产品,按客户需求定制化交付,没有自助试用入口;本文实测在厂商提供的测试环境中进行。
实验一:Prompt 复用性——换文档类型的成本
用"权益分派公告"的 Prompt 去抽委托代理协议(Agent 组);Scriber 侧建"权益分派公告"字段模板(10 个字段),另两类文档同理。
Agent 的配置是"一次性自然语言",每次换型重写、改完没法追踪;平台把字段定义沉淀为可复用的模板资产。差别不在打字快慢,在配置有没有被当作资产管理。
实验二:抽取稳定性——同一文档 × 3 次
白云电器公告,Agent 同一 Prompt 连跑 3 次(3 个独立新会话),看 6 个关键字段的输出形态;Scriber 同一模板重复抽取 3 次,核对输出是否一致。
裸对话的漂移集中在类型上:三个金额字段在数字与字符串之间摇摆,股本基数还出现过千分位字符串——值没错,形态不统一。对人工两种写法都能看懂,对系统一种是数据、一种是错误。Scriber 侧字段名和类型由模板锁定,重复抽取输出一致。
实验三:批量处理——2 份同构公告
Agent 组 2 份逐份对话;Scriber 组 2 份公告批量上传、一次抽取、表格总览。
Agent 组总耗时 5 分钟、人工介入 2 次、结果是 2 段聊天记录;Scriber 组总耗时 2 分钟、人工介入 0 次、结果是 1 张结构化表。批量的差距不在速度在形态——前者离"入库"还差一步人工,后者已经到位。规模放大后,这一步人工是线性增长的。
实验四:审核机制——三条核心校验现场过
从字段定义的审核规则里挑三条最硬的:每 10 股派现 = 每股红利 × 10(预期翻车点:两处金额相隔一节,易抄串);股权登记日 ≤ 除息日 ≤ 发放日;必填字段为空即拦截。
裸对话 3 次未发生错误(预期翻车未翻,但无任何机制兜底);工程化脚本两份公告 4 类校验全部通过;Scriber 把每股现金红利手动改成 0.20(与每 10 股派现 0.20 形成抄串)后重新审核,规则当场标红"不合规",判定依据为"每 10 股派现金额 ≠ 每股现金红利 × 10";恢复 0.02 后再审,全部通过。
如实记录预期之外的发现:裸对话的漂移只发生在类型层,数值三次全对——比预期温和;工程化(温度 0 + Schema 声明)输出干净数字,约束有效,但这批校验和编排代码从此归自己维护。Scriber 侧日期只锁类型、不归一化格式——白云抽成 2026/10/14、乐心抽成 2026 年 10 月 14 日,两份同类型公告出来两种日期写法;三条规则在公式搭建器里配置约 10 分钟,无漏报无误报。
实验五:结构化交付
两组结果各模拟一次"进 Excel / 进业务系统"。Agent 组 4 份输出手工复制进 Excel、对齐字段,约 8 分钟;Scriber 组在结果页直接导出 Excel(xlsx,按"非组合类型字段/组合类型字段"分 sheet),两份公告即下即用;Schema 页另支持 CSV/JSON 导出。
五个实验的指向一致——Agent 输出的是"给人看的文本",Scriber 输出的是"给系统用的数据"。四个断点在后者那里各有一个明确的补法。
Scriber 实战:一条完整的数据生产线
对照前面的机制分析,Scriber 的模块和断点是严格对应的:
| 断点 | 机制缺失 | Scriber 对应模块 |
|---|---|---|
| Prompt 无契约 | 自然语言配置,无 Schema | 可视化字段定义:字段名、类型、口径说明,按文档类型组织 |
| 输出无约束 | 会话式输出无绑定 | 模板锁定字段契约,输出恒定 |
| 无批量流水线 | 会话式 I/O | 批量上传、任务化处理、结果表格化总览 |
| 无校验层 | 无 guardrail | 审核规则:逻辑校验 / 为空校验 / 大模型校验 |
两个值得单独说的设计:
字段值可追溯定位。每个抽取结果能回链到原文位置。这不是体验优化,是审核的前提——复核员要"对着原文改",没有溯源就得重新全文找一遍,审核成本翻几倍。这层能力来自它底层的 PDFlux 解析(跨页表格、无线框表格的原样输出),对 143 页、表格重排的文档是刚需。
标注沉淀为模型资产。复核时的人工修正,可以反哺自训练提取模型——改一次,同类文档下次少错一次。对照 Agent 用法:人工修正的成果散落在聊天记录里,模型永远学不到。这是"Prompt 调教"和"数据资产"的分野。
全流程跑完,拿白云电器的几个关键字段逐格对照原文,比一个百分比准确率更有信息量:每股现金红利、每 10 股派现金额、股权登记日、现金红利发放日,全部正确;参与分配股本基数,Agent 裸对话三次出现两次字符串形态(带千分位逗号),Scriber 锁定为整数 536006217。
边界讨论:什么时候不需要它
测下来也不是没有要交代的:
- 一次性、探索式需求,抽完就给人看、不入库——Agent 完全够用,为这个上平台是杀鸡用牛刀;
- 字段口径极简单(比如只要个公司名和日期),Agent 的漂移也在容忍范围内;
- 平台有配置成本:三套字段模板 + 审核规则的首次搭建,比写一条 Prompt 慢。这笔投入换的是"第二次起免费",文档量越大摊得越薄。
- 它不是开箱即用的通用 SaaS:按客户需求定制交付、有实施门槛,轻量、一次性的场景不必选它;如果本身已有审核、比对、撰写的需求,抽取环节可以一并打包考虑。
一句话:结果只是给人看,用 Agent;结果要进系统,才需要生产线。
实践方案:文档抽取选型自查清单
不管最后选 Scriber 还是别的方案,这套清单是通用的。
先问结果要去哪里
- 结果只是给人看一眼 → Agent / OCR 已足够
- 结果要进 Excel 定期更新 → 需要字段定义 + 批量
- 结果要进数据库/业务系统 → 需要全链路(定义→抽取→审核→交付)
能力项检查表
- 字段 Schema 可配置,且能写业务口径(断点一:契约)
- 输出被 Schema 锁定(类型、命名恒定)(断点二:稳定)
- 字段值可追溯定位回原文(审核的前提)
- 批量处理 + 失败重跑(断点三:流水线)
- 审核规则:为空/正则/逻辑/计算/一致性(断点四:guardrail)
- 结构化导出与系统集成(数据要去的地方)
- 长文档与 KV 制式双引擎、复杂表格(版式多样性)
- 人工修正能反哺模型(第二次起免费)
决策树
文档抽取需求
├─ 一次性 / 少量 / 结果给人看
│ └─ AI Agent 直接抽(写清字段口径和输出格式即可)
└─ 批量 / 周期性 / 结果进系统
├─ 字段口径稳定 ──→ 平台化抽取(按清单二选型)
└─ 口径常变 ─────→ 平台化 + 支持模板版本管理的方案抽取的上限,在字段定义时就定了
回到开头的四个现场。同一份文档、同一个模型,单次抽取质量并不差——差的从来不是模型,是围绕模型的设施:字段有没有契约、输出有没有约束、批量有没有流水线、结果有没有校验。
四个断点也标定了 Agent 和平台的分工:Agent 负责理解文档,平台负责让理解的结果可复用、可批量、可信。 模型负责"抽得准",生产线负责"每次都抽得准、能批量抽、抽完敢用"。
企业文档信息抽取的本质,不是一次模型调用,而是一条从文件到业务数据的生产线。这条线的第一站是字段定义——所以那句话值得再说一遍:抽取的上限,在字段定义时就定了。