375 lines
8.9 KiB
Markdown
375 lines
8.9 KiB
Markdown
|
|
# 网关转发企业微信消息到 SmartClaw 处理计划
|
|||
|
|
|
|||
|
|
## 目标
|
|||
|
|
将网关收到的企业微信和微信小程序消息通过 WebSocket 转发给 SmartClaw 进行处理,采用异步回复模式,支持混合消息类型,并确保多端同步和不串线。
|
|||
|
|
|
|||
|
|
## 核心架构:异步回复模式
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
用户发消息
|
|||
|
|
→ 企业微信/微信小程序
|
|||
|
|
→ 网关(5秒内立即回复"思考中...")
|
|||
|
|
→ 网关通过 WebSocket 发给 SmartClaw
|
|||
|
|
→ SmartClaw 调用 LMStudio(耗时5~15秒都没关系)
|
|||
|
|
→ 完成后 → SmartClaw 把结果发给网关
|
|||
|
|
→ 网关根据平台类型分发:
|
|||
|
|
- 微信小程序:通过 WebSocket 流式推送
|
|||
|
|
- 企业微信:通过 HTTP 轮询一次性返回
|
|||
|
|
→ 用户收到回复
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 统一数据协议
|
|||
|
|
|
|||
|
|
### 1. 消息请求格式
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"type": "wechat_message",
|
|||
|
|
"uid": "用户ID",
|
|||
|
|
"session_id": "会话ID",
|
|||
|
|
"request_id": "消息唯一ID",
|
|||
|
|
"platform": "wecom|wechat",
|
|||
|
|
"content": "消息内容",
|
|||
|
|
"msg_type": "text|image|voice|svg",
|
|||
|
|
"segments": [
|
|||
|
|
{
|
|||
|
|
"type": "text",
|
|||
|
|
"content": "文本内容"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"type": "image",
|
|||
|
|
"url": "图片URL",
|
|||
|
|
"width": 100,
|
|||
|
|
"height": 100
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"type": "svg",
|
|||
|
|
"content": "SVG内容"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"type": "voice",
|
|||
|
|
"url": "语音URL",
|
|||
|
|
"duration": 10
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"timestamp": 1234567890
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 消息响应格式
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"type": "wechat_response",
|
|||
|
|
"uid": "用户ID",
|
|||
|
|
"session_id": "会话ID",
|
|||
|
|
"request_id": "消息唯一ID",
|
|||
|
|
"platform": "wecom|wechat",
|
|||
|
|
"success": true,
|
|||
|
|
"content": "纯文本内容(企业微信使用)",
|
|||
|
|
"segments": [
|
|||
|
|
{
|
|||
|
|
"type": "text",
|
|||
|
|
"content": "文本内容"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"type": "image",
|
|||
|
|
"url": "图片URL",
|
|||
|
|
"width": 100,
|
|||
|
|
"height": 100
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"type": "svg",
|
|||
|
|
"content": "SVG内容"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"type": "voice",
|
|||
|
|
"url": "语音URL",
|
|||
|
|
"duration": 10
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"timestamp": 1234567890,
|
|||
|
|
"streaming": true, // 是否流式输出
|
|||
|
|
"finished": false // 是否输出完成
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 实现步骤
|
|||
|
|
|
|||
|
|
### 1. 修改网关 (gateway) - 实现异步处理
|
|||
|
|
|
|||
|
|
#### 1.1 立即回复企业微信
|
|||
|
|
- 在 `handle_wechat_callback` 中,收到消息后立即返回 200 OK + "思考中..." 消息
|
|||
|
|
- 不等待 SmartClaw 处理结果
|
|||
|
|
- 企业微信要求在5秒内回复,否则会重试发送消息
|
|||
|
|
|
|||
|
|
#### 1.2 统一消息处理
|
|||
|
|
- 新增 `unified_message_handler` 函数,处理来自不同平台的消息
|
|||
|
|
- 生成三级ID:uid + session_id + request_id
|
|||
|
|
- 根据平台类型选择不同的处理方式
|
|||
|
|
|
|||
|
|
#### 1.3 添加 WebSocket 消息发送
|
|||
|
|
- 在 TaskService 中添加 `forward_to_smartclaw()` 方法
|
|||
|
|
- 异步通过 WebSocket 连接池发送消息到 SmartClaw
|
|||
|
|
- 消息格式使用统一数据协议
|
|||
|
|
|
|||
|
|
#### 1.4 处理 SmartClaw 回调
|
|||
|
|
- 在 WebSocket 处理器中添加处理 SmartClaw 回复的逻辑
|
|||
|
|
- 根据平台类型分发消息:
|
|||
|
|
- 微信小程序:通过 WebSocket 流式推送
|
|||
|
|
- 企业微信:通过 HTTP 轮询一次性返回
|
|||
|
|
- 实现会话管理和消息路由,确保不串线
|
|||
|
|
|
|||
|
|
### 2. 修改 SmartClaw - 添加消息处理功能
|
|||
|
|
|
|||
|
|
#### 2.1 接收并处理消息
|
|||
|
|
- 在 `handle_incoming_message` 中添加处理 "wechat_message" 类型消息的逻辑
|
|||
|
|
- 解析消息内容,调用现有的任务处理逻辑
|
|||
|
|
- 支持混合消息类型的处理
|
|||
|
|
|
|||
|
|
#### 2.2 消息处理流程
|
|||
|
|
- 文本消息 → 调用 AI 处理
|
|||
|
|
- 图片消息 → 调用图像处理
|
|||
|
|
- 语音消息 → 调用语音识别
|
|||
|
|
- SVG消息 → 保持原样
|
|||
|
|
- 处理完成后返回统一格式的回复
|
|||
|
|
|
|||
|
|
#### 2.3 流式输出支持
|
|||
|
|
- 实现流式输出逻辑,支持小程序的打字机效果
|
|||
|
|
- 分段处理消息,实时返回处理结果
|
|||
|
|
|
|||
|
|
## 后端架构
|
|||
|
|
|
|||
|
|
### 1. 会话管理
|
|||
|
|
- 使用 Redis 存储会话信息
|
|||
|
|
- 会话结构:
|
|||
|
|
```
|
|||
|
|
session:{session_id} = {
|
|||
|
|
"uid": "用户ID",
|
|||
|
|
"platforms": ["wecom", "wechat"],
|
|||
|
|
"last_active": 1234567890,
|
|||
|
|
"connections": {
|
|||
|
|
"wecom": "connection_id",
|
|||
|
|
"wechat": "connection_id"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 消息路由
|
|||
|
|
- 使用 Redis 发布订阅机制
|
|||
|
|
- 消息分发:
|
|||
|
|
```
|
|||
|
|
PUBLISH session:{session_id} {message}
|
|||
|
|
```
|
|||
|
|
- 连接管理:
|
|||
|
|
```
|
|||
|
|
SET connection:{connection_id} {session_id}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 高并发不串线机制
|
|||
|
|
- 使用三级ID确保消息唯一性
|
|||
|
|
- 消息队列保证顺序
|
|||
|
|
- 连接池管理确保消息正确路由
|
|||
|
|
- 超时机制避免消息阻塞
|
|||
|
|
|
|||
|
|
## 服务器实现逻辑
|
|||
|
|
|
|||
|
|
### 1. 服务器A(网关)
|
|||
|
|
- 监听企业微信回调:`/wecom`
|
|||
|
|
- 监听微信小程序连接:`/api/v1/ws/wechat`
|
|||
|
|
- 管理 WebSocket 连接池
|
|||
|
|
- 处理 SmartClaw 回调
|
|||
|
|
- 根据平台类型分发消息
|
|||
|
|
|
|||
|
|
### 2. 服务器B(SmartClaw)
|
|||
|
|
- 主动连接服务器A的 WebSocket
|
|||
|
|
- 处理来自网关的消息
|
|||
|
|
- 调用 LMStudio 进行 AI 处理
|
|||
|
|
- 支持流式输出
|
|||
|
|
- 返回统一格式的处理结果
|
|||
|
|
|
|||
|
|
## 前端实现
|
|||
|
|
|
|||
|
|
### 1. 微信小程序(wechat_app目录)
|
|||
|
|
```javascript
|
|||
|
|
// WebSocket 连接
|
|||
|
|
const socket = wx.connectSocket({
|
|||
|
|
url: 'wss://pactgo.cn/api/v1/ws/wechat',
|
|||
|
|
header: {
|
|||
|
|
'content-type': 'application/json'
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 发送消息
|
|||
|
|
socket.send({
|
|||
|
|
data: JSON.stringify({
|
|||
|
|
type: 'wechat_message',
|
|||
|
|
uid: 'user123',
|
|||
|
|
session_id: 'session456',
|
|||
|
|
request_id: 'req789',
|
|||
|
|
platform: 'wechat',
|
|||
|
|
content: '你好',
|
|||
|
|
msg_type: 'text',
|
|||
|
|
segments: [{
|
|||
|
|
type: 'text',
|
|||
|
|
content: '你好'
|
|||
|
|
}],
|
|||
|
|
timestamp: Date.now()
|
|||
|
|
})
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 接收消息
|
|||
|
|
socket.onMessage((res) => {
|
|||
|
|
const data = JSON.parse(res.data);
|
|||
|
|
if (data.streaming) {
|
|||
|
|
// 流式渲染,打字机效果
|
|||
|
|
renderStreamingMessage(data);
|
|||
|
|
} else if (data.finished) {
|
|||
|
|
// 渲染完整消息
|
|||
|
|
renderCompleteMessage(data);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 渲染消息
|
|||
|
|
function renderMessage(message) {
|
|||
|
|
message.segments.forEach(segment => {
|
|||
|
|
switch (segment.type) {
|
|||
|
|
case 'text':
|
|||
|
|
renderText(segment.content);
|
|||
|
|
break;
|
|||
|
|
case 'image':
|
|||
|
|
renderImage(segment.url);
|
|||
|
|
break;
|
|||
|
|
case 'svg':
|
|||
|
|
renderSVG(segment.content);
|
|||
|
|
break;
|
|||
|
|
case 'voice':
|
|||
|
|
renderVoice(segment.url);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 企业微信
|
|||
|
|
```javascript
|
|||
|
|
// 轮询获取消息
|
|||
|
|
function pollMessages() {
|
|||
|
|
wx.request({
|
|||
|
|
url: 'https://pactgo.cn/api/v1/wecom/messages',
|
|||
|
|
method: 'GET',
|
|||
|
|
data: {
|
|||
|
|
session_id: 'session456',
|
|||
|
|
last_timestamp: lastTimestamp
|
|||
|
|
},
|
|||
|
|
success: (res) => {
|
|||
|
|
if (res.data.messages) {
|
|||
|
|
res.data.messages.forEach(message => {
|
|||
|
|
// 只渲染文本内容
|
|||
|
|
renderText(message.content);
|
|||
|
|
});
|
|||
|
|
lastTimestamp = res.data.last_timestamp;
|
|||
|
|
}
|
|||
|
|
setTimeout(pollMessages, 3000);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 发送消息
|
|||
|
|
function sendMessage(content) {
|
|||
|
|
wx.request({
|
|||
|
|
url: 'https://pactgo.cn/wecom',
|
|||
|
|
method: 'POST',
|
|||
|
|
data: {
|
|||
|
|
content: content
|
|||
|
|
},
|
|||
|
|
success: (res) => {
|
|||
|
|
console.log('消息发送成功');
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 渲染文本
|
|||
|
|
function renderText(content) {
|
|||
|
|
// 只渲染纯文本
|
|||
|
|
const messageElement = document.createElement('div');
|
|||
|
|
messageElement.textContent = content;
|
|||
|
|
document.getElementById('messageList').appendChild(messageElement);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 前后端交互流程
|
|||
|
|
|
|||
|
|
1. **用户发送消息**:
|
|||
|
|
- 微信小程序:通过 WebSocket 发送消息
|
|||
|
|
- 企业微信:通过 HTTP POST 发送消息
|
|||
|
|
|
|||
|
|
2. **网关处理**:
|
|||
|
|
- 立即回复 "思考中..."
|
|||
|
|
- 生成三级ID
|
|||
|
|
- 通过 WebSocket 转发给 SmartClaw
|
|||
|
|
|
|||
|
|
3. **SmartClaw 处理**:
|
|||
|
|
- 调用 LMStudio 处理消息
|
|||
|
|
- 支持流式输出
|
|||
|
|
- 返回统一格式的结果
|
|||
|
|
|
|||
|
|
4. **网关分发**:
|
|||
|
|
- 微信小程序:通过 WebSocket 流式推送
|
|||
|
|
- 企业微信:存储消息等待轮询
|
|||
|
|
|
|||
|
|
5. **前端渲染**:
|
|||
|
|
- 微信小程序:流式渲染、富媒体完整显示
|
|||
|
|
- 企业微信:只渲染文本内容
|
|||
|
|
|
|||
|
|
## 实现顺序
|
|||
|
|
|
|||
|
|
1. **修改 SmartClaw**:
|
|||
|
|
- 添加接收和处理企业微信消息的功能
|
|||
|
|
- 实现混合消息处理
|
|||
|
|
- 支持流式输出
|
|||
|
|
|
|||
|
|
2. **修改网关**:
|
|||
|
|
- 实现统一消息处理
|
|||
|
|
- 添加会话管理和消息路由
|
|||
|
|
- 实现平台区分和分发
|
|||
|
|
|
|||
|
|
3. **前端实现**:
|
|||
|
|
- 微信小程序:流式渲染、富媒体支持
|
|||
|
|
- 企业微信:纯文本渲染
|
|||
|
|
|
|||
|
|
4. **测试完整流程**:
|
|||
|
|
- 多设备并发测试
|
|||
|
|
- 消息不串线测试
|
|||
|
|
- 混合消息类型测试
|
|||
|
|
- 流式输出测试
|
|||
|
|
|
|||
|
|
## 注意事项
|
|||
|
|
|
|||
|
|
1. **企业微信限制**:
|
|||
|
|
- 不支持流式输出
|
|||
|
|
- 不支持富媒体
|
|||
|
|
- 不支持 SVG
|
|||
|
|
- 只显示纯文本
|
|||
|
|
|
|||
|
|
2. **微信小程序特性**:
|
|||
|
|
- 支持流式输出
|
|||
|
|
- 支持富媒体
|
|||
|
|
- 支持 SVG(使用 rich-text 渲染)
|
|||
|
|
- 支持打字机效果
|
|||
|
|
|
|||
|
|
3. **后端处理**:
|
|||
|
|
- 统一数据协议
|
|||
|
|
- 自动区分平台
|
|||
|
|
- 确保消息不串线
|
|||
|
|
- 支持高并发
|
|||
|
|
|
|||
|
|
4. **性能优化**:
|
|||
|
|
- 使用 WebSocket 连接池
|
|||
|
|
- 实现消息队列
|
|||
|
|
- 优化流式输出
|
|||
|
|
- 合理使用缓存
|
|||
|
|
|
|||
|
|
## 总结
|
|||
|
|
|
|||
|
|
本方案通过统一数据协议和平台区分,实现了企业微信和微信小程序的消息处理,支持混合消息类型,并确保多端同步和不串线。采用异步回复模式,满足企业微信的5秒内回复要求,同时通过流式输出提升用户体验。
|