# 陪练功能数据流程图 ## 一、总体流程概览 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 考培练系统 │ │ │ │ ┌────────────────┐ ┌────────────────┐ │ │ │ 陪练中心入口 │ │ 课程中心入口 │ │ │ │ (直接模式) │ │ (课程模式) │ │ │ └───────┬────────┘ └───────┬────────┘ │ │ │ │ │ │ │ 选择场景 │ 提取场景 │ │ │ │ │ │ ▼ ▼ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ 陪练对话页面 (统一入口) │ │ │ │ - 实时SSE对话 │ │ │ │ - 消息展示 │ │ │ │ - 对话控制 │ │ │ └────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ``` ## 二、陪练中心入口流程(直接模式) ### 2.1 场景选择流程 ``` ┌──────┐ │ 学员 │ └───┬──┘ │ │ 1. 访问陪练中心 ▼ ┌─────────────────────────┐ │ 陪练中心页面 │ │ /trainee/ai-practice-center │ └───────┬─────────────────┘ │ │ 2. 获取场景列表 ▼ ┌───────────────────────────┐ │ GET /api/v1/practice/scenes│ │ 参数:筛选条件、分页 │ └───────┬───────────────────┘ │ │ 3. 查询数据库 ▼ ┌──────────────────────┐ │ MySQL: practice_scenes│ │ WHERE status='active' │ │ AND is_deleted=false│ └───────┬──────────────┘ │ │ 4. 返回场景列表 ▼ ┌──────────────────────┐ │ 场景卡片展示 │ │ - 名称、描述 │ │ - 类型、难度标签 │ │ - 统计信息 │ └───────┬──────────────┘ │ │ 5. 点击"开始陪练" ▼ ┌──────────────────────┐ │ 跳转到对话页面 │ │ 携带场景参数 │ └──────────────────────┘ ``` ### 2.2 对话流程 ``` ┌──────┐ │ 学员 │ └───┬──┘ │ │ 1. 进入对话页面 ▼ ┌───────────────────────────┐ │ 陪练对话页面 │ │ /trainee/ai-practice │ │ query: sceneId, mode=direct│ └───────┬───────────────────┘ │ │ 2. 加载场景详情 ▼ ┌─────────────────────────────┐ │ GET /api/v1/practice/scenes/1│ └───────┬─────────────────────┘ │ │ 3. 返回场景完整信息 │ (background, ai_role, objectives) ▼ ┌──────────────────────┐ │ 显示场景背景和目标 │ └───────┬──────────────┘ │ │ 4. 用户输入第一条消息 ▼ ┌────────────────────────────┐ │ POST /api/v1/practice/start│ │ 请求体: │ │ - scene_id: 1 │ │ - scene_name │ │ - scene_description │ │ - scene_background │ │ - scene_ai_role │ │ - scene_objectives │ │ - scene_keywords │ │ - user_message │ │ - is_first: true │ └───────┬───────────────────┘ │ │ 5. ⚠️ 后端构建完整场景提示词 │ (关键步骤) ▼ ┌──────────────────────────────┐ │ 构建Markdown格式场景文本: │ │ # 陪练场景设定 │ │ ## 场景名称 │ │ 初次电话拜访客户 │ │ ## 场景背景 │ │ 你是一名销售专员... │ │ ## AI角色要求 │ │ AI扮演一位忙碌的采购经理... │ │ ## 练习目标 │ │ 1. 学会专业的电话开场白 │ │ 2. 快速建立信任关系 │ │ --- │ │ 现在开始陪练对话... │ │ 学员的第一句话:您好... │ └───────┬──────────────────────┘ │ │ 6. 发送完整提示词给Coze ▼ ┌──────────────────────────┐ │ Python FastAPI后端 │ │ coze_service.py │ └───────┬─────────────────┘ │ │ 7. 调用Coze API(发送场景提示词) ▼ ┌─────────────────────────────┐ │ Coze Chat API (流式) │ │ https://api.coze.cn │ │ Bot ID: 7560643598174683145 │ │ │ │ Message.build_user_question_text(│ │ 完整的场景提示词 Markdown │ │ ) │ └───────┬─────────────────────┘ │ │ 8. Coze AI理解场景并生成回复 │ (AI根据场景扮演角色) ▼ ┌──────────────────────────┐ │ AI推理生成对话内容 │ │ - 理解场景背景 │ │ - 扮演指定角色 │ │ - 符合难度设定 │ └───────┬─────────────────┘ │ │ 9. SSE流式返回 ▼ ┌──────────────────────────┐ │ SSE事件流 │ │ event: message.delta │ │ data: {"content":"您"} │ │ │ │ event: message.delta │ │ data: {"content":"好"} │ │ │ │ event: message.completed │ │ event: done │ └───────┬─────────────────┘ │ │ 10. 前端实时显示 ▼ ┌──────────────────────┐ │ AI消息打字效果展示 │ │ (AI已理解场景角色) │ └───────┬──────────────┘ │ │ 11. 用户继续对话(后续消息) ▼ ┌────────────────────────────┐ │ POST /api/v1/practice/start│ │ 请求体: │ │ - user_message │ │ - conversation_id │ │ - is_first: false │ │ (⚠️不再包含场景信息) │ └───────┬───────────────────┘ │ │ 12. 直接发送用户消息 │ (重复步骤7-11) ▼ ┌──────────────────────┐ │ 多轮对话交互 │ │ 使用conversation_id │ │ 保持对话上下文 │ │ AI持续扮演角色 │ └──────────────────────┘ ``` ## 三、课程中心入口流程(课程模式) ### 3.1 场景提取流程 ``` ┌──────┐ │ 学员 │ └───┬──┘ │ │ 1. 访问课程中心 ▼ ┌─────────────────────────┐ │ 课程中心页面 │ │ /trainee/course-center │ └───────┬─────────────────┘ │ │ 2. 点击课程卡片"陪练"按钮 ▼ ┌───────────────────────────────┐ │ POST /api/v1/practice/extract-scene│ │ 请求体: │ │ { "course_id": 5 } │ └───────┬───────────────────────────┘ │ │ 3. 调用Dify工作流 ▼ ┌──────────────────────────────────┐ │ Dify API (流式) │ │ POST /v1/workflows/run │ │ URL: dify.ireborn.com.cn │ │ API Key: app-rYP6LNM4iPmNjIHns... │ │ Workflow ID: 待确认 │ └───────┬──────────────────────────┘ │ │ 4. Dify从数据库获取课程信息 ▼ ┌──────────────────────────┐ │ MySQL: courses │ │ - 课程名称 │ │ - 课程描述 │ │ - 关联的知识点 │ │ - 学习资料 │ └───────┬─────────────────┘ │ │ 5. Dify AI分析生成场景 │ (大模型推理) ▼ ┌──────────────────────────┐ │ Dify SSE事件流 │ │ event: workflow_started │ │ event: text_chunk │ │ event: workflow_finished │ └───────┬─────────────────┘ │ │ 6. 后端消费SSE,聚合结果 ▼ ┌──────────────────────────┐ │ 解析场景JSON数据 │ │ { │ │ name: "场景名称", │ │ description: "...", │ │ background: "...", │ │ ai_role: "...", │ │ objectives: [...], │ │ keywords: [...] │ │ } │ └───────┬─────────────────┘ │ │ 7. 返回场景数据给前端 ▼ ┌──────────────────────────┐ │ 前端接收场景数据 │ └───────┬─────────────────┘ │ │ 8. 跳转到对话页面 ▼ ┌──────────────────────────┐ │ /trainee/ai-practice │ │ query: │ │ - mode=course │ │ - courseId=5 │ │ - sceneData=JSON.stringify(scene)│ └──────────────────────────┘ ``` ### 3.2 课程模式对话流程 课程模式的对话流程与直接模式基本相同,区别在于: 1. 场景数据来自URL参数(Dify生成)而非数据库查询 2. 首次消息会带上课程上下文信息 ``` ┌──────┐ │ 学员 │ └───┬──┘ │ │ 1. 从URL解析场景数据 ▼ ┌──────────────────────────┐ │ const sceneData = │ │ JSON.parse( │ │ route.query.sceneData│ │ ) │ └───────┬─────────────────┘ │ │ 2. 显示Dify生成的场景 ▼ ┌──────────────────────┐ │ 场景背景和目标展示 │ │ (来自Dify) │ └───────┬──────────────┘ │ │ 3-9. 对话流程 │ (同直接模式) ▼ ┌──────────────────────┐ │ SSE流式对话交互 │ └──────────────────────┘ ``` ## 四、场景管理流程(Manager) ### 4.1 创建场景流程 ``` ┌──────┐ │管理员 │ └───┬──┘ │ │ 1. 访问场景管理页面 ▼ ┌────────────────────────────────┐ │ 场景管理页面 │ │ /manager/practice-scene-management│ └───────┬────────────────────────┘ │ │ 2. 点击"新增场景" ▼ ┌──────────────────────┐ │ 打开创建场景表单 │ │ - 场景名称 │ │ - 场景描述 │ │ - 类型、难度 │ │ - 场景背景 │ │ - AI角色描述 │ │ - 练习目标(数组) │ │ - 关键词(数组) │ └───────┬──────────────┘ │ │ 3. 填写并提交表单 ▼ ┌──────────────────────────────┐ │ POST /api/v1/manager/practice-scenes│ │ 请求体:CreateSceneRequest │ └───────┬──────────────────────┘ │ │ 4. 后端验证数据 ▼ ┌──────────────────────┐ │ 字段验证: │ │ - 必填字段检查 │ │ - 长度限制 │ │ - 类型枚举验证 │ │ - 名称唯一性 │ └───────┬──────────────┘ │ │ 5. 写入数据库 ▼ ┌──────────────────────┐ │ INSERT INTO │ │ practice_scenes │ │ VALUES (...) │ └───────┬──────────────┘ │ │ 6. 返回创建的场景 ▼ ┌──────────────────────┐ │ 前端刷新列表 │ │ 提示创建成功 │ └──────────────────────┘ ``` ### 4.2 场景列表查询流程 ``` ┌──────┐ │管理员 │ └───┬──┘ │ │ 1. 访问场景管理页面 ▼ ┌────────────────────────────────┐ │ GET /api/v1/manager/practice-scenes│ │ 参数: │ │ - page, size (分页) │ │ - type, difficulty (筛选) │ │ - search (关键词) │ └───────┬────────────────────────┘ │ │ 2. 构建查询条件 ▼ ┌──────────────────────────┐ │ SELECT * FROM │ │ practice_scenes │ │ WHERE is_deleted = false │ │ AND type = ? │ │ AND difficulty = ? │ │ AND name LIKE ? │ │ ORDER BY created_at DESC │ │ LIMIT ? OFFSET ? │ └───────┬─────────────────┘ │ │ 3. 返回分页数据 ▼ ┌──────────────────────────┐ │ { │ │ items: [...], │ │ total: 15, │ │ page: 1, │ │ page_size: 20 │ │ } │ └───────┬─────────────────┘ │ │ 4. 前端渲染列表 ▼ ┌──────────────────────────┐ │ 场景列表展示 │ │ - 筛选器 │ │ - 场景卡片 │ │ - 分页器 │ │ - 操作按钮 │ └──────────────────────────┘ ``` ## 五、SSE流式通信详细流程 ### 5.1 SSE连接建立 ``` ┌────────┐ ┌────────┐ ┌──────────┐ │ 前端 │ │ 后端 │ │ Coze API │ └───┬────┘ └───┬────┘ └─────┬────┘ │ │ │ │ 1. fetch POST /practice/start │ ├─────────────────────────>│ │ │ │ │ │ │ 2. 构建场景上下文 │ │ │ (background + ai_role) │ │ │ │ │ │ 3. coze.chat.stream() │ │ ├───────────────────────────>│ │ │ │ │ │ │ 4. 开始流式处理 │ │<───────────────────────────┤ │ │ event: conversation.chat.created │<─────────────────────────┤ │ │ 5. 设置conversation_id │ │ │ │ │ │ │<───────────────────────────┤ │<─────────────────────────┤ event: message.delta │ │ 6. 追加内容: "您" │ data: {"content":"您"} │ │ │ │ │ │<───────────────────────────┤ │<─────────────────────────┤ event: message.delta │ │ 7. 追加内容: "好" │ data: {"content":"好"} │ │ │ │ │ │<───────────────────────────┤ │<─────────────────────────┤ event: message.delta │ │ 8. 追加内容: "," │ data: {"content":","} │ │ │ │ │ ... (持续接收增量) ... │ │ │ │ │ │<───────────────────────────┤ │<─────────────────────────┤ event: message.completed │ │ 9. 消息完成标记 │ │ │ │ │ │ │<───────────────────────────┤ │<─────────────────────────┤ event: conversation.completed│ │ 10. 对话完成 │ data: {"token_count":156} │ │ │ │ │<─────────────────────────┤ │ │ event: done │ │ │ 11. 关闭SSE连接 │ │ │ │ │ ``` ### 5.2 SSE错误处理流程 ``` ┌────────┐ ┌────────┐ ┌──────────┐ │ 前端 │ │ 后端 │ │ Coze API │ └───┬────┘ └───┬────┘ └─────┬────┘ │ │ │ │ 1. SSE连接正常 │ │ │ │ │ │ │ │ 2. 网络错误 │ │<───────────────────────────┤ │ │ Exception: Network Error │ │ │ │ │ │ 3. 捕获异常 │ │<─────────────────────────┤ │ │ event: error │ │ │ data: {"error":"..."} │ │ │ │ │ │ 4. 前端显示错误提示 │ │ │ ElMessage.error(...) │ │ │ │ │ │ 5. 关闭SSE连接 │ │ │ │ │ ``` ## 六、数据流转汇总 ### 6.1 数据流向图 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 数据流向总览 │ └─────────────────────────────────────────────────────────────────┘ 用户输入 │ ▼ 前端Vue页面 │ ├─ 陪练中心: 从MySQL读取场景 ────> practice_scenes表 │ │ │ ▼ └─ 课程中心: Dify提取场景 ────> courses表 + knowledge_points表 │ ▼ Dify工作流分析 │ ▼ 生成场景JSON 场景数据 │ ▼ 前端对话页面 │ │ 用户消息 + 场景上下文 ▼ 后端FastAPI │ │ 构建完整Prompt ▼ Coze Chat API │ │ AI推理 ▼ SSE流式响应 │ ├─ message.delta (增量) ├─ message.completed (完成) └─ conversation.completed (结束) │ ▼ 前端实时展示 │ └─ 对话历史由Coze管理(不存MySQL) ``` ### 6.2 核心数据对象流转 ``` 1. 场景数据 (PracticeScene) MySQL practice_scenes表 ↓ Python Model (SQLAlchemy) ↓ Pydantic Schema ↓ JSON Response ↓ TypeScript Interface ↓ Vue Reactive Data 2. 对话消息 (Message) 用户输入 (Frontend) ↓ HTTP Request Body ↓ Python Request Model ↓ Coze Message Object ↓ Coze API Request ↓ AI Response (SSE Stream) ↓ Frontend Message Array 3. Dify场景 (ExtractedScene) Course Data (MySQL) ↓ Dify Workflow Input ↓ AI Analysis ↓ Workflow Output (JSON) ↓ Python Response Model ↓ Frontend Scene Object ``` ## 七、关键时序说明 ### 7.1 用户完整陪练流程时序 ``` 时刻T0: 用户访问陪练中心 ↓ (立即) 时刻T1: 加载场景列表 (MySQL查询 ~100ms) ↓ (用户浏览场景 ~30s) 时刻T2: 用户选择场景 ↓ (立即) 时刻T3: 跳转到对话页面 ↓ (立即) 时刻T4: 加载场景详情 (MySQL查询 ~100ms) ↓ (用户阅读背景 ~20s) 时刻T5: 用户输入第一条消息 ↓ (立即) 时刻T6: 发送SSE请求到后端 (网络延迟 ~50ms) ↓ 时刻T7: 后端调用Coze API (网络延迟 ~100ms) ↓ 时刻T8: 开始接收AI响应流 (首字节延迟 ~500ms) ↓ (流式传输 ~2-5s) 时刻T9: AI回复完成 ↓ (用户阅读 ~10s) 时刻T10: 用户继续输入下一条消息 ↓ (重复T5-T10) ``` ### 7.2 Dify场景提取时序 ``` 时刻T0: 用户点击课程"陪练"按钮 ↓ (立即) 时刻T1: 前端显示"提取场景中..." ↓ (立即) 时刻T2: 发送HTTP请求到后端 (网络延迟 ~50ms) ↓ 时刻T3: 后端调用Dify工作流 (网络延迟 ~100ms) ↓ 时刻T4: Dify查询数据库 (MySQL ~200ms) ↓ 时刻T5: Dify AI分析推理 (大模型 ~10-30s) ↓ 时刻T6: 后端接收完整场景数据 ↓ (立即) 时刻T7: 返回给前端 (网络延迟 ~50ms) ↓ (立即) 时刻T8: 跳转到对话页面 ``` ## 八、异常流程处理 ### 8.1 网络异常流程 ``` 正常流程 │ ▼ 发送SSE请求 │ ├─ 成功 ──> 接收流式数据 │ └─ 失败 ──> catch Error │ ▼ 判断错误类型 │ ├─ NetworkError ──> 提示"网络错误,请检查连接" │ └─> 提供重试按钮 │ ├─ TimeoutError ──> 提示"请求超时,请稍后重试" │ └─> 自动重试(最多3次) │ └─ ServerError ──> 提示"服务器错误,请联系管理员" └─> 记录错误日志 ``` ### 8.2 Coze API异常流程 ``` 后端调用Coze │ ▼ coze.chat.stream() │ ├─ 成功 ──> 正常SSE流 │ └─ 失败 ──> catch CozePyError │ ▼ 判断错误 │ ├─ Token过期 ──> 刷新Token + 重试 │ ├─ 余额不足 ──> 通知管理员 + 提示用户稍后重试 │ ├─ Bot不存在 ──> 检查Bot配置 + 使用备用Bot │ └─ API限流 ──> 等待重试 + 记录日志 ``` ## 九、性能优化要点 ### 9.1 数据库查询优化 ``` 场景列表查询 │ ├─ 使用索引: idx_type, idx_difficulty, idx_status ├─ 分页限制: LIMIT + OFFSET ├─ 只查必要字段: SELECT id, name, description, type... └─ 缓存热门场景 (可选) ``` ### 9.2 SSE连接优化 ``` SSE流式传输 │ ├─ 使用HTTP/2 (多路复用) ├─ 合理设置超时: 180秒 ├─ 心跳保活: ping event └─ 断线重连: 保存conversation_id ``` ### 9.3 前端渲染优化 ``` 消息列表展示 │ ├─ 虚拟滚动 (消息数 > 100) ├─ 防抖输入: debounce 300ms ├─ 消息缓存: localStorage └─ 懒加载历史消息 ``` --- **文档版本**:v1.0 **最后更新**:2025-10-13 **维护人**:考培练系统开发团队