Просмотр исходного кода

feat: parsePreview 先调 LangGraph 解析,失败回退 Java

Xiaogang Liao 1 месяц назад
Родитель
Сommit
d3f4eab0e7

+ 144 - 2
cfc-backend/src/main/java/com/etotem/cfc/controller/HealthReportController.java

@@ -50,6 +50,7 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -57,6 +58,9 @@ import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+
 /**
  * 健康检测报告接口 — 体检报告/菌群检测报告的录入与查询
  */
@@ -66,6 +70,9 @@ import java.util.UUID;
 @RequestMapping("/api/health")
 public class HealthReportController {
 
+    private static final String LANGGRAPH_BASE_URL = "http://localhost:9000";
+    private static final String REPORT_PARSE_URL = LANGGRAPH_BASE_URL + "/api/v1/report/parse";
+
     @Resource
     private HealthReportService healthReportService;
 
@@ -90,6 +97,9 @@ public class HealthReportController {
     @Resource
     private ObjectMapper objectMapper;
 
+    @Resource
+    private RestTemplate restTemplate;
+
     @Resource
     private DimensionScoreService dimensionScoreService;
 
@@ -475,13 +485,71 @@ public class HealthReportController {
                 return Result.error("仅支持PDF文件");
             }
 
+            // 保存文件到磁盘(LangGraph 和本地解析共用)
+            String fileUrl = saveUploadFile(file, userId);
+            String absolutePath = new File(fileUrl).getAbsolutePath();
+
+            // 尝试 LangGraph 远程解析
+            try {
+                Map<String, Object> lgRequest = new HashMap<>();
+                lgRequest.put("file_path", absolutePath);
+                lgRequest.put("user_id", userId);
+                if (familyId != null) {
+                    lgRequest.put("family_id", familyId);
+                }
+
+                ResponseEntity<Map> lgResponse = restTemplate.postForEntity(
+                        REPORT_PARSE_URL, lgRequest, Map.class);
+                Map<String, Object> lgBody = lgResponse.getBody();
+                if (lgBody != null && Integer.valueOf(200).equals(lgBody.get("code"))) {
+                    Map<String, Object> lgData = (Map<String, Object>) lgBody.get("data");
+                    if (lgData != null) {
+                        ParsedReportPayload.Payload lgPayload = buildPayloadFromLgData(lgData);
+
+                        String payloadJson = objectMapper.writeValueAsString(lgPayload);
+
+                        HealthReportDraft draft = healthReportDraftService.createDraft(
+                                userId, familyId, "gut_flora", fileUrl, originalFilename, payloadJson);
+
+                        Map<String, Object> overview = (Map<String, Object>) lgData.get("overview");
+                        String personName = overview != null ? (String) overview.get("person_name") : null;
+                        String gender = overview != null ? (String) overview.get("gender") : null;
+                        Integer age = overview != null ? toInteger(overview.get("age")) : null;
+
+                        MemberMatchResult matchResult = healthReportService.matchMemberByProfile(
+                                personName, gender, age, familyId);
+
+                        Map<String, Object> result = new LinkedHashMap<>();
+                        result.put("draftId", draft.getId());
+                        result.put("payload", lgPayload);
+                        result.put("matchedMemberId", matchResult.getMatchedMemberId());
+                        result.put("confidence", matchResult.getConfidence());
+                        result.put("matchLabel", matchResult.getMatchLabel());
+                        result.put("candidates", matchResult.getCandidates());
+                        result.put("extractedName", personName);
+                        result.put("extractedGender", gender);
+                        result.put("extractedAge", age);
+                        result.put("needBind", matchResult.getMatchedMemberId() == null && familyId != null);
+
+                        try {
+                            saveResultToJsonFile(result);
+                        } catch (Exception e) {
+                            log.warn("保存结果到 JSON 文件失败:{}", e.getMessage());
+                        }
+
+                        return Result.success(result);
+                    }
+                }
+            } catch (Exception e) {
+                log.warn("LangGraph 解析失败,回退到本地 Java 解析: {}", e.getMessage());
+            }
+
+            // Fallback: 本地 Java 解析
             ParsedReportResult parsed = pdfParseService.parse(file.getInputStream());
             if (parsed.getOverallScore() == null && parsed.getGutHealthScore() == null) {
                 return Result.error("无法解析PDF文件,请确认是募极生物肠道菌群报告");
             }
 
-            String fileUrl = saveUploadFile(file, userId);
-
             ParsedReportPayload.Payload payload = convertToPayload(parsed);
 
             String payloadJson = objectMapper.writeValueAsString(payload);
@@ -1178,6 +1246,80 @@ public class HealthReportController {
         return f;
     }
 
+    private ParsedReportPayload.Payload buildPayloadFromLgData(Map<String, Object> lgData) {
+        ParsedReportPayload.Payload payload = new ParsedReportPayload.Payload();
+
+        Map<String, Object> overview = (Map<String, Object>) lgData.get("overview");
+        if (overview != null) {
+            ParsedReportPayload.Summary summary = new ParsedReportPayload.Summary();
+            summary.setPersonName((String) overview.get("person_name"));
+            summary.setAge(toInteger(overview.get("age")));
+            summary.setGender((String) overview.get("gender"));
+            summary.setOverallScore(toInteger(overview.get("overallScore")));
+            summary.setGutHealthScore(toInteger(overview.get("gutHealthScore")));
+            summary.setChronicDiseaseScore(toInteger(overview.get("chronicDiseaseScore")));
+            summary.setNutritionScore(toInteger(overview.get("nutritionScore")));
+            summary.setBalanceScore(toInteger(overview.get("balanceScore")));
+            summary.setDiversityScore(toInteger(overview.get("diversityScore")));
+            summary.setBeneficialScore(toInteger(overview.get("beneficialScore")));
+            summary.setHarmfulScore(toInteger(overview.get("harmfulScore")));
+            summary.setCoreGenusScore(toInteger(overview.get("coreGenusScore")));
+            summary.setGutAge(objectToString(overview.get("gutAge")));
+            summary.setGutType(objectToString(overview.get("gutType")));
+            summary.setReportNumber(objectToString(overview.get("report_number")));
+            summary.setBirthday(objectToString(overview.get("birthday")));
+            payload.setSummary(summary);
+        }
+
+        List<Map<String, Object>> diseaseRisks = (List<Map<String, Object>>) lgData.get("disease_risks");
+        if (diseaseRisks != null) {
+            List<ParsedReportPayload.DiseaseRisk> risks = new ArrayList<>();
+            for (Map<String, Object> dr : diseaseRisks) {
+                ParsedReportPayload.DiseaseRisk risk = new ParsedReportPayload.DiseaseRisk();
+                risk.setDiseaseName((String) dr.get("name"));
+                risk.setRiskValue(objectToString(dr.get("value")));
+                risk.setRiskLevel((String) dr.get("status"));
+                risks.add(risk);
+            }
+            payload.setDiseaseRisks(risks);
+        }
+
+        List<Map<String, Object>> indicators = (List<Map<String, Object>>) lgData.get("indicators");
+        if (indicators != null) {
+            List<ParsedReportPayload.Indicator> inds = new ArrayList<>();
+            for (Map<String, Object> ind : indicators) {
+                ParsedReportPayload.Indicator indicator = new ParsedReportPayload.Indicator();
+                indicator.setCategory((String) ind.get("category"));
+                indicator.setIndicatorName((String) ind.get("indicatorName"));
+                indicator.setIndicatorValue(objectToString(ind.get("indicatorValue")));
+                indicator.setUnit((String) ind.get("unit"));
+                indicator.setRefRange((String) ind.get("refRange"));
+                indicator.setStatus((String) ind.get("status"));
+                indicator.setSymptoms((String) ind.get("symptoms"));
+                inds.add(indicator);
+            }
+            payload.setIndicators(inds);
+        }
+
+        return payload;
+    }
+
+    private static Integer toInteger(Object value) {
+        if (value == null) return null;
+        if (value instanceof Integer) return (Integer) value;
+        if (value instanceof Number) return ((Number) value).intValue();
+        try {
+            return Integer.valueOf(value.toString());
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    private static String objectToString(Object value) {
+        if (value == null) return null;
+        return value.toString();
+    }
+
     private HealthReport buildReportFromPayload(HealthReportDraft draft, ParsedReportPayload.Payload payload, Long subjectId) {
         HealthReport report = new HealthReport();
         report.setUserId(draft.getUserId());