AI PDF 提取表格:合计正确,还要检查有没有漏行
最后更新:
先保留全部记录,再按业务状态汇总。取消项、空值和来源页码,都属于应交付的数据。
先检查 PDF 类型,再决定如何读取
打开文件,尝试选中一段正文,并把包含表头、两行数据和页脚的区域复制到纯文本中。能复制不等于列关系完整,也可能读出错位的列、重复页眉或隐藏的识别文本。先拿一页做样本,检查编号与金额是否仍对应同一条记录,再处理整批。
文字型 PDF 可以先提取文本,再让模型理解字段。扫描页需要另做 OCR 和识别质量检查。本页实际案例使用文字型 PDF,没有验证扫描 OCR。pypdf 官方说明它能提取已有文本,但不是 OCR 工具;PDF 的视觉表格也未必存有可直接读取的行列语义。查阅日期:2026-09-12。pypdf 文本提取说明。
实测输入:四行资料必须都进入来源清单
2026-09-11 的本地测试使用自有虚构物料采购资料,不是客户订单。pypdf 提出的文字包含 A01 至 A04 四条记录;下表是人工对照原文件后的基准,不是把模型结果再交给模型认可。可打开原始 PDF逐项复核。
“取消”只是 A03 的状态,不是删除理由。A04 的数量未填写,也必须保留这一行。把所有可见业务记录纳入来源清单后,才能区分“原文件不存在”“识别不到”和“模型漏掉”这三种问题。这里四行都在第 1 页;多页资料还应记录表名、行号或能定位的短摘录。

| 编号 / 第 1 页 | 物料 | 数量 × 单价 | 状态 | 汇总处理 |
|---|---|---|---|---|
| A01 | 画纸套装 | 12 × 20 元 | 有效 | 计入 240 元 |
| A02 | 画笔套装 | 3 × 50 元 | 有效 | 计入 150 元 |
| A03 | 收纳袋 | 2 × 30 元 | 取消 | 保留记录,不计入有效合计 |
| A04 | 展示架 | null × 80 元 | 待确认 | 保留空值,等待确认 |
实测结果:三个字段准确的记录,仍不是完整表格
同批 GPT-5.5 结构化结果只返回 A01、A02、A04 三条 records。已返回记录的品名、数量、单价和状态与基准一致;程序对有效记录复算得到 240 + 150 = 390 元。但 A03 没有进入 records,完整性判定为 FAIL。可下载当次抽取 CSV,它保留这个失败,没有事后补成四行成功文件。
模型在汇报要点里提到了 A03,也不能抵消结构化表格中的缺失。后续程序消费 records,不会自动从另一段文字恢复取消项。这个样例说明:字段准确率、业务合计、记录覆盖是三个独立检查。只验金额,就会让恰好不参与求和的漏行通过。
抽取提示词要明确:筛选发生在完整抽取之后
输入按文件和页分块,每块保留表头、单位、来源标签及必要上下文。跨页表格把续表与原表关联,不能把重复表头识别成数据,也不能在分页处丢掉一半记录。对没有稳定编号的资料,先人工定义来源行标识,再安排抽取。
下面是针对本次漏行改写的教学提示词,尚未重新发起模型验证。它将完整性要求直接写进 records 契约,但提示词本身不是检查器。先保存原始响应,再解析和校验;遇到无法解析或缺字段时,把该页记为失败,不输出看似完整的空表。
只处理标有 source_file 和 source_page 的输入资料。
提取所有业务行,包括有效、取消、待确认;不要先按状态筛选。
每行输出 id、item、quantity、unit_price_cny、status、source_file、source_page、source_excerpt。
缺失数量为 null,不用 0 或平均值补齐。
无法判断的字段写入 issues,包含记录编号、原文和原因。
records 中必须保留取消行,即使它不参与后续合计。
不自行生成最终金额;金额由单独的程序计算。
输出 records 和 issues,所有结果进入待审核状态。先比编号集合,再检查重复、字段与金额
记录数相同也不一定完整:漏掉一行再重复一行,数量仍会相等。因此同时比较缺失编号、意外编号与重复编号。下面用真实样例的编号集合复现检查,运行后 missing 为 A03,complete 为 false。基准必须来自原文件盘点,不能从模型输出反向生成。
实际业务还应逐字段比较人工抽样结果,检查空值是否被填零、千元是否被当元、括号负数是否丢了负号。模型给出的“置信度很高”只能帮助安排人工检查顺序,不能跳过金额与记录覆盖的硬检查。
const expected = ["A01", "A02", "A03", "A04"];
const actual = ["A01", "A02", "A04"];
const missing = expected.filter(id => !actual.includes(id));
const unexpected = actual.filter(id => !expected.includes(id));
const duplicates = actual.filter((id, i) => actual.indexOf(id) !== i);
const complete = !missing.length && !unexpected.length && !duplicates.length;
console.log(JSON.stringify({ missing, unexpected, duplicates, complete }));修复漏行要有修订记录,不覆盖原始失败
发现 A03 缺失后,先定位第 1 页的原文,确认编号、数量 2、单价 30 元和取消状态。人工修订时另存 reviewed 版本,保留修改人、修改时间、原值和新值;如果重新请求模型,只重做受影响页,仍以原文逐行检查。不能因为修订后凑齐四行,就抹掉前一版的失败记录。
A04 的 null 不属于抽取错误,原文件确实没有数量。它需要业务资料补充,不应通过反复提问让模型猜数。修订版可以交付“有效合计 390 元,A04 待确认”,但只有 A03 已确实回补并核验后,才可把记录覆盖状态改为通过。本页下载 CSV 仍是当次三行输出。

批量处理以文件和页为单位恢复
先做输入清单:文件标识、内容哈希、总页数、预计表格、处理状态。保留只读原文件,输出放到不同目录。内容相同但改了文件名的资料可识别为重复输入;文件同名但内容改变,则应形成新版本,不能沿用旧结果。
逐页记录 parsed、extracted、validated、reviewed 等阶段。某页失败只恢复这一页,最后核对输入页数与处理清单是否对得上。跨页重复记录用业务编号加来源判断,不能只按金额相同去重。导出 CSV 时正确引用含逗号与换行的单元格;编号、前导零和以等号开头的来源文本,应在表格导入时指定合适的文本类型并检查显示。
交付一套可复核资料,而不只是一个表格
最小交付包含原文索引、完整记录表、异常表、独立复算结果与审核状态。接收人应能从某一行回到具体文件和位置,并知道哪些值经过人工修订。需要继续做汇报时,把同一异常清单传给文档转 PPT 流程,不能在排版环节隐藏它。
收益按每批净节省时间评估:原手工整理时间减去解析操作、校验、返工和人工确认时间。本页没有客户节省工时或完整通过率数据。调用成本查看实时价格,把失败尝试与复核成本一起记录。扩大批量的前提是异常可定位、失败可恢复,而不是第一份 CSV 能下载。
常见问题
取消记录不参与合计,为什么还必须抽取?
抽取负责保留原文记录,汇总负责按状态筛选。取消项仍可影响核对、版本追踪与解释;提前丢弃它会造成不可见的漏行。
390 元正确,为什么本次仍判失败?
两条有效记录的计算正确,但四条原始记录只返回三条,缺 A03。金额检查通过与完整性失败可以同时成立。
扫描件可以直接照着做吗?
先补上 OCR 与识别质量检查。本页实跑的是文字型 PDF,不能用这次结果证明扫描页、手写字或复杂跨页表格已通过。
下载的 CSV 已经修好了吗?
没有。下载文件保留当次三行结构化结果,目的是让读者复核真实漏行。人工修订应另存带审核记录的新版本。
没有记录编号时怎么查漏行?
用文件、页、表格和人工标定的行位置构成来源标识,再检查覆盖;业务编号缺失时,不应仅靠行数或合计判定完整。