Appearance
memory_search 通过并行运行 BM25 关键词搜索和向量语义搜索,加权合并结果(只有一路可用时单路运行)。当 embeddings 不可用时自动降级为词频排序。支持本地离线、多模态索引(Gemini)、MMR 去重和时间衰减。配置 provider 后自动启用,无结果时运行 openclaw memory status 和 openclaw memory index --force 重建索引。
OpenClaw memory_search:混合检索、MMR 与时间衰减配置
memory_search 找出 memory 文件中语义相关的笔记(即使措辞不同)。它将 memory 切分成小块,通过 embedding 语义搜索、BM25 关键词搜索或两者结合进行检索。
快速开始
已配置 GitHub Copilot、OpenAI、Gemini、Voyage 或 Mistral API Key 时,memory search 自动生效。显式指定 provider:
json5
{
agents: {
defaults: {
memorySearch: {
provider: "openai", // 或 "gemini", "local", "ollama" 等
},
},
},
}多端点部署时,provider 也可以是自定义的 models.providers.<id> 条目(如 ollama-5080),只要该 provider 设置了 api: "ollama" 或其他 embedding 适配器所有者。
本地 embedding 不需要 API Key:设置 provider: "local"。源码检出可能需要 native 构建批准:先执行 pnpm approve-builds,再执行 pnpm rebuild node-llama-cpp。
部分 OpenAI 兼容的 embedding 端点要求非对称标签(例如搜索用 input_type: "query",索引分块用 input_type: "document" 或 "passage")。通过 memorySearch.queryInputType 和 memorySearch.documentInputType 配置,详见 Memory 配置参考。
支持的 Provider
| Provider | ID | 需要 API Key | 说明 |
|---|---|---|---|
| Bedrock | bedrock | 否 | AWS 凭据链解析时自动检测 |
| Gemini | gemini | 是 | 支持图片/音频索引 |
| GitHub Copilot | github-copilot | 否 | 自动检测,使用 Copilot 订阅 |
| Local | local | 否 | GGUF 模型,约 0.6 GB 下载 |
| Mistral | mistral | 是 | 自动检测 |
| Ollama | ollama | 否 | 本地运行,需显式配置 |
| OpenAI | openai | 是 | 自动检测,速度快 |
| Voyage | voyage | 是 | 自动检测 |
搜索工作原理
OpenClaw 并行运行两条检索路径,对结果加权合并:
mermaid
flowchart LR
Q["Query"] --> E["Embedding"]
Q --> T["Tokenize"]
E --> VS["Vector Search"]
T --> BM["BM25 Search"]
VS --> M["Weighted Merge"]
BM --> M
M --> R["Top Results"]- 向量搜索:找到语义相近的笔记("gateway host" 匹配 "运行 OpenClaw 的机器")。
- BM25 关键词搜索:精确匹配 ID、错误消息、配置键等。
如果只有一路可用(没有 embedding 或没有 FTS),则单独运行该路。
当 embedding 完全不可用时,OpenClaw 不会直接降级为纯精确匹配排序,而是对有 FTS 的结果使用词频排序。这种降级模式会提升查询词覆盖度更高或来自相关文件路径的片段,即使没有 sqlite-vec 或 embedding provider,也能保持不错的召回效果。
提升搜索质量
笔记量大时,以下两个可选功能帮助提升召回质量:
时间衰减(Temporal Decay)
旧笔记的排名权重随时间逐渐降低,使最近的信息优先浮现。默认半衰期 30 天:上个月的笔记评分降至原始权重的 50%。MEMORY.md 这类常青文件不参与衰减。
如果 agent 有数月的日常笔记,且旧信息总是盖过新上下文,建议启用时间衰减。
MMR(多样性过滤)
减少重复结果。如果 5 条笔记都提到同一个路由器配置,MMR 确保 top 结果覆盖不同话题,而不是重复。
如果
memory_search总从不同日记文件返回近乎重复的片段,建议启用 MMR。
同时启用
json5
{
agents: {
defaults: {
memorySearch: {
query: {
hybrid: {
mmr: { enabled: true },
temporalDecay: { enabled: true },
},
},
},
},
},
}多模态记忆
使用 Gemini Embedding 2,可在 Markdown 之外索引图片和音频文件。搜索查询仍为文本,但能匹配视觉和音频内容。详见 Memory 配置参考。
会话记忆搜索
可以选择将会话记录纳入索引,使 memory_search 能够召回历史对话。通过 memorySearch.experimental.sessionMemory 启用(opt-in)。详见 配置参考。
排查
没有结果? 运行 openclaw memory status 检查索引状态。如果索引为空,运行 openclaw memory index --force。
只有关键词匹配? Embedding provider 可能未配置或配置错误。运行 openclaw memory status --deep 检查。
本地 embedding 超时? ollama、lmstudio 和 local 使用默认较长的内联批处理超时。如果只是主机慢,可设置 agents.defaults.memorySearch.sync.embeddingBatchTimeoutSeconds,然后重新运行 openclaw memory index --force。
CJK 文本找不到? 运行 openclaw memory index --force 重建 FTS 索引。
常见问题
为什么只有关键词匹配,没有语义检索?
Embedding provider 可能未正确配置。运行 openclaw memory status --deep 确认向量索引是否存在。如果显示 "no embeddings",检查 agents 配置中的 memorySearch.provider 是否设置,且 API Key 是否可用。GitHub Copilot 和 Bedrock 会自动检测,无需额外配置。
本地离线环境如何启用语义搜索?
设置 provider: "ollama" 并安装对应 embedding 模型,或使用 provider: "local"(自动下载约 0.6 GB GGUF 模型)。注意 local 需要 node-llama-cpp 原生构建,先执行 pnpm approve-builds 再 pnpm rebuild node-llama-cpp。
MMR 会丢失重要信息吗?
MMR 侧重多样性,如果多条笔记都是有效答案,可能只保留其中一条。对于精确查找(如找特定错误码),建议不启用 MMR。可在 agent 配置中单独控制启用/禁用。
相关
- Active Memory —— 交互会话的子 agent 记忆
- Memory —— 文件布局、后端、工具
- Memory 配置参考 —— 全部配置参数