95 个 Skill,每轮对话就消耗 5000 多个 Token?本文将分享我们如何通过 Elasticsearch 语义搜索和一个 OpenClaw Plugin,将 Skill 列表从“全量注入”变为“按需加载”,将 Token 消耗减少 92%,并且即时生效。
一、你的 OpenClaw,正被 Skill 列表“偷走”Token
玩 OpenClaw 的人都知道:安装 Skill 一时爽,Token 消耗火葬场。
起初,你只装了 5 个 Skill,体验非常好。但随着你不断添加天气、GitHub、飞书文档、企业微信、腾讯云、Elasticsearch等功能,系统中逐渐堆积了 50 个、80 个,甚至 100 个 Skill。
你可能觉得“多就是好”,但 OpenClaw 每次对话都会将所有 Skill 的名称和描述放入 System Prompt。我们的实测结果是:
- • 95 个 Skill → System Prompt 占用 ~5,238 Token
- • 用户即使只说一句“你好”,这 5000 个 Token 也先被耗掉
- • 按 OpenRouter 的价格计算,每轮对话仅 Skill 列表就烧掉约 $0.005
更要命的是——无关的 Skill 还会干扰 LLM 的判断,导致“幻觉率上升”。明明是问天气,模型却在纠结是否应该用 GitHub Skill。
二、思路:为 OpenClaw 安装一个“智能筛子”
解决方案非常直观——按需供给。
用户问天气,就只提供天气相关的 Skill。用户问代码,就只提供 GitHub 相关的 Skill。其他 90 个 Skill 不注入,Token 自然节省。
这本质上就是 RAG(检索增强生成)的思路:先用语义搜索筛选,再将结果提供给 LLM。
但这里面临一个技术选型的问题:用什么做语义检索?用什么 Embedding 模型?
三、技术选型:为什么选择 Elasticsearch + Jina v5?
市面上有一些方案——基于本地 ONNX 模型和对象存储向量桶。它们的思路是:使用本地量化模型生成向量,写入对象存储,查询时再次生成向量进行检索。整个流程需要:Embedding API、向量存储和手动管理维度与距离度量。
我们选择了 Elasticsearch semantic_text + Jina Embeddings v5,原因如下:
1. 一步到位,零 Embedding 管理
传统方案需要两步:先调用 Embedding API 生成向量,然后写入向量存储。查询时也需两步:先将用户消息向量化,再去向量库检索。
而 ES 的 semantic_text 字段类型自动处理一切——只需写入文本,ES 会在内部自动调用推理端点生成向量。查询时也一样,直接传文本,ES 内部完成 Embedding 和向量检索。不需要外部 Embedding API,也不需要管理向量维度。
2. Jina Embeddings v5:紧凑型顶尖多语言模型
我们的 Embedding 推理端点使用的是 Jina Embeddings v5——由 Jina AI 和 Elastic 联合发布的新一代文本嵌入模型,在多语言 MTEB(MMTEB)基准测试中同级别第一。
jina-embeddings-v5-text-small 的核心数据:
- • 677M 参数,远小于许多同类模型
- • 32,768 Token 输入上下文窗口
- • 1024 维嵌入向量
- • 支持 211 种语言,中英文均衡,不偏科
它的杀手锏是 LoRA 插件架构:一个基础模型加上四个任务专用的 LoRA 插件(检索、文本匹配、聚类、分类),在不增加模型体积的前提下,每个任务都能做到最优。ES 在索引和检索时会自动选择合适的 LoRA 插件。
更进一步,Jina v5 支持 Matryoshka 表示学习——嵌入截断。默认 1024 维可以截断到 512 甚至 256 维,存储和计算成本成倍下降,精度损失极小。加上 二进制量化,嵌入大小可以从 2KB 压缩到 128 字节(减少 94%),性能几乎无损。
对我们的场景意味着什么? 95 个 Skill 描述的语义索引,即使全量存储也只需极小的空间。而且因为 Jina v5 原生多语言,中文查询“企业微信发消息”能精准匹配英文 description 的 wecom-msg Skill,不偏科。
jina-embeddings-v5-text MMTEB 得分
3. 检索延迟从秒级降到百毫秒级
基于本地模型和对象存储的方案,链路是:用户消息 → 本地模型推理(500ms)→ 网络请求到向量存储(500ms)→ 返回结果。总计 ~1-2 秒。
ES 方案:用户消息 → ES 集群内完成 Embedding 和检索(~100ms)。推理在集群内完成,没有额外的网络往返。用户几乎无感知。
4. 关键发现——异步 Hook 方案存在“永远差一轮”的致命缺陷
我们在深入研究过程中发现了一个严重问题:很多方案使用 message:received 事件 Hook 来做路由——这个 Hook 在 Gateway 层面异步执行,与 Agent Loop 是并行的。
代码语言:javascript
AI代码解释
1 2 3 4 时间线: 00:00 消息到达,Agent 开始加载 Skill(用旧的配置) 00:20 Hook 才完成向量检索,写入配置文件 00:21 SIGUSR1 热重载——但 Agent 已经在运行了!
结果是:Agent 永远用的是上一轮的 Skill 配置,当前轮永远失效。 而且因为每轮都会覆盖配置,连续对话时 Skill 列表一直在变,Agent 永远追不上。
我们的方案绕过了这个问题:使用 OpenClaw 的 Plugin 机制,注册 before_prompt_build Hook。这个 Hook 在 Agent Loop 内部同步执行——检索、过滤、注入,一气呵成,当轮就生效。
四、效果实测
我们在 95 个 Skill 的环境下测试:
指标
无 Router
有 ES Skill Router
变化
System Prompt Token
~5,238
~391
-92.5%
单轮成本
\(0.0053
\)0.0004
-92.5%
Top-1 Skill 命中率
N/A
80%+
—
检索延迟
N/A
100ms
零感知
几个真实场景:
场景 A:查天气
- • 用户:“深圳明天天气怎么样”
- • Router 推荐:[weather, tavily-search, gemini, …]
- • Token 节省:97.8%
场景 B:企业微信发消息
- • 用户:“企业微信发消息”
- • Router 推荐:[wecom-msg, bluebubbles, wacli, …](wecom-msg 命中,0.87 分)
- • Token 节省:92%
场景 C:创建飞书文档
- • 用户:“创建飞书文档”
- • Router 推荐:[feishu-doc, wecom-doc-manager, tencent-docs, …](feishu-doc 命中,0.83 分)
- • Token 节省:92%
场景 D:中文查英文 Skill
- • 用户:“腾讯云开发者社区任务”
- • Router 推荐:[tencent-cloud-community, tencent-cos-skill, …](0.81 分命中)
- • 跨语言语义理解,零配置
[图片位置6:Token 消耗对比柱状图——95 Skills vs 5 Skills]
五、5 分钟安装教程
前置条件
- • 一个 Elasticsearch 集群(Elastic Cloud 或自建)
- • 集群已配置
.jina-embeddings-v5-text-small推理端点(Elastic Cloud 默认可用) - • Python 3 +
pip install elasticsearch pyyaml
步骤 1:安装 Plugin
代码语言:javascript
AI代码解释
1 2 git clone https://github.com/oldcodeoberyn/es-skill-router.git openclaw plugins install -l ./es-skill-router
步骤 2:配置 ES 连接
编辑 /.openclaw/openclaw.json,在 plugins.entries 中添加:
代码语言:javascript
AI代码解释
{ “plugins”: {
"entries": { "es-skill-router": { "enabled": true, "config": { "esUrl": "https://your-cluster:9243", "esUser": "elastic", "esPassword": "your-password", "index": "openclaw-skills", "topK": 5, "minScore": 0.5 } } }
} }
也可以用环境变量(ES_URL、ES_USER、ES_PASSWORD)。
步骤 3:索引你的 Skill
代码语言:javascript
AI代码解释
export ES_URL=“https://your-cluster:9243"; export ES_USER=”elastic“ export ES_PASSWORD=”your-password“
python3 es-skill-router/skills/es-vector-skill/scripts/index_skills.py –index openclaw-skills –recreate
输出:
代码语言:javascript
AI代码解释
Found 95 skills Created index: openclaw-skills {”success“: true, ”indexed“: 95, ”errors“: 0}
步骤 4:重启 Gateway
代码语言:javascript
AI代码解释
1 openclaw gateway restart
步骤 5:验证
发一条消息给你的 Agent,然后检查日志:
代码语言:javascript
AI代码解释
1 grep ”es-skill-router|ready.*index“ /tmp/openclaw/openclaw-$(date +%Y-%m-%d).log
你应该看到:
代码语言:javascript
AI代码解释
1 2 ready: index=openclaw-skills topK=5 minScore=0.5
”message_id“: ”om_x100b53fc8“ → [tencent-cloud-community(0.74), tlon-skill(0.71), session-logs(0.71), wecom-msg(0.71), tencent-cos-skill(0.69)]
大功告成!
六、进阶配置
参数
默认值
说明
topK
5
保留的 Skill 数量,建议 3-10
minScore
0.5
最低相关度分数,低于此值的 Skill 不注入
index
openclaw-skills
ES 索引名
enabled
true
开关,设 false 可临时禁用
安装新 Skill 后,重新运行索引脚本即可(增量更新,不会覆盖已有的):
代码语言:javascript
AI代码解释
1 python3 es-skill-router/skills/es-vector-skill/scripts/index_skills.py –index openclaw-skills
七、总结
传统本地+对象存储方案
ES Skill Router(本文)
Embedding
需要外部 API 或本地模型
ES 内置(Jina v5)
路由机制
异步 Hook + SIGUSR1
同步 Plugin Hook
生效时序
永远差一轮
当轮生效
部署复杂度
Embedding 服务 + 向量存储 + Hook
一个 Plugin
延迟
1-2 秒
~100ms
多语言
取决于模型选择
Jina v5 原生 211 语言
Token 节省
~92%
~92%
一句话:做减法才是工程功底的试金石。 为大模型减轻上下文负担,它反而会表现得更聪明。
开源地址:github.com/oldcodeoberyn/es-skill-router
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/251037.html