baodan/docs/PDF实时解析提速与精准抽取方案.md
2026-07-28 16:45:14 +08:00

16 KiB
Raw Blame History

PDF 实时解析提速与精准抽取方案

1. 背景

当前 PPT 生成和海报生成都依赖用户上传 PDF 计划书,再从 PDF 中抽取结构化数据。实际业务中,用户上传的 PDF 不一定是公共资料,也不一定会重复使用,同一份 PDF 缓存命中率有限。

因此,优化目标不能只依赖“同文件缓存”,而应该围绕实时解析链路做改造:

  • 少读:不全量读取无关页面
  • 少传:不把整本 PDF 文本都交给模型
  • 先准:金额、年龄、保费、利益表等字段优先用规则和表格抽取
  • 补漏:模型只处理缺失字段和语义判断
  • 可追溯:关键字段保留来源页和置信度
  • 可降级:快速解析失败时进入精确解析或人工确认

2. 总体目标

将现有链路:

上传 PDF -> 全文抽取 -> 截断前 2 万字 -> LLM 完整解析 -> 等待 -> 生成 PPT/海报

改造为:

上传 PDF
-> 按页快速抽文本
-> 页面打分和字段覆盖分析
-> 选取关键页
-> 规则/表格优先抽取
-> LLM 补全缺失字段
-> 完整性校验
-> 缺什么补什么
-> 返回可编辑结构化数据
-> 生成 PPT/海报

预期效果:

海报解析5-15 秒返回可编辑数据
PPT 快速解析20-60 秒返回初版结构化数据
PPT 精确解析:仅在字段缺失或用户要求时触发

3. 核心原则

3.1 不依赖重复 PDF 缓存

PDF 每次可能不同,所以缓存只能作为辅助能力。主优化方向是让每次实时解析都更轻。

3.2 不一次性相信关键页筛选

关键页筛选只是第一步,后面必须有字段完整性校验。如果缺字段,需要定向补页。

3.3 不让 LLM 自由生成精确数值

年龄、保费、保额、利益演示表、现金价值、身故赔偿等字段应优先来自规则、表格解析或原文证据。LLM 主要负责:

识别字段语义
补全规则抽不到的内容
总结产品卖点
处理复杂版式
输出统一 JSON

3.4 每个关键字段都要有来源

关键字段建议保存:

{
  "value": 100000,
  "source_page": 3,
  "confidence": 0.92,
  "source_type": "rule"
}

这样可以支持前端展示“来自第几页”,方便用户确认。

4. 解析模式设计

系统提供两种解析模式。

4.1 快速解析模式

默认模式,适合海报和大部分 PPT 初稿。

特点:

只读取关键页
优先规则抽取
LLM 输入控制在 6000-10000 字
返回可编辑结构化草稿

适用场景:

海报生成
销售快速演示
用户希望尽快看到结果

4.2 精确解析模式

用户主动点击,或快速解析校验不通过时触发。

特点:

扩大关键页范围
补充更多候选页面
加强表格解析
必要时读取全文
模型输入允许更大

适用场景:

正式 PPT
关键字段缺失
利益演示表识别失败
用户对金额准确性要求较高

5. 字段清单

5.1 海报必填字段

product_name        产品名称
company_name        保司名称
age                 年龄
gender              性别
currency            币种
annual_premium      年缴保费
premium_term        缴费期
coverage_period     保障期
sum_assured         保额/保障额
key_benefits        核心利益/卖点

5.2 PPT 必填字段

product_name             产品名称
company_name             保司名称
plan_type                计划类型
age                      年龄
gender                   性别
currency                 币种
annual_premium           年缴保费
premium_term             缴费期
coverage_period          保障期
sum_assured              基本保额
benefit_illustration     利益演示表
death_benefit            身故保障
cash_value               现金价值/退保价值

6. 页面筛选策略

6.1 按页抽取文本

不要一开始就拼整本文本。应先得到页面数组:

[
  {
    "page": 1,
    "text": "第一页文本",
    "char_count": 1200
  },
  {
    "page": 2,
    "text": "第二页文本",
    "char_count": 900
  }
]

6.2 页面关键词打分

海报关键词:

被保人、投保人、年龄、性别、保费、缴费期、保障期、保额、基本保额、身故、重疾、现金价值、退保价值、利益演示

PPT 关键词:

计划书、产品名称、投保摘要、保障摘要、利益演示、现金价值、保证现金价值、非保证、红利、退保价值、身故赔偿、年度保费、缴费期、保障期、内部回报率

英文关键词:

Insured, Policyholder, Age, Gender, Premium, Annual Premium, Sum Assured,
Payment Term, Benefit Term, Cash Value, Surrender Value, Death Benefit,
Policy Year, Guaranteed, Non-guaranteed, Illustration

6.3 页面字段覆盖分析

每页不仅要打分,还要记录它可能覆盖哪些字段:

{
  "page": 5,
  "score": 18,
  "candidate_fields": [
    "annual_premium",
    "premium_term",
    "sum_assured"
  ]
}

6.4 页面选择规则

不是固定选前 5 页,而是按字段覆盖选择:

1. 必选首页、摘要页、利益演示页
2. 按得分从高到低加入候选页
3. 加到字段覆盖率达到目标值
4. 或达到最大字符数限制

建议限制:

海报:最多 6000 字
PPT 快速解析:最多 10000 字
PPT 精确解析:最多 20000-30000 字

7. 规则抽取策略

新增规则抽取层,先从关键页文本中抽取确定性字段。

7.1 基础字段规则

可优先抽取:

年龄
性别
币种
年缴保费
缴费期
保障期
基本保额
产品名称
保司名称

示例规则方向:

年龄:年龄 35 / Age: 35 / Insured Age 35
性别:男 / 女 / M / F / Male / Female
币种USD / HKD / CNY / 美元 / 港元 / 人民币
年缴保费:年缴保费 / 年度保费 / Annual Premium
缴费期:缴费期 5年 / Payment Term 5 Years
保障期:终身 / 至100岁 / Whole Life / To Age 100
基本保额:基本保额 / 保额 / Sum Assured / Basic Sum Assured

7.2 表格字段规则

利益演示表是 PPT 里最重要、也最容易出错的部分。建议单独解析,不要完全交给模型。

重点识别列:

保单年度
年龄
年度保费
累计保费
保证现金价值
非保证红利
终期红利
总退保价值
身故赔偿

英文列:

Policy Year
Age
Annual Premium
Total Premium Paid
Guaranteed Cash Value
Non-guaranteed Bonus
Terminal Dividend
Total Surrender Value
Death Benefit

8. LLM 补全策略

LLM 不应该收到整本 PDF而应该收到

{
  "mode": "poster",
  "rule_data": {
    "age": 35,
    "currency": "USD",
    "annual_premium": 100000
  },
  "missing_fields": [
    "gender",
    "sum_assured",
    "coverage_period",
    "key_benefits"
  ],
  "pdf_text": "关键页文本..."
}

Prompt 要求:

请基于 PDF 关键页文本补全缺失字段。
已有 rule_data 中的字段优先保留,不要随意覆盖。
如果无法确认,字段返回 null。
金额字段必须来自原文,不得估算。
输出 JSON不要输出 markdown。

9. 校验与补页闭环

9.1 第一次解析后校验

解析后立即运行 validator检查必填字段

字段是否存在
金额是否为正数
币种是否合理
利益演示表是否为空
年度表是否连续
总退保价值是否小于保证现金价值

9.2 缺失字段定向补页

如果缺字段,不直接失败,而是按缺失字段补页。

示例:

benefit_illustration 时,补页关键词:

利益演示、现金价值、退保价值、保证现金价值、非保证、保单年度、Policy Year

sum_assured 时,补页关键词:

保额、基本保额、保障金额、Sum Assured、Basic Sum Assured

annual_premium 时,补页关键词:

保费、年缴、年度保费、Annual Premium、Premium

9.3 补页后再次解析

第二轮只把新增页面和缺失字段交给模型:

{
  "missing_fields": ["sum_assured", "benefit_illustration"],
  "additional_pages": [
    {
      "page": 8,
      "text": "..."
    }
  ],
  "current_data": {
    "product_name": "xxx",
    "age": 35
  }
}

10. 结果状态设计

解析结果分为四类:

success       字段齐全,关键字段有来源页
partial       基本可用,但存在低置信度字段
needs_review  缺关键字段,需要人工确认或精确解析
error         解析失败

建议每个结果保存解析元信息:

{
  "parse_meta": {
    "mode": "fast",
    "selected_pages": [1, 2, 5, 8],
    "page_count": 36,
    "text_chars": 5820,
    "rule_fields": ["age", "annual_premium", "currency"],
    "llm_fields": ["coverage_period", "key_benefits"],
    "missing_fields": [],
    "duration_ms": 12600
  }
}

11. 后端改造范围

11.1 新增 PDF 预处理模块

新增:

api/insurance/ppt/pdf_preprocessor.py

职责:

按页抽取文本
页面关键词打分
字段覆盖率分析
构建关键页文本
必要时兜底全文抽取

核心函数:

def extract_pages(pdf_path: str) -> list[dict]:
    pass

def rank_key_pages(pages: list[dict], mode: str) -> list[dict]:
    pass

def build_compact_text(key_pages: list[dict], max_chars: int) -> str:
    pass

def extract_compact_pdf_text(pdf_path: str, mode: str) -> dict:
    pass

11.2 新增规则抽取模块

新增:

api/insurance/ppt/rule_extractor.py

职责:

正则抽基础字段
解析利益演示表
生成字段来源和置信度

核心函数:

def extract_basic_fields(text: str) -> dict:
    pass

def extract_benefit_rows(text: str) -> list[dict]:
    pass

def merge_rule_and_llm_data(rule_data: dict, llm_data: dict) -> dict:
    pass

11.3 改造 PPT 抽取服务

修改:

api/insurance/ppt/extraction.py

调整点:

extract_for_poster 使用关键页文本
extract_plan 使用关键页文本
保留 _extract_pdf_text 作为兜底
LLM prompt 改为“补全缺失字段”
返回 parse_meta

11.4 改造 PPT 后台任务

修改:

api/insurance/ppt/parse_worker.py

调整点:

取消 force_reparse=True
支持 fast / accurate 两种解析模式
多 PDF 有限并发,建议并发数 2
进度信息显示当前解析阶段

11.5 改造海报后台任务

修改:

api/insurance/poster/tasks.py

调整点:

海报解析默认 fast 模式
开启缓存作为辅助
保存解析元信息
解析结果允许 partial但前端要求用户确认

12. 前端改造范围

12.1 PPT 解析页面

修改:

frontend/src/pages/components/ppt/PptParsing.vue

新增体验:

显示解析模式:快速解析 / 精确解析
显示解析进度:扫描 PDF、筛选关键页、规则抽取、AI 补全、校验
如果 partial显示“精确解析”按钮
展示字段来源页

12.2 PPT 数据确认页

修改:

frontend/src/pages/components/ppt/PptDataReview.vue

新增:

字段置信度展示
来源页展示
缺失字段高亮
用户可手动修正

12.3 海报上传页

修改:

frontend/src/components/poster/PosterStepUpload.vue

新增:

上传后快速解析
解析完成后进入字段确认
字段不完整时允许用户手动补齐
不强制等待精确解析

13. 接口设计建议

13.1 PPT 触发解析

POST /insurance/ppt/parse/{session_id}

请求:

{
  "mode": "fast",
  "force": false
}

精确解析:

{
  "mode": "accurate",
  "force": true
}

13.2 解析状态返回

{
  "sessionId": "xxx",
  "status": "parsing",
  "progress": 55,
  "message": "正在补全缺失字段",
  "extractions": [
    {
      "pdfName": "plan.pdf",
      "planType": "savings",
      "status": "partial",
      "productName": "xxx",
      "yearCount": 20,
      "error": null,
      "parseMeta": {
        "mode": "fast",
        "selectedPages": [1, 2, 5, 8],
        "pageCount": 36,
        "textChars": 5820,
        "missingFields": ["sum_assured"]
      }
    }
  ]
}

14. 实施顺序

第一阶段:低风险提速

1. 取消 PPT 强制重解析
2. 海报解析开启缓存
3. 增加耗时日志
4. 增加 parse_meta

第二阶段:关键页筛选

1. 新增 pdf_preprocessor.py
2. 按页抽文本
3. 页面关键词打分
4. 海报使用关键页文本
5. PPT 使用关键页文本

第三阶段:规则抽取

1. 新增 rule_extractor.py
2. 抽取基础字段
3. 抽取利益演示表
4. LLM 只补缺失字段

第四阶段:精准闭环

1. validator 检查字段完整性
2. 缺字段定向补页
3. 二次补全
4. 前端展示来源页和置信度

第五阶段:体验优化

1. 增加快速解析 / 精确解析切换
2. 增加字段确认页面
3. 支持用户手动修正后生成
4. 记录人工确认后的金标数据

15. 验收标准

15.1 性能标准

海报快速解析:常规 PDF 15 秒内返回
PPT 快速解析:常规 PDF 60 秒内返回
同一会话重复解析:优先命中缓存
多文件解析:支持最多 2 个并发

15.2 准确性标准

关键金额字段必须有来源页
利益演示表不能由模型凭空生成
缺少必填字段时不能标记 success
partial 状态必须允许用户确认或精确解析

15.3 用户体验标准

用户能看到解析进度
用户能看到哪些字段缺失
用户能看到关键字段来源页
用户能手动修正解析结果
用户能选择精确解析

16. 最终结论

PDF 每次都不同的情况下,不能主要依赖同文件缓存。最佳方案是建立实时解析闭环:

关键页筛选
+ 规则/表格优先抽取
+ LLM 补漏
+ 字段校验
+ 缺失字段定向补页
+ 来源页证据
+ 人工确认

这套方案既能减少等待时间,又能保证关键数据不会因为”只抽部分页面”而漏掉。快速解析负责效率,校验和补页负责准确性,精确解析和人工确认负责兜底。

17. 实施状态

更新于 2026-07-27

已完成

模块 文件 说明
正则提取引擎 api/insurance/ppt/regex_extractor.py 纯正则提取产品信息 + 利益演示表 + 提领表,零 LLM 调用
产品类型识别 regex_extractor._detect_product_type() savings / ci / iul 自动识别
轻量分析 Prompt api/insurance/ppt/prompts.pyANALYSIS_SYSTEM_PROMPT 正则提取后仅做关键发现分析(~300字输出
关键页筛选 prompts.select_key_pages() 从全文中选取最相关的 4-5 页(~8000字符
Orchestrator 重构 api/insurance/ppt/extraction.py 正则优先 → 行数≥3用正则+分析 → 不足则回退 LLM
LLM 回退 Prompt 精简 prompts.py SAVINGS/CI/IUL prompt 移除销售分析职责,仅保留数据提取
任务重命名 parse_worker.py + PptParsing.vue “解析” → “处理/结构化”
缓存版本升级 extraction.py CACHE_VERSION 3 → 4
繁体中文列名 regex_extractor._COLUMN_ALIASES AIA/CTF/FWD 风格表头全覆盖
单元测试 tests/test_regex_extractor.py 58 个测试全部通过
前端字段匹配 frontend/src/utils/ppt-parser.ts 模糊匹配、行标准化、回本计算、数据校验
死代码清理 extraction.py 移除未使用的 import field

未完成

优先级 任务 说明
真实 PDF 集成测试 用真实计划书批量验证提取率 > 80%
提取率报告脚本 批量测试工具