本地意图识别
ai/localIntent 组件:v0.36.0+ 基于嵌入向量的本地意图分类,无需调用 LLM,通过语义相似度匹配用户输入到预定义意图,并将识别结果作为 Relation Type 路由到匹配的下游节点。
适合意图数量少、语义差异大、对延迟和成本敏感的场景。意图数量多或语义边界模糊时,建议使用 LLM 意图识别。
# 配置
| 字段 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| url | string | 嵌入模型 API 地址 | |
| key | string | 嵌入模型 API Key,私有部署可为空 | |
| model | string | 嵌入模型名称 | |
| input | string | 用户输入表达式,支持 ${msg.key} 和 ${metadata.key}。为空时使用 msg.GetData() | |
| intents | []LocalIntent | 预定义意图列表(至少定义一个) | 内置3个示例意图 |
| intentsFile | string | 外部意图配置文件路径,支持 YAML 和 JSON 格式 | |
| threshold | float64 | 最低匹配相似度阈值,低于该值时使用默认意图 | 0.65 |
| minGap | float64 | 最高分与第二高分的最小差值,低于该值时使用默认意图 | 0.05 |
| defaultIntent | string | 默认意图(无法识别时使用) | Default |
# LocalIntent 结构
| 字段 | 类型 | 说明 |
|---|---|---|
| name | string | 意图名称(作为 Relation Type 路由) |
| description | string | 意图描述(参与语义匹配) |
| examples | []string | 该意图的典型示例语句,建议 8-10 条 |
# 意图文件格式
支持 YAML 和 JSON 两种格式:
YAML 格式:
intents:
- name: createRule
description: "创建条件触发的自动化联动规则"
examples:
- "有人就开灯"
- "温度大于30度开空调"
- "水浸时开风机"
- "下雨天自动关窗"
- "离开家的时候关掉所有电器"
- "每天早上7点开窗帘"
- "空气质量差就开净化器"
- "燃气泄漏立刻关阀门"
- name: control
description: "控制设备开关或调节参数"
examples:
- "打开灯光"
- "把风机关闭"
- "关闭客厅灯"
- "空调调到26度"
- "让窗帘拉下来"
- "把门锁上"
- "电视声音大一点"
- "关掉所有灯"
- "启动扫地机器人"
- name: query
description: "查询设备当前状态或数值"
examples:
- "当前温度多少"
- "灯是不是开着的"
- "风机状态怎么样"
- "空调现在几度"
- "窗帘拉开着吗"
- "门锁了没"
- "现在湿度多少"
- "热水器还在加热吗"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
JSON 格式:
{
"intents": [
{
"name": "createRule",
"description": "创建条件触发的自动化联动规则",
"examples": ["有人就开灯", "温度大于30度开空调", "水浸时开风机", "下雨天自动关窗"]
}
]
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 匹配原理
- 初始化时,将所有意图的
description和examples通过嵌入模型生成向量(内部按每批 10 条分批调用 API) - 运行时,将用户输入通过同一嵌入模型生成向量
- 计算用户输入与所有意图向量的余弦相似度
- 如果最高分低于
threshold,或最高分与第二高分差值低于minGap,则使用defaultIntent - 否则使用最高分对应的意图作为识别结果
# 执行结果
- 识别结果写入
msg.Metadata["intent"],不修改msg.Data(原始消息透传下游) - 通过
TellNext(msg, intentName)路由到匹配的连接类型 - 未通过阈值判断时,使用
defaultIntent
# 最佳实践
# Description 编写原则
description 直接参与向量计算,质量决定匹配上限:
- 精确描述意图语义,避免模糊:
"控制设备开关或调节参数"比"控制设备"好 - 突出与其他意图的区别:
"创建条件触发的自动化联动规则"比"创建联动规则"好 - 不要包含意图名称本身,描述应独立表达语义
# Examples 编写原则
examples 是泛化能力的核心,直接决定模型能否识别"没见过"的表达:
- 覆盖不同设备:不要只用灯和风机,加入窗帘、门锁、空调、机器人等
- 覆盖不同句式:祈使句("打开灯光")、口语("灯开没开")、疑问句("空调开着吗")、否定句("别让洗衣机转了")
- 覆盖不同动作词:"打开""关掉""调到""启动""拉下来" 等
- 每个意图 8-10 条,太少泛化不足(测试表明仅 2 条时泛化率 0%),太多会增加噪音
- 避免不同意图的 examples 语义重叠
# Threshold 调优
0.65(默认):适合意图间语义差异大的场景,误匹配少但可能拒掉部分正确输入0.50-0.60:适合意图间有一定相似度的场景,提高召回率但增加误匹配风险minGap一般保持0.05,用于拦截与第二名意图分数接近的模糊输入- 建议用实际业务数据测试后调优:收集一批典型输入,逐步降低 threshold 直到误匹配出现,再回调 0.05
- 不同嵌入模型的向量空间不同,换模型后需要重新调优 threshold
# 配置示例
{
"id": "node_local_intent",
"type": "ai/localIntent",
"name": "本地意图分类",
"configuration": {
"url": "https://ai.gitee.com/v1/embeddings",
"key": "sk-xxx",
"model": "Qwen3-Embedding-8B",
"threshold": 0.65,
"minGap": 0.05,
"intents": [
{
"name": "createRule",
"description": "创建条件触发的自动化联动规则",
"examples": [
"有人就开灯", "温度大于30度开空调", "水浸时开风机",
"下雨天自动关窗", "离开家的时候关掉所有电器", "每天早上7点开窗帘",
"空气质量差就开净化器", "燃气泄漏立刻关阀门"
]
},
{
"name": "control",
"description": "控制设备开关或调节参数",
"examples": [
"打开灯光", "把风机关闭", "关闭客厅灯",
"空调调到26度", "让窗帘拉下来", "把门锁上",
"电视声音大一点", "关掉所有灯", "启动扫地机器人"
]
},
{
"name": "query",
"description": "查询设备当前状态或数值",
"examples": [
"当前温度多少", "灯是不是开着的", "风机状态怎么样",
"空调现在几度", "窗帘拉开着吗", "门锁了没",
"现在湿度多少", "热水器还在加热吗"
]
}
],
"defaultIntent": "unknown"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 应用示例
IoT 设备智能路由(云端嵌入 API):
{
"ruleChain": {"id": "iot-router", "name": "IoT智能路由", "root": true},
"metadata": {
"firstNodeIndex": 0,
"nodes": [
{
"id": "node_local_intent", "type": "ai/localIntent", "name": "本地意图识别",
"configuration": {
"url": "https://ai.gitee.com/v1/embeddings",
"key": "sk-xxx",
"model": "Qwen3-Embedding-8B",
"threshold": 0.65,
"minGap": 0.05,
"intents": [
{
"name": "createRule",
"description": "创建条件触发的自动化联动规则",
"examples": [
"有人就开灯", "温度大于30度开空调", "水浸时开风机",
"下雨天自动关窗", "离开家的时候关掉所有电器", "每天早上7点开窗帘",
"空气质量差就开净化器", "燃气泄漏立刻关阀门"
]
},
{
"name": "control",
"description": "控制设备开关或调节参数",
"examples": [
"打开灯光", "把风机关闭", "关闭客厅灯",
"空调调到26度", "让窗帘拉下来", "把门锁上",
"电视声音大一点", "关掉所有灯", "启动扫地机器人"
]
},
{
"name": "query",
"description": "查询设备当前状态或数值",
"examples": [
"当前温度多少", "灯是不是开着的", "风机状态怎么样",
"空调现在几度", "窗帘拉开着吗", "门锁了没",
"现在湿度多少", "热水器还在加热吗"
]
}
],
"defaultIntent": "unknown"
}
},
{"id": "node_create", "type": "restApiCall", "name": "创建规则",
"configuration": {"url": "http://api/createRule", "requestMethod": "POST"}},
{"id": "node_control", "type": "restApiCall", "name": "控制设备",
"configuration": {"url": "http://api/control", "requestMethod": "POST"}},
{"id": "node_query", "type": "restApiCall", "name": "查询状态",
"configuration": {"url": "http://api/query", "requestMethod": "POST"}},
{"id": "node_unknown", "type": "ai/llm", "name": "兜底回复",
"configuration": {"url": "https://ai.gitee.com/v1", "key": "sk-xxx", "model": "Qwen2-7B-Instruct", "systemPrompt": "你是一个IoT助手,帮助用户解答问题"}}
],
"connections": [
{"fromId": "node_local_intent", "toId": "node_create", "type": "createRule"},
{"fromId": "node_local_intent", "toId": "node_control", "type": "control"},
{"fromId": "node_local_intent", "toId": "node_query", "type": "query"},
{"fromId": "node_local_intent", "toId": "node_unknown", "type": "unknown"}
]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
本地私有化部署(离线运行,无需联网):
{
"id": "node_local_intent",
"type": "ai/localIntent",
"name": "离线意图识别",
"configuration": {
"url": "http://localhost:8080/v1/embeddings",
"model": "BAAI/bge-small-zh-v1.5",
"threshold": 0.60,
"intentsFile": "/etc/rulego/intents.yaml"
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
多语言意图识别:
{
"id": "node_local_intent",
"type": "ai/localIntent",
"name": "多语言意图分类",
"configuration": {
"url": "https://ai.gitee.com/v1/embeddings",
"key": "sk-xxx",
"model": "Qwen3-Embedding-8B",
"threshold": 0.65,
"intents": [
{
"name": "control",
"description": "Control device on/off or adjust parameters",
"examples": [
"打开灯光", "Turn on the light", "把风机关闭",
"Close the curtain", "空调调到26度", "Lock the door"
]
}
]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 私有化部署嵌入模型
本地意图识别依赖嵌入模型计算语义向量。除使用云端 API 外,可以通过 HuggingFace Text Embeddings Inference (TEI) (opens new window) 在本地部署嵌入服务,实现完全离线运行。
# 推荐模型
| 模型 | 参数量 | 维度 | 特点 | 适用场景 |
|---|---|---|---|---|
| BAAI/bge-small-zh-v1.5 | 33M | 512 | 轻量快速,中文效果好 | 边缘网关、资源受限设备 |
| BAAI/bge-base-zh-v1.5 | 102M | 768 | 质量与速度平衡 | 通用服务端部署 |
| BAAI/bge-large-zh-v1.5 | 326M | 1024 | 最高精度 | 对准确率要求高的场景 |
| Qwen/Qwen3-Embedding-0.6B | 600M | 1024 | 多语言支持 | 中英混合或多语言场景 |
模型选择原则:先从小模型(bge-small-zh)开始测试,如果准确率不够再升级大模型。
# Docker 部署 TEI
GPU 部署(推荐):
model=BAAI/bge-small-zh-v1.5
volume=$PWD/data
docker run -d --gpus all -p 8080:80 \
-v $volume:/data \
--name tei-server \
ghcr.io/huggingface/text-embeddings-inference:latest \
--model-id $model
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
CPU 部署:
model=BAAI/bge-small-zh-v1.5
volume=$PWD/data
docker run -d -p 8080:80 \
-v $volume:/data \
--name tei-server \
ghcr.io/huggingface/text-embeddings-inference:latest \
--model-id $model
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
首次启动会自动从 HuggingFace 下载模型权重。推荐使用 volume 挂载避免重复下载。
# 国内镜像加速
如果无法访问 ghcr.io,可以使用国内镜像:
# 拉取镜像
docker pull docker.aityp.com/ghcr.io/huggingface/text-embeddings-inference:latest
# 运行时使用本地镜像
docker run -d -p 8080:80 \
-v $PWD/data:/data \
--name tei-server \
docker.aityp.com/ghcr.io/huggingface/text-embeddings-inference:latest \
--model-id BAAI/bge-small-zh-v1.5
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 离线部署(无网络环境)
预先下载模型权重,然后在离线环境中加载:
# 1. 在有网络的机器上下载模型(需要安装 git-lfs)
git lfs install
git clone https://huggingface.co/BAAI/bge-small-zh-v1.5 models/bge-small-zh-v1.5
# 2. 将 models 目录拷贝到离线机器
# 3. 在离线机器上挂载本地模型启动
docker run -d -p 8080:80 \
-v $PWD/models:/data \
--name tei-server \
ghcr.io/huggingface/text-embeddings-inference:latest \
--model-id /data/bge-small-zh-v1.5
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 验证部署
启动后验证服务是否正常:
# 测试嵌入接口
curl http://localhost:8080/v1/embeddings \
-H "Content-Type: application/json" \
-d '{"input": "打开灯光", "model": "BAAI/bge-small-zh-v1.5"}'
# 应返回包含 embedding 向量的 JSON 响应
1
2
3
4
5
6
2
3
4
5
6
# 对接 LocalIntentNode
TEI 部署后提供 OpenAI 兼容的 /v1/embeddings 接口,url 配置为该地址即可:
{
"url": "http://localhost:8080/v1/embeddings",
"model": "BAAI/bge-small-zh-v1.5",
"key": ""
}
1
2
3
4
5
2
3
4
5
TEI 本地部署不需要 API Key,
key留空即可。
在 GitHub 上编辑此页 (opens new window)
上次更新: 2026/05/28, 01:50:04