# 五维家庭自检 AI 结合(P0 + P1)设计 > 日期:2026-08-31 > 状态:已获用户方案确认(P0+P1 第一批,P2 后续) > 关联:`FiveDimensionSelfCheckService` / `AiGateway` / `cfc-langgraph` --- ## 1. 背景与目标 现有五维自检使用**静态五行寻源表**(`WuxingSourcingService` 硬编码 5 条建议)生成结果,所有用户看到相同文案,无个性化、无趋势感知。 本批次实现 P0+P1 共 4 个子系统,按优先级排序: | 优先级 | 子系统 | 目标 | |:------:|--------|------| | **P0-1** | 静态建议 → AI 个性化建议 | 每次自检生成有温度、有针对性的解读 | | **P0-2** | 用户点击生成健康计划 | 自检低分可一键生成家庭健康计划草稿 | | **P1-1** | 历史趋势 + AI 解读 | 3 次自检趋势可视化 + AI 趋势分析 | | **P1-2** | 自检结果注入 AI Chat | 聊天页自动携带自检上下文 | P2(家庭成员差异化建议)延后单独实现。 已确认决策: - P0-1:**纯 AI 替换**,不保留静态五行寻源建议(`WuxingSourcingService` 仅保留 `levelOf/levelName/dimensionName`) - P0-2:**用户点击才生成**,不自动创建 draft plan - P0-1 字段设计:**直接改造 `advices` 字段**,新结构 `[{dimension, interpretation, microActions, aiInsight}]` --- ## 2. 现状盘点 ### 后端(自检) - `FiveDimensionSelfCheckController`:`/questions` `/submit` `/latest` `/history` - `FiveDimensionSelfCheckService`: - `QUESTION_BANK`(15题)、`SUB_DIMENSION_QUESTION_BANK`(19题) - `submitSelfCheck`:计分 → `wuxingSourcingService.getAdvicesForLowScores()` → 落库 `adviceJson` - `getQuestions()` 已改为支持 `retake` 参数(上个计划完成) - `WuxingSourcingService`:静态 `SOURCING_TABLE`(5行×5列)+ `levelOf/levelName/dimensionName` 纯工具方法 - 表 `five_dimension_self_checks`:`adviceJson TEXT` ### 后端(AI 基础设施) - `AiGateway.java`:统一网关(熔断+降级+PII脱敏) - `chat(query, userId, conversationId, inputs)` → `POST /api/v1/chat` - `generateInnateReading(portrait)` → `POST /api/v1/innate/reading` - `generateHealthPlan(inputs)` → `POST /api/v1/analysis/run` - LangGraph Python(`cfc-langgraph/app/`,端口 9000): - `app/graphs/chat_graph.py`(78行,Dify 兼容) - `app/graphs/health_plan_graph.py`(297行,Java 客户端 JavaClient 读取家庭数据) - `app/graphs/innate_portrait_graph.py`(65行,参考实现) - `app/api/adapter.py`(Dify 兼容路由) - `app/api/innate_portrait.py`(`/api/v1/innate/reading`) - `app/main.py` 注册各 router - 参考链路:`InnatePortraitController` → `InnatePortraitService.generateAiReading()` → `AiGateway.generateInnateReading()` → LangGraph `/api/v1/innate/reading` → `innate_portrait_graph.py` → 成功返回 reading,失败 null(调用方降级模板) ### 前端 - `pages/family/self-check-result.vue`:结果页,advices 展示在第 71-123 行(五行相生寻源建议区块) - `pages/family/self-check-entry.vue`:中间页(刚实现) - `pages/ai/chat.vue`:AI 聊天页(需确认路径) - `utils/api.js`:自检相关方法(`getSelfCheckStatus/ignoreSelfCheck/getSelfCheckQuestions/submitSelfCheck/getSelfCheckLatest/getSelfCheckHistory`) --- ## 3. 数据层设计 ### 3.1 `adviceJson` 结构变更 **旧结构**(静态五行寻源): ```json [ { "dimension": "mind", "dimensionName": "心", "element": "火", "color": "#FF6B9D", "score": 2, "level": "tense", "levelName": "紧绷", "upstreamDimension": "action", "upstreamName": "行", "upstreamElement": "木", "upstreamColor": "#10B981", "upstreamReason": "关系顺畅了,内心才安定", "restrainerDimension": "wealth", "restrainerName": "富", "restrainerElement": "水", "restrainerColor": "#F59E0B", "restrainerReason": "钱多了,情薄了", "action": "关系周记;家庭夜谈" } ] ``` **新结构**(AI 生成): ```json [ { "dimension": "mind", "dimensionName": "心", "element": "火", "color": "#FF6B9D", "score": 2, "level": "tense", "levelName": "紧绷", "interpretation": "你的心能量偏低,可能最近情绪压力较大...", "microActions": ["今晚睡前做10分钟深呼吸", "和伴侣约定每周一次夜谈"], "aiInsight": "建议从'行'维度入手...", "fallbackUsed": false } ] ``` **注意**:`dimension`/`dimensionName`/`element`/`color`/`score`/`level`/`levelName` 字段保留,与现有 VO 兼容。`upstreamDimension`/`upstreamReason`/`restrainerDimension` 等静态字段移除,新增 `interpretation`/`microActions`/`aiInsight`/`fallbackUsed`。 ### 3.2 新增 LangGraph Graph 输入/输出 **self_check_analysis_graph**(P0-1): - 输入 `dict`:`scores`(Map)、`questionIds`(List[int])、`userId`(int)、`recentHistory`(List[dict] 最近3次自检快照) - 输出 `dict`:`advice_json`(新结构 JSON string)、`fallback_used`(bool) **self_check_trend_graph**(P1-1): - 输入 `dict`:`history`(List[dict] 最近3次含 totalScore/dimensions/createdAt)、`userId`(int) - 输出 `dict`:`aiInsight`(str)、`trendSummary`(str) --- ## 4. 后端接口设计 ### 4.1 修改 `POST /api/family/self-check/submit`(P0-1) AI 建议在 `submitSelfCheck` 时**同步生成**并落库 `adviceJson`(不单独暴露 analysis 接口,避免 YAGNI 冗余)。 ``` POST /api/family/self-check/submit ↓ submitSelfCheck():计分 → selfCheckAnalysisService.generateAdvice(...) → 落库 ``` ### 4.2 新增 `POST /api/family/self-check/generate-plan`(P0-2) 请求:`{ "checkId": 12 }`(可空,默认取最近一次)。 响应 `Result`: ```json { "planId": 45, "status": "draft" } ``` ### 4.3 新增 `POST /api/family/self-check/trend-analysis`(P1-1) 请求:无 body(JWT 取 `userId`)。 响应 `Result`: ```json { "history": [{ "createdAt": "...", "totalScore": 32, "dimensions": [...] }], "aiInsight": "近三次身维度持续下降,可能...", "trendSummary": "身-2 智+1 富0 行-1 心+2" } ``` ### 4.4 修改 `POST /api/family/self-check/submit`(P0-1) 删除 `WuxingSourcingService.getAdvicesForLowScores()` 调用,改为: ```java SelfCheckAdviceResult adviceResult = selfCheckAnalysisService.generateAdvice(userId, scoreMap, questionIds); // adviceResult 含 adviceJson + fallbackUsed // 直接落库 ``` ### 4.5 `SelfCheckResultVO` 字段 `SelfCheckResultVO.advices` 类型保持 `List` 不变,字段结构按 5.4 改造后的 VO 承载 AI 建议内容。 --- ## 5. Java 服务层设计 ### 5.1 新增 `SelfCheckAnalysisService` ```java @Service public class SelfCheckAnalysisService { @Resource private AiGateway aiGateway; @Resource private FiveDimensionSelfCheckMapper selfCheckMapper; /** 生成自检建议(AI 优先,LangGraph 失败返回 null) */ public SelfCheckAdviceResult generateAdvice(Long userId, Map scoreMap, List questionIds) { // 1. 组装 inputs // 2. 调 aiGateway.generateSelfCheckAdvice(inputs) // 3. 返回 SelfCheckAdviceResult(含 adviceJson + fallbackUsed) } /** 生成趋势分析 */ public TrendAnalysisVO getTrendAnalysis(Long userId) { ... } } ``` ### 5.2 AiGateway 新增方法 ```java public Map generateSelfCheckAdvice(Map inputs) { // POST /api/v1/self-check/analysis // 失败返回 null(调用方设置 fallbackUsed=true) } public Map generateSelfCheckTrend(Map inputs) { // POST /api/v1/self-check/trend } ``` ### 5.3 WuxingSourcingService 变更 - **保留**:`DIMENSION_META`、`levelOf()`、`levelName()`、`dimensionName()`(被 `buildDimensionScoreVO` 使用) - **删除**:`SOURCING_TABLE`、`getAdvice()`、`getAdvicesForLowScores()` ### 5.4 `WuxingSourcingAdviceVO` 改造(P0-1) 不新建 VO,直接改造现有 `dto/WuxingSourcingAdviceVO.java`(保持 `SelfCheckResultVO.advices` 类型不变,最小改动): - **保留字段**:`dimension` / `dimensionName` / `element` / `color` / `score` / `level` / `levelName`(与现有 VO 兼容) - **移除字段**:`upstreamDimension` / `upstreamName` / `upstreamElement` / `upstreamColor` / `upstreamReason` / `restrainerDimension` / `restrainerName` / `restrainerElement` / `restrainerColor` / `restrainerReason` / `action` - **新增字段**: - `interpretation`(String,AI 对低分维度的解读) - `microActions`(List<String>,2-3 个本周微行动) - `aiInsight`(String,AI 补充洞察,可空) - `fallbackUsed`(Boolean,AI 不可用降级标记) --- ## 6. LangGraph Python 设计 ### 6.1 新增 `self_check_analysis_graph.py` ```python # cfc-langgraph/app/graphs/self_check_analysis_graph.py SYSTEM_PROMPT = """你是一位家庭健康顾问,基于五维自检结果(身·智·富·行·心,每维0-9分,满分45)给出个性化建议。 要求: 1. 用第二人称"你"称呼 2. 对每个低分维度(≤6分)给出1-2句解读和2-3个具体可执行的微行动 3. 如有历史数据,简要对比趋势 4. 语气温暖口语化,不超过300字/维度 5. 最后给出1句家庭整体洞察 返回 JSON: { "advice": [ {"dimension": "mind", "dimensionName": "心", "interpretation": "...", "microActions": ["...", "..."]}, ... ], "familyInsight": "..." } """ class SelfCheckAnalysisAgent: async def run(self, scores: dict, questionIds: list, recentHistory: list, userId: int) -> dict: # 格式化输入 → LLM → JSON 解析 → 返回 ``` ### 6.2 新增 `self_check_trend_graph.py` ```python SYSTEM_PROMPT = """分析用户近3次五维自检趋势,输出: - aiInsight: 趋势解读(2-3句,指出最大变化维度和可能原因) - trendSummary: 各维度 delta(如"身-2 智+1 富0 行-1 心+2") 返回 JSON:{"aiInsight": "...", "trendSummary": "..."} """ ``` ### 6.3 注册路由 `cfc-langgraph/app/api/self_check.py`: - `POST /api/v1/self-check/analysis` → `self_check_analysis_graph` - `POST /api/v1/self-check/trend` → `self_check_trend_graph` `cfc-langgraph/app/main.py`:追加 `app.include_router(self_check.router)` --- ## 7. 前端设计 ### 7.1 P0-1:`self-check-result.vue` 建议区块重写 删除现有 `scr-card` 寻源建议区块(第 71-123 行),替换为: ```html AI 健康解读 基于你的五维自检结果 {{ item.dimensionName }} {{ item.score }}分 {{ item.interpretation }} 本周行动: {{ i+1 }}. {{ action }} 💡 家庭整体洞察 {{ result.adviceJson[0].familyInsight }} AI 分析暂时不可用,请稍后再试 ``` ### 7.2 P0-2:结果页加「生成健康计划」按钮 在结果页底部按钮区追加(有低分维度时显示): ```html ``` ### 7.3 P1-1:趋势展示 新增 `POST /api/family/self-check/trend-analysis`,结果页中间页可展示(或结果页底部加「查看趋势」链接)。 ### 7.4 P1-2:Chat 注入 context 在 `self-check-result.vue` 加「问问 AI」按钮: ```html ``` 跳转:`uni.navigateTo({ url: '/pages/ai/chat?selfCheckId=' + result.id })` `AIChatController` 读取 `selfCheckId`,调 `getSelfCheckLatest`,将结果放入 context 传给 AiGateway。 --- ## 8. 边界行为与错误处理 1. **LangGraph 不可用**:`AiGateway` 熔断/open 时,`generateAdvice` 返回 `fallbackUsed=true`,`adviceJson=null`,前端显示"AI 分析暂时不可用" 2. **LLM 返回非 JSON**:Python 侧 `validate` 节点捕获,返回 error,Java 侧 fallbackUsed=true 3. **P0-2 计划生成失败**:toast "计划生成失败,请稍后重试",不阻断结果页 4. **P1-1 历史不足 3 次**:用现有次数展示(1-2 次),LLM 做有限对比 5. **P1-2 chat 上下文**:selfCheckId 无效时静默跳过,不影响 chat 正常流程 --- ## 9. 测试与验证 - 后端:`mvn clean compile` BUILD SUCCESS - 前端:`node --check` api.js 语法校验 - 手动验证路径: 1. 提交自检 → 查看 adviceJson 含 AI 生成内容(非静态表) 2. 点「生成健康计划」→ 跳转 plan 详情(draft 状态) 3. 点「查看趋势」→ 展示趋势 + AI 解读 4. 点「问问 AI」→ chat 页,LLM 回答知晓自检背景 --- ## 10. 文件变更清单 **LangGraph Python(新增 2 graph + 1 api + 改 main)**: - `cfc-langgraph/app/graphs/self_check_analysis_graph.py`(P0-1) - `cfc-langgraph/app/graphs/self_check_trend_graph.py`(P1-1) - `cfc-langgraph/app/api/self_check.py`(路由注册) - `cfc-langgraph/app/main.py`(追加 router include) **Java 后端**: - `dto/WuxingSourcingAdviceVO.java`(改造:移除 upstream/restrainer/action,新增 interpretation/microActions/aiInsight/fallbackUsed) - `service/SelfCheckAnalysisService.java`(新建) - `service/WuxingSourcingService.java`(删除 SOURCING_TABLE/getAdvice/getAdvicesForLowScores) - `service/FiveDimensionSelfCheckService.java`(修改 submitSelfCheck 调新 Service,新增 trend 方法) - `service/AiGateway.java`(新增 2 方法) - `controller/family/FiveDimensionSelfCheckController.java`(新增 3 接口,修改 submit) - `service/HealthPlanService.java`(新增 generateFromSelfCheck) - `service/impl/HealthPlanServiceImpl.java`(实现 generateFromSelfCheck) **前端**: - `utils/api.js`(新增 3 方法) - `pages/family/self-check-result.vue`(P0-1/P0-2/P1-2 改造) - `pages/family/self-check-entry.vue`(P1-1 趋势展示) - `pages/ai/chat.vue`(P1-2 context 注入,需确认是否存在)