Files
ai-device/docs/bert_integration_analysis.md
2026-06-11 16:28:00 +08:00

372 lines
14 KiB
Markdown
Raw Permalink 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.
# intelligent_cabin BERT 接入 · 冲突分析与整合方案
> 作者AI 分析
> 日期2026-05-26
> 状态:待你确认
---
## 背景速览
| 侧 | 项目 | 技术栈 | 角色 |
|---|---|---|---|
| **Canvas前端/编排侧)** | ai-canvas / Next.js | TypeScript + React | 画布渲染、Artifact 管理、LLM 编排、工业工具调用DBus/PLC|
| **BERT 服务侧** | intelligent_cabin | Python / FastAPI | 本地 NLUintent + slot语音控制场景 |
这两个项目目前是独立的,尚未对接。
---
## 一、冲突点(需要明确决策的地方)
### 冲突 1Domain 语义完全不匹配 ⚠️ 重要
**问题**`intelligent_cabin/config/domain.yml` 里的 intent 全部来自车机场景(导航、空调、音乐、车窗、车灯……),与 `DBUS_API.md` 描述的线切割工控场景电压、电流、速度、NC 加工、空走、回零)**毫无重叠**。
**后果**:如果直接把 BERT 服务接进来,意图识别的类别集合完全覆盖不了工控指令,识别结果几乎全是 unknown/reject。
**需确认**
- [ ] 你们会用智能车机的这套预训练模型做迁移学习,还是重新训练工控专属的 BERT 模型?
- [ ] 还是说这个 BERT 服务只是作为基础推理框架,`domain.yml` 需要被替换成工控版 domain
---
### 冲突 2置信度阈值体系 vs. Canvas 路由体系
**Canvas 流程**(参考 `architecture_overview.html`)的技术视图里:
```
输入 → BERT NLU → confidence 判断 → [高置信+设备控制域] / [知识域/低置信] / [smalltalk]
```
**intelligent_cabin 的路由体系**`router.py`
```
输入 → Classifier → FusionGrader →
decision = execute / clarify / route_to_cloud / reject
阈值execute_score=0.55, execute_margin=0.18, route_to_cloud=0.75
```
两套路由各有自己的 confidence 分级,**如果串联,会出现双重过滤**
- BERT 服务输出的 `score` 未必能直接映射到 Canvas 的 `confidence ≥ 阈值` 判断
- Canvas 目前只依赖 BERT 输出的 `domain/intent/slot/confidence`,但 BERT 服务输出的是 `intent_id + score + decision`
**需确认**
- [ ] Canvas 侧是否需要直接消费 `decision` 字段execute/clarify/route_to_cloud/reject还是只取 `intent_id + score`Canvas 自己做二次路由?
---
### 冲突 3`textAliases`(大流程 Bvs. BERT 意图识别的竞争
**Canvas 大流程 B调机流程中的路由逻辑**
```
输入 → 优先匹配 textAliases如"完成"/"下一步"/"确认"
→ 未命中 → BERT NLU 重新识别
```
**intelligent_cabin** 里的 `DialogActEngine``dialog_act.py`)也在做相似的事情:
```python
affirm: ["确认", "好的", "继续", "可以", "确定"]
cancel: ["取消", "算了", "不用了", "停止"]
```
**冲突**
- `textAliases` 是每个 Artifact Step 私有的,属于 Canvas 状态机层面的规则匹配
- `DialogActEngine` 是系统级对话行为分类,优先级/触发顺序未对齐
- 如果两套都跑,"确认"这个词可能被 `DialogActEngine` 吃掉后不再传给 Canvas 的步骤推进逻辑
**整合建议**
- 大流程 B 中textAliases 匹配应在 BERT 服务之前Canvas 侧处理,不交给 BERT 服务
-`dialog_acts.yml``affirm/deny/cancel/modify` 从 BERT 服务中剥离,改为 Canvas 路由层的前置规则
- 或者让 BERT 服务的 dialog_act 结果作为辅助 metadata 透传Canvas 侧自行决策
---
### 冲突 4slot 语义不兼容
**BERT 服务的 slot 体系**(按车机场景设计):
- `temperature`空调温度16-30°C
- `destination`:导航目的地
- `order_id`:订单号
- `song`:歌曲名
**线切割工控的 slot 需求**(从 `DBUS_API.md` 推导):
- `speed`加工速度mm/min1-9999
- `voltage`:放电码/电压
- `current`:跟踪值/电流
- `workpiece_id`工件编号0-8
- `knife_id`刀号1-11
- `param_type`参数类型voltage/current/servo
- `nc_path`NC 文件绝对路径
- `axis`轴编号0-5X/Y/Z/U/V/C
两套 slot 定义**完全不同**,需要重写 `domain.yml``rewrite_engine.py` 里的工控版本。
---
### 冲突 5rewrite_engine 的上下文改写逻辑是车机特化的
`rewrite_engine.py` 里写死了:
```python
_AC_CONTEXT_INTENTS = {"cabin_set_ac", "cabin_ac_on", "cabin_ac_off", ...}
_AC_DEFAULT_TEMPERATURE = 24
_AC_STEP = 2
_AC_MIN_TEMPERATURE = 16
_AC_MAX_TEMPERATURE = 30
```
这些都是车机空调的业务逻辑,工控场景需要换成类似:
```python
_PARAM_CONTEXT_INTENTS = {"wirecut_set_speed", "wirecut_set_voltage", "wirecut_set_current"}
_SPEED_STEP = 5 # mm/min
_VOLTAGE_STEP = 5 # 放电码
```
**但这恰恰也是最有价值可以复用的能力**:多轮相对调节("再快一点"→ 改写为 "速度设为 85mm/min")在工控场景同样刚需。
---
## 二、可以直接整合的能力(不需要改动或改动很小)
### ✅ 整合点 1FastAPI 服务直接作为 NLU 微服务接入
CanvasNext.js 侧)可以通过 HTTP 调用 `POST /api/v1/agent/chat``POST /api/v1/agent/fill-slots`,作为 Canvas 的 "感知语义层"。
接入位置Canvas 的"BERT NLU 意图识别"节点(技术流程视图第 2 层)
```
Canvas 输入 → HTTP POST → intelligent_cabin :8000/api/v1/agent/chat
← {intent_id, score, slots, decision}
Canvas 路由层根据 intent_id + score 继续分发
```
### ✅ 整合点 2分级融合决策逻辑router.py可以直接复用
`MultiStageIntentMatcher` 里的 `execute / clarify / route_to_cloud / reject` 四态决策逻辑,与 Canvas 流程中"高置信执行 / 知识域兜底 / smalltalk" 的三路分发思路高度一致,可以直接用。
Canvas 只需要消费 BERT 服务返回的 `decision` 字段,然后:
- `execute` → Canvas 走工具调用路径DBus
- `clarify` → Canvas 展示澄清确认卡
- `route_to_cloud` → Canvas 走 LLM 兜底路径
- `reject` → Canvas 走 smalltalk / fallback
### ✅ 整合点 3会话状态管理session_store.py
`SessionState` 里的 `context_memory``slots` 持久化机制,可以支持工控场景的多轮短句恢复(比如 "再快一点" → 记住上次速度值)。
### ✅ 整合点 4多命令拆分planner.py
现有的 `sequence workflow``conditional workflow` 对工控多命令("先回零,再开始加工")直接可用。
### ✅ 整合点 5高风险确认机制dialog_rules.py
`requires_confirmation` + `confirmation_required_risk_levels` 这套机制,完全可以映射到 Canvas 流程中"操控确认卡"的场景Canvas 大流程 A 的场景 1直接支持危险操作二次确认。
---
## 三、需要新建或重写的工控专属配置
### 3.1 新建 `config/domain_wirecut.yml`
需要把 DBUS_API.md 里的每个接口映射成 intent
| intent_id | 对应 DBus 方法 | 示例语句 | 需要 slot |
|---|---|---|---|
| `wirecut_start_run` | `startRun()` | "开始加工" / "启动" | 无 |
| `wirecut_stop_run` | `stopRun()` | "停止加工" / "停机" | 无 |
| `wirecut_pause_run` | `pauseRun()` | "暂停" / "变频暂停" | 无 |
| `wirecut_home_all` | `homeAll()` | "全轴回零" / "回零" | 无 |
| `wirecut_start_kongzou` | `startKongZou()` | "开始空走" | 无 |
| `wirecut_stop_kongzou` | `stopKongZou()` | "停止空走" | 无 |
| `wirecut_set_speed` | `setSpeed(speed)` | "速度调到80" / "加快一点" | `speed:int` |
| `wirecut_set_voltage` | `setVoltage(vol)` | "电压设为90" | `voltage:int` |
| `wirecut_set_current` | `setCurrent(cur)` | "电流设为5" | `current:int` |
| `wirecut_get_status` | `getStatus()` | "查一下状态" / "当前状态" | 无 |
| `wirecut_load_nc` | `loadNC(path)` | "加载NC文件" | `nc_path:str` |
| `wirecut_set_discharge` | `SetDischargePara(...)` | "设置工件0刀1放电码80" | `workpiece_id, knife_id, param_type, value` |
### 3.2 重写 `rewrite_engine.py` 里的工控上下文改写规则
```python
# 工控版示例
_SPEED_CONTEXT_INTENTS = {"wirecut_set_speed"}
_SPEED_STEP = 5 # mm/min 每步调节
_SPEED_MIN = 1
_SPEED_MAX = 9999
_VOLTAGE_CONTEXT_INTENTS = {"wirecut_set_voltage"}
_VOLTAGE_STEP = 5
# 改写规则
"再快一点" "速度设为 {last_speed + 5} mm/min"
"再慢一点" "速度设为 {last_speed - 5} mm/min"
"电压再高一点" "电压设为 {last_voltage + 5}"
```
### 3.3 更新 `dialog_acts.yml` 适配工控确认场景
当前 `dialog_acts.yml``affirm/deny/cancel` 词表可以保留,但需要补充工控场景的特化语句:
```yaml
# 工控场景补充
affirm:
+ "执行" / "开始" / "运行" / "启动"
cancel:
+ "停机" / "急停" / "中止"
inform:
+ 纯数字(速度值/电压值/电流值的slot填写
```
---
## 四、关于 dialog_act 和 rewrite_engine 能否通过配置文件驱动
**直接回答:当前已经部分支持,但工控场景需要扩展。**
### 4.1 dialog_act 配置化现状
`dialog_act.py` 里的 `DialogActEngine` 是数据驱动的:
```python
@dataclass
class DialogActEngine:
patterns: dict[str, tuple[str, ...]] = field(default_factory=...)
```
`config_loader.py` 里已经实现了从 `dialog_acts.yml` 加载:
```python
def _load_dialog_act_engine(self) -> DialogActEngine:
...
return DialogActEngine(patterns={item.act_id: tuple(item.phrases) for item in parsed.acts})
```
**✅ 结论**`dialog_acts.yml` 已经是配置文件,直接修改 `config/dialog_acts.yml` 就能修改 act 词表,**无需改代码**。
**但是有个缺口**:当前 `dialog_acts.yml` 只支持 `字符串包含` 匹配(`phrase in normalized`),没有支持正则或数值范围匹配。工控场景里 "85" 这样的纯数字(作为速度 slot 的 `inform`)目前是靠 Python 代码里的 `if re.search(r"\d", normalized): return "inform"` 处理的,这个逻辑是硬编码在 `dialog_act.py` 里的,暂时没有配置化。
**建议优化**(详见第五节)。
### 4.2 rewrite_engine 配置化现状
`rewrite_engine.py` 里的上下文改写逻辑**全部硬编码**,没有配置文件支持:
```python
_AC_CONTEXT_INTENTS = {"cabin_set_ac", ...} # 硬编码
_AC_DEFAULT_TEMPERATURE = 24 # 硬编码
_AC_STEP = 2 # 硬编码
```
**❌ 问题**:不同设备(线切割 / 激光切割 / 注塑机 / 其他)的参数名、步长、范围都不同,每台设备都要改代码是不合理的。
**建议优化**(详见第五节)。
---
## 五、建议优化:将 rewrite_engine 和 dialog_act 配置化
这是你关心的核心问题,以下是具体方案。
### 5.1 新增 `config/context_rewrite.yml`
```yaml
# context_rewrite.yml
param_contexts:
- intent_ids: ["wirecut_set_speed"]
slot_name: "speed"
unit: "mm/min"
step: 5
min_value: 1
max_value: 9999
default_value: 80
up_phrases: ["再快一点", "加快", "速度调高", "快一点"]
down_phrases: ["再慢一点", "减慢", "速度调低", "慢一点"]
rewrite_template: "速度设为 {value} mm/min"
- intent_ids: ["wirecut_set_voltage"]
slot_name: "voltage"
unit: ""
step: 5
min_value: 0
max_value: 200
default_value: 90
up_phrases: ["电压高一点", "电压调高"]
down_phrases: ["电压低一点", "电压调低"]
rewrite_template: "电压设为 {value}"
- intent_ids: ["wirecut_set_current"]
slot_name: "current"
unit: ""
step: 1
min_value: 0
max_value: 30
default_value: 5
up_phrases: ["电流大一点", "跟踪值高一点"]
down_phrases: ["电流小一点", "跟踪值低一点"]
rewrite_template: "电流设为 {value}"
```
然后修改 `rewrite_engine.py`,从 `context_rewrite.yml` 驱动逻辑,而不是硬编码。
### 5.2 扩展 `config/dialog_acts.yml` 支持 inform 的数值捕获
```yaml
# dialog_acts.yml 新增字段
acts:
- act_id: inform
phrases: []
# 新增:数值模式检测
numeric_patterns: ["\\d+"] # 包含数字就认为是 inform
```
并在 `dialog_act.py` 里支持 `numeric_patterns` 字段,这样 "85" / "22度" 是否算 inform 就可以通过配置控制。
### 5.3 `Settings`config.py里增加工控设备配置项
`app/core/config.py` 里的 `Settings` 类目前通过环境变量驱动,建议增加工控配置路径:
```python
# 新增到 Settings 类
context_rewrite_config_path: str = "config/context_rewrite.yml"
device_domain_config_path: str = "config/domain_wirecut.yml" # 可按设备切换
```
这样不同设备(线切割、激光机)只需要切换 `.env` 文件里的 `AGENT_DEVICE_DOMAIN_CONFIG_PATH` 就能换一套 domain + rewrite 配置,**不改代码**。
---
## 六、整合架构建议(整体链路)
```
语音输入
↓ ASR前端 / 设备侧)
文本输入
Canvas 路由层Next.js / TypeScript
├── [大流程 B 激活] textAliases 匹配 → 直接推进 Artifact 步骤(不过 BERT
└── [其他] HTTP → intelligent_cabin :8000
context rewrite工控版配置化
BERT NLU工控 domain
fusion decision
├── execute → Canvas 走 DBus 工具调用
├── clarify → Canvas 渲染 Artifact 确认卡
├── route_to_cloud → Canvas 走 LLM 兜底 + 知识库
└── reject → Canvas smalltalk / fallback
```
---
## 七、待你确认的清单
| # | 问题 | 选项 |
|---|---|---|
| 1 | BERT 模型是否会重训成工控版,还是继续用车机模型迁移? | A. 重训工控 BERT B. 车机→工控迁移 C. 暂时用 mock/keyword |
| 2 | Canvas 是消费 BERT 的 `decision` 字段,还是只取 `intent_id+score` 自己路由? | A. 消费 decision B. 自路由 |
| 3 | 大流程 B 的 textAliases 匹配,确认在 Canvas 侧做,不经过 BERT 服务? | A. 是 B. 也经过 BERT 但 BERT 优先级低 |
| 4 | rewrite_engine 配置化的优先级?现在要做还是等工控 domain 确定后一起做? | A. 现在就做 B. 等 domain 定了再做 |
| 5 | dialog_acts.yml 的 `inform` 数值识别是否需要配置化? | A. 配置化 B. 保持硬编码即可 |
| 6 | 不同设备部署时,是一个 BERT 服务实例 + 不同 `.env` 配置,还是多个实例? | A. 单实例多配置 B. 多实例 |
---
*本文档由 Antigravity 生成,请确认后继续推进实现。*