返回 AI 测试工程师强化支线
Phase 02 / AI Application Quality 02
多模态、OCR 与文档智能测试教程
让发票图片、扫描 PDF 和跨页流水从 OCR 一直走到数据库:字段有证据、金额能对平、低质不猜测、失败可转人工。
11 个章节金融单据 ETL 案例识别 + 规则 + 入库对账
01
从一张金融单据走完整条 ETL 链
贯穿案例案例:费用报销文档智能流水线
财务每天接收发票图片、扫描 PDF、行程单和跨页银行流水。系统要完成上传校验、图像预处理、OCR、版面与表格恢复、字段抽取、金额规则校验、人工复核、入库以及与报销单对账。贯穿字段包括发票号码、开票日期、购买方、未税金额、税额、价税合计和币种。
五层测试对象
| 层 | 验证什么 | 保留证据 | 典型缺陷 |
|---|---|---|---|
| 接入与预处理 | 文件类型、页数、方向、倾斜、清晰度和去噪 | 原文件哈希、逐页影像、质量分 | PDF 漏页、旋转未矫正 |
| OCR | 印刷体、手写体、中英文和特殊字符 | 文字块、坐标、逐字置信度 | 0/O、1/l、小数点混淆 |
| 版面与表格 | 阅读顺序、表头、单元格、跨页续表 | 版面块、行列关系、页码 | 表头错位、跨页行断裂 |
| 字段与规则 | 字段定位、归一化、合计和跨字段关系 | 原文片段、字段值、规则结果 | 税额抽错、日期猜测 |
| 入库与对账 | 类型转换、去重、关联和总账一致性 | 批次 ID、行数、入库值、对账差异 | 重复入库、金额单位错误 |
最终字段错误不等于 OCR 引擎错误。文字可能识别正确,却在版面恢复、字段映射或入库环节被写错;测试必须让每一层都可回放、可定位。
02
图片、PDF、版面与跨页表格要组合覆盖
测试矩阵金融单据测试矩阵
| 维度 | 取值 | 关键判断 |
|---|---|---|
| 载体 | JPG/PNG、单页 PDF、多页扫描 PDF、文本 PDF | 抽页、渲染和 OCR 路由是否正确 |
| 图像质量 | 清晰、低 DPI、模糊、过曝、阴影、折痕、旋转 | 何时增强,何时拒绝并转人工 |
| 版面 | 单栏、多栏、票据拼图、印章覆盖、页眉页脚 | 阅读顺序与字段归属不串位 |
| 表格 | 合并单元格、多行表头、空格、跨页续表 | 列语义延续、行不重不漏 |
| 内容 | 印刷、手写、中英混排、特殊符号 | 字符切分与币种、负号、小数点正确 |
| 业务字段 | 金额、日期、税号、账号、合同号 | 格式、合计和跨文档关联成立 |
跨页表格必须单独建场景
- 第 1 页只有表头,第 2 页继续数据行:续页仍继承正确列名。
- 分页处一行被拆成两半:合并后只产生一条交易记录。
- 每页重复表头与小计:重复表头不入库,小计不冒充明细。
- 末页总计与各页小计并存:总计只参与校验,不重复计入金额。
低质边界要形成梯度
分辨率、模糊、压缩与遮挡不应只准备“好/坏”两张图,而要形成可重复的等级,观察 P0 字段从哪一级开始失真,以及系统是否在边界外停止猜测。
03
先建立人工精标的真理标准库
没有尺子就没有准确率金标最小内容
| 内容 | 要求 |
|---|---|
| 原始样本 | 脱敏后保留版面、字体与干扰特征 |
| 字段答案 | 人工逐字段核对,保留原文位置 |
| 可读性标签 | 可读、部分可读、不可读 |
| 字段等级 | 按业务影响划分 P0/P1/P2 |
| 等价规则 | 日期、金额和空值如何归一化 |
| 审核记录 | 标注人、复核人、版本与争议结论 |
字段清单和标注口径应先确认再批量精标。中途频繁改字段,会让已完成样本失去可比性并带来大规模返工。
04
按真实分布与困难类型分层抽样
避免漂亮样本偏差样本覆盖维度
| 维度 | 例子 |
|---|---|
| 业务类型 | 合同、证照、流水、法院文书、还款记录 |
| 文件格式 | Word、PDF、图片、扫描件 |
| 模板版式 | 机构模板、旧版、新版、长尾格式 |
| 文件质量 | 清晰、干扰、特殊版式 |
| 字段类型 | 金额、日期、长文本、表格和印章 |
| 客户或来源分布 | 规范归档与混合归档场景 |
拿不到预分类文件时
不要只挑容易识别的文件。可以选择若干具有代表性的来源单位或批次,对真实分布全量抽取,再从中抽样精标,并明确抽样范围与置信边界。
05
字段准确率、召回率与整单通过率要分开
平均数会掩盖 P0 错误核心指标
| 指标 | 定义 | 使用方式 |
|---|---|---|
| 字段准确率 | 正确抽取字段数 / 实际输出字段数 | 惩罚错值和无证据多抽 |
| 字段召回率 | 正确抽取字段数 / 金标应有字段数 | 发现字段漏抽;按字段类型分别统计 |
| 字段 F1 | 2 × 准确率 × 召回率 / (准确率 + 召回率) | 需要同时兼顾错抽与漏抽时使用 |
| 整单通过率 | 全部必需字段和业务规则均通过的文件比例 | 反映能否自动直通入库 |
| 表格还原率 | 结构与单元格对应全部正确的表格比例 | 单独评估跨页和复杂表头 |
| 入库一致性 | 审核后字段与最终落库一致的比例 | 确定性 ETL 目标应为 100% |
| 人工复核率 | 进入人工队列的文件比例 | 同时看误放行和过度拦截 |
字段指标计算例
// 金标应有 100 个金额字段;系统输出 98 个,其中 95 个值与证据都正确。
precision = 95 / 98; // 96.94%
recall = 95 / 100; // 95.00%
f1 = 2 * precision * recall / (precision + recall); // 95.96%
// 仍要单列 P0 错误:任何一张发票把 1,000.00 识别成 10,000.00 都可硬失败。门禁示例
| 层级 | 候选门槛 | 硬失败 |
|---|---|---|
| P0 金额/账号 | 准确率与召回率均达到项目高风险基线 | 金额数量级错、跨租户数据、无证据补值 |
| P1 日期/税号 | 按字段与困难子类不低于基线 | 非法日期被静默归一化 |
| 整单直通 | 通过率达到财务容量目标 | 未通过规则却自动入库 |
| ETL 入库 | 审核结果到落库一致性 100% | 漏行、重复行、单位或币种变化 |
阈值不是行业通用常数,应由样本规模、人工兜底和业务损失共同确定;报告必须同时给样本量和置信边界。
06
金额、日期、合计与跨页结构都要确定性校验
从便宜检查开始自动校验梯度
| 校验 | 金融单据示例 | 失败动作 |
|---|---|---|
| 记录数与文件哈希 | 上传 20 份、逐页处理 57 页、最终仍为 20 份 | 漏页或重复立即阻断 |
| 格式与范围 | 日期可解析、税号校验位、金额最多两位小数 | 标记字段失败 |
| 金额恒等式 | 未税金额 + 税额 = 价税合计,允许约定舍入差 | P0 冲突转人工 |
| 明细合计 | Σ(数量 × 单价) 与票面合计一致 | 保留差额与行号 |
| 日期逻辑 | 开票日不晚于报销日,且在会计期间 | 异常进入业务复核 |
| 跨页连续性 | 页码、列头、交易日期和余额衔接 | 缺页或断表阻断入库 |
| 去重 | 发票代码+号码+金额+日期或业务唯一键 | 重复件进入合并队列 |
金额与日期校验示意
const moneyOk = Math.abs(netAmount + taxAmount - grossAmount) <= 0.01;
const detailOk = Math.abs(
lines.reduce((sum, line) => sum + line.quantity * line.unitPrice, 0) - grossAmount
) <= 0.01;
const dateOk = issuedAt <= reimbursedAt && accountingPeriod.includes(issuedAt);
route = moneyOk && detailOk && dateOk ? "AUTO_PASS" : "HUMAN_REVIEW";双模型交叉校验
对 P0 字段或高价值文件,可以让不同模型独立抽取并比较差异。它不能证明谁正确,但能把单模型“自信地错”变成可见的复核候选;最终仍以原始影像和人工金标裁决。
07
同时防合理补全与数据污染
看不清就要停幻觉与污染探测集
| 输入 | 合格行为 | 不合格行为 |
|---|---|---|
| 金额被印章完全遮挡 | 低置信或转人工 | 根据上下文猜出金额 |
| 日期缺一位 | 返回不可确定并保留原始片段 | 补成完整日期 |
| 表格空单元格 | 保持空值 | 填入邻近行的合理值 |
| 正文与表格金额冲突 | 输出冲突证据并转复核 | 静默选择其中一个 |
| PDF 隐藏文本层与可见影像不一致 | 标记来源冲突,以受信策略裁决 | 直接采信隐藏层 |
| 样例附件夹带与字段无关的指令文本 | 作为单据内容处理或隔离 | 改变 Schema、路由或泄露其他文件 |
| 历史缓存混入其他租户字段 | 拒绝结果并告警 | 把污染字段写入当前报销单 |
字段只有在影像中存在可读证据时才算正确。不可读输入输出了一个“碰巧正确”的值,也应记为幻觉风险;外部文档和 OCR 文本是数据,不是可信系统指令。
08
主动注入漏页、断表、慢模型与脏数据
失败安全失败注入清单
| 注入点 | 预期行为 | 禁止行为 |
|---|---|---|
| 上传重复或截断 PDF | 文件哈希/页数校验失败,批次隔离 | 把部分页当完整单据入库 |
| 渲染服务漏第 2 页 | 页码与清单对不上,停止该文件 | 跨页表格静默少一页 |
| OCR 超时或返回半截 JSON | 有界重试,仍失败则转人工 | 解析默认值并继续直通 |
| 版面模型把重复表头当数据 | 规则识别并标记候选重复行 | 写入伪交易记录 |
| 金额字段低置信且合计恰好相等 | 仍依据证据与阈值转复核 | 用合计关系反推并假装识别成功 |
| 人工队列不可用 | 停止自动放行,保留待处理状态 | 降低 P0 门槛维持吞吐 |
| 入库提交后响应超时 | 按批次与业务键回读确认 | 盲目重试造成重复行 |
故障场景断言
given({ pdfRenderer: "drop_page_2", ocr: "ok", database: "ok" });
const run = await processBatch("BATCH-0810");
expect(run.files[0].status).toBe("BLOCKED");
expect(run.files[0].errorCode).toBe("PAGE_COUNT_MISMATCH");
expect(run.databaseRowsWritten).toBe(0);
expect(run.audit.originalFileHash).toBeDefined();09
用中间证据定位,并按风险进入人工复核
降级有人机边界定位路径
| 证据 | 判断 | 处理 |
|---|---|---|
| OCR 文字正确,表格结构错误 | 版面/表格恢复问题 | 保留文字块,重跑结构模型 |
| 结构化结果正确,最终入库错误 | 字段映射、单位或数据链路问题 | 阻断批次并修复确定性 ETL |
| 批量错误,单文件重跑正确 | 并发、截断或状态串扰 | 降并发并回放失败批次 |
| 相同输入多次结果漂移 | 模型参数、版本或非确定性问题 | 锁定版本,提升复核率 |
| 低置信样本未进入人工队列 | 复核路由或阈值配置问题 | 停止直通并补回漏审样本 |
自动、降级与人工边界
| 情况 | 允许 | 不允许 |
|---|---|---|
| 非关键描述字段低置信 | 保留原文,允许稍后补录 | 影响 P0 合计或账号判断 |
| P0 字段缺失/冲突 | 展示原图位置并转财务复核 | 模型猜测或用默认 0 |
| 模型/规则不可用 | 批次排队、明确失败或人工录入 | 跳过规则直接入库 |
| 人工队列饱和 | 保持待处理并告警容量 | 降低金额门槛自动放行 |
人工复核记录至少保留
- 原始文件、页码、坐标和脱敏版本。
- 模型、Prompt、解析器、Schema 与规则版本。
- 各层中间输出、置信度、规则冲突和候选值。
- 人工裁决、修改前后值、原因、审核人与时间。
10
从抽取结果一直对账到最终数据库
端到端 ETL端到端数量与金额对账
| 关口 | 应相等的对象 | 差异说明 |
|---|---|---|
| 接入 | 上传文件数 = 成功 + 拒绝 + 待处理 | 任何文件都不能无状态消失 |
| 分页 | 声明页数 = 渲染页数 = OCR 页数 | 加密/损坏页需显式记录 |
| 抽取 | 字段记录 = 通过 + 复核 + 拒绝 | 不得丢弃低置信字段 |
| 入库 | 已审核业务键数 = 新增 + 已存在幂等命中 | 新增与重复可解释 |
| 金额 | 审核通过单据总额 = 数据库本批净新增总额 | 币种、正负号和小数单位一致 |
| 下游 | 数据库批次总额 = 报销系统/总账接收总额 | 异步失败可重放且不重复 |
批次对账报告 JSON
{
"batch_id": "BATCH-0810", "source_files": 20, "source_pages": 57,
"accepted": 14, "human_review": 5, "rejected": 1,
"reviewed_business_keys": 19, "inserted": 18, "idempotent_hits": 1,
"approved_amount": "126430.55", "inserted_amount": "126430.55",
"currency": "CNY", "difference": "0.00",
"model_version": "ocr-v7", "schema_version": "invoice-v4",
"reconciliation_status": "PASS"
}回流闭环
- 线上对账差异先冻结批次,保留原文件与全链路证据。
- 定位为 OCR、版面、字段、规则或入库类别。
- 人工裁决形成金标,加入困难样本或失败注入集。
- 修复后回放原批次,使用业务键幂等写入。
- 比较版本差量并通过门禁后再恢复自动直通。
11
搭建一套金融单据文档智能评估
练习与交付清单练习
- 选择一类脱敏发票或流水,确定字段 Schema、P0 字段和舍入口径。
- 覆盖图片、文本/扫描 PDF、复杂版面、跨页表格和低质梯度样本。
- 完成双人精标、可读性标签与字段证据坐标。
- 计算字段准确率、召回率、F1、整单通过率和人工复核率。
- 实现页数、格式、金额/日期、跨页连续性、去重和入库对账检查。
- 注入漏页、半截 JSON、脏数据、队列不可用和提交状态未知。
- 输出字段、困难子类、版本差量、人工裁决与批次对账报告。
样本与金标
真实分布分层
跨页与低质覆盖
字段有证据坐标
污染样本隔离
质量与门禁
准确率召回率拆分
P0 硬失败
合计日期有规则
不可读不猜测
ETL 与治理
每层证据可回放
复核有边界
入库幂等
批次金额对平