0x00 序※
上一篇文章《Hermes 记忆引擎实践》记录了记忆引擎的选型:Holographic——本地、轻量、SQLite 存储,配 HRR 全息向量检索。当时觉得它够用。
但用起来很快发现一个致命问题:它用正则提取实体,而正则对中文、小写主机名、域名这些我们天天打交道的名词完全失效。写进去的事实,实体关系建立不起来,图谱是一盘散沙。
这篇文章记录的就是后续的完整进化:发现问题 → 调研行业 → 决定自己造 → 数据治理 → 方法论沉淀。
发现缺陷:正则的无力※
Holographic 的实体提取用三条正则规则:大写多词短语("John Doe")、引号内术语、AKA 模式。它假设实体都是英文命名习惯。
但我们的知识图谱里全是这样的实体:
- 中文:百度网盘、天翼云、移动电脑
- 小写主机名:sad、silk、cynic
- 域名:tm.aketer.me、poto.aketer.me
正则一条都匹配不上。实测:写一条含这些名词的事实,引擎提取不出任何实体,图谱里的实体全是手动建的。
这不是修修补补能解决的——正则的范式就是错的。
调研:行业怎么解决※
先看主流记忆引擎的做法:
| 引擎 | 实体提取 | 问题 |
| Holographic | 正则 | 中文/小写/域名全废 |
| Mem0 | LLM 提取 | 图谱是实体集合,非可视化 |
| OpenViking | LLM 提取 | 文件树非真图谱 |
| Zep/Graphiti | LLM + Neo4j | Neo4j 依赖重,社区版弃用 |
为什么说 Neo4j 重?对比实际数据:
| 项目 | Neo4j 要求 | 我们的 sad 本机 |
| 运行时 | Java 17/21(JVM + 调优 heap/pagecache) | 纯二进制,无 JVM |
| 内存 | 官方手册最低 2GB,生产建议 4GB+(heap + page cache) | 7.7GB 总,已用 2.8GB,同时跑 14 个服务 |
| 存储 | 最小 10GB,数据目录含索引/日志,推荐 NVMe | 37GB 可用,普通磁盘 |
| CPU | 2 核最低 / 4 核推荐 | 8 核(够,但内存是瓶颈) |
核心矛盾在内存:Neo4j 是 Java 应用,官方手册最低 2GB 只是"能跑",生产要 4GB 以上才流畅。而我们的服务器 7.7GB 内存同时跑着 Trilium、Vaultwarden、Kuma、OpenList、Caddy、frps、Easytier 等 14 个服务,剩余不到 5GB——给 Neo4j 分 2-4GB,所有服务都会被挤到 swap。
更关键的是:Neo4j 提供的能力是"图数据库",但我们要的不是又一个数据库,而是把记忆图谱可视化。Trilium 已经承担了这个角色(1900+ 笔记、noteMap 图视图、属性关系),Neo4j 是重复造轮子还更重。
另外,Graphiti(Zep 的图谱层)社区版已标记 deprecated(弃用),自建路径官方不再维护——长期风险大。
结论:没有"图谱 + LLM 提取"都强的轻量自托管方案。要么重(Neo4j),要么图谱能力弱(文件树)。
而我们已经有了 Trilium——真正的可视化知识图谱,1900+ 笔记沉淀。缺的只是"LLM 实体提取"这一环。
自研:Seraph 记忆引擎※
既然没有现成的,就自己造。以 Holographic 为基底 fork,加 LLM 提取层,命名 Seraph。
Seraph 在 Holographic 基础上增加了三个 LLM 通道:
- 实体提取(带类型):LLM 识别实体并分类,返回 [名字, 类型] 对——server/domain/service/project/repo 等 12 类
- 关系提取:LLM 提取实体三元组(A -resolves_to-> B),存独立的 entity_relations 表
- 实体描述生成:LLM 根据实体的关联事实生成结构化描述——点开 sad 实体节点,就是完整的服务器画像
关键设计:复用 Hermes 已有的模型配置(config.yaml 的 model.provider + .env 的 API key),不新增任何凭据。聚合类 provider(如 opencode-go)自动回退到可用的 deepseek。
实测效果——同一句话,正则 vs LLM:
| 方法 | 提取结果 |
| 正则 | (空)——全是中文和小写 |
| Seraph LLM | tm.aketer.me(domain)、trilium(project)、sad(server)、百度网盘(service)、rclone(tool) |
数据治理:422 到 265※
切到 Seraph 后做了存量回填——134 条事实全部跑 LLM 提取。结果喜忧参半:
- 喜:title 全补齐、567 条关系边自动生成、实体描述批量生成
- 忧:LLM 提取创建了 422 个实体,其中 351 个是垃圾——DNS 记录类型(MX/TXT/SPF)、泛词(在线/离线/用户)、路径(/etc)、英文短语(multiple_machines)
于是开始实体表治理:
- 识别噪声:DNS 类型/IP 段/端口/泛词/路径/0 关系实体
- IP 是有效实体:IP 地址(38.76.190.84、10.126.126.3)是服务器核心属性,标 resource 类型,建 has_ip 关系——不删
- 类型归一化:kuma→service、R2→resource、Ankia→project 等
- 优化提示词:在 LLM 提示词里明确排除 DNS 类型、IP、泛词
最终:422 → 265 个实体,0 unknown,12 类分布合理。类型化的好处是 Trilium 里实体按类型分域归位(server→主机目录、service→服务目录),图谱结构清晰。

方法论:图谱建模的常识※
治理过程中踩的坑,沉淀成几条建模原则:
- 主动探索:更新图谱时用常识探索部署位置、多机、依赖、外部托管——不被动等提醒
- 多实体建模:一个事物多个角色 = 多个独立实体 + 关系。poto 是项目、仓库、域名三个实体
- 禁止汇总实体:不建"15 个域名"这种汇总——每个域名独立建实体、独立连 cloudflare
- 域名分类型:解析到主机的(tm.aketer.me→sad)vs Cloudflare 托管的(poto.aketer.me)建模不同
- 中心实体:cloudflare/github/vaultwarden/easytier 作为汇聚节点,新资源先判断属于哪个中心
0xFF 跋※
Seraph 解决了实体提取的根本问题,但还有未完成的事:
- 信任评分未激活:fact_feedback 反馈闭环设计好了,但依赖使用习惯——每次检索后标记 helpful/unhelpful,评分才会分化,高价值事实才会浮上来
- LLM 提取仍有噪声:提示词大幅减少,但复杂文本偶尔还会抽出概念词,需要增量治理
- 实体描述 67% 覆盖:次级实体还没生成描述
下一个可能的方向:让实体描述随关系变化自动更新(现在需要手动刷新),或者把反馈闭环做成自动的——检索命中就隐式加分。
记忆引擎不是一次性项目,它会跟着使用持续进化。这篇文章是它的第一个里程碑。
参考资料※
- Neo4j Operations Manual:System requirements——Neo4j 硬件/软件要求(JVM 版本、最小内存)
- Neo4j Community Edition——社区版能力与限制(无高可用)
- Neo4j GitHub Issue #6442:Minimum memory and disc space——社区版小库最低内存讨论(2GB/512MB)
- Hermes Agent 官方文档:Memory Providers——8 种记忆提供者对比(Holographic/Mem0/OpenViking/Zep 等)
- Holographic 插件源码(NousResearch/hermes-agent)——Seraph 的上游,正则实体提取实现
- Seraph Memory(GitHub)——本文主角,自研记忆引擎