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-improvingontology。装完之后 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 多大,而在于你少解释几遍。就这么点事。