前端 (ai/chat.vue) → AIChatController → AIService → Dify Chatbot API (http://dify.bianwoyou.cn/v1)
↕
FamilyContextService (家庭上下文)
AiConversationSummary (记忆层)
AiUserFact (用户事实)
核心数据流:
POST /api/ai/chat/send (参数: query + conversationId + reportId/surveyId)FamilyContextService.buildContext(userId, reportId, surveyId) 组装家庭上下文AiService.enrichInputsWithMemory() 注入记忆层(最近摘要 + 关键事实)/chat-messages API已有能力:
报告上传 (report-upload.vue)
├── 体检报告 (physical_exam) → HealthReportService
├── 肠道菌群报告 (gut_flora) → HealthAnalysisService 分析 → 营养推荐
└── 舌诊拍照 (tongue) → AIService.sendTongueDiagnosis()
DAN 报告上传 (DanReportController)
└── Upload PDF → DanReportParseService 解析 → 编辑/确认 → 入库到 DanAssessmentResult
└── 确认后刷新五维能量分数
健康分析流程:
HealthAnalysisService.analyze(reportId) → 分析菌群、指标 → 生成 findings/suggestions/nutritionTagsProductRecommendationLog)RecommendationService.search(RecommendationQuery)
├── searchProducts(tags, limit) → Product 表(状态=上架, stock>0, 名称/描述模糊匹配)
├── searchActivities(tags, limit) → Activity 表(状态=published, 未过期)
├── searchArticles(tags, limit) → Article 表(状态=published)
├── searchViaDify(tags, limit) → Dify 知识库 fallback
└── getDimensionProducts(dimensionCode) → ProductDimensionMapping 维度匹配
// 营养模式下:Dify 返回 [RECOMMEND:{"tags":["益生菌","膳食纤维"],"types":["product"],"limit":3}]
// AIChatController 解析 → RecommendationService.search → 返回推荐列表
GrowthTaskService 管理预定义 DAILY/NEWBIE 任务(如 DAILY_AI = 每日 AI 对话)AIChatController 在每次 AI 对话后调用 growthTaskService.updateProgress(userId, "DAILY_AI", 1)MealRecommendController → MealRecommendService → 聚合用户上下文 → 调用 Dify 营养助手生成食谱触发场景:
| 场景 | 入口 | 报告类型 | 解读方式 |
|---|---|---|---|
| 健康报告上传 | report-upload.vue |
health_report | 上传后弹窗"去问浠宝/福宝" → 跳转 chat.vue?mode=report&reportId=X |
| 菌群报告完成 | gut-index.vue |
gut_flora | 分析完成后自动弹出 AI 解读入口 |
| DAN 报告确认 | DanReportController.confirm |
dan_assessment | 确认入库后自动触发 AI 解读任务 |
| 舌诊完成 | tongue-index.vue |
tongue | 舌诊结果页面→点击"AI 分析"→跳转 chat |
流程图:
用户上传报告
↓
解析/保存成功
↓
页面显示"AI 解读"按钮 (浠宝/福宝 头像 + "让XX帮你解读")
↓
用户点击 → 跳转 chat.vue?mode=report&reportId=X&dimension=body
↓
AIChatController.sendMessage(reportId=X)
↓
FamilyContextService.buildContext(userId, reportId) 注入报告详情
↓
Dify 根据报告数据生成个性化解读 + 建议
前端改动:
每个报告详情页底部增加"AI 解读"入口,使用用户设置的 mascot 角色:
<view class="ai-entry" @click="goAIChat">
<text class="ai-entry-icon">{{ mascotIcon }}</text>
<text class="ai-entry-text">让 {{ mascotName }} 帮你解读这份报告</text>
</view>
当前问题: 通用助手、营养助手、舌诊分析各自独立,上下文隔离。
目标架构: 单一增强型 Dify Chatbot,通过 inputs 实现场景路由:
Dify Workflow:
User Input → 场景分类节点 →
├─ 报告解读 → 注入报告上下文 → 专业解读
├─ 营养建议 → 注入健康分析 → 营养推荐
├─ 日常对话 → 家庭上下文 → 通用回答
├─ 任务生成 → 检测任务意图 → 生成任务
└─ 内容推荐 → 检测推荐意图 → 返回推荐标记
inputs 注入数据层级:
{
// === 基础层(每次必带)===
"user": {"nickname": "...", "role": "parent"},
"mascot_name": "XIBAO",
"mascot_gender": "女",
"mascot_persona": "温柔可爱的浠宝小女孩",
"children": [{"name": "小明", "age": 8, "taskCompletionRate": 0.8}],
"dimensionScores": {"body": 85, "mind": 72, "wisdom": 90, "action": 78, "wealth": 65},
// === 场景层(按需注入)===
// 报告解读场景
"reportDetail": { /* 完整报告数据 */ },
"reportSurvey": { /* 问卷数据 */ },
// 健康分析场景
"health_analysis": { /* findings, suggestions, nutritionTags */ },
// 对话记忆层
"conversation_summary": "家长很关心孩子的肠道健康...",
"user_facts": "小明对乳糖不耐受\n小明喜欢运动",
// 任务上下文
"recentTasks": [{"title": "每日阅读30分钟", "status": "in_progress"}]
}
方案: 在 Dify Workflow 中增加"任务生成"节点,当检测到用户意图包含"任务"、"计划"、"目标"等关键词时,按约定格式返回任务数据。
Dify 返回格式约定:
[TASK:{"title":"每日阅读30分钟","description":"选择一本感兴趣的课外书","deadline":"2026-07-25","dimension":"wisdom","rewardPoints":10}]
后端解析流程(新增 TaskParseService):
AIChatController
├── 调用 Dify → 获取 answer
├── 解析 [TASK:...] 标记 → TaskParseService
│ ├── 校验参数完整性
│ ├── 调用 GrowthTaskService.createDynamicTask() → 插入 growth_tasks 表(新增 type=AI_GENERATED)
│ └── 返回 taskId
├── 从 answer 移除 TASK 标记
└── 返回 result { answer, tasks: [...] }
GrowthTaskService 新增方法:
@Transactional
public Long createDynamicTask(Long userId, String title, String description,
String deadline, String dimension, Integer rewardPoints) {
// 新增 growth_tasks 记录(type=AI_GENERATED)
GrowthTask task = new GrowthTask();
task.setType("AI_GENERATED");
task.setTitle(title);
task.setDescription(description);
// 自动创建 GrowthTaskLog 并分配给对应用户
// 返回 taskId
}
数据库:
-- growth_tasks 新增 AI_GENERATED 类型
ALTER TABLE growth_tasks MODIFY COLUMN type
ENUM('DAILY','NEWBIE','AI_GENERATED') NOT NULL DEFAULT 'DAILY';
-- 新增字段
ALTER TABLE growth_tasks ADD COLUMN dimension VARCHAR(20) NULL COMMENT '五维维度(body/mind/wisdom/action/wealth)';
ALTER TABLE growth_tasks ADD COLUMN source_conversation_id VARCHAR(100) NULL COMMENT '来源AI会话ID';
前端展示:
AI 消息气泡中增加任务卡片,显示任务标题+描述+截止时间,点击"接受任务"按钮:
<view class="task-card" v-if="msg.tasks && msg.tasks.length > 0">
<view class="task-item" v-for="(task, ti) in msg.tasks" :key="ti">
<text class="task-title">📋 {{ task.title }}</text>
<text class="task-desc">{{ task.description }}</text>
<text class="task-deadline" v-if="task.deadline">截止:{{ task.deadline }}</text>
<button class="task-accept-btn" @click="acceptTask(task)">接受任务</button>
</view>
</view>
当前限制: 仅营养模式下支持 [RECOMMEND] 标记,普通对话模式不支持推荐。
增强方案: 所有 Dify 回复统一支持推荐标记
// 通用推荐解析(AIChatController.sendMessage 中统一处理)
if (answer.contains("[RECOMMEND]")) {
// 解析推荐标记 → RecommendationService.search
// 返回 recommendations 列表
}
推荐范围扩展:
| 推荐类型 | 匹配方式 | 数据源 |
|---|---|---|
| product | 营养标签 → 商品名称/描述 | Product(state=上架) |
| activity | 营养标签 → 活动标题/描述 | Activity(已发布+未过期) |
| article | 营养标签 → 文章标题/摘要/标签 | Article(已发布) |
| meal | 营养标签+健康分析 → Dify 生成 | MealRecommend |
推荐排序优化:
RecommendationService.search 增强:
1. 标签匹配度排序(匹配标签数多的优先)
2. 用户已购商品降权(不重复推荐已购买商品)
3. 五维维度匹配加分(与用户当前关注维度对齐的优先)
4. 时效性排序
当前 Dify 应用:
目标: 合并为单一应用 + 场景路由
Dify Workflow 设计:
[Start] User Input + Inputs (family context)
│
▼
[Classifier Node] 场景分类(基于 query + context)
├── "report" → [Report Analysis Agent]
│ ├── 解读报告数据
│ ├── 生成个性化建议
│ ├── [Recommend Items] → 输出 [RECOMMEND...]
│ └── [Generate Tasks] → 输出 [TASK...]
│
├── "nutrition" → [Nutrition Advisor Agent]
│ ├── 基于 health_analysis 给出营养建议
│ ├── [Recommend Items]
│ └── [Generate Tasks]
│
├── "meal" → [Meal Planner Agent]
│ ├── 根据健康数据和候选食材生成食谱
│ └── [Generate Tasks]
│
├── "task" → [Task Manager Agent]
│ ├── 创建/修改/查询任务
│ └── [TASK...]
│
└── "general" → [Family Assistant Agent]
├── 基于家庭上下文的日常问答
└── [Recommend Items] (可选)
所有 Agent 输出 → [Post Processor]
├── 合并 RECOMMEND / TASK 标记
└── 返回最终 answer
新增能力:
| 特性 | 实现方式 |
|---|---|
| 报告解读模式 | mode=report&reportId=X → 自动注入报告上下文 |
| 任务卡片渲染 | 解析 msg.tasks → 展示任务卡片 + 接受按钮 |
| 推荐卡片增强 | 全模式支持推荐展示(目前仅 nutrition) |
| 上下文来源显示 | 消息气泡上标注"基于你的健康报告"等来源标签 |
| Mascot 动效 | 浠宝/福宝各有不同的动画和语气 |
消息类型扩展:
// 消息结构
{
id: 'msg_xxx',
role: 'assistant',
content: '根据你的肠道报告...',
type: 'report_analysis' | 'nutrition' | 'general' | 'task',
recommendations: [
{ type: 'product', id: 1, name: '益生菌', ... }
],
tasks: [
{ id: 'task_1', title: '每日补充益生菌', description: '...', deadline: '...' }
],
sourceReport: { id: 123, type: 'gut_flora', score: 85 }
}
[RECOMMEND] 标记| 文件 | 改动类型 | 说明 |
|---|---|---|
AIChatController.java |
修改 | 通用化推荐解析、增加 task 标记解析 |
AIService.java |
修改 | 支持新 Dify Workflow 格式 |
GrowthTaskService.java |
修改 | 新增 createDynamicTask() 方法 |
FamilyContextService.java |
修改 | 增加任务上下文注入 |
RecommendationService.java |
修改 | 推荐排序优化 |
service/TaskParseService.java |
新增 | 解析 [TASK] 标记 |
entity/GrowthTask.java |
修改 | 新增 dimension/sourceConversationId 字段 |
schema.sql |
修改 | 新增字段定义 |
DatabaseInitializer.java |
修改 | 数据库迁移 |
| 文件 | 改动类型 | 说明 |
|---|---|---|
pages/ai/chat.vue |
修改 | 任务卡片渲染、全模式推荐展示 |
pages/health/report-upload.vue |
修改 | 上传后 AI 解读入口 |
pages/body-detail/health-report.vue |
修改 | 报告详情页 AI 入口 |
pages/health/gut-index.vue |
修改 | 菌群报告 AI 入口 |
pages/health/tongue-index.vue |
修改 | 舌诊 AI 入口 |
utils/api.js |
修改 | 新增 chat 相关 API 类型 |
components/AITaskCard.vue |
新增 | 任务卡片组件 |
| 配置 | 说明 |
|---|---|
| Dify Workflow 改造 | 合并为单一应用+场景分类 |
| 新增 Agent 节点 | Report Analysis / Task Manager |
| API Key 统一 | 由多个 API Key 合并为单一 Key |
Dify 端做场景分类 vs 后端分类
任务结构:growth_tasks vs 独立任务表
推荐触发:Dify 标记 vs 后端规则
AI 记忆:Dify 自带 vs 本地存储