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

284 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 与课程对话功能实施总结
> 完成时间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
```
### 后端转换后的事件
```json
// 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. 启动服务
```bash
# 后端
cd kaopeilian-backend
docker-compose up -d
# 前端
cd kaopeilian-frontend
npm run dev
```
### 2. 运行测试脚本
```bash
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
**请求体:**
```json
{
"course_id": 1,
"query": "这门课程讲什么?",
"conversation_id": "可选,续接对话时传入"
}
```
**响应SSE**
```
data: {"event":"conversation_started","conversation_id":"xxx"}
data: {"event":"message_content","answer":"这门课程..."}
data: {"event":"message_end"}
```
## 🔍 关键代码片段
### 后端 SSE 生成
```python
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 消费
```typescript
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 事件...
}
```
## ✅ 验收标准
- [x] 后端配置添加完成
- [x] 后端 API 接口实现
- [x] 后端路由注册
- [x] 前端 API 封装
- [x] 前端页面改造
- [x] SSE 流式响应正常
- [x] 会话管理正常
- [x] 错误处理完善
- [x] 无 linter 错误
- [x] 测试脚本创建
## 🚀 下一步
### 可选优化
1. **Markdown 渲染**:如果 Dify 返回 Markdown 格式,前端可添加 Markdown 渲染器
2. **会话持久化**:如需要持久化历史,可在后端存储 conversation_id 与用户/课程的映射
3. **实时打字效果**:如 Dify 支持逐字返回,可修改事件处理逻辑
4. **语音对话**:未来可集成语音输入/输出
## 📚 相关文档
- [Dify 对话流 API 文档](./Dify对话流API文档.md)
- [实施计划](../../../------dify---.plan.md)
- [规范与约定-团队基线](../../规范与约定-团队基线.md)
- [联调经验汇总](../../联调经验汇总.md)
## 🎉 总结
成功将与课程对话功能从 Coze 迁移到 Dify 对话流,实现了:
✅ 完整的 SSE 流式对话
✅ 会话持续性conversation_id 管理)
✅ 前后端解耦API 代理模式)
✅ 良好的错误处理
✅ 友好的用户界面
代码质量:无 linter 错误,代码结构清晰,注释完善。