模板检索还是向量检索?SkillClaw技能注入2种模式完整源码级解析
【免费下载链接】SkillClawLet Skills Evolve Collectively with Agentic Evolver项目地址: https://gitcode.com/gh_mirrors/sk/SkillClaw
SkillClaw 是一个让 AI Agent 技能随真实会话集体进化的开源项目,它的客户端代理会在每次请求时把本地技能库注入到模型的 system prompt 中。本文深入解析 SkillClaw 技能注入的 2 种检索模式——默认的模板检索(template)与可选的向量检索(embedding),带你从源码看懂它们的工作原理、差异与适用场景。
技能注入在 SkillClaw 中是怎么发生的?
先建立一个整体印象:SkillClaw 客户端代理拦截 Agent 的请求,从本地目录(如~/.hermes/skills)加载所有 SKILL.md 文件,然后调用注入逻辑把它们放进 system message。
核心入口在 api_server.py 的_inject_skills()方法,每次"主对话轮次"触发。而"选哪些技能进 prompt"这一决策,就是两种检索模式的分水岭,全部实现集中在 skill_manager.py 的retrieve()方法中:
def retrieve(self, task_description: str, top_k: int = 6) -> list[dict]: if self.retrieval_mode == "embedding": return self._embedding_retrieve(task_description, top_k) # 模板模式:按有效性评分平铺排序 all_skills_sorted = sorted( all_skills, key=lambda s: self.get_effectiveness(s.get("name", "")), reverse=True, ) return all_skills_sorted[:top_k]👉 一句话概括:模板模式"不看任务内容",只看技能历史表现;向量模式"先看懂任务",再做语义匹配。
模式一:模板检索 —— 零延迟的默认方案
模板模式(retrieval_mode: "template")是 SkillClaw 的默认配置,可在 config_store.py 看到其默认值:
"skills": { "enabled": true, "retrieval_mode": "template", "top_k": 6 }工作原理:有效性评分平铺排序
模板模式的检索完全不使用任务描述文本,而是给每个技能算一个"有效性分数"(effectiveness),然后按分数从高到低取前top_k个。
有效性分数在 skill_manager.py 中持续统计:每次技能被注入请求就 +1 次inject_count,每次收到 PRM(过程奖励模型)的正向反馈就 +1 次positive_count,最终:
effectiveness = positive_count / inject_count # 未知技能默认 0.5这意味着越"好用"的技能排名越靠前——用过、且被用户认可的技能会自然浮上来,没验证过的技能沉底。这是一个朴素但高效的"用数据投票"机制。
模板模式的特点
| 特点 | 说明 |
|---|---|
| ⚡ 延迟 | 零,不需要编码任何文本 |
| 🧠 依赖 | 无,不需要 embedding 模型 |
| 🎯 精准度 | 与当前任务内容无关,靠历史表现排序 |
| 📦 适用 | 技能库较小(几十个以内)、想要开箱即用 |
模式二:向量检索 —— 按语义找最相关的技能
把配置中的retrieval_mode改为"embedding"后,检索逻辑切换到 skill_manager.py 的_embedding_retrieve()方法,整个过程分 4 步:
第 1 步:技能向量化(一次缓存)
启动时,每个技能的"名称 + 描述 + 正文前 200 字"被编码成向量,缓存在内存中(skill_manager.py)。技能库变化时缓存自动重建。
第 2 步:任务描述匹配
把当前请求的任务描述编码成同样的向量,与所有技能向量做余弦相似度计算:
query_emb = model.encode([task_description], normalize_embeddings=True) sims = cache["embeddings"] @ query_emb第 3 步:相似度 × 有效性 加权排序
纯相似度不够——一个描述很像但实际不好用的技能,不该排在前面。skill_manager.py 用这个公式融合两个信号:
score = similarity * (0.3 + 0.7 * effectiveness)有效性为 0 的技能被压到相似度的 30%,有效性拉满则可拿满 100%。
第 4 步:近重复去重
技能库里常有多个"长得像"的技能。skill_manager.py 会取前top_k * 3个候选,两两比较向量相似度,超过0.9的视为近重复,只保留加权分更高的那个,空出的名额由下一名候选补上。
本地模型 vs 调用 API
向量模式支持两种 embedding 来源,在 config.py 配置:
- 本地模型(默认):基于
sentence-transformers,默认模型为Qwen/Qwen3-Embedding-0.6B,零成本但需要装依赖、吃内存; - API 模式:走任何 OpenAI 兼容的 embedding 接口(如
text-embedding-3-small),实现在 embedding_api_client.py,省本地资源但每次冷启动有一次网络编码。
两种模式怎么选?一张表看懂
| 维度 | 模板检索 template | 向量检索 embedding |
|---|---|---|
| 默认状态 | ✅ 默认开启 | 需手动切换 |
| 是否看任务内容 | ❌ 不看 | ✅ 语义匹配 |
| 依赖 | 无 | 本地模型或 embedding API |
| 检索延迟 | 零 | 首次编码有开销 |
| 额外机制 | 有效性排序 | 有效性加权 + 0.9 阈值去重 |
| 适合场景 | 小技能库、开箱即用 | 技能库大、任务类型多样 |
💡 经验建议:技能数在几十个以内时模板模式通常够用且最稳;当技能库膨胀到上百个、覆盖编程/研究/数据等多类任务时,向量模式能显著减少"注入一堆不相关技能"的噪音。
注入的最终形态:XML 目录 + 懒加载
值得注意的细节:无论哪种模式,SkillClaw 都不是把技能全文塞进 prompt。skill_manager.py 的build_injection_prompt()会生成一个精简的<available_skills>XML 目录,每个技能只有name、description、location三个字段:
## Skills (mandatory) <available_skills> <skill> <name>debug-systematically</name> <description>Use when diagnosing a bug...</description> <location>~/.skillclaw/skills/debug-systematically/SKILL.md</location> </skill> </available_skills>模型看到任务与某个技能描述匹配时,才会用read工具去加载对应的 SKILL.md 全文——这是借鉴 OpenClaw 的懒加载设计,目录超长(超过 30000 字符)时还会自动降级为省略 description 的紧凑格式,严格控制 token 开销。
小结
SkillClaw 的技能注入用了一个很务实的分层设计:
- 模板模式解决"零配置可用"——靠历史有效性投票,零延迟零依赖;
- 向量模式解决"技能多了找不准"——语义匹配 + 有效性加权 + 去重三重保障;
- 最后统一收敛到 XML 目录 + 懒加载,把注入成本压到最低。
想自己动手验证,只需改一行配置:skillclaw config skills.retrieval_mode embedding,重启代理即可。核心实现都在 skillclaw/skill_manager.py,相关测试可参考 tests/test_embedding_api.py,欢迎深挖源码。
【免费下载链接】SkillClawLet Skills Evolve Collectively with Agentic Evolver项目地址: https://gitcode.com/gh_mirrors/sk/SkillClaw
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考