Files
012-kaopeilian/docs/规划/全链路联调/Ai工作流/dify/对话流/与课程对话功能实施总结.md
111 998211c483 feat: 初始化考培练系统项目
- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
2026-01-24 19:33:28 +08:00

6.8 KiB
Raw Blame History

与课程对话功能实施总结

完成时间2025-10-14 功能状态: 已完成实施

📋 功能概述

基于 Dify 对话流实现了与课程的智能对话功能,用户可以在课程中心点击"对话"按钮,与课程内容进行智能问答互动。

🎯 技术方案

架构设计

前端 chat-course.vue
    ↓ (SSE)
后端 /api/v1/course/chat
    ↓ (HTTP Stream)
Dify 对话流 API

核心特性

  1. 流式响应:使用 SSEServer-Sent Events实现实时对话
  2. 会话管理conversation_id 由前端管理,支持多轮对话
  3. 无持久化:对话历史由 Dify 托管,系统不存储
  4. 纯文本:当前版本仅支持文本对话

📁 已修改文件

后端

  1. 配置文件kaopeilian-backend/app/core/config.py

    • 添加 DIFY_COURSE_CHAT_API_KEY = "app-lJzD6COkL8z7Eez8t6ZrYoJS"
  2. API 接口kaopeilian-backend/app/api/v1/course_chat.py(新建)

    • POST /api/v1/course/chat - 与课程对话接口
    • 实现 SSE 流式代理
    • 事件转换Dify → 前端友好格式
  3. 路由注册kaopeilian-backend/app/api/v1/__init__.py

    • 注册 course_chat_router/course 前缀

前端

  1. API 封装kaopeilian-frontend/src/api/courseChat.ts(新建)

    • courseChatApi.sendMessage() - 发送消息并返回 ReadableStream
    • TypeScript 类型定义:CourseChatEvent
  2. 对话页面kaopeilian-frontend/src/views/trainee/chat-course.vue

    • 删除 Coze 集成代码
    • 改用 Dify 对话流
    • 前端管理 conversationId
    • SSE 事件处理conversation_started / message_content / message_end

测试

  1. 测试脚本test_course_chat.py(新建)
    • 测试登录 → 首次对话 → 续接对话
    • 验证 SSE 事件流
    • 验证会话管理

🔄 SSE 事件流程

Dify 原始事件

workflow_started → node_finished → workflow_finished → message_end

后端转换后的事件

// 1. 会话开始(首次对话)
{"event": "conversation_started", "conversation_id": "xxx"}

// 2. 消息块(逐字返回,实现打字机效果)
{"event": "message_chunk", "chunk": "这"}
{"event": "message_chunk", "chunk": "门"}
{"event": "message_chunk", "chunk": "课"}
...

// 3. 消息结束
{"event": "message_end"}

// 4. 错误(如有)
{"event": "error", "message": "错误信息"}

📊 数据流

首次对话

用户输入问题
  ↓
前端调用 courseChatApi.sendMessage({course_id, query})
  ↓
后端转发到 Dify (无 conversation_id)
  ↓
Dify 创建新会话
  ↓
SSE: conversation_started → 前端保存 conversation_id
SSE: message_content → 前端显示答案
SSE: message_end → 对话完成

续接对话

用户输入问题
  ↓
前端调用 courseChatApi.sendMessage({course_id, query, conversation_id})
  ↓
后端转发到 Dify (带 conversation_id)
  ↓
Dify 基于上下文回答
  ↓
SSE: message_content → 前端显示答案
SSE: message_end → 对话完成

🧪 测试步骤

1. 启动服务

# 后端
cd kaopeilian-backend
docker-compose up -d

# 前端
cd kaopeilian-frontend
npm run dev

2. 运行测试脚本

python test_course_chat.py

3. 手动测试

  1. 登录系统
  2. 进入课程中心:http://localhost:3001/trainee/course-center
  3. 点击课程卡片的"对话"按钮
  4. 输入问题并发送
  5. 验证:
    • AI 回复显示正常
    • 可以进行多轮对话
    • 点击"清空对话"后会话重置

🎨 UI 特性

  • 欢迎界面(首次进入时显示)
  • 快速提问(预设问题点击发送)
  • 消息加载动画(三个点跳动)
  • 消息复制功能
  • 消息收藏功能
  • 侧边栏(知识要点、对话历史)
  • 响应式设计(移动端适配)

⚠️ 注意事项

1. conversation_id 管理

  • 前端使用 ref<string> 保存
  • 页面刷新后丢失(符合"每次进入对话页面都创建新会话"的需求)
  • 点击"清空对话"时重置

2. 流式打字机效果

  • 已实现Dify streaming 模式支持 event: message 逐字返回
  • 前端通过 message_chunk 事件逐字追加文本
  • 实现类似 ChatGPT 的实时打字效果

3. 超时设置

  • 后端180 秒httpx.Timeout
  • 前端:依赖浏览器默认(通常无限制)

4. 错误处理

  • 网络错误:显示友好提示
  • Dify API 错误:记录日志并返回错误事件
  • 解析错误:跳过当前行,继续处理

📝 API 接口文档

POST /api/v1/course/chat

请求体:

{
  "course_id": 1,
  "query": "这门课程讲什么?",
  "conversation_id": "可选,续接对话时传入"
}

响应SSE

data: {"event":"conversation_started","conversation_id":"xxx"}

data: {"event":"message_content","answer":"这门课程..."}

data: {"event":"message_end"}

🔍 关键代码片段

后端 SSE 生成

async def generate_stream():
    async with client.stream("POST", url, headers=headers, json=payload) as response:
        async for line in response.aiter_lines():
            if line.startswith("data: "):
                event_data = json.loads(line[6:])
                # 处理事件...
                yield f"data: {json.dumps(frontend_event)}\n\n"

前端 SSE 消费

const stream = await courseChatApi.sendMessage({...})
const reader = stream.getReader()
const decoder = new TextDecoder()

while (true) {
  const { done, value } = await reader.read()
  if (done) break
  
  const text = decoder.decode(value)
  // 解析 SSE 事件...
}

验收标准

  • 后端配置添加完成
  • 后端 API 接口实现
  • 后端路由注册
  • 前端 API 封装
  • 前端页面改造
  • SSE 流式响应正常
  • 会话管理正常
  • 错误处理完善
  • 无 linter 错误
  • 测试脚本创建

🚀 下一步

可选优化

  1. Markdown 渲染:如果 Dify 返回 Markdown 格式,前端可添加 Markdown 渲染器
  2. 会话持久化:如需要持久化历史,可在后端存储 conversation_id 与用户/课程的映射
  3. 实时打字效果:如 Dify 支持逐字返回,可修改事件处理逻辑
  4. 语音对话:未来可集成语音输入/输出

📚 相关文档

🎉 总结

成功将与课程对话功能从 Coze 迁移到 Dify 对话流,实现了:

完整的 SSE 流式对话
会话持续性conversation_id 管理)
前后端解耦API 代理模式)
良好的错误处理
友好的用户界面

代码质量:无 linter 错误,代码结构清晰,注释完善。