fix: IoT快速通道补充关掉/关上 + 多设备上下文窗口扩展至30字节
- intent_analyzer: isStrongIoTCommand controlWords新增"关掉""关上" - iot_provider: 操作检测上下文窗口±15→±30字节,新增全文回退逻辑 - 修复多设备命令中远处关键词无法匹配导致操作误判为query E2E: "关掉"快速通道2.57s✅ 多设备同时开关✅ 8设备查询✅ Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -130,7 +130,7 @@ func (a *IntentAnalyzer) isStrongIoTCommand(userMessage string) bool {
|
|||||||
msgLower := strings.TrimSpace(strings.ToLower(userMessage))
|
msgLower := strings.TrimSpace(strings.ToLower(userMessage))
|
||||||
|
|
||||||
// 控制类关键词 + 设备类关键词组合出现,即可判断为 IoT 命令
|
// 控制类关键词 + 设备类关键词组合出现,即可判断为 IoT 命令
|
||||||
controlWords := []string{"打开", "关闭", "调到", "设置", "开关", "调节", "调高", "调低", "开一下", "关一下"}
|
controlWords := []string{"打开", "关闭", "关掉", "关上", "调到", "设置", "开关", "调节", "调高", "调低", "开一下", "关一下"}
|
||||||
deviceWords := []string{"灯", "空调", "窗帘", "电视", "风扇", "加湿器", "插座", "门锁", "传感器"}
|
deviceWords := []string{"灯", "空调", "窗帘", "电视", "风扇", "加湿器", "插座", "门锁", "传感器"}
|
||||||
|
|
||||||
hasControl := false
|
hasControl := false
|
||||||
|
|||||||
@@ -230,21 +230,30 @@ func (p *IoTProvider) Execute(ctx context.Context, subCtx []model.LLMMessage) (*
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断此设备的操作:检查设备名附近的意图词
|
// 判断此设备的操作:先检查附近上下文,再回退到全文匹配
|
||||||
devIdx := strings.Index(msgLower, devNameLower)
|
devIdx := strings.Index(msgLower, devNameLower)
|
||||||
contextStart := devIdx - 15
|
contextStart := devIdx - 30
|
||||||
if contextStart < 0 {
|
if contextStart < 0 {
|
||||||
contextStart = 0
|
contextStart = 0
|
||||||
}
|
}
|
||||||
contextEnd := devIdx + len(devNameLower) + 15
|
contextEnd := devIdx + len(devNameLower) + 30
|
||||||
if contextEnd > len(msgLower) {
|
if contextEnd > len(msgLower) {
|
||||||
contextEnd = len(msgLower)
|
contextEnd = len(msgLower)
|
||||||
}
|
}
|
||||||
nearbyContext := msgLower[contextStart:contextEnd]
|
nearbyContext := msgLower[contextStart:contextEnd]
|
||||||
|
|
||||||
if strings.Contains(nearbyContext, "打开") || strings.Contains(nearbyContext, "开") {
|
hasOpen := strings.Contains(nearbyContext, "打开") || strings.Contains(nearbyContext, "开")
|
||||||
|
hasClose := strings.Contains(nearbyContext, "关闭") || strings.Contains(nearbyContext, "关掉") || strings.Contains(nearbyContext, "关上") || strings.Contains(nearbyContext, "关")
|
||||||
|
|
||||||
|
// 附近上下文不足以判断时,回退到全文搜索
|
||||||
|
if !hasOpen && !hasClose {
|
||||||
|
hasOpen = strings.Contains(msgLower, "打开")
|
||||||
|
hasClose = strings.Contains(msgLower, "关闭") || strings.Contains(msgLower, "关掉") || strings.Contains(msgLower, "关上")
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasOpen {
|
||||||
actions = append(actions, deviceAction{dev: dev, operation: "on"})
|
actions = append(actions, deviceAction{dev: dev, operation: "on"})
|
||||||
} else if strings.Contains(nearbyContext, "关闭") || strings.Contains(nearbyContext, "关掉") || strings.Contains(nearbyContext, "关上") {
|
} else if hasClose {
|
||||||
actions = append(actions, deviceAction{dev: dev, operation: "off"})
|
actions = append(actions, deviceAction{dev: dev, operation: "off"})
|
||||||
} else {
|
} else {
|
||||||
actions = append(actions, deviceAction{dev: dev, operation: "query"})
|
actions = append(actions, deviceAction{dev: dev, operation: "query"})
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# Cyrene 第五轮修复报告 — IoT 边界情况 + 快速通道完善
|
||||||
|
|
||||||
|
> **报告日期**:2026-05-22
|
||||||
|
> **分支**:`dev`
|
||||||
|
> **涉及文件数**:2 个
|
||||||
|
> **E2E 测试**:全部通过
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、修复项
|
||||||
|
|
||||||
|
| # | 类别 | 问题 | 涉及文件 |
|
||||||
|
|---|------|------|---------|
|
||||||
|
| 1 | 🟡 功能 | IoT 快速通道遗漏 "关掉"/"关上" 关键词 | [`intent_analyzer.go`](backend/ai-core/internal/orchestrator/intent_analyzer.go) |
|
||||||
|
| 2 | 🟡 功能 | IoT 多设备命令上下文窗口过小(±15字节) | [`iot_provider.go`](backend/ai-core/internal/subsession/iot_provider.go) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、详细说明
|
||||||
|
|
||||||
|
### 2.1 IoT 快速通道关键词补充
|
||||||
|
|
||||||
|
**问题**:`isStrongIoTCommand()` 的控制词列表缺少 "关掉"、"关上",导致 "关掉客厅灯" 等常见命令无法命中快速通道,浪费 2-3s LLM 意图分析。
|
||||||
|
|
||||||
|
**修复**:在 `controlWords` 中新增 `"关掉"`, `"关上"`。
|
||||||
|
|
||||||
|
```
|
||||||
|
修复前: controlWords := []string{"打开", "关闭", "调到", "设置", ...}
|
||||||
|
修复后: controlWords := []string{"打开", "关闭", "关掉", "关上", "调到", "设置", ...}
|
||||||
|
```
|
||||||
|
|
||||||
|
**验证**:
|
||||||
|
```
|
||||||
|
"关掉客厅灯" → 修复前: LLM路径 5.12s → 修复后: 快速通道 2.57s (节省 2.55s)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 IoT 多设备上下文窗口扩展
|
||||||
|
|
||||||
|
**问题**:多设备命令如 "帮我把卧室灯和卧室空调都关掉" 中,"卧室灯" 与 "关掉" 之间间隔超过 15 字节,导致操作判断错误(将 "off" 误判为 "query"),设备未被实际控制。
|
||||||
|
|
||||||
|
**根因分析**:
|
||||||
|
```
|
||||||
|
msgLower = "帮我把卧室灯和卧室空调都关掉" (42 bytes)
|
||||||
|
"卧室灯" 起始偏移 = 9
|
||||||
|
contextEnd = 9 + 9 + 15 = 33
|
||||||
|
nearbyContext = msgLower[0:33] = "帮我把卧室灯和卧室空调" ← 缺少 "都关掉"!
|
||||||
|
```
|
||||||
|
|
||||||
|
**修复**:
|
||||||
|
1. 上下文窗口从 ±15 扩展至 ±30 字节
|
||||||
|
2. 新增全文回退逻辑:附近上下文无法判断时,搜索整条消息
|
||||||
|
3. 调整判断逻辑为先计算 `hasOpen`/`hasClose` 布尔值,避免级联 if-else 误判
|
||||||
|
|
||||||
|
**验证**:
|
||||||
|
```
|
||||||
|
"帮我把卧室灯和卧室空调都关掉" →
|
||||||
|
修复前: IoT 子会话完成: 卧室灯当前状态: on; 已帮你关闭卧室空调~ (灯仅查询,未关闭)
|
||||||
|
修复后: IoT 子会话完成: 卧室空调已经是关闭状态啦~; 已帮你关闭卧室灯~ (两个设备都正确匹配)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、E2E 验证
|
||||||
|
|
||||||
|
| 场景 | 输入 | 预期 | 结果 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| "关掉" 快速通道 | 关掉客厅灯 | fast path, <3s | 2.57s, fast path ✅ |
|
||||||
|
| 多设备打开 | 打开客厅灯和卧室灯 | 两设备均匹配 | 已帮你打开客厅灯♪; 卧室灯已经是打开状态啦~ ✅ |
|
||||||
|
| 多设备关闭 | 帮我把卧室灯和卧室空调都关掉 | 两设备均 match "off" | 卧室空调关闭 + 已帮你关闭卧室灯~ ✅ |
|
||||||
|
| 设备状态查询 | 看看家里设备状态怎么样 | 返回全部设备 | 家里设备状态:8 台设备 ✅ |
|
||||||
|
| 长消息拆分 | 讲星星故事 | action + 多段 chat | 1 action + 2 chat (69+16 chars at sentence break) ✅ |
|
||||||
|
| 审查消息格式 | 所有场景 | action/chat 分离 | msg_type 正确 ✅ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、构建流程修正
|
||||||
|
|
||||||
|
本次调试中发现 DevTools 构建产物名为 `main.exe` 而非 `ai-core.exe`。后续所有编译应通过 DevTools 的 `/api/services/:id/build` 接口执行,避免手动构建到错误文件名。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、性能总结
|
||||||
|
|
||||||
|
| 场景 | Round 4 | Round 5 | 改善 |
|
||||||
|
|------|---------|---------|------|
|
||||||
|
| "打开" IoT 命令 | ~3.4s | ~2.6s | -0.8s |
|
||||||
|
| "关掉" IoT 命令 | ~6.2s (LLM路径) | ~2.6s (快速通道) | -3.6s |
|
||||||
|
| 多设备 IoT 命令 | 仅执行第一个 | 全部执行 | 功能修复 |
|
||||||
|
| 一般聊天 | ~3.9s | ~3.9s | 持平 |
|
||||||
Reference in New Issue
Block a user