Przeglądaj źródła

docs: 报告解析迁移设计 — Java→LangGraph(Python算法+LLM兜底)

Xiaogang Liao 1 miesiąc temu
rodzic
commit
74e30ca361

+ 120 - 0
docs/superpowers/specs/2026-08-04-report-parsing-migration-design.md

@@ -0,0 +1,120 @@
+# 报告解析迁移设计:Java → LangGraph(Python 算法 + LLM 兜底)
+
+## 背景
+
+当前健康报告(菌群检测 PDF)解析在 Java 侧通过 `PdfParseService`(PDFBox + 规则解析)实现,但存在以下问题:
+
+- 格式兼容性差:inline 格式频繁抛出 `StringIndexOutOfBoundsException`
+- 采集不全:Python 版 `extract_full_report_v5.py` 覆盖 13 个分组,Java 版只有 8 个
+- 维护成本高:同一套解析逻辑在 Java 和 Python 各维护一份
+
+## 目标架构
+
+```
+用户上传 PDF
+    ↓
+Java HealthReportController
+    ├─ 保存文件到磁盘
+    ├─ 调 LangGraph /api/v1/report/parse
+    └─ 返回结构化数据给前端
+         ↓
+LangGraph report_parse_agent
+    ├─ Python 算法解析(复用 extract_full_report_v5.py)
+    │   ├─ 成功 → 返回结构化 JSON
+    │   └─ 失败 → LLM 兜底解析
+    └─ 返回结构化数据给 Java
+```
+
+## 组件职责
+
+### Java 侧(`HealthReportController`)
+
+- 接收文件上传(MultipartFile)
+- 保存文件到磁盘(`/tmp/uploads/` 或配置路径)
+- 调用 LangGraph 解析接口(POST `/api/v1/report/parse`)
+- 将 LangGraph 返回的结构化数据转换为 `ParsedReportPayload.Payload`
+- 后续流程不变(草稿 → 确认 → 入库)
+
+### LangGraph 侧(新增 `report_parse_agent`)
+
+- 接收文件路径
+- 调用 Python 解析脚本(从 `extract_full_report_v5.py` 提取核心逻辑)
+- 算法解析失败时,调用 LLM 进行结构化提取
+- 返回统一格式的 JSON
+
+## API 接口设计
+
+### LangGraph 解析接口
+
+```
+POST /api/v1/report/parse
+Content-Type: application/json
+
+Request:
+{
+    "file_path": "/tmp/uploads/xxx.pdf",
+    "family_id": 123,
+    "user_id": 456
+}
+
+Response:
+{
+    "code": 200,
+    "data": {
+        "summary": { ... },
+        "disease_risks": [ ... ],
+        "indicators": [ ... ],
+        "gut_flora": [ ... ],
+        "probiotic_species": [ ... ],
+        "food_suitability": [ ... ],
+        "extracted_name": "某人",
+        "extracted_gender": "male",
+        "extracted_age": 53
+    }
+}
+```
+
+## 数据流
+
+1. 用户上传 PDF → `Java HealthReportController.parsePreview()`
+2. Java 保存文件 → `POST /api/v1/report/parse?file_path=...`
+3. LangGraph 收到请求:
+   a. 调用 Python 算法解析模块(复用 `extract_full_report_v5.py` 核心逻辑)
+   b. 算法成功 → 返回结构化数据
+   c. 算法失败 → 调用 LLM(GPT-4o 等)提取结构化数据
+4. LangGraph 返回结构化 JSON 给 Java
+5. Java 将 JSON 转为 `ParsedReportPayload.Payload`,后续流程不变
+
+## 算法解析模块(Python)
+
+从 `extract_full_report_v5.py` 提取核心逻辑,封装为可调用的 Python 函数:
+
+```python
+def parse_report_pdf(file_path: str) -> dict:
+    """解析菌群报告 PDF,返回结构化数据"""
+    # 1. 读取 PDF 文本(PyPDF2)
+    # 2. 检测格式(triplet / inline)
+    # 3. 提取各分组数据
+    # 4. 返回统一格式字典
+```
+
+## LLM 兜底
+
+当算法解析失败时(返回空数据或关键字段缺失),调用 LLM:
+
+```python
+async def parse_with_llm(file_path: str) -> dict:
+    """LLM 兜底解析"""
+    # 1. 提取 PDF 文本
+    # 2. 构造 prompt,要求 LLM 按指定 JSON Schema 输出
+    # 3. 解析 LLM 输出
+    # 4. 返回结构化数据
+```
+
+## 迁移步骤
+
+1. 在 LangGraph 中创建 `report_parse_agent`(算法 + LLM 兜底)
+2. 创建 `POST /api/v1/report/parse` 接口
+3. 修改 Java `HealthReportController.parsePreview()`,先调 LangGraph,失败时回退到本地 Java 解析
+4. 验证通过后,移除 Java 端的 `PdfParseService`
+5. 编写测试用例覆盖 triplet/inline 两种格式