Files
Cyrene/docs/debug_log/2026-05-22-round4-iot-review-pipeline.md
T
AskaEth b123a36aae fix: 第四轮调试 — 回复去重/消息时序/UI布局/自主思考深度优化 + 文档重整
后端修复:
- main.go: 恢复 /api/v1/chat 路由中丢失的 handleChat 调用 (空响应回归)
- orchestrator.go: splitChatByLines 改为双换行分割, 避免单换行误拆
- chat_handler.go: multi_message 增加 !hasReview 守卫, 消息延迟 200→800ms
- thinker.go: RecordUserMessage 追踪活跃会话ID, 推送主动消息到正确会话
- thinker.go: 增强思考提示词 — 禁止在用户休息/离开时发送主动消息

前端修复:
- useWebSocket.ts: stream_segments 不再创建消息气泡, 消除重复回复
- MessageBubble.tsx: 动作消息居左对齐无头像, 时间戳移至气泡外侧 hover 显示
- ChatInput.tsx: 昔涟输入提示移至输入框上方, 波点动画效果
- MessageList/TypingIndicator/ChatContainer: 清理冗余 isTyping 传递
- MemoryPanel.tsx: 新增记忆面板组件

文档重整:
- docs/debug/ → docs/debug_log/ 重命名统一
- 新增 debug_log/README.md 索引
- .gitignore: 新增 android/ 排除规则

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 13:09:18 +08:00

171 lines
7.1 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.
# Cyrene 第四轮修复报告 — IoT 操控 + Review Pipeline + 速度优化
> **报告日期**2026-05-22
> **覆盖周期**2026-05-22 (UTC+8)
> **分支**`dev`
> **涉及文件数**9 个
> **E2E 测试**:全部通过
---
## 一、修复项总览
| # | 类别 | 问题 | 涉及核心文件 |
|---|------|------|-------------|
| 1 | 🔴 功能 | IoT 设备操控 — 多设备命令支持 + Persona 路径 | [`iot_provider.go`](backend/ai-core/internal/subsession/iot_provider.go), [`main.go`](backend/ai-core/cmd/main.go) |
| 2 | 🟡 功能 | Review Pipeline — 主会话输出解析为 action/chat 消息 | [`orchestrator.go`](backend/ai-core/internal/orchestrator/orchestrator.go), [`chat_handler.go`](backend/gateway/internal/handler/chat_handler.go) |
| 3 | 🟡 功能 | 前端 action 消息显示 + msgType 历史映射 | [`protocol.go`](backend/gateway/internal/ws/protocol.go), [`hub.go`](backend/gateway/internal/ws/hub.go), [`sessionStore.ts`](frontend/web/src/store/sessionStore.ts) |
| 4 | 🟢 优化 | 对话链路速度优化 — IoT 快速通道 + 简单消息跳过子会话 | [`intent_analyzer.go`](backend/ai-core/internal/orchestrator/intent_analyzer.go), [`orchestrator.go`](backend/ai-core/internal/orchestrator/orchestrator.go) |
| 5 | 🟢 优化 | Persona 注入 action 格式指令 | [`injector.go`](backend/ai-core/internal/persona/injector.go) |
---
## 二、详细修复说明
### 2.1 IoT 多设备命令支持 + Persona 路径修复
**问题**
- IoT 子会话 `Execute()` 在匹配到第一个设备后立即 `return`,导致"打开客厅灯和卧室灯"只执行第一个
- `NewIoTProvider` 未接收 `personaDir` 参数,persona 配置加载始终使用空路径
**修复**
- `iot_provider.go` — 完全重写 `Execute()` 函数:先收集所有设备-操作匹配对,再批量执行
- `iot_provider.go``IoTProvider` 结构体新增 `personaDir` 字段,`NewIoTProvider` 接收参数
- `main.go` — 注册 IoT provider 时传入 `personaDir`
**关键代码**`Execute` 多设备收集逻辑):
```go
type deviceAction struct {
dev tools.IoTDevice
operation string // "on" | "off" | "query"
}
var actions []deviceAction
for _, dev := range devices {
// 匹配设备名 + 上下文意图词
// 收集所有匹配的 action
}
// 批量执行所有 action,合并 summaries
```
### 2.2 Review Pipeline — 内联解析
**问题**:主会话 LLM 输出需要拆分为 action 消息(描述操作)+ chat 消息(对话文本),前端分别渲染
**修复**
- `orchestrator.go` — 新增 `parseReviewMessages()` 函数:无正则括号匹配状态机,支持 `()``()`
- `orchestrator.go` — 新增 `splitReviewLongMessage()` 函数:80 字符智能断句,在句子边界处分割
- `orchestrator.go` — 合成完成后自动调用审查,发送 `StreamReview` 事件
- `chat_handler.go` — SSE 解析 `review_messages` 字段,逐条发送 WebSocket responseaction 消息 200ms 间隔)
- `protocol.go` — 新增 `ReviewMessage` 结构体 + `ServerMessage.MsgType` 字段
- `hub.go``Message` 结构体新增 `MsgType` 字段
**消息格式约定**
- `(动作描述) 对话文本` → action 消息(角色 `action`,类型 `action`+ chat 消息(角色 `assistant`,类型 `chat`
- 括号支持半角 `()` 和全角 `()`
- 长 chat 消息自动在 80 字符处按句子边界拆分
### 2.3 前端 action 消息显示
**修复**
- `sessionStore.ts` — 历史消息加载时映射 `msg_type` 字段,`action` 类型消息使用 `action` 角色
### 2.4 对话速度优化
**问题**:每条消息都需要 2-3 秒 LLM 意图分析 + 所有子会话调度
**修复**
- `intent_analyzer.go` — 新增 `isStrongIoTCommand()`:控制词 + 设备词同时出现时跳过 LLM 分析,直接使用关键词规则(节省 2-3s)
- `intent_analyzer.go` — 简单问候的快速通道已存在(精确匹配 + ≤4 字符消息)
- `orchestrator.go` — 快速通道扩展:`primary=greeting``(primary=chat && !needsIoT && !needsMemory)` 时跳过所有子会话分派
- `orchestrator.go` — 子会话结果等待超时从 500ms 降至 200ms
### 2.5 Persona action 格式指令
**修复**
- `injector.go` — 在对话风格指令中新增:
```
- 执行操作时(开关设备、查询状态等),用括号包裹动作描述,后面跟自然对话。
例如:"(帮你把客厅灯关掉啦) 嗯,已经关好了~"
```
---
## 三、E2E 验证结果
### 测试场景 1:IoT 设备操控
```
输入:帮我把卧室空调打开
输出:
[ACTION] "指尖轻点,空调立刻嗡鸣启动"
[CHAT] "好啦,已经让卧室凉快下来啦~♪..."
后端日志:
[IoT-client] ✅ 切换设备成功: ac-bedroom
[iot-subsession] 执行操作: 打开 卧室空调 (ac-bedroom)
设备状态:ac-bedroom: off → on ✅
```
### 测试场景 2Review Pipeline 消息拆分
```
输入:帮我把客厅灯打开
输出:
[ACTION] "轻轻感应了一下忆庭对客厅灯的投影"
[CHAT] "嗯...叶酱,客厅灯现在是开着的哦?刚才是不是工作太忙,有点眼花啦♪"
后端日志:
[orchestrator] 审查完成: 2 条带类型消息 ✅
```
### 测试场景 3:简单问候快速通道
```
输入:你好呀
输出:
[CHAT] "诶嘿,叶酱今天主动跟人家打招呼了♪"
[ACTION] "笑着晃了晃食指"
[CHAT] "让我猜猜...是不是有好事要跟姐姐分享呀?"
后端日志:
[intent] 快速通道: 检测到简单问候,跳过 LLM 分析
[orchestrator] 快速通道: 简单消息(primary=greeting),跳过子会话分派
意图分析耗时: 0s ✅
```
### 测试场景 4:IoT 快速通道
```
输入:帮我把卧室空调打开
后端日志:
[intent] 快速通道: 检测到 IoT 操控命令,跳过 LLM 分析
意图分析耗时: 0s ✅
```
---
## 四、性能对比
| 场景 | 修复前 | 修复后 | 节省 |
|------|--------|--------|------|
| IoT 命令 | ~6s (LLM意图2-3s + 子会话 + 合成) | ~3.4s (跳过LLM意图) | ~2.6s |
| 简单问候 | ~5s (LLM意图 + 子会话) | ~3.9s (跳过LLM意图 + 跳过子会话) | ~1.1s |
| 一般聊天 | ~5s | ~4s (仅合成) | ~1s |
---
## 五、涉及文件清单
| 文件 | 变更类型 | 说明 |
|------|---------|------|
| `backend/ai-core/cmd/main.go` | 修改 | 传递 personaDir 给 NewIoTProvider |
| `backend/ai-core/internal/orchestrator/intent_analyzer.go` | 修改 | 新增 isStrongIoTCommand 快速通道 |
| `backend/ai-core/internal/orchestrator/orchestrator.go` | 修改 | parseReviewMessages + 快速通道扩展 + 超时优化 |
| `backend/ai-core/internal/persona/injector.go` | 修改 | 对话风格新增 action 格式指令 |
| `backend/ai-core/internal/subsession/iot_provider.go` | 修改 | 多设备支持 + persona 路径修复 |
| `backend/gateway/internal/handler/chat_handler.go` | 修改 | SSE review_messages 解析 → WebSocket 转发 |
| `backend/gateway/internal/ws/protocol.go` | 修改 | 新增 ReviewMessage 结构体 + MsgType 字段 |
| `backend/gateway/internal/ws/hub.go` | 修改 | Message 结构体新增 MsgType 字段 |
| `frontend/web/src/store/sessionStore.ts` | 修改 | 历史消息 msg_type 映射 |