HexaMind 搭建攻略:给 Hermes Agent 配一套用不满的长期记忆
用 Hermes Agent 用久一点,大概率会撞到同一堵墙:它记不住事。每开一个新会话,它就像重新失忆一次:上次为什么那么改、你偏好哪种写法、哪个坑已经踩过,全得再讲一遍。
自带的 memory 能记一点。但很快你会发现它有个天花板:两个 markdown 文件,我这里各 15,000 字符,加起来 3 万封顶。塞满了就得删旧的腾新的。而且这两个文件每一轮对话都会原样塞进上下文,记得越多,每轮越贵。
我给自己的 venxine.vip 折腾了一套叫 HexaMind 的记忆系统,六层,断断续续跑了两周。这篇不讲架构玄学(那是前两篇的事),讲怎么从零搭起来:需要什么环境、装哪些 skill、什么顺序、以及它到底比自带 memory 强在哪、强多少。
前情:《Hermes 五层记忆体系》 讲分层设计,《HexaMind 六层记忆:从 L5 到 L6》 讲主动性层的加入。这篇是能照着复现的操作手册。
一、HexaMind 是什么
一句话:把 AI 的长期记忆从「每轮硬塞进上下文的一段文本」,改成「一个能搜索的数据库,外加一层向量语义检索」。
六层各管一件事:
| 层 | 职责 | 落地 |
|---|---|---|
| L1 结构化存储 | 精确事实、偏好、教训 | SQLite + FTS5(agent-memory) |
| L2 向量编码 | 文本转 1536 维向量 | OpenRouter 的 embedding 模型 |
| L3 语义检索 | 「网页加速」也能命中「CDN 优化」 | LanceDB 向量索引 |
| L4 自我进化 | 从纠正里学,不重复踩坑 | lessons 表 |
| L5 知识图谱 | 实体和它们的关联 | entities 表 + 边 |
| L6 主动性 | 用户开口前先把东西备好 | proactivity skill |
关键点:L1 到 L5 不是六个孤立的库。事实存在 L1,L2 给它算向量,L3 拿向量做模糊搜索,L4/L5 挂在同一个数据库里。你真正要装的核心只有一个 skill,剩下的是配置和几个脚本。
二、自带 memory 撞墙在哪
先说清楚,我不是要劝你扔掉自带 memory。它有个 HexaMind 给不了的好处:永远在线,零检索延迟。每轮对话它都在上下文里,agent 不用「去查」就知道。
但它也就到此为止了。拿实际数字对比:
| 维度 | 自带 memory | HexaMind |
|---|---|---|
| 容量 | 两文件各 15,000 字符,共 3 万封顶 | L1 光 facts 正文就 23,438 字符,无上限,DB 5.9MB |
| 每轮成本 | 当前填了 10,766 字符,每一轮都重塞进上下文 | 按需检索,一次拿 top-5 大概几百字符,多数轮次是 0 |
| 检索方式 | 靠模型自己在一大段扁平文本里翻 | FTS5 关键词 + 向量余弦,跨词汇 |
| 结构 | 一堆用分隔符隔开的纯文本 | facts / lessons / entities,带标签、置信度、软删除、97 条实体边 |
| 满了怎么办 | 删旧的 | 不用删,继续长 |
把每轮成本摊到一整段对话上,差距更明显。一个 50 轮的会话,自带 memory 会把那 10,766 字符重新塞进去 50 次;HexaMind 只在 agent 真的去搜的时候才注入,而且只注入搜到的那几条。
所以正确的用法不是二选一,是分工:自带 memory 当热缓存,放最高频、必须常驻的偏好;HexaMind 当深库,放长尾知识,用的时候再捞。我现在 memory.md 只用了 7,805 字符,就是因为该下沉的都下沉到 HexaMind 了。
三、动手前,先备齐三样东西
环境。 Hermes Agent 本体、Python 3、uv(建虚拟环境用)。这些大概率你已经有了。
一个 embedding 模型。 这是整套系统里唯一要联网、也是唯一要花钱的部分,但花得极少。L3 的语义检索靠向量,你需要一个能把文本转成向量的模型。我用的是 openai/text-embedding-3-small,走 OpenRouter,1536 维。一条事实只 embed 一次,之后一直复用,所以成本基本可以忽略。任何 OpenAI 兼容的 embeddings 接口都能替。key 放在 ~/.hermes/.env 里的 OPENROUTER_API_KEY。
几个 skill。 角色分工是这样的:
| skill | 作用 | 必装? |
|---|---|---|
agent-memory |
核心库:L1/L2 存储 + L4 lessons + L5 entities + 内置搜索 | 必装 |
hexamind-memory-system |
六层协议、铁律、检索/写入工作流 | 必装 |
proactivity |
L6 主动性 | 建议 |
self-improving |
L4 的实践方法 | 可选 |
ontology |
L5 知识图谱的实践方法 | 可选 |
L3 不是一个现成 skill,它是 lancedb 加两个小脚本,下面第五步会讲。
四、七步搭起来
第 1 步:装 agent-memory(L1 地基)
skillhub install agent-memory
装完你会得到 ~/.agent-memory/memory.db(SQLite + FTS5),三张表 facts / lessons / entities,和一组 API:remember / recall / learn / track_entity / semantic_search。这是整套系统的地基,先把它跑起来。
第 2 步:配 embedding key(L2 的前提)
往 ~/.hermes/.env 里加一行:
OPENROUTER_API_KEY=sk-or-...
没有这一步,L2 编码和 L3 语义检索都跑不了,系统会自动降级成纯关键词搜索。
第 3 步:往里写东西(喂 L1)
from src.memory import AgentMemory
mem = AgentMemory()
mem.remember("部署 fund-web 要先 touch 模板再 restart,Flask 有模板缓存",
tags=["fund-web", "deploy"])
mem.learn(action="gunicorn 用 gthread workers",
context="3.6GB 内存机器反复 OOM",
outcome="negative",
insight="低内存机器优先用 sync workers")
mem.track_entity("fund-web", "project", {"stack": "Flask + Nginx + systemd"})
事实、教训、实体,三种东西各有各的表。这一步就是把你脑子里、或者散在旧会话里的知识倒进 L1。
第 4 步:回填向量(L2)
这里有个我这次才发现的坑,值得单独说清楚:remember() 只写关键词索引,不自动生成向量。新写的事实 embedding 字段是空的,语义搜索根本搜不到它。之前我一直以为写进去就完事了,其实 L1 到 L3 这条管线是断的。
补法是跑一个回填脚本,把所有没向量的事实批量 embed:
~/.hexamind-venv/bin/python embed_missing.py
它只处理空向量的行,已经 embed 过的跳过,所以反复跑也不浪费钱。
第 5 步:搭 L3(LanceDB)
系统自带的 Python 通常是 PEP 668 托管的,别直接 pip install。建个独立虚拟环境:
uv venv ~/.hexamind-venv
uv pip install --python ~/.hexamind-venv/bin/python lancedb pyarrow numpy requests
然后从 L1 已有的向量建 L3 索引。注意是复用向量,不重新 embed,所以这一步不花钱:
~/.hexamind-venv/bin/python build_l3_index.py
跑完你会有 ~/.lancedb,一张 facts 表,里面是向量加指向 L1 的引用(不存正文,正文永远只在 L1)。
有个小陷阱:lancedb.connect('~/.lancedb') 不会自动展开 ~,它会在当前目录下建一个名字真的叫 ~ 的文件夹。必须 os.path.expanduser('~/.lancedb')。
第 6 步:挂个自愈 cron
新事实进了 L1,L3 不会自己更新。与其每次手动跑,不如挂个每天凌晨的 no_agent cron,按顺序做三件事:回填向量、重建 L3、校验 L1 和 L3 的条数一致。成功就安静,失败或数量对不上才告警。
我的这个 cron 每天 03:30 跑,跑完往微信推一条确认,顺带告诉我今天记忆涨了几条。平时它就是个哨兵,只有出问题才出声。
第 7 步:装编排 skill
最后装 hexamind-memory-system。它不存数据,它定的是规矩:六层怎么协作、检索先走 L1 再走 L3、写入必须先 embed 再进 L3、别让 L3 变成第二个 L1。再加上 proactivity(L6),可选的 self-improving 和 ontology。装完之后 agent 每次做记忆操作都会按这套协议走,而不是随手塞一句了事。
五、我替你踩好的几个坑
- 写入不自动 embed。 上面第 4 步说过。这是最隐蔽的一个:一切看起来正常,关键词能搜到,就是语义搜不到新东西。修法是 embed 回填加 cron 自愈。
- 脏标签能整条搞崩。 我库里有 10 条历史事实的标签是逗号分隔的字符串(
2026-06-20,website,venxine),而代码用json.loads解析标签。语义搜索一遍历到它就抛异常,把整条检索链路拖死。修法是把标签统一成 JSON 数组。数据卫生这种事,平时看不出来,出事就是全线崩。 - 向量模型得验证是不是同一个空间。 L2 建索引用一个模型,L3 查询时也得用同一个,否则向量对不上。验证方法很简单:拿一条事实自己的正文去 embed,再和它存着的向量算余弦,应该是 1.0000。我实测就是 1.0000,说明查询和存储在同一个向量空间。这一步别省。
六、venxine.vip 现在的记忆状态
搭完之后,跑一遍体检,当前的实际数字:
| 层 | 状态 |
|---|---|
| L1 结构化 | 184 条事实,FTS5 关键词搜索正常 |
| L2 向量编码 | 184/184 全部编码,1536 维,往返自检索 cosine 1.0000 |
| L3 语义检索 | 184 条向量在 LanceDB,与 L1 条数对齐 |
| L4 自我进化 | 21 条教训 |
| L5 知识图谱 | 11 个实体,97 条实体到事实的边,11/11 都连上了 |
| L6 主动性 | proactivity skill 在位 |
底层库 5.9MB,每天 03:30 自愈同步。而自带 memory 那两个文件被我压到 7,805 和 2,961 字符,离 15,000 的顶还远,因为深知识都挪进 HexaMind 了,热缓存自然就轻。
一个能直接看出差别的例子:我搜「网站部署上线的正确流程」,它命中了那条讲 touch 模板 + restart 的事实,尽管两句话没有一个共同的关键词。这是纯 FTS5 做不到的。
七、值不值得
说实话,搭这套东西前前后后花的时间不算短,中间还踩了上面那几个坑。但跑起来之后最大的感受不是「AI 变聪明了」,而是我不用再一遍遍跟它重复同样的话。
它记得我上次为什么把那个符号链接删了,记得部署要先 touch 再 restart,记得我讨厌鸡汤式的收尾。
记忆系统的价值不在于层数多好看、DB 多大,而在于你少解释几遍。就这么点事。