# ⚠️ 核心差异点速查卡

> 考培练系统 vs 参考代码的关键不同

## 🎯 最重要的差异：场景提示词

### 参考代码（简单对话）
```typescript
// 直接发送用户消息
await startChatStream({
  content: "你好",  // 仅用户输入
  bot_id: "7509379008556089379",
  user_id: "user_123"
})
```

### 考培练系统（场景驱动）
```typescript
// 首次消息：场景信息 + 用户输入
await fetch('/api/v1/practice/start', {
  method: 'POST',
  body: JSON.stringify({
    // ⚠️ 完整场景信息
    scene_name: "初次电话拜访客户",
    scene_background: "你是一名销售专员...",
    scene_ai_role: "AI扮演一位忙碌的采购经理...",
    scene_objectives: ["学会专业开场白", "建立信任"],
    scene_keywords: ["开场白", "需求挖掘"],
    
    // 用户输入
    user_message: "您好，我是XX公司的销售顾问",
    
    // ⚠️ 首次标记
    is_first: true
  })
})

// 后续消息：仅用户输入
await fetch('/api/v1/practice/start', {
  method: 'POST',
  body: JSON.stringify({
    user_message: "我们提供轻医美整体解决方案",
    conversation_id: "conv_abc123",  // 保持上下文
    is_first: false  // 不再包含场景信息
  })
})
```

## 📝 后端场景提示词构建

### 标准模板（Python）
```python
if request.is_first:
    scene_prompt = f"""
# 陪练场景设定

## 场景名称
{request.scene_name}

## 场景描述
{request.scene_description}

## 场景背景
{request.scene_background}

## AI角色要求
{request.scene_ai_role}

## 练习目标
{chr(10).join(f"{i+1}. {obj}" for i, obj in enumerate(request.scene_objectives))}

## 关键词
{', '.join(request.scene_keywords)}

---

现在开始陪练对话。请你严格按照上述场景设定扮演角色，与学员进行实战对话练习。
不要提及"场景设定"或"角色扮演"等元信息，直接进入角色开始对话。

学员的第一句话：{request.user_message}
"""
    # 发送给Coze
    stream = coze.chat.stream(
        bot_id=COZE_PRACTICE_BOT_ID,
        user_id=user_id,
        additional_messages=[Message.build_user_question_text(scene_prompt)]
    )
else:
    # 后续消息直接发送
    stream = coze.chat.stream(
        bot_id=COZE_PRACTICE_BOT_ID,
        user_id=user_id,
        additional_messages=[Message.build_user_question_text(request.user_message)],
        conversation_id=request.conversation_id  # 使用同一个对话ID
    )
```

## 🔄 完整对话流程对比

### 参考代码流程
```
用户输入 "你好"
  ↓
发送给Coze: "你好"
  ↓
AI回复: "你好，我是AI助手..."
  ↓
用户继续输入...
```

### 考培练系统流程
```
用户在场景确认页面点击"开始陪练"
  ↓
用户输入第一句话 "您好，我是XX公司的销售顾问"
  ↓
后端构建完整提示词:
  """
  # 陪练场景设定
  ## 场景名称: 初次电话拜访客户
  ## 场景背景: 你是一名销售专员...
  ## AI角色要求: AI扮演一位忙碌的采购经理...
  ## 练习目标:
  1. 学会专业的电话开场白
  2. 快速建立信任关系
  ---
  现在开始陪练。学员第一句话：您好，我是XX公司的销售顾问
  """
  ↓
发送给Coze: 完整提示词（Markdown格式）
  ↓
AI理解场景后回复: "喂？什么事？我现在很忙..."（扮演采购经理）
  ↓
用户继续输入 "我想占用您几分钟..."
  ↓
发送给Coze: "我想占用您几分钟..."（仅用户输入，不含场景）
  ↓
AI继续扮演角色回复...
```

## 💡 为什么这样设计？

### 1. AI角色一致性
- **问题**：如果不传场景信息，AI可能无法理解要扮演什么角色
- **解决**：首次消息包含完整场景设定，让AI明确角色

### 2. 对话上下文保持
- **机制**：使用conversation_id续接对话
- **效果**：后续消息AI会记住场景设定，无需重复发送

### 3. 性能优化
- **首次**：发送完整提示词（~500字符）
- **后续**：仅发送用户输入（~50字符）
- **节省**：减少Token消耗，提升响应速度

### 4. 用户体验
- **界面显示**：用户仅看到自己的输入，不看到场景设定文本
- **沉浸感**：用户专注于对话，不被技术细节干扰

## 📋 实现检查清单

### 后端实现
- [ ] 判断is_first标记
- [ ] 构建Markdown格式场景提示词
- [ ] 拼接user_message
- [ ] 发送给Coze
- [ ] 保存conversation_id

### 前端实现
- [ ] 页面加载时获取场景信息
- [ ] 首次发送时携带完整场景参数
- [ ] 设置is_first=true
- [ ] 保存返回的conversation_id
- [ ] 后续消息仅发送user_message和conversation_id
- [ ] 设置is_first=false

### 测试验证
- [ ] 首次消息AI回复符合场景角色
- [ ] 后续消息AI持续扮演角色
- [ ] conversation_id正确续接
- [ ] 场景信息不显示在消息列表中

## 🚨 常见错误

### ❌ 错误1：每次都发送场景信息
```python
# 错误示范
stream = coze.chat.stream(
    additional_messages=[Message.build_user_question_text(
        scene_prompt + user_message  # 每次都拼接，浪费Token
    )]
)
```

### ✅ 正确：仅首次发送
```python
# 正确示范
if is_first:
    message_content = scene_prompt + user_message
else:
    message_content = user_message

stream = coze.chat.stream(
    additional_messages=[Message.build_user_question_text(message_content)],
    conversation_id=conversation_id  # 关键：保持上下文
)
```

### ❌ 错误2：不保存conversation_id
```python
# 错误示范：每次创建新对话
stream = coze.chat.stream(
    bot_id=bot_id,
    user_id=user_id,
    additional_messages=[...]
    # 没有传conversation_id，AI会忘记场景
)
```

### ✅ 正确：保持对话连续性
```python
# 正确示范
stream = coze.chat.stream(
    bot_id=bot_id,
    user_id=user_id,
    additional_messages=[...],
    conversation_id=saved_conversation_id  # 使用同一个ID
)
```

### ❌ 错误3：前端显示场景提示词
```javascript
// 错误示范：用户看到场景设定文本
messageList.value.push({
  role: 'user',
  content: scenePrompt + userInput  // 显示完整提示词
})
```

### ✅ 正确：仅显示用户输入
```javascript
// 正确示范：用户仅看到自己的输入
messageList.value.push({
  role: 'user',
  content: userInput  // 仅显示用户输入
})

// 后端负责拼接场景信息
```

## 📊 数据流示例

### 首次消息数据流
```
前端发送:
{
  scene_name: "初次电话拜访",
  scene_background: "...",
  scene_ai_role: "...",
  scene_objectives: [...],
  user_message: "您好",
  is_first: true
}
  ↓
后端构建:
"""
# 陪练场景设定
## 场景名称: 初次电话拜访
...
学员第一句话：您好
"""
  ↓
发送给Coze:
Message.build_user_question_text(完整提示词)
  ↓
前端显示:
用户: 您好
AI: 喂？什么事？
```

### 后续消息数据流
```
前端发送:
{
  user_message: "我想占用您几分钟",
  conversation_id: "conv_abc123",
  is_first: false
}
  ↓
后端直接发送:
Message.build_user_question_text("我想占用您几分钟")
  ↓
发送给Coze:
使用conversation_id, AI记住之前的场景
  ↓
前端显示:
用户: 我想占用您几分钟
AI: 好吧，说吧，你有什么产品？
```

## 🎓 学习建议

### 新手开发者
1. 先理解参考代码的基本对话流程
2. 再理解场景提示词的必要性
3. 对比两种实现方式的差异
4. 按照文档实现考培练版本

### 有经验开发者
1. 快速浏览参考代码结构
2. 重点关注场景提示词构建逻辑
3. 理解is_first标记的作用
4. 直接开始实现

## 📞 技术支持

遇到问题时查阅：
1. **场景不生效** → 检查is_first标记和提示词构建
2. **AI忘记角色** → 检查conversation_id是否正确续接
3. **Token消耗大** → 检查是否每次都发送场景信息
4. **前端显示问题** → 检查消息列表是否只显示user_message

---

**版本**：v1.0
**更新**：2025-10-13
**维护**：考培练系统开发团队

**快速链接**：
- [完整技术方案](./陪练功能技术方案.md)
- [API接口规范](./陪练功能API接口规范.md)
- [参考代码分析](./参考代码分析-Training模块.md)
- [开发任务清单](./📋开发任务清单.md)

