update at 2025-10-14 21:52:11
This commit is contained in:
522
CHAT_V2.1_UPDATE.md
Normal file
522
CHAT_V2.1_UPDATE.md
Normal file
@@ -0,0 +1,522 @@
|
||||
# 聊天模块 V2.1 优化更新
|
||||
|
||||
## 📅 更新日期
|
||||
2025年10月14日
|
||||
|
||||
## 🎯 本次优化内容
|
||||
|
||||
### 1. ✅ 右侧对话列表可折叠
|
||||
|
||||
**功能描述**:右侧的对话列表现在支持折叠/展开,节省屏幕空间。
|
||||
|
||||
**实现细节**:
|
||||
- 在对话头部添加折叠按钮
|
||||
- 按钮图标根据状态变化(ChevronLeft / ChevronRight)
|
||||
- 按钮文字显示"显示列表" / "隐藏列表"
|
||||
- 使用 CSS transition 实现平滑动画
|
||||
|
||||
**代码实现**:
|
||||
```vue
|
||||
<!-- 头部按钮 -->
|
||||
<n-button text @click="showSidebar = !showSidebar">
|
||||
<n-icon :component="showSidebar ? ChevronRightIcon : ChevronLeftIcon" />
|
||||
<span>{{ showSidebar ? '隐藏列表' : '显示列表' }}</span>
|
||||
</n-button>
|
||||
|
||||
<!-- CSS 动画 -->
|
||||
<style>
|
||||
.topics-sidebar {
|
||||
width: 320px;
|
||||
transition: all 0.3s ease;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.topics-sidebar:not(.visible) {
|
||||
width: 0;
|
||||
border-left: none;
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
**使用方法**:
|
||||
- 点击对话头部右上角的折叠按钮
|
||||
- 对话列表会平滑地隐藏/显示
|
||||
- 响应式设计:小屏幕时自动变为浮动面板
|
||||
|
||||
---
|
||||
|
||||
### 2. ✅ AI 模型选择列表动态加载
|
||||
|
||||
**功能描述**:模型选择器现在会动态读取"模型服务"中已配置的所有可用模型。
|
||||
|
||||
**实现细节**:
|
||||
```typescript
|
||||
// 从 modelStore 动态读取模型列表
|
||||
const modelOptions = computed(() => {
|
||||
const services = modelStore.providers
|
||||
const options: any[] = []
|
||||
|
||||
services.forEach((service: any) => {
|
||||
if (service.enabled && service.models) {
|
||||
service.models.forEach((model: any) => {
|
||||
options.push({
|
||||
label: `${service.name} | ${model.name}`,
|
||||
key: `${service.id}:${model.id}`,
|
||||
icon: () => h(NIcon, { component: BrainIcon })
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return options
|
||||
})
|
||||
|
||||
// 显示选中的模型名称
|
||||
const selectedModelName = computed(() => {
|
||||
if (!selectedModel.value) return undefined
|
||||
const [serviceId, modelId] = selectedModel.value.split(':')
|
||||
const service = modelStore.providers.find((s: any) => s.id === serviceId)
|
||||
const model = service?.models?.find((m: any) => m.id === modelId)
|
||||
return model ? `${service?.name} | ${model.name}` : undefined
|
||||
})
|
||||
```
|
||||
|
||||
**工作流程**:
|
||||
1. 用户在"模型服务"页面添加服务(如火山引擎、OpenAI)
|
||||
2. 服务连接成功后,其模型会自动出现在聊天页面的模型选择器中
|
||||
3. 选择模型后,该模型会被用于当前对话
|
||||
4. 模型信息格式:`服务名 | 模型名`(如"火山引擎 | doubao-1.5-pro-32k")
|
||||
|
||||
**特性**:
|
||||
- ✅ 实时同步:添加新服务后立即可用
|
||||
- ✅ 多服务支持:同时显示所有服务的模型
|
||||
- ✅ 清晰标识:服务名和模型名分开显示
|
||||
- ✅ 图标辅助:每个选项都有模型图标
|
||||
|
||||
---
|
||||
|
||||
### 3. ✅ MCP 服务支持(基础架构)
|
||||
|
||||
**功能描述**:聊天对话中现在支持选择和使用 MCP 服务器。
|
||||
|
||||
**实现细节**:
|
||||
|
||||
#### 3.1 MCP 服务器列表动态加载
|
||||
```typescript
|
||||
// 从 mcpStore 读取已连接的服务器
|
||||
const mcpOptions = computed(() => {
|
||||
const options: any[] = [
|
||||
{
|
||||
label: '不启用 MCP 服务',
|
||||
key: 'none'
|
||||
}
|
||||
]
|
||||
|
||||
// 添加已连接的服务器
|
||||
mcpStore.connectedServers.forEach((server) => {
|
||||
const toolCount = server.capabilities?.tools?.length || 0
|
||||
options.push({
|
||||
label: `${server.name} (${toolCount} 个工具)`,
|
||||
key: server.id,
|
||||
icon: () => h(NIcon, { component: PlugIcon })
|
||||
})
|
||||
})
|
||||
|
||||
return options
|
||||
})
|
||||
|
||||
// 显示选中的 MCP 服务器名称
|
||||
const selectedMCPName = computed(() => {
|
||||
if (!selectedMCP.value || selectedMCP.value === 'none') return '不启用 MCP 服务'
|
||||
const server = mcpStore.servers.find(s => s.id === selectedMCP.value)
|
||||
return server?.name || '未知服务'
|
||||
})
|
||||
```
|
||||
|
||||
#### 3.2 MCP 服务器传递到聊天服务
|
||||
```typescript
|
||||
// ChatLayout.vue - 发送消息时传递 MCP 服务器 ID
|
||||
const handleSendMessage = async () => {
|
||||
const mcpId = selectedMCP.value === 'none' ? undefined : selectedMCP.value
|
||||
await store.sendMessageStream(
|
||||
content,
|
||||
selectedModel.value,
|
||||
mcpId, // 传递 MCP 服务器 ID
|
||||
() => { scrollToBottom() }
|
||||
)
|
||||
}
|
||||
|
||||
// chatStore.ts - 转发到 chatService
|
||||
const sendMessageStream = async (
|
||||
content: string,
|
||||
model?: string,
|
||||
mcpServerId?: string, // 新增参数
|
||||
onChunk?: (chunk: string) => void
|
||||
) => {
|
||||
await chatService.sendMessageStream(
|
||||
{ topicId, content, model, stream: true },
|
||||
onChunk,
|
||||
mcpServerId // 传递给 service
|
||||
)
|
||||
}
|
||||
|
||||
// chatService.ts - 接收并准备使用
|
||||
async sendMessageStream(
|
||||
options: SendMessageOptions,
|
||||
onChunk: (event: StreamEvent) => void,
|
||||
mcpServerId?: string // 接收 MCP 服务器 ID
|
||||
): Promise<void> {
|
||||
// TODO: 在这里实现 MCP 工具调用逻辑
|
||||
await this.callModelStream(conversation, model, onChunk, mcpServerId)
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.3 自动加载和重连
|
||||
```typescript
|
||||
// 初始化时加载 MCP 服务器
|
||||
onMounted(async () => {
|
||||
store.initialize()
|
||||
scrollToBottom()
|
||||
|
||||
// 加载 MCP 服务器配置
|
||||
mcpStore.loadServers()
|
||||
|
||||
// 尝试自动重连之前已连接的服务器
|
||||
try {
|
||||
await mcpStore.autoReconnect()
|
||||
} catch (error) {
|
||||
console.warn('自动重连 MCP 服务器失败:', error)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
**工作流程**:
|
||||
1. 用户在"MCP 设置"页面添加并连接服务器
|
||||
2. 服务器连接成功后,自动出现在聊天页面的 MCP 选择器中
|
||||
3. 选择服务器后,该服务器 ID 会被传递到聊天服务
|
||||
4. 聊天服务可以使用该服务器的工具(待实现)
|
||||
|
||||
**当前状态**:
|
||||
- ✅ 基础架构完成:MCP 服务器 ID 可以从 UI 传递到服务层
|
||||
- ✅ 服务器列表动态加载:实时显示已连接的服务器和工具数量
|
||||
- ✅ 自动重连:页面刷新后自动重连之前的服务器
|
||||
- ⏳ 工具调用逻辑:已预留接口,等待实现
|
||||
|
||||
**下一步实现**:
|
||||
```typescript
|
||||
// 在 callModelStream 中检测 AI 的工具调用请求
|
||||
private async callModelStream(
|
||||
conversation: Conversation,
|
||||
model: string | undefined,
|
||||
onChunk: (chunk: string) => void,
|
||||
mcpServerId?: string
|
||||
): Promise<void> {
|
||||
if (mcpServerId) {
|
||||
// 1. 获取 MCP 服务器的可用工具列表
|
||||
const server = mcpStore.servers.find(s => s.id === mcpServerId)
|
||||
const tools = server?.capabilities?.tools || []
|
||||
|
||||
// 2. 将工具列表传递给 AI 模型
|
||||
// 让 AI 知道可以调用哪些工具
|
||||
|
||||
// 3. 如果 AI 返回工具调用请求,执行工具
|
||||
// const toolResult = await mcpStore.callTool(mcpServerId, toolName, params)
|
||||
|
||||
// 4. 将工具结果返回给 AI,让它生成最终回复
|
||||
}
|
||||
|
||||
// 正常的流式响应
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 完整功能清单
|
||||
|
||||
### 已完成功能
|
||||
1. ✅ 左侧导航可折叠(V2.0)
|
||||
2. ✅ 右侧对话列表(V2.0)
|
||||
3. ✅ **右侧对话列表可折叠(V2.1 新增)**
|
||||
4. ✅ 工具栏 - MCP 服务选择
|
||||
5. ✅ **工具栏 - 模型动态加载(V2.1 优化)**
|
||||
6. ✅ **MCP 服务集成基础架构(V2.1 新增)**
|
||||
7. ✅ 快捷操作按钮
|
||||
8. ✅ 消息实时更新
|
||||
9. ✅ 消息条数正确显示
|
||||
|
||||
### 待实现功能
|
||||
1. ⏳ MCP 工具调用实际逻辑
|
||||
2. ⏳ Markdown 渲染
|
||||
3. ⏳ 代码语法高亮
|
||||
4. ⏳ 真正的流式响应(SSE)
|
||||
5. ⏳ 图片和文件消息
|
||||
|
||||
---
|
||||
|
||||
## 🎬 使用示例
|
||||
|
||||
### 场景1:使用特定模型对话
|
||||
|
||||
1. **添加模型服务**
|
||||
```
|
||||
侧边栏 → 模型服务 → 添加服务
|
||||
例如:添加"火山引擎"服务
|
||||
```
|
||||
|
||||
2. **在聊天中选择模型**
|
||||
```
|
||||
聊天页面 → 工具栏 → 点击"选择模型▼"
|
||||
选择:火山引擎 | doubao-1.5-pro-32k-character
|
||||
```
|
||||
|
||||
3. **发送消息**
|
||||
```
|
||||
输入框 → 输入"你好" → Enter
|
||||
AI 使用选中的模型回复
|
||||
```
|
||||
|
||||
### 场景2:使用 MCP 服务器扩展能力
|
||||
|
||||
1. **添加 MCP 服务器**
|
||||
```
|
||||
侧边栏 → MCP 设置 → 添加服务器
|
||||
例如:添加"xhs-sse"服务器
|
||||
URL: http://localhost:3200
|
||||
```
|
||||
|
||||
2. **连接服务器**
|
||||
```
|
||||
点击"连接"按钮
|
||||
等待连接成功,显示可用工具数量
|
||||
```
|
||||
|
||||
3. **在聊天中选择 MCP**
|
||||
```
|
||||
聊天页面 → 工具栏 → 点击"不启用 MCP 服务▼"
|
||||
选择:xhs-sse (5 个工具)
|
||||
```
|
||||
|
||||
4. **发送消息(准备使用工具)**
|
||||
```
|
||||
输入框 → 输入"搜索最新的 Vue 3 教程"
|
||||
AI 可以调用 MCP 工具进行搜索(功能待实现)
|
||||
```
|
||||
|
||||
### 场景3:折叠对话列表获得更大空间
|
||||
|
||||
1. **隐藏对话列表**
|
||||
```
|
||||
点击右上角"隐藏列表"按钮
|
||||
对话列表平滑隐藏
|
||||
主对话区域扩大
|
||||
```
|
||||
|
||||
2. **再次显示**
|
||||
```
|
||||
点击"显示列表"按钮
|
||||
对话列表平滑显示
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 技术细节
|
||||
|
||||
### 数据流:模型选择
|
||||
|
||||
```
|
||||
用户添加服务
|
||||
↓
|
||||
ModelService 连接
|
||||
↓
|
||||
modelStore.providers 更新
|
||||
↓
|
||||
modelOptions 计算属性更新
|
||||
↓
|
||||
下拉列表自动刷新
|
||||
↓
|
||||
用户选择模型
|
||||
↓
|
||||
selectedModel = "serviceId:modelId"
|
||||
↓
|
||||
发送消息时使用该模型
|
||||
↓
|
||||
modelServiceManager.sendChatRequest(serviceId, messages, modelId)
|
||||
```
|
||||
|
||||
### 数据流:MCP 集成
|
||||
|
||||
```
|
||||
用户添加 MCP 服务器
|
||||
↓
|
||||
MCPClientService 连接
|
||||
↓
|
||||
mcpStore.servers 更新
|
||||
↓
|
||||
mcpOptions 计算属性更新
|
||||
↓
|
||||
下拉列表自动刷新
|
||||
↓
|
||||
用户选择 MCP 服务器
|
||||
↓
|
||||
selectedMCP = serverId
|
||||
↓
|
||||
发送消息时传递 serverId
|
||||
↓
|
||||
chatService.sendMessageStream(..., mcpServerId)
|
||||
↓
|
||||
callModelStream(..., mcpServerId)
|
||||
↓
|
||||
[待实现] mcpStore.callTool(mcpServerId, toolName, params)
|
||||
```
|
||||
|
||||
### 关键组件关系
|
||||
|
||||
```
|
||||
ChatLayout.vue
|
||||
├─ uses chatStore (聊天状态管理)
|
||||
├─ uses modelStore (模型列表)
|
||||
├─ uses mcpStore (MCP 服务器列表)
|
||||
└─ calls sendMessageStream(content, model, mcpServerId)
|
||||
|
||||
chatStore.ts
|
||||
└─ calls chatService.sendMessageStream(options, onChunk, mcpServerId)
|
||||
|
||||
chatService.ts
|
||||
└─ calls callModelStream(conversation, model, onChunk, mcpServerId)
|
||||
└─ [TODO] 实现 MCP 工具调用逻辑
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 配置示例
|
||||
|
||||
### 模型服务配置示例
|
||||
```json
|
||||
{
|
||||
"id": "volcengine-001",
|
||||
"name": "火山引擎",
|
||||
"type": "volcengine",
|
||||
"url": "https://ark.cn-beijing.volces.com/api/v3",
|
||||
"apiKey": "your-api-key",
|
||||
"enabled": true,
|
||||
"models": [
|
||||
{
|
||||
"id": "doubao-1.5-pro-32k",
|
||||
"name": "豆包-1.5-pro-32k",
|
||||
"type": "chat"
|
||||
},
|
||||
{
|
||||
"id": "doubao-1.5-pro-32k-character",
|
||||
"name": "豆包-1.5-pro-32k-角色扮演",
|
||||
"type": "chat"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### MCP 服务器配置示例
|
||||
```json
|
||||
{
|
||||
"id": "mcp-xhs-001",
|
||||
"name": "xhs-sse",
|
||||
"url": "http://localhost:3200",
|
||||
"transport": "sse",
|
||||
"status": "connected",
|
||||
"capabilities": {
|
||||
"tools": [
|
||||
{
|
||||
"name": "search",
|
||||
"description": "搜索互联网内容"
|
||||
},
|
||||
{
|
||||
"name": "read_file",
|
||||
"description": "读取本地文件"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 下一步开发计划
|
||||
|
||||
### 优先级1:MCP 工具调用实现
|
||||
```typescript
|
||||
// 实现 AI 工具调用流程
|
||||
1. 将 MCP 工具列表格式化为 OpenAI Function Calling 格式
|
||||
2. 在调用模型时传递工具定义
|
||||
3. 解析 AI 返回的工具调用请求
|
||||
4. 执行 MCP 工具
|
||||
5. 将结果返回给 AI
|
||||
6. 显示完整的对话过程
|
||||
```
|
||||
|
||||
### 优先级2:模型切换优化
|
||||
```typescript
|
||||
// 记住每个对话的模型选择
|
||||
1. 在 Topic 中保存 modelId
|
||||
2. 切换对话时自动选择对应模型
|
||||
3. 支持为不同对话设置默认模型
|
||||
```
|
||||
|
||||
### 优先级3:UI 优化
|
||||
```typescript
|
||||
// 更好的用户体验
|
||||
1. 工具调用进度显示
|
||||
2. MCP 工具调用结果可视化
|
||||
3. 模型和 MCP 状态指示器
|
||||
4. 更多的快捷键支持
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### MCP 服务器要求
|
||||
1. **必须先配置**:在"MCP 设置"中添加并连接服务器
|
||||
2. **连接状态**:只有已连接的服务器才会出现在选择器中
|
||||
3. **自动重连**:页面刷新后会自动尝试重连
|
||||
4. **工具数量**:选择器显示每个服务器的工具数量
|
||||
|
||||
### 模型服务要求
|
||||
1. **必须先配置**:在"模型服务"中添加服务
|
||||
2. **启用状态**:只有启用的服务的模型才会出现
|
||||
3. **连接状态**:建议先测试连接再使用
|
||||
4. **API Key**:确保 API Key 有效且有足够配额
|
||||
|
||||
### 性能建议
|
||||
1. **服务器数量**:建议不超过 5 个 MCP 服务器同时连接
|
||||
2. **模型选择**:根据对话复杂度选择合适的模型
|
||||
3. **工具调用**:复杂工具可能需要更长时间
|
||||
|
||||
---
|
||||
|
||||
## 📖 更新记录
|
||||
|
||||
### V2.1(2025/10/14)
|
||||
- ✅ 右侧对话列表支持折叠
|
||||
- ✅ 模型选择器动态加载已配置的模型
|
||||
- ✅ MCP 服务集成基础架构完成
|
||||
- ✅ 自动重连 MCP 服务器
|
||||
- ✅ 完善的数据流和状态管理
|
||||
|
||||
### V2.0(2025/10/14)
|
||||
- ✅ 左侧导航可折叠
|
||||
- ✅ 右侧对话列表布局
|
||||
- ✅ 完整工具栏
|
||||
- ✅ 消息实时更新
|
||||
- ✅ 消息条数修复
|
||||
|
||||
---
|
||||
|
||||
**优化完成!** 🎉
|
||||
|
||||
现在您可以:
|
||||
1. ✅ 折叠对话列表获得更大空间
|
||||
2. ✅ 使用已配置的任意模型对话
|
||||
3. ✅ 选择 MCP 服务器(基础架构就绪)
|
||||
|
||||
继续完善 MCP 工具调用功能,敬请期待 V2.2!
|
||||
Reference in New Issue
Block a user