# 报告解析迁移设计: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 两种格式