30 KiB
PPT PDF 解析与数据核对页面问题修复报告
日期:2026-07-30
范围:api/insurance/ppt/、api/insurance/generation/celery_tasks.py、frontend/src/pages/PptPage.vue、frontend/src/pages/components/ppt/PptDataReview.vue
结论性质:源码、测试与静态界面审查结论;本次不修改业务代码
1. 执行结论
当前问题不是单纯的“模型不够聪明”或“页面样式不好看”,而是两条链路都存在结构性错误。
1.1 PDF 解析的核心问题
系统当前用“正则识别出至少 3 行利益表数据”作为整份计划书识别成功的主要分流条件。只要表格行数达到阈值,即使产品名称仍为 unknown、被保人年龄仍为空,也不会进入完整 LLM 结构化提取;后续 LLM 仅生成销售分析,不回填关键字段。
这直接解释了“利益表似乎有数据,但年龄和保险名称反而识别不出来”的现象。
同时还存在以下放大因素:
- 上传时已经选择的保司、产品及产品别名没有传入解析器作为先验信息;
- 文本提取采用“第一个可读结果即返回”,没有比较各解析器的字段和表格质量;
- 混合型 PDF 只按整份文档判断是否 OCR,文本页正常但局部扫描页可能完全漏掉;
- Docker OCR 只安装简体中文与英文,香港保险常见繁体中文未覆盖;
- 关键页筛选最多取 10 页、28,000 字符,却要求模型提取“所有页面、所有年度”,目标与输入不一致;
- 正则表格解析依赖理想化换行和列顺序,无法稳定处理多层表头、多页表格和视觉布局复杂的计划书;
- 某些数值会在解析后被代码静默改写,可能把列错位伪装成“合理结果”。
1.2 数据核对页面的核心问题
用户的真实任务不是“编辑一份 JSON”,而是:
用最少时间确认 AI 提取值是否与 PDF 原文一致,并安全地修正少量异常。
现有页面没有 PDF 原文、页图、高亮区域、字段来源或置信度。用户看到的是全部字段和整张可编辑表格,却看不到判断正确与否所需的证据。因此页面虽然叫“核对数据”,实际交互是“人工重新录入数据”。
此外,外层页面已经有步骤栏、上下文栏和底部操作栏,核对组件内部又增加产品栏、问题栏和第二套操作栏,形成“外层三栏套内层三栏”。错误状态还分散在四个位置,并且部分计数永远不同步。用户会持续产生三种不确定感:
- 我现在到底应该先看哪里?
- 我刚才改的值是否已经保存、是否已经通过?
- 系统说的错误到底对应哪个产品、哪一页、哪一个输入框?
2. 调用链与根因链
flowchart TD
A["上传 PDF,并选择险种/保司/产品"] --> B["保存 companyId / productId"]
B --> C["解析任务只传 pdf_path + plan_type"]
C --> D["首个整体可读的文本解析器直接返回"]
D --> E["正则提取产品、年龄、利益表"]
E --> F{"利益表行数 ≥ 3?"}
F -->|是| G["直接采用正则结果"]
G --> H["LLM 只做销售分析,不回填名称/年龄"]
F -->|否| I["选最多 10 个关键页交给 LLM"]
I --> J["校验并可选二次纠错"]
H --> K["partial 数据进入核对页"]
J --> K
K --> L["用户看不到 PDF 证据,只能编辑全量表格"]
关键断点是:
- 上传阶段已有可靠先验,但解析阶段丢弃;
- 分流只看“表格行数”,不看“关键字段完整性”;
- 核对阶段只给结果,不给证据。
3. PDF 解析问题明细
PARSE-P0-01:解析分流条件错误
证据
ExtractionOrchestrator.REGEX_ROW_THRESHOLD = 3:api/insurance/ppt/extraction.py:391- 分支只判断
regex_rows >= 3 and not used_ocr:api/insurance/ppt/extraction.py:468 - 进入该分支后直接使用
regex_data:api/insurance/ppt/extraction.py:470 - LLM 输出只合并到
sales_insights:api/insurance/ppt/extraction.py:480-491 ANALYSIS_SYSTEM_PROMPT明确要求输出keyPoints/gaps/suggestedQuestions,不输出修复后的结构化字段:api/insurance/ppt/prompts.py:64-92
影响
一份 PDF 只要利益表被识别出 3 行,即使:
product_name = "unknown";insured.age = null;- 保额、缴费期、指数账户缺失;
仍会绕过完整 LLM 提取。最终只在末尾被标记为 partial,把解析失败的成本转移给用户人工修正。
修复
将分流条件改成“结构化质量门”,至少同时判断:
- 产品名称可确认;
- 被保人年龄可确认;
- 对应险种的必填保单字段完整;
- 表格字段覆盖率和年度覆盖率达标;
- 表格列关系通过基本一致性校验。
只要关键字段缺失,即使已经识别出很多利益表行,也必须进入“字段补全/冲突校验”流程,而不是销售分析流程。
PARSE-P0-02:上传阶段的产品先验被丢弃
证据
- 上传记录保存
companyId和productId:api/insurance/ppt/routes.py:140-145、169-175 - Celery 任务也读取了这两个字段:
api/insurance/generation/celery_tasks.py:142-147 - 实际调用解析器时只传
filepath和plan_type:api/insurance/generation/celery_tasks.py:167-172 - 产品表已经维护
display_name和aliases_json:api/insurance/models/ppt_config.py:64-65
影响
用户如果已经明确选择了某个产品,解析器仍然从零猜产品名称。封面文字是图片、艺术字、缩写或 OCR 错字时,系统无法利用产品目录做标准化与纠错。
修复
解析器接收以下上下文:
company_id;product_id;- 产品标准名称;
- 产品别名、英文名、产品代码;
- 险种;
- 可选的产品小册子规则。
解析结果与用户选择冲突时,不应静默覆盖任何一方,而应产生结构化冲突问题供用户确认。
PARSE-P1-01:文本提取只判断“可读”,不判断“适合提取”
证据
- PyMuPDF 第一个通过整体乱码检测就直接返回:
api/insurance/ppt/extraction.py:119-127 - 后续 PyPDF2、pypdf、pdfplumber 只有前一个失败才会尝试:
api/insurance/ppt/extraction.py:135-180 - 乱码检测只按整份文本的可见字符比例判断:
api/insurance/ppt/extraction.py:201-225 - 文本超过 120,000 字符时从尾部直接截断:
api/insurance/ppt/extraction.py:105、127
影响
“能读出文字”不等于“字段和表格顺序正确”。PyMuPDF 可能读出大量正常文本,但:
- 表单标签和值被拆散;
- 表格按绘制顺序而非视觉列顺序输出;
- 封面产品名是图片,没有任何文本;
- 后半部分利益表在 120,000 字符截断后消失。
由于整体文本仍然“可读”,系统不会尝试更适合表格的解析方式或局部 OCR。
修复
改为逐页质量评估,并为每页记录:
- 字符数;
- 可读字符比例;
- 标签命中数;
- 数字密度;
- 表格结构得分;
- 是否需要 OCR;
- 使用的解析器。
不同页允许使用不同策略,不能用整份 PDF 的单一结果决定全部页面。
PARSE-P1-02:关键页筛选与“提取全部数据”的目标冲突
证据
- 完整 LLM 提取最多取 10 页、28,000 字符:
api/insurance/ppt/extraction.py:523-530 - 页面评分只使用少量通用关键词和数字密度:
api/insurance/ppt/prompts.py:147-176 - 字符预算耗尽时直接截断当前页并停止:
api/insurance/ppt/prompts.py:178-187 - Prompt 却要求“扫描所有页面,提取所有保单年度数据”:
api/insurance/ppt/prompts.py:19-23
影响
当计划书包含:
- 多页利益演示;
- 单独的客户资料页;
- 附加险页;
- 繁体字段名;
- 产品名只出现在图形化封面;
模型根本没有看到对应页面,却被要求输出完整结果。模型只能遗漏或猜测。
修复
先识别页面角色,再强制选入:
- 封面/产品身份页;
- 客户或受保人资料页;
- 保单摘要页;
- 所有利益演示表页;
- 所有退保/提取表页;
- 对应险种的专属页面。
利益表不应通过“一次大 JSON”从 100 个年度一起生成;应按页或表块解析,再在后端合并和校验。
PARSE-P1-03:正则规则只覆盖理想化标签和表格
证据
- 产品名称必须依赖
产品名称:、Product Name:、Plan Name:等带标签格式:api/insurance/ppt/regex_extractor.py:38-53 - 年龄规则不覆盖繁体
年齡、Issue Age、Age at Entry、出生日期等常见表达:api/insurance/ppt/regex_extractor.py:94-110 Age:采用整份文档第一次匹配,可能误取其他人的年龄或利益表年龄;- 表格列按换行和数字出现顺序分配,而不是按 PDF 几何坐标:
api/insurance/ppt/regex_extractor.py:266-289、350-397 - 进入第一张表后,连续 5 行非数据就
break整个扫描:api/insurance/ppt/regex_extractor.py:292-347 - 金额解析把合法的
0转为None:api/insurance/ppt/regex_extractor.py:14-27 - 未识别币种时默认
USD:api/insurance/ppt/regex_extractor.py:56-76
影响
- 香港繁体计划书年龄漏识别;
- 产品名以大标题或图片出现时漏识别;
- 多页表格、双层表头、保证/非保证子列容易错位;
- 合法 0 值被当成缺失;
- 未知币种被伪装成已确认的 USD。
修复
- 扩展繁体、英文、缩写和无冒号标签;
- 对年龄引入“受保人上下文窗口”,区分投保人、受保人、保单年度年龄;
- 支持出生日期加投保日期推算,并保留推算标记;
- 基于 PDF 词块坐标和表格边界重建列;
- 支持多页重复表头与表格续页;
0、null、未识别必须保持不同语义;- 未知币种必须返回
null并进入待确认队列。
PARSE-P1-04:OCR 对香港保险 PDF 的适配不足
证据
- OCR 仅在整份文本为空或整体疑似乱码后执行:
api/insurance/ppt/extraction.py:125-186 - 最多 OCR 40 页:
api/insurance/ppt/extraction.py:228-247 - 使用固定
chi_sim+eng:api/insurance/ppt/extraction.py:257-265 - Docker 只安装
tesseract-ocr-chi-sim与英文包:Dockerfile.dify-custom:9-10 - 所有页面固定使用
--psm 6,假设整页为单一文本块。
影响
繁体中文、图形化封面、复杂多栏表单和“部分页面扫描、部分页面可选文字”的混合 PDF 都容易漏识别。
修复
- 安装并启用
chi_tra+chi_sim+eng; - 按页判断是否 OCR,只 OCR 低质量页;
- 表单页、封面页、表格页使用不同版面模式;
- 加入旋转检测、去噪、二值化和 300 DPI 基线;
- OCR 结果必须保留页码、词块坐标和置信度。
PARSE-P1-05:LLM 输出约束不足
证据
- 最大输出固定为 8192 tokens:
api/insurance/ppt/llm_client.py:21-22 - Prompt 可能要求输出 20 至 100 个年度的多列 JSON;
structured_output没有传入正式 JSON Schema,只依赖 Prompt 示例:api/insurance/ppt/extraction.py:527-530- 只在 JSON 无法解析时重试;JSON 合法但字段遗漏时,主要依赖后置完整性检查。
影响
大表格容易被截断、压缩为里程碑年度,或生成合法但不完整的 JSON。模型供应商不同,对同一 Prompt 的字段一致性也会不同。
修复
- 身份字段、保单字段、各类表格分开调用;
- 表格按页/块输出小 JSON,再后端合并;
- 使用正式 JSON Schema;
- 结构化提取温度设为 0;
- 对字段类型、必填项、枚举和数组行建立程序化校验;
- 只对缺失块重试,不重复整份文档。
PARSE-P1-06:静默“修复”可能掩盖解析错位
证据
储蓄险中若 total_surrender_value < guaranteed_cash_value,代码直接把总退保价值改成保证价值、红利和终期红利之和:api/insurance/ppt/extraction.py:572-582。
影响
如果真实原因是列错位或提取错误,系统会修改原始数字,使结果看起来符合业务常识,但不再忠实于 PDF。保险数据场景中,这比显式报错风险更高。
修复
禁止静默覆盖来源数据。应产生:
- 原始值;
- 规则计算值;
- 差异;
- 来源页;
blocking_conflict问题。
只有用户确认后才能采用修正值。
PARSE-P1-07:缺少字段级可观测性和真实回归样本
证据
extraction_stats只写日志,没有保存到 extraction 结果:api/insurance/ppt/extraction.py:459-463、593-602- 解析结果没有字段置信度、来源文本或坐标;
- 当前相关测试能通过 70 项,但主要覆盖理想化文本、少量页面筛选和流程状态;
- 没有发现真实保司 PDF 的金标回归语料。
影响
无法回答以下关键问题:
- 哪个解析器最常失败?
- 哪家保司、哪种模板、哪个字段准确率最低?
- 产品名是正则、产品目录、OCR 还是 LLM 得出的?
- 用户修改最多的字段是什么?
修复
建立脱敏金标 PDF 语料和字段级评估:
- 数字版简体、繁体、英文、双语;
- 扫描版与混合版;
- 多页利益表、多层表头、图形化封面;
- 储蓄险、重疾险、IUL;
- 每次发布输出字段准确率、表格行召回率、数字单元格准确率。
4. 校验接口与前端契约问题
CONTRACT-P0-01:解析失败的产品可能不进入错误列表
证据
校验接口直接跳过 status 不是 success/partial 或没有 data 的 extraction:api/insurance/ppt/routes.py:581-583。
影响
某个产品解析失败时,校验问题列表可能没有对应阻断项。页面的总体错误数可能为 0,“确认生成”可能被错误启用;后续生成接口又只要求至少存在一个有效 extraction:api/insurance/ppt/routes.py:463-469。
修复
每个上传文件必须产生校验结果。解析失败必须返回带产品/文件身份的 blocking issue,除非用户明确移除该文件。
CONTRACT-P1-02:问题没有产品和字段定位信息
证据
- 后端把所有产品的问题汇总成
{field: code, severity, message}:api/insurance/ppt/routes.py:575-599 - 没有
extractionId/productIndex/pdfName/path/rowKey/sourcePage; - 前端只能用产品名称或
[idx]字符串猜测归属:frontend/src/pages/components/ppt/PptDataReview.vue:374-384 - 问题代码是大写枚举,前端却用小写字符串判断标签页:
frontend/src/pages/components/ppt/PptDataReview.vue:392-410
影响
多产品场景下错误徽标可能全部为 0;点击 BENEFIT_ROWS_INCOMPLETE、ANNUAL_PREMIUM_INVALID 等问题时,无法可靠切换到正确产品和字段,也不会聚焦具体输入框。
修复
统一 issue 契约:
{
"id": "stable-id",
"extractionId": "pdf-or-product-id",
"pdfName": "plan.pdf",
"productIndex": 0,
"path": "insured.age",
"section": "fields",
"rowKey": null,
"sourcePage": 2,
"severity": "error",
"state": "unresolved",
"message": "被保险人年龄缺失",
"suggestedAction": "fill_or_confirm"
}
CONTRACT-P1-03:字段数据类型前后端不一致
证据
- 正则和 LLM 将缴费年期输出为
"5年":api/insurance/ppt/regex_extractor.py:131-150、api/insurance/ppt/prompts.py:14 - 前端用
el-input-number绑定该字段:frontend/src/pages/components/ppt/PptDataReview.vue:102-104 - 前端性别选项值是
male/female:frontend/src/pages/components/ppt/PptDataReview.vue:93-97 - 后端正则输出
男/女:api/insurance/ppt/regex_extractor.py:112-128 data.product_type、ext.planType同时存在并可能不一致;- 正则结果固定写
product_type: savings:api/insurance/ppt/regex_extractor.py:659-679
影响
- 缴费年期控件可能无法正常显示字符串;
- 指标可能显示“5年年”或计算失败;
- 已识别性别在下拉框中没有匹配项;
- 页面显示 IUL 标签,但“产品类型”下拉可能显示储蓄险;
- 保存后重新推断险种可能改变原始上传选择。
修复
建立唯一 DTO:
premium_payment_years: number | null;gender: "male" | "female" | "unknown";plan_type只保留一个权威字段;- 展示层自行追加“年”“岁”等单位;
- API 入参出参都做 schema 校验和迁移兼容。
5. 核对页面 UX 问题明细
UX-P1-01:没有原始证据层
证据
PptDataReview只接收sessionId:frontend/src/pages/components/ppt/PptDataReview.vue:305-307- 页面没有 PDF 预览或来源文本;
- “来源页”被设计为可编辑数字:
frontend/src/pages/components/ppt/PptDataReview.vue:183-186、227-230 - PPT 模块没有面向当前用户的源 PDF 预览接口。
第一性原理
核对必须同时看到“系统答案”和“原始证据”。没有证据,用户只能猜、回忆或另开窗口,认知负担和出错率都会上升。
修复
点击任一待确认字段时:
- 展示对应 PDF 页;
- 高亮来源区域;
- 同时显示提取值、原文、置信度、识别方式;
- 支持“接受”“修改”“标记无法确认”;
- 来源页由系统记录,不作为普通业务值自由编辑。
UX-P1-02:外层三栏套内层三栏
证据
- 外层:步骤导航、中央内容、240px 上下文栏:
frontend/src/pages/PptPage.vue:39-132 - 内层:200px 产品栏、编辑器、240px 问题栏:
frontend/src/pages/components/ppt/PptDataReview.vue:25-275 - 外层和内层各有一套底部操作栏:
frontend/src/pages/PptPage.vue:76-83、frontend/src/pages/components/ppt/PptDataReview.vue:277-291
影响
固定区域在进入编辑器前已经占用大量宽度,大表格只能依赖横向滚动。状态、导航和操作同时竞争注意力,用户无法形成稳定视觉路径。
修复
核对步骤进入专注模式:
- 隐藏冗余外层上下文栏;
- 产品切换合并到顶部;
- 主体只保留“PDF 证据 + 当前核对任务”两栏;
- 只保留一套粘底操作栏。
UX-P1-03:校验状态重复且互相矛盾
证据
状态同时出现在:
- 核对组件顶部;
- 核对组件右栏;
- 外层步骤导航;
- 外层上下文栏。
父级 stepErrors/stepWarnings 初始化后没有接收子组件更新:frontend/src/pages/PptPage.vue:197-198。因此外层可能始终显示 0,内层却显示真实错误。
右侧栏关闭按钮也没有真正控制 aside 的 v-if:frontend/src/pages/PptPage.vue:87-90。
修复
- 校验状态只保留一个权威 store;
- 父子组件共享同一状态;
- 顶部只显示总进度;
- 详细问题只出现在问题队列;
- 修复关闭按钮条件或移除冗余栏。
UX-P1-04:问题点击不是真正的“定位”
证据
jumpToIssue 只尝试:
- 用产品名猜产品;
- 用字符串包含关系猜标签页。
它不会:
- 滚动到目标字段;
- 聚焦输入框;
- 高亮表格行或单元格;
- 打开 PDF 来源页;
- 将焦点移到下一条未解决问题。
影响
用户点击问题后仍需自己搜索。产品名本身缺失时,恰好无法靠产品名定位。
修复
使用结构化 path + rowKey + sourcePage,实现:
点击问题 → 切正确产品 → 打开正确分区 → 滚动并高亮字段 → PDF 跳页并高亮 → 修改后自动进入下一问题。
UX-P1-05:把“核对”设计成“全表编辑”
证据
利益表的每一个单元格始终显示 el-input-number:frontend/src/pages/components/ppt/PptDataReview.vue:117-193。IUL 最多同时展示十余列。
影响
- 数值与控件外观混在一起,扫描速度低;
- 用户不知道哪些值真的有问题;
- 20 至 100 行时出现数百个输入控件;
- 缺少键盘移动、批量粘贴、只看异常和批量确认。
修复
- 默认只读格式化表格;
- 只把缺失、冲突、低置信单元格高亮;
- 单击或 Enter 进入编辑;
- 支持“仅看异常”“接受当前页”“从 Excel 粘贴”;
- 支持上下一个问题和键盘导航;
- 全量表格放在二级入口,默认先完成异常队列。
UX-P1-06:保存机制给出错误安全感
证据
- 数据变化时所谓自动保存只提交
{workflow_step: "review", hasEdits: true}:frontend/src/pages/components/ppt/PptDataReview.vue:322-331 - 实际 extraction 数据只有点击“保存修改”才调用
updateExtractions:frontend/src/pages/components/ppt/PptDataReview.vue:588-603 - 页面离开前也只保存步骤和时间戳:
frontend/src/pages/PptPage.vue:169-176 - 编辑后校验问题不会实时刷新,只有显式保存后重新校验。
影响
顶部草稿指示器可能显示“已保存”,但用户修改的真实保险数据并未保存。返回步骤、点击导航或刷新都可能丢失编辑。
修复
- 自动保存必须保存真实 extraction patch;
- 保存状态明确区分“正在保存数据”“已保存并已校验”;
- 离开前强制 flush;
- 冲突时展示字段级差异;
- 编辑后本地即时校验,防抖服务端校验;
- 提供撤销与恢复。
UX-P1-07:缺失字段反而没有输入入口
证据
保额字段使用 v-if="currentExt.data.policy.sum_insured":frontend/src/pages/components/ppt/PptDataReview.vue:105-107。
影响
AI 漏识别保额时,该字段被隐藏,用户无法补录;而 CI/IUL 校验又要求保额大于 0。
修复
字段是否显示应由险种 schema 决定,而不是由当前值是否存在决定。缺失的必填字段必须最醒目。
UX-P2-08:状态与编辑值不同步
证据
- 产品列表和标题优先显示
ext.productName; - 输入框修改的是
currentExt.data.product_name; - 保存响应中的重算状态没有合并回本地 extraction。
相关代码:frontend/src/pages/components/ppt/PptDataReview.vue:43、61、80-82、599-603。
影响
用户修改产品名称后,标题可能仍显示旧名称;修复 partial 数据后,标签也可能继续显示“解析不完整”。
UX-P2-09:返回、删除与辅助功能问题
- 内层按钮写“返回上传”,实际只回到解析步骤:
frontend/src/pages/components/ppt/PptDataReview.vue:279 - 外层还有一个“返回上一步”,形成重复;
- 删除表格行无确认、无撤销;
- 顶部返回和右栏关闭是可点击图标,不是语义按钮:
frontend/src/pages/PptPage.vue:6、90 - 产品状态圆点主要依靠颜色表达;
- 多个独立滚动区使键盘和 200% 缩放用户难以定位。
6. 设计健康度
基于 Nielsen 10 项可用性原则:
| # | 原则 | 分数 | 主要问题 |
|---|---|---|---|
| 1 | 系统状态可见 | 2/4 | 有加载和错误数,但校验陈旧、父子计数矛盾 |
| 2 | 符合现实世界 | 2/4 | 保险术语正确,但没有真实 PDF 证据 |
| 3 | 用户控制与自由 | 1/4 | 无撤销,删除立即执行,关闭按钮失效 |
| 4 | 一致性与标准 | 2/4 | 基础组件一致,状态、返回、底栏和字段类型不一致 |
| 5 | 错误预防 | 1/4 | 缺失字段隐藏,来源页可误改,0 与缺失混淆 |
| 6 | 识别而非记忆 | 1/4 | 必须另开 PDF 或凭记忆比对 |
| 7 | 灵活与高效 | 1/4 | 无异常队列、批量、粘贴、快捷键 |
| 8 | 美观与极简 | 1/4 | 外层三栏叠内层三栏,所有单元格长期编辑态 |
| 9 | 错误识别与恢复 | 1/4 | 问题不能定位、聚焦、高亮或提供恢复路径 |
| 10 | 帮助与文档 | 0/4 | 无置信度、字段口径、警告处理指导 |
| 总分 | 12/40 | Poor,需要重做核对任务架构 |
认知负荷检查有 6/8 项失败,属于高负荷:
- 不能保持单一焦点;
- 视觉层级不清;
- 不能一次只处理一个决策;
- 同屏选择过多;
- 依赖工作记忆;
- 没有渐进披露。
7. 推荐目标交互
7.1 页面结构
┌─────────────────────────────────────────────────────────────────┐
│ 产品/文件切换 · 已解决 4/7 · 2错误 1待确认 · 已保存并校验 │
├──────────────────────────────┬──────────────────────────────────┤
│ PDF 原文 / 页图 │ 当前待核对问题 │
│ │ 被保人年龄 │
│ 自动跳到第 2 页 │ AI 值:— │
│ 高亮“受保人年齡 38” │ 原文:受保人年齡 38 │
│ │ 置信度:低 · OCR │
│ │ [接受 38] [修改] [无法确认] │
│ │ │
│ │ 下一个问题:产品名称 │
├──────────────────────────────┴──────────────────────────────────┤
│ 撤销 · 上一个问题 保存状态 · 下一个问题/确认生成 │
└─────────────────────────────────────────────────────────────────┘
7.2 信息优先级
- 阻断错误;
- 字段冲突;
- 低置信字段;
- 缺来源字段;
- 普通警告;
- 已确认的正常数据;
- 全量原始表格。
高置信且通过交叉校验的数据默认折叠,不要求用户逐项确认。
7.3 操作原则
- 一个页面只保留一个主要任务:清空待核对问题;
- 一个时刻只编辑一个异常;
- 所有判断依据与当前异常同屏;
- 修改后立即反馈是否解决;
- 自动保存真实数据;
- 用户可随时撤销、返回,且不会丢失工作;
- 全量编辑是高级入口,不是默认入口。
8. 修复顺序
阶段 1:先修数据安全与分流
- 以关键字段完整度替换
regex_rows >= 3单一门槛; - 解析失败的每个文件都生成 blocking issue;
- 移除数值静默覆盖;
- 将
companyId/productId/aliases传入解析器; - 统一
plan_type/gender/premium_payment_yearsDTO; - 增加针对当前错误分支的回归测试。
阶段 2:改造 PDF 解析
- 逐页文本质量评估;
- 混合页 OCR;
- 支持繁体 OCR;
- 页面角色识别与必选页策略;
- 基于坐标的表格重建;
- 身份、保单、表格分块结构化提取;
- 字段级 provenance/confidence。
阶段 3:重做校验契约
- issue 带产品、路径、行、页码和状态;
- 本地即时校验与服务端权威校验统一;
- 多产品问题不再使用字符串猜归属;
- 记录用户接受、修改和无法确认状态。
阶段 4:重构核对页面
- 核对步骤专注模式;
- PDF 与当前问题双栏;
- 待核对队列;
- 默认只读、异常才编辑;
- 真正的数据自动保存;
- 撤销、批量、粘贴和键盘操作;
- 去掉重复状态栏、上下文栏和底栏。
阶段 5:真实数据回归与灰度
- 建立脱敏金标 PDF 集;
- 按保司、险种、语言、扫描类型统计准确率;
- 记录用户修改率与问题处理耗时;
- 新旧解析器双跑对比;
- 达标后切换默认流程。
9. 验收标准
9.1 解析准确性
- 产品名称标准化准确率 ≥ 98%;
- 被保人年龄精确准确率 ≥ 99%;
- 关键保单字段准确率 ≥ 97%;
- 可读数字版 PDF 的利益表行召回率 ≥ 95%;
- 已识别数字单元格精确准确率 ≥ 99%;
- 关键字段缺失时 100% 进入待核对,不得显示整体通过;
- 所有自动修正都可追溯,不允许静默改变 PDF 来源值。
9.2 核对体验
- 用户进入页面 5 秒内能看懂还有多少问题、先处理哪一个;
- 点击问题后一次操作内看到正确产品、字段和 PDF 来源页;
- 修正后 1 秒内本地状态更新,服务端校验完成后明确确认;
- 高置信数据无需逐项进入编辑;
- 正常离开、刷新、返回步骤均不丢失修改;
- 只有一套错误计数、一套主操作栏;
- 1280px 宽度下不出现“多层侧栏挤压核心编辑区”;
- 键盘可完成上一个问题、修改、接受、下一个问题和确认。
9.3 测试覆盖
必须新增:
- “利益表 ≥3 行但产品名/年龄缺失时仍进入字段补全”的测试;
- 繁体
年齡、受保人年齡、Issue Age、出生日期测试; - 产品名无标签、别名、产品代码和 OCR 错字测试;
- 多页利益表、重复表头、多层表头测试;
- 混合型 PDF 局部 OCR 测试;
- 超过 40 页、超过 120,000 字符测试;
- 多产品 issue 精确定位测试;
- 解析失败产品阻断生成测试;
- 自动保存真实编辑数据和离开恢复测试;
- 核对页键盘、响应式和 200% 缩放测试。
10. 本次诊断的证据边界
- 已运行相关后端测试:70 项全部通过;
- 测试通过说明现有理想化样例没有回归,不代表真实计划书准确率达标;
- 当前工作区未发现可用于复现的真实失败 PDF,因此无法对具体保司模板给出字段级误差统计;
- 自动界面检测器扫描
PptDataReview.vue返回 0 条规则问题,但该检测器不理解“核对必须有原始证据”等业务交互问题; - 当前浏览器运行环境不可用,未进行实页截图和交互录屏验证;
- 上述高优先级问题均可由源码调用链直接证实,真实 PDF 与实页验证主要用于量化影响,而不是决定问题是否存在。
11. 最终判断
修复顺序必须先保证“机器不把不完整结果当成功”,再优化 OCR 和模型,最后重做核对交互。
如果只换模型:
- 正则成功分支仍不会让模型回填名称和年龄;
- 上传产品先验仍然浪费;
- 关键页仍可能不包含所需页面;
- 用户仍然看不到来源证据。
如果只美化页面:
- 外层和内层状态仍会矛盾;
- 问题仍无法定位;
- 自动保存仍不保存真实修改;
- 用户仍然需要人工重录整张表。
因此,这次应按“解析质量门 → 来源与置信度 → 校验契约 → 核对任务架构”的顺序进行,而不是做局部样式微调。