HexaMind 运维篇:中文搜索、自动去重、热缓存双向同步
记忆系列第四篇写于 7 月 7 号。那是 HexaMind 搭好后的一个基本形态:六层架构在那儿,290 条事实在 SQLite 里,LanceDB 每天凌晨同步一次,能用。
但能用和不用管之间还隔着一大截。这 17 天里修了六件事,每件都是"用着用着发现不对"然后改的。
截止今天,HexaMind 的状态是:290 条事实、290 条向量全覆盖、52 条教训(44 条标注了领域标签)、33 个实体 187 条边、32 条中文镜像。热缓存从 86% 压到 72%。两条 cron:02:30 每日整理 + 03:30 全层同步,管着所有自动化。
一、为什么中文搜不到自己的事实
问题出得很早。我写了不少事实在 L1 里,中文搜"gunicorn 部署"打不到,搜"ECharts 图表规范"也打不到。搜了一圈发现:L1 里 271 条事实,只有不到 30 条是中文的,大部分是英语。HexaMind 的检索链路是 FTS5 优先,FTS5 没法跨语言,中文查询对着一堆英文事实只能抓瞎。
L3 语义检索理论上能跨语言,但中→英的余弦相似度只有 0.45 到 0.56,太低,基本不顶用。
解决这件事的办法我叫它 zh-mirror:给每条高频英文事实写一条 50 到 100 字的中文镜像,不删英文原文。tag 带 zh-mirror 标记,source 打上日期。一条典型镜像长这样:
原文: gunicorn zero-downtime reload: find master PID (PPID=1), sudo kill -HUP <pid>
镜像: gunicorn 零停机重载:找 master PID(PPID=1 的那个进程),sudo kill -HUP <pid>。
部署 venxine.vip 用。nginx 改完同理 sudo cp sites-available→sites-enabled + reload。
第一轮手动补了 24 条,覆盖部署流程、ECharts 规范、常见坑(Python dict.get 的 None 陷阱、Jinja2 endif、Nginx location 前缀吞并、CSS sticky/flexbox)、博客流水线、SEO 配置、热缓存机制这些高频领域。补完后中文搜索从"基本搜不到"变成"FTS 直接命中第一条"。
手动补 24 条花了半小时,但 L1 里还剩一百多条英文事实。不能每次都手动补。所以在 02:30 的"每日记忆整理"cron 里加了一步:当天没有新对话需要整理时,别空转,扫存量英文事实,每次补 1 到 2 条中文镜像。这样两个月内就能把存量消化干净。补完以后 03:30 的同步任务会自动跑 embedding 和重建 L3 索引。
二、热缓存快撑爆了
Hermes 自带的热缓存(MEMORY.md)每轮对话都会被原封不动塞进上下文。它有 15,000 字符的硬顶。
到 7 月 24 号,这个文件已经胀到 152 行、12,992 字符,使用率 86%。再涨一点就要开始报满了。
翻了一遍,发现不是信息太多,而是同一件事被记了很多遍。网关重启这件事出现了 4 处(一条初始记录 + 三条不同时间的更新),Demo 入口导航出现了 3 处,AI 新闻 cron 的踩坑出现了 5 处。HexaMind 架构那段有将近 800 字符,其实一句"skill:hexamind-memory-system"就够。X/Twitter 的支付细节写了 600 字符,也已经进了 L1 的 fact 库里。
处理方式很直接:合并同类项,删掉过时的,把冗长的压缩成关键词引用。16 组合并下来,152 条缩到 65 条,12,992 字符压到 10,644,使用率 70%,空出 2,300 字符。
三、L4 教训:三个月 55 条,有 3 组是重复的
7 月初写 L4 去重脚本的时候,逻辑很保守:只删 action 和 insight 完全相同的条目。跑到今天,55 条教训里藏了 3 组近重复:
- Flask 自调用诊断(2 条,一正一反,说的是同一件事)
- Nginx location 块缺失→404(3 条,action 措辞略不同,insight 几乎一模一样)
- /system/ 版本排查(2 条,一条是 Agent 版本,一条是 Studio 版本:这条其实不算重复,是同 root cause 的两个 symptom)
问题出在:02:30 cron 写 lesson 的时候,它做了一个语义查重,但只对 facts 生效,lessons 没有走这个流程。去重脚本也是机械兜底,不认模糊匹配。
修了两处:去了那 3 组里的 5 条(合并 insight 到最早那条),然后给去重脚本加了模糊匹配(SequenceMatcher > 0.85 且同领域 tag 加分)。
顺手做了一件事:给 lessons 表加了 tags 列。52 条教训里 44 条回填了领域标签(deployment / frontend / backend / cron / data / config / blog / agent),同领域的近似条目在去重时多给 0.05 分的加成,更容易被合并。02:30 cron 写 lesson 时也得带上 tags。
四、L5 实体时间戳一直不更新
L5 的实体(entities)有个 last_updated 字段,设计上是每次有新 fact 连到这个实体时就更新。但实际上,03:30 cron 的 link_entities.py 只管连边,不管更新时间戳。导致一些老实体:比如 CORE-V2、Venxine 的 last_updated 还停在 6 月 17 号。
加了一个 refresh_entity_timestamps.py,03:30 cron 在连边之后跑一次:对比当前边数和上一次记录的值,变了就更新所有实体的 last_updated。这样实体时效性能反映真实活跃度。
同时补了 4 个今天新增的实体:heatmap-optimization(热力图优化)、blog-desc-fix(博客文章首段重复修复)、zh-mirror(中文镜像系统)、static-homepage-seo(首页 SEO 描述)。实体从 29 涨到 33,边从 174 涨到 187。
五、热缓存和 L1 之间的双向裂缝
之前的数据流是单向的:02:30 cron 从当天对话里提炼事实,写进 L1。但 L1 里积累的事实,并不会自动回到热缓存。如果一条事实在 L1 里躺了半个月,agent 在对话里还是看不到它,除非热缓存里本来就有,或者 agent 刚好跑了 hexamind_search。
补了一个双向同步:hexamind-hotcache-sync.py,挂在 03:30 cron 里。每次全层同步之后,扫 L1 里新增的 daily-digest 类事实,摘出首句摘要(不超过 130 字符),追加到 MEMORY.md。同一条不会重复加。首次运行加了 5 条。
方向反过来,热缓存 → L1,02:30 cron 已经在做了,它本来就是从对话里提炼写 L1。
六、会话中也能搜 HexaMind 了
之前 agent 在对话里需要事实的时候,只看热缓存。热缓存没写的,它不知道 L1 里有。266 条事实大部分是白存的。
加了最简单的一步:在热缓存末尾塞了一条触发规则:遇到 venxine / fund-web / deployment / cron / 已知错误 / 配置 / 路径 类问题时,如果热缓存不够,就调 hexamind_search 查 L1→L3。不是什么复杂的自动注入,就是一条记忆提示。
命令是一条 terminal 调用:
~/.hexamind-venv/bin/python hexamind_search.py "gunicorn 部署 HUP" 5
返回 FTS 优先 + L3 语义补缺的混合结果。
收尾
HexaMind 这套系统写了快一个月。从最早的"记不住"到六层架构,到搭建攻略,到今天的运维优化。现在它不需要我每天看着了。02:30 自动整理对话和补中文镜像,03:30 重建索引、连边、去重、刷新时间、同步热缓存。每天凌晨两段 cron 跑完,微信上收到一条报告。