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

14 KiB
Raw Blame History

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 + scoreCanvas 自己做二次路由?

冲突 3textAliases(大流程 Bvs. BERT 意图识别的竞争

Canvas 大流程 B调机流程中的路由逻辑

输入 → 优先匹配 textAliases如"完成"/"下一步"/"确认"
     → 未命中 → BERT NLU 重新识别

intelligent_cabin 里的 DialogActEnginedialog_act.py)也在做相似的事情:

affirm: ["确认", "好的", "继续", "可以", "确定"]
cancel: ["取消", "算了", "不用了", "停止"]

冲突

  • textAliases 是每个 Artifact Step 私有的,属于 Canvas 状态机层面的规则匹配
  • DialogActEngine 是系统级对话行为分类,优先级/触发顺序未对齐
  • 如果两套都跑,"确认"这个词可能被 DialogActEngine 吃掉后不再传给 Canvas 的步骤推进逻辑

整合建议

  • 大流程 B 中textAliases 匹配应在 BERT 服务之前Canvas 侧处理,不交给 BERT 服务
  • dialog_acts.ymlaffirm/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_pathNC 文件绝对路径
  • axis轴编号0-5X/Y/Z/U/V/C

两套 slot 定义完全不同,需要重写 domain.ymlrewrite_engine.py 里的工控版本。


冲突 5rewrite_engine 的上下文改写逻辑是车机特化的

rewrite_engine.py 里写死了:

_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

这些都是车机空调的业务逻辑,工控场景需要换成类似:

_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/chatPOST /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_memoryslots 持久化机制,可以支持工控场景的多轮短句恢复(比如 "再快一点" → 记住上次速度值)。

整合点 4多命令拆分planner.py

现有的 sequence workflowconditional 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 里的工控上下文改写规则

# 工控版示例
_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.ymlaffirm/deny/cancel 词表可以保留,但需要补充工控场景的特化语句:

# 工控场景补充
affirm:
  + "执行" / "开始" / "运行" / "启动"
cancel:
  + "停机" / "急停" / "中止"
inform:
  + 纯数字(速度值/电压值/电流值的slot填写

四、关于 dialog_act 和 rewrite_engine 能否通过配置文件驱动

直接回答:当前已经部分支持,但工控场景需要扩展。

4.1 dialog_act 配置化现状

dialog_act.py 里的 DialogActEngine 是数据驱动的:

@dataclass
class DialogActEngine:
    patterns: dict[str, tuple[str, ...]] = field(default_factory=...)

config_loader.py 里已经实现了从 dialog_acts.yml 加载:

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 里的上下文改写逻辑全部硬编码,没有配置文件支持:

_AC_CONTEXT_INTENTS = {"cabin_set_ac", ...}  # 硬编码
_AC_DEFAULT_TEMPERATURE = 24                  # 硬编码
_AC_STEP = 2                                  # 硬编码

问题:不同设备(线切割 / 激光切割 / 注塑机 / 其他)的参数名、步长、范围都不同,每台设备都要改代码是不合理的。

建议优化(详见第五节)。


五、建议优化:将 rewrite_engine 和 dialog_act 配置化

这是你关心的核心问题,以下是具体方案。

5.1 新增 config/context_rewrite.yml

# 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 的数值捕获

# dialog_acts.yml 新增字段
acts:
  - act_id: inform
    phrases: []
    # 新增:数值模式检测
    numeric_patterns: ["\\d+"]   # 包含数字就认为是 inform

并在 dialog_act.py 里支持 numeric_patterns 字段,这样 "85" / "22度" 是否算 inform 就可以通过配置控制。

5.3 Settingsconfig.py里增加工控设备配置项

app/core/config.py 里的 Settings 类目前通过环境变量驱动,建议增加工控配置路径:

# 新增到 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 生成,请确认后继续推进实现。