DeepAI Paper Hermes Agent 教程,Hermes 记忆、技能与辅助任务 你明明发过,session_search 却说没见过:Hermes 记忆检索少了哪一块

你明明发过,session_search 却说没见过:Hermes 记忆检索少了哪一块

有时候,Agent 的问题不是忘了,而是明明存了,却搜不到

NousResearch/hermes-agent issue #16751 讲的就是这种很烦的记忆检索盲区:session_search 只索引了 messages.content,却没有覆盖 tool_callstool_name

结果是:

  • 用户明明在前面会话里调用过某个工具;
  • 工具名或参数里明明出现过关键字;
  • 数据库里那条消息也确实存在;
  • session_search 搜不到。

这会让长任务恢复和上下文追查变得特别难。

因为你以为“它没发生过”,其实只是“没进搜索索引”。


现象:正文能搜到,工具字段却完全失明

issue 的复现很有代表性。

作者构造了几类 marker:

  • BUCKETMARKER_CONTENT:出现在 message content
  • BUCKETMARKER_TOOLCALL:出现在 tool_calls JSON args
  • FUNCNAMEMARKER:出现在 tool function name
  • TOOLNAMEMARKER:出现在 tool_name

然后比较两种查询:

通过 search_messages

结果只有 content 中的 token 能命中:

BUCKETMARKER_CONTENT: 1 hit
BUCKETMARKER_TOOLCALL: 0 hit
FUNCNAMEMARKER: 0 hit
TOOLNAMEMARKER: 0 hit

直接查 messages 表

所有字段其实都在:

BUCKETMARKER_CONTENT: 1 hit
BUCKETMARKER_TOOLCALL: 1 hit
FUNCNAMEMARKER: 1 hit
TOOLNAMEMARKER: 1 hit

这说明不是数据没存,而是搜索层没索引到。


根因:FTS5 只盯着 content 字段

issue 里把 schema 说得非常清楚。

当前 messages_fts 是一个外部内容 FTS5 表:

CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(
    content,
    content=messages,
    content_rowid=id
);

对应 triggers 也只读取:

new.content / old.content

也就是说,FTS 只看 messages.content

但 Hermes 的消息表里,很多关键上下文其实藏在:

  • tool_calls
  • tool_name
  • 未来可能还有更多结构化字段

这些字段对于工具轨迹、任务恢复、错误分析非常关键。

如果只索引正文,就会出现“工具调用痕迹消失”的问题。


这不是 CJK tokenizer 问题

issue 特别强调,这个不是之前那个 CJK tokenization 问题。

这里用的是 ASCII marker:

BUCKETMARKER_CONTENT
BUCKETMARKER_TOOLCALL
FUNCNAMEMARKER
TOOLNAMEMARKER

所以不是分词器不认识中文,也不是 trigram 失灵。

而是索引层本身就没覆盖工具列。

这点很重要,因为它决定了修复方向完全不同。


为什么这对长任务尤其致命?

长任务恢复时,最需要查的往往不是“对话正文”,而是:

  • 哪个工具刚刚调用过;
  • 工具名是什么;
  • 参数里带了什么路径、ID、URL;
  • 有没有执行过某个副作用动作;
  • 是否已经发布、删除、移动、重启过。

这些信息在 Agent 场景里经常比正文更重要。

比如:

  • 文章发布流程里,工具名可能比正文更能定位到“是否发布过”;
  • debug 时,tool_calls.arguments 里的参数比正文更能定位问题;
  • 多步 agent 任务中,工具轨迹就是事实链。

如果 session_search 搜不到这些字段,用户会以为 Hermes 没记住,但实际上只是记忆不可检索。


可能的修复方向

issue 里列了三种靠谱方向。

1. 给 FTS5 增加更多列

tool_callstool_name 也作为 FTS 列:

content
tool_calls
tool_name

优点:

  • 可以列级查询;
  • external-content 语义更完整;
  • 工具轨迹能被搜索。

2. 新增 messages.search_text

把正文和结构化字段拼成一个可搜索的派生列:

content + tool_calls + tool_name

然后让 FTS 只镜像这个派生列。

优点:

  • 逻辑清晰;
  • 对现有查询改动相对可控。

缺点:

  • 需要 backfill;
  • 需要重建 FTS;
  • 字段同步要严谨。

3. 改成内部内容或 contentless FTS5

让触发器直接维护索引文本,而不是绑定单一 content 列。

优点:

  • 灵活;
  • 索引内容可完全由 Hermes 控制。

缺点:

  • 需要重新设计 snippet/highlight 体验。

为什么 naive 拼接不可取?

tool_callstool_name 直接拼进 content,看起来最简单。

但 issue 提醒,这会破坏外部内容表的一致性:

content=messages

这个绑定意味着 FTS 列和原始 source column 应该一致。

如果你把别的字段塞进去,后面 rebuildsnippet()highlight() 的语义就容易错位。

所以这不是“加个字符串”就能糊过去的事。


用户怎么判断自己是否踩到了这个坑?

如果你有这种体验,就很像 #16751

  • session 里明明出现过某个 tool name;
  • 工具参数里明明有某个 token;
  • 你在正文里搜不到;
  • session_search 返回空;
  • 但你直接看数据库或消息原文却能找到。

典型症状就是:

它明明发生过,但搜索说没发生过。

这在长任务 recovery 里很要命。


和 DeepAI API 中转站的关系

这个问题和 DeepAI API 中转站没有直接关系。

不管你用的是:

  • DeepAI;
  • OpenAI-compatible provider;
  • 本地模型;
  • GitHub Copilot;
  • 其他 provider;

只要 Hermes 的 session search 只索引 messages.content,工具轨迹就会丢。

DeepAI 负责模型 API 入口,不负责 Hermes 内部 session DB 的 FTS schema。

所以这不是换 provider 能解决的问题,而是 Hermes 记忆检索层的 schema 覆盖范围问题。


FAQ

为什么正文能搜到,工具字段搜不到?

因为 FTS 只索引了 messages.content,没有覆盖 tool_callstool_name

这和中文分词问题一样吗?

不一样。issue 明确说明这不是 CJK tokenizer 问题,而是 schema / trigger 层的问题。

会影响哪些场景?

长任务恢复、工具轨迹追查、发布记录检索、debug、会话复盘。

修复最稳的方式是什么?

给 FTS 增加工具字段,或者引入专门的 search_text 派生列,再重建索引。

DeepAI 能修这个吗?

不能。DeepAI 不负责 Hermes 的 session DB indexing。


总结

#16751 的教训很直接:

存了,不等于能搜到。

Hermes 的 session_search 只看正文,不看 tool_calls / tool_name,会让很多关键工具轨迹在搜索里“消失”。

对长任务来说,这不是小瑕疵,而是恢复链路的断点。

如果你做的是 Agent 记忆系统,正文索引只是底线,工具轨迹才是半条命。

Related Post

Discord 明明发了代码,Hermes 却像没看见:message.txt 附件被静默吞掉的原因Discord 明明发了代码,Hermes 却像没看见:message.txt 附件被静默吞掉的原因

Discord 会把长代码自动转成 message.txt 附件,Hermes 旧版在读取这类文本附件时可能因 Brotli br 解码失败而静默忽略内容。本文复盘 #12511:为什么 PDF 和图片能过,txt/py/html 却进不了 Agent 上下文。

Hermes Agent 报 UnicodeEncodeError?ASCII locale、API Key 和 reasoning_content 排错指南Hermes Agent 报 UnicodeEncodeError?ASCII locale、API Key 和 reasoning_content 排错指南

Hermes Agent 报 UnicodeEncodeError: ascii codec can't encode character?本文从 LANG=C、API Key 混入 Unicode 近似字符、OpenAI SDK Authorization header、tool schema、api_messages 和 reasoning_content 角度给出完整排错清单。

Hermes Agent 报 No module named agent.transports?pip / Nix 源码安装缺包排错指南Hermes Agent 报 No module named agent.transports?pip / Nix 源码安装缺包排错指南

Hermes Agent 源码安装后报 ModuleNotFoundError: No module named agent.transports?这通常不是 Anthropic API Key 或模型名问题,而是 setuptools include 缺少 agent.*,导致 pip / Nix 安装产物漏掉 agent/transports 子包。