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

Hermes 的 Custom Endpoint 和 API Server 不是一回事:接 DeepAI 前先别搞反Hermes 的 Custom Endpoint 和 API Server 不是一回事:接 DeepAI 前先别搞反

Hermes 里有两个 OpenAI-compatible:Custom Endpoint 用来接 DeepAI 这样的上游模型,API Server 用来让 Open WebUI、LobeChat 等前端连接 Hermes。本文讲清 Base URL、API Key 和链路区别。

Hermes 安装卡在 [sudo] password:非 sudo 用户遇到 Playwright –with-deps 的半安装问题Hermes 安装卡在 [sudo] password:非 sudo 用户遇到 Playwright –with-deps 的半安装问题

在 Debian 上用非 sudo 服务用户安装 Hermes 时,安装器可能卡在 Playwright Chromium 的 `npx playwright install --with-deps chromium` sudo 密码提示,且发生在 setup_path 之前,导致没有 hermes 命令和 hermes doctor。本文客观复盘 #25816 的触发条件、安装顺序和降级处理。

OpenRouter / NVIDIA 模型一接入就 400?Hermes Agent reasoning 参数误发排错指南OpenRouter / NVIDIA 模型一接入就 400?Hermes Agent reasoning 参数误发排错指南

Hermes 接入 OpenRouter、MiniMax 或 NVIDIA 模型时一发请求就 BadRequestError 400?问题可能不是 API Key,而是 reasoning extra_body 被发给了不支持 reasoning 扩展的模型。本文教你读 request_dump 并分层排查。