fix(复习):AI 对比结果由 Java 端标注标准树,不再依赖 LLM 输出树结构

根因:LLM 无法可靠输出 CompareResult 所需的完整嵌套树 JSON,
实际返回格式(coverage/matched/missed)与预期不符。

修复:
- AiServiceClient.compareRecall() 返回 Optional<JsonNode>(原始 JSON),
  不再尝试直接反序列化为 CompareResult
- StandardMindMapServiceImpl 新增 buildCompareResultFromAI():
  解析 AI 返回的平铺 matches/missedTitles/extraNodes 列表,
  将 MATCHED|/MISSED| 标注写入标准树,确定性构建 CompareResult
- AI 只负责语义匹配判断,树结构操作由 Java 端保证可靠性
This commit is contained in:
2026-07-04 16:09:07 +08:00
parent 7ac7868511
commit af4f536980
2 changed files with 77 additions and 7 deletions
@@ -2,7 +2,6 @@ package com.guo.learningprogresstracker.service.impl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.guo.learningprogresstracker.utils.CompareResult;
import jakarta.annotation.PostConstruct;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@@ -133,10 +132,12 @@ public class AiServiceClient {
/**
* 调用 lpt-ai 进行语义化回忆对比。
* 注意:AI 返回平铺的匹配列表,不返回完整树结构。
* 树标注(MATCHED/MISSED)由 StandardMindMapServiceImpl 基于本方法返回的 JSON 完成。
*
* @return 带 MATCHED/MISSED 标注和评价文本的对比结果;服务未配置或调用失败时返回 empty
* @return AI 返回的原始 JSON;服务未配置或调用失败时返回 empty
*/
public Optional<CompareResult> compareRecall(String taskName, String standardOutline, String recallOutline) {
public Optional<JsonNode> compareRecall(String taskName, String standardOutline, String recallOutline) {
if (!isConfigured()) {
return Optional.empty();
}
@@ -160,7 +161,7 @@ public class AiServiceClient {
response.body() != null ? response.body().substring(0, Math.min(200, response.body().length())) : "");
return Optional.empty();
}
return Optional.of(objectMapper.readValue(response.body(), CompareResult.class));
return Optional.of(objectMapper.readTree(response.body()));
} catch (Exception e) {
log.warn("lpt-ai 回忆对比调用异常,将降级为内置算法: {}", e.getMessage());
return Optional.empty();