P12 12_能力篇_会话存储和跨会话搜索
P12 · 12_能力篇_会话存储和跨会话搜索(16:25)
课时概要
能力篇 · 会话存储与跨会话搜索。官方 README「A closed learning loop」一条:FTS5 session search with LLM summarization for cross-session recall —— 用 SQLite FTS5 全文索引会话 + LLM 摘要做跨会话召回。
本分P 没有逐P 的官方简介(视频简介只有资源链接)。以下「本节要点 / 关键概念 / 代码实操」均改写自 Hermes 官方文档与官方仓库原文并标注来源;「我的收获」里标 本机实测 的是在本机实跑得到的真实状态。
视频:12_能力篇_会话存储和跨会话搜索 | 时长 16:25 | P12
本节要点
- 存储位置(官方 Storage Locations 表):所有会话元数据与消息都在
~/.hermes/state.db这一个 SQLite 文件里(含 FTS5 全文索引);gateway 路由索引在同一库的gateway_routing表里。 - 三件套:
state.db+state.db-wal(预写日志)+state.db-shm(共享内存索引)。SQLite 自行管理后两者,多个 Hermes 进程(gateway / Desktop / dashboard / cron / CLI)靠 SQLite 自身锁安全共享。 - Schema 关键三表:
sessions(会话元数据:id / source / user_id / model / title / 时间戳 / token 计数)|messages(完整消息历史:role / content / tool_calls / tool_name / token_count)|messages_fts(FTS5 虚拟表,跨消息内容的全文搜索)。标题有唯一索引(允许 NULL,非 NULL 必须唯一)。 ~/.hermes/sessions/sessions.json不是会话列表:它只是 gateway 路由索引的遗留镜像(gateway.write_sessions_json,默认 true),只含消息平台条目。真正的会话列表在state.db里 —— CLI / TUI / gateway 会话全都在。- 遗留 JSONL:在
state.db成为正典之前创建的会话可能在~/.hermes/sessions/留下*.jsonl;现在已不再写入或读取,确认对应会话已存在于 state.db 后可安全删除。 session_search工具(跨会话搜索的核心):用 SQLite 的 FTS5 引擎对所有历史会话做全文搜索,并允许 agent 在命中的会话里滚动阅读。⚠️ 官方明确写了 it makes no LLM calls —— 它返回的是 DB 里真实消息的视图,不是生成的摘要(这也是它与「记忆蒸馏」的分工所在)。- 四种调用形态(不靠
mode参数,而是由你传了哪些参数推断):① discovery 传query② scroll 传session_id+around_message_id③ read 只传session_id④ browse 不带参数(按时间倒序列最近会话)。 - FTS5 查询语法:简单关键词
docker deployment(FTS5 默认 AND)|短语"exact phrase"|布尔docker OR kubernetes、python NOT java|前缀deploy*。 - 搜索可选参数:
sort(newest/oldest,叠加在 FTS5 排序之上;省略则纯相关性排序)|detail(adaptive默认只完整水合第一条,full全部水合)|role_filter(默认user,assistant,搜索工具输出需显式加tool)。 - discovery 结果字段:
session_id/title/when/source/snippet(FTS5 高亮片段)/detail/bookend_start/bookend_end/messages(命中点 ±5 条)/match_message_id/messages_before/messages_after。 - 自动清理:
sessions.auto_prune(默认 true)、sessions.retention_days(默认 90)、vacuum_after_prune(默认 true)、min_vacuum_interval_days(默认 30)。只有已结束的会话会被删,活跃会话永不自动清理。 - 官方点名的失效模式:不做任何清理时,实测出现过 384 MB 的
state.db、约 1000 个会话,拖慢 FTS5 插入与/resume列表。 - 超大转录守卫:
sessions.max_resume_messages与sessions.max_export_messages(默认各 20000,设 0 关闭)—— 防止把失控的长转录一次性读进内存;被拒时客户端收到错误码 4130。 - 存储恢复(Session Storage Recovery)三件套铁律:不要删
state.db-wal/state.db-shm(日志里是已提交、尚未并进 state.db 的对话,删它是唯一会把「拒写」变成真丢数据的动作);不要只拷贝state.db(三件套是一个镜像,要用hermes backup或hermes sessions recover)。维护命令(optimize/prune)在别的进程持有该库时会拒绝执行并列出持有者 PID。 - 非破坏性的第一步:
hermes sessions optimize合并 FTS5 索引段并 VACUUM,不碰任何会话数据;hermes sessions prune才真删。日志模式可在 WAL 与 DELETE 间自服务切换(hermes sessions set-journal-mode)。 - 导入其他 CLI 的会话:
hermes sessions import读 Claude Code(~/.claude/projects/)与 Codex CLI(~/.codex/sessions/)的日志,新建一条Imported from Claude Code: <首条用户消息>的会话;hermes --resume @claude可导入并直接续接。源文件只读不改。 - 压缩两层(与存储直接相关):gateway 会话卫生在 85% 上下文触发(粗估,安全网),agent 的 ContextCompressor 在 50%(默认,真实 token)触发;手动
/compress可强制压缩。压缩减少的是活动上下文,不是隐私删除。
关键概念
- state.db:每个 profile 一个 SQLite 会话库,是所有会话的唯一正典(canonical)存储。
- WAL(Write-Ahead Log):
state.db-wal是 SQLite 的预写日志,支撑「多读 + 单写」的并发模型;gateway / Desktop 运行时-wal较大是正常现象。 - FTS5:SQLite 的全文搜索扩展,Hermes 用它建
messages_fts虚拟表,实现毫秒级跨会话检索。 - session_search 工具:agent 内置的会话检索工具(discovery / scroll / read / browse 四种形态),不调 LLM。
- auto_prune / retention_days:自动清理已结束会话的开关与保留窗口(默认开 / 90 天)。
- Session Storage Recovery:当有进程仍持有旧 WAL 时 Hermes 主动拒写以保护数据的机制,以及配套的三步恢复法。
代码 / 实操
bash
# 看一眼存储与统计
hermes sessions stats # 会话数 / 消息数 / 分来源 / DB 体积
hermes sessions export backup.jsonl # 先备份再清理
# 非破坏性维护(先做这个)
hermes sessions optimize # 合并 FTS5 段 + VACUUM,不动数据
# 真清理(先预览)
hermes sessions prune --older-than 90 --dry-run
hermes sessions prune --older-than 90 --yes
# 导入其他 CLI 的会话
hermes sessions import
hermes --resume @codexagent 侧的检索调用(官方示例):
python
session_search(query="auth refactor", limit=3)
session_search(session_id="20260510_174648_805cc2", around_message_id=590803, window=10)
session_search(session_id="20260510_174648_805cc2")
session_search() # 浏览最近会话本机实测:state.db 365 MB | state.db-shm 32 KB | state.db-wal 0 B(已 checkpoint)| ~/.hermes/sessions/ 目录 285 MB。
我的收获
用户此前已学过本模块;以下是本机实测状态(2026-09-25 01:3x):
- 本机正好落在官方点名的失效模式上:官方说「不清理时会看到 ~384 MB 的 state.db 与约 1000 个会话」,本机是 365 MB / 682 个会话 —— 同一个量级。
- 本机
config.yaml实录:sessions.auto_prune: false(不自动清理)、retention_days: 90、vacuum_after_prune: true、write_json_snapshots: false—— 所以 365 MB 是「主动保留全部历史」的结果,不是 bug;要瘦身第一步应该走非破坏性的hermes sessions optimize。 - 三件套体积实测(2026-09-25 01:31):
state.db365 MB +-shm32 KB +-wal0 B ——-wal为 0 说明当时的写入已 checkpoint 回主库。 ~/.hermes/sessions/的 285 MB 里有 94 个遗留.jsonl(最新一个停在 2026-06-08,正好对应官方说的「state.db 成为正典前的老会话」)外加 843 个.json(其中 796 个session_*.json、46 个request_dump_*.json调试转储,另 1 个其他;不在官方会话存储定义内)—— 这两类是值得考虑的目录卫生项。- 官方文档纠正了 README 的措辞:
session_search用 FTS5 检索、不做任何 LLM 调用;README 里「FTS5 session search with LLM summarization」的 LLM 摘要指的是更大的记忆 / 召回叙事,不是这个检索工具。 - 压缩配置本机实录:
compression.enabled: true、threshold: 0.5(= 官方默认 50%)、target_ratio: 0.2、protect_last_n: 20、hygiene_hard_message_limit: 400、abort_on_summary_failure: false。
(个人感想部分待补写。)
待深入
(待填:没听懂、想回头查的。)