Hermes 与 openClaw 记忆增强 BGE-M3 + Ollama 实践
内附 Hermes 开源插件,BGE-M3 + Ollama,零云依赖,本地语义搜索,及 Hermes 与 openClaw 双端实践

Hermes 有一个一直没解决的问题:跨会话失忆。也不是说它完全不记得 —— 内置的 session_search 可以搜历史对话,底层是 SQLite FTS5 全文索引。但 FTS5 只认词面,这是啥意思呢。比如,有一次我问 Hermes:「之前那个处理 xxx 文章摘要的方案怎么搞的?」,结果它没找到。因为历史对话里用的词是「文章总结」,不是「摘要」。意思一样,但 FTS5 有点矬,字面不匹配那就是没有了。这是检索工具的局限,但让人觉得是模型有点矬,模型表示冤啊……
一、搜索的两条路
文本搜索大致分两类。
-
• 关键词匹配:代表是 FTS5、Elasticsearch。核心是词面 —— 搜「摘要」,找含「摘要」这个词的文档。知道准确词的时候很好用,换个说法就失效。 -
• 语义搜索:把文本变成向量,用距离衡量「意思接近程度」。「摘要」和「文章总结」在向量空间里距离很近,搜一个能找到另一个。
代价还是有点的,但不多,仅仅需要一个嵌入模型把文本变成向量,也就是本文的主角:BGE-M3。
二、基础设施:BGE-M3 + Ollama
BGE-M3 是什么
BGE-M3 是一个开源的嵌入模型,「M3」代表三个特性:Multi-Lingual(多语言)、Multi-Granularity(多粒度)、Multi-Functionality(多功能)。
几个关键数字:
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
中英混合表现很好,代码注释夹中文这种场景识别程度,甚至比纯英文模型还要好。仅 1.2 GB,CPU 也可以跑。
Ollama:三行命令把它跑起来
本地运行 BGE-M3 最省事的方式是 Ollama —— 一个本地模型托管工具,macOS 的同学都知道。装上之后用命令行管理模型,提供统一的 HTTP API,也有客户端 chat 用。
1 2 3 brew install ollamaollama serveollama pull bge-m3
装好之后,一个本地 HTTP 即可拿到向量:
1 2 curl http://127.0.0.1:11434/api/embed \ -d '{"model": "bge-m3", "input": ["你想向量化的文本"]}'
返回 1024 维浮点数组。全程在本机完成,数据不出门,不需要 API Key。
三、给 Hermes 装上语义记忆
设计原则:不动源码,插件扩展
Hermes 的 session_search 工具底层是 SQLite FTS5,要加语义搜索最简单的思路是直接改源码(毕竟都是 AI 干活,就是费 token)。但改源码有两个问题:升级 Hermes 时改动会被覆盖;FTS5 的精确词面匹配(搜函数名、域名、错误码)本来也有价值,丢弃似乎也可惜了,成年人嘛,都想要。
最终决策:双路 —— FTS5 保留,新增 semantic_session_search 工具做语义搜索。
Hermes 提供用户插件目录 ~/.hermes/plugins/,这是设计上明确支持的扩展点:放在这里的插件格式统一为 plugin.yaml + __init__.py,其中 register(ctx) 函数通过 ctx.register_tool() 向 Hermes 注册新工具,挂载到指定的 toolset 下。
这两个工具都注册在 session_search toolset 里,Hermes 在每次会话开始时加载所有工具,模型推理时可以看到两个工具并按需路由 —— 这是 Hermes 工具系统的核心设计:工具是平等的,走哪条路由模型决定。
这里要说清楚:这不是并行。并行指两路同时执行、结果自动合并 —— 那是 openClaw 在引擎层做的事。Hermes 这里是串行按需路由:模型根据查询意图选一条路,或者先调一个、结果不满意再调另一个。
-
• 知道准确词(函数名、域名、错误码)→ 路由到 session_search,更快 -
• 记不清词但有大概印象 → 路由到 semantic_session_search,按语义找 -
• 两者都不确定时 → 两条都调,模型整合结果再回答
升级 Hermes 源码不影响 ~/.hermes/plugins/ 下的用户插件。
向量数据库:为什么选 sqlite-vec
嵌入向量需要一个地方存储和检索,常见选项有 LanceDB、Chroma、Qdrant 等。这里选 sqlite-vec,原因只有一个:和 Hermes 现有数据库同体系(SQLite),无需额外进程。
sqlite-vec 是 SQLite 的 C 扩展,通过 pip install sqlite-vec 装进 Python 环境,增量写入直接用 SQL,不需要启动额外的服务进程。向量查询语法:
1 2 3 SELECT * FROM vec_chunksWHERE embedding MATCH ? AND k = 50ORDER BY distance
distance 是 L2 欧氏距离,BGE-M3 输出的是归一化向量,L2 距离和余弦距离等价,按升序排即是最相关结果。
整体架构
核心文件路径:
1 2 3 4 5 6 7 8 ~/.hermes/scripts/semantic_index.py # 索引 + 搜索核心逻辑~/.hermes/plugins/semantic-search/ plugin.yaml # 插件声明 __init__.py # register(ctx) 注册工具~/.hermes/semantic_index.db # sqlite-vec 向量数据库~/.hermes/cli-config.yaml # on_session_finalize hook~/.hermes/scripts/session_finalize_hook.py~/.hermes/scripts/semantic_index_cron.sh
三层触发,保持索引实时
三层互补触发:
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
三层跑同一个增量索引函数,用文件 mtime 去重,WAL 模式并发安全,不会重复索引。
切块与索引
每个会话文件(.jsonl)里,提取 user 和 assistant 消息,按 400 字滑窗切块(80 字重叠),每块用 BGE-M3 编码后存入 sqlite-vec。索引完成后可用 stats 命令查看结果,以 300 个历史会话为例,状态大致如下:
1 2 3 4 5 sessions: 304chunks: 11431vectors: 11431db size: 57.2 MBlast indexed: 2026-05-26 07:41:03
四、开源插件:装好就能用
这套东西已经整理成了 Hermes 插件,开源在 GitHub:
🔗 https://github.com/shengting/hermes-semantic-search
前置条件: Hermes Agent 已安装,Ollama 已运行且拉好 bge-m3。
安装:
1 2 3 git clone https://github.com/shengting/hermes-semantic-searchcd hermes-semantic-searchbash install.sh
install.sh 一次做完所有配置:
-
• sqlite-vec 装进 Hermes venv -
• 核心脚本放到 ~/.hermes/scripts/ -
• 插件放到 ~/.hermes/plugins/semantic-search/(升级不覆盖) -
• config.yaml里自动 enable 插件 -
• 注册 on_session_finalizehook 和 hourly cron
安装后只需做一件事 —— 跑初始索引:
1 2 ~/.hermes/hermes-agent/venv/bin/python \ ~/.hermes/scripts/semantic_index.py index
这一步把你现有的历史对话全部建索引。跑完之后重启 Hermes,semantic_session_search 工具就出现了。之后的新对话自动增量索引,不需要再手动操作。
五、openClaw 里的同款实践
openClaw 是另一个本地 AI 助手框架,在记忆搜索这里走得更早,设计也更完整 —— 在引擎层做混合检索:dense 向量搜索和 BM25 关键词搜索同时跑,结果加权合并(默认 0.7 : 0.3),再经过 MMR 多样性重排和时间衰减。
配置只需在 openclaw.json 加几行:
1 2 3 4 5 6 7 8 { "memorySearch": { "enabled":true, "provider": "ollama", "model": "bge-m3", "sources": ["memory", "sessions"] }}
启用 sessions 来源后,历史会话进入向量索引,memory_search 能跨会话回忆。实际索引状态:
1 2 3 Indexed: 21 memory files · 92 chunks 125 session files · 401 chunksEmbedding cache: enabled (521 entries)
两个方案的区别:
openClaw 是引擎层合并 —— 两路结果在搜索时自动加权融合,对上层透明;Hermes 插件是工具层并列 —— 两个独立工具,合并逻辑在模型侧,实现更轻量,可以后续在引擎层补混合搜索。openClaw 的方案也验证了「FTS5 + 向量双路」这条路的可行性,是 Hermes 方案设计时的重要参考。
六、一个有意思的细节
写这篇文章时,我让 Hermes 搜了一下这个项目的历史对话 —— 用的正是 semantic_session_search,把实现过程里的技术细节全捞出来了。
跨会话记忆问题,用语义搜索来解决;写关于语义搜索的文章,用语义搜索来回忆。
小结
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AI 助手的记忆问题,本质是检索问题。本地跑一个嵌入模型,多开一条搜索路,就补上了 FTS5 够不到的那部分。
插件开源:https://github.com/shengting/hermes-semantic-search MIT 协议,欢迎 issue 和 PR
再来一张图片版本:

夜雨聆风