OpenClaw工具拆解之memory_search+memory_get

1.1 工具概述

功能 :语义搜索记忆文件
核心特性

  • 搜索 MEMORY.md + memory/*.md
  • 支持向量嵌入搜索
  • 支持混合搜索(向量 + 文本)
  • 支持分数阈值过滤
  • 支持结果数量限制
  • 返回路径 + 行号

1.2 Schema 定义

位置:约第 5957 行(工具元数据)

javascript 复制代码
"memory_search": {
    "emoji": "🧠",
    "title": "Memory Search",
    "detailKeys": ["query"]
}

实际参数 Schema(动态构建):

javascript 复制代码
const MemorySearchSchema = Type.Object({
    query: Type.String({ description: "Search query string" }),
    minScore: Type.Optional(Type.Number({ description: "Minimum similarity score threshold" })),
    maxResults: Type.Optional(Type.Number({ description: "Maximum number of results to return" }))
});

1.3 配置结构

位置:约第 18615 行

javascript 复制代码
// 默认配置
const DEFAULT_OPENAI_MODEL = "text-embedding-3-small";
const DEFAULT_GEMINI_MODEL = "gemini-embedding-001";
const DEFAULT_VOYAGE_MODEL = "voyage-4-large";
const DEFAULT_MISTRAL_MODEL = "mistral-embed";
const DEFAULT_OLLAMA_MODEL = "nomic-embed-text";
const DEFAULT_CHUNK_TOKENS = 400;
const DEFAULT_CHUNK_OVERLAP = 80;
const DEFAULT_MAX_RESULTS = 6;
const DEFAULT_MIN_SCORE = 0.35;
const DEFAULT_HYBRID_ENABLED = true;
const DEFAULT_HYBRID_VECTOR_WEIGHT = 0.7;
const DEFAULT_HYBRID_TEXT_WEIGHT = 0.3;

1.4 完整配置结构

javascript 复制代码
memorySearch: {
    enabled: true,                    // 是否启用
    provider: "auto",                 // 提供商(auto/openai/gemini/voyage/mistral/ollama/local)
    model: "text-embedding-3-small",  // 模型名称
    outputDimensionality: 1536,       // 输出维度
    
    // 远程配置
    remote: {
        baseUrl: "...",               // API 基础 URL
        apiKey: "...",                // API 密钥
        batch: {
            enabled: false,           // 启用批量处理
            wait: true,               // 等待批量完成
            concurrency: 2,           // 并发数
            pollIntervalMs: 2000,     // 轮询间隔
            timeoutMinutes: 60        // 超时时间
        }
    },
    
    // 本地配置
    local: {
        modelPath: "...",             // 本地模型路径
        modelCacheDir: "..."          // 模型缓存目录
    },
    
    // 数据源
    sources: ["memory"],              // 数据源(memory/sessions)
    extraPaths: [],                   // 额外路径
    
    // 分块配置
    chunking: {
        tokens: 400,                  // 每块 token 数
        overlap: 80                   // 重叠 token 数
    },
    
    // 查询配置
    query: {
        maxResults: 6,                // 最大结果数
        minScore: 0.35,               // 最小分数
        hybrid: {
            enabled: true,            // 启用混合搜索
            vectorWeight: 0.7,        // 向量权重
            textWeight: 0.3,          // 文本权重
            candidateMultiplier: 4,   // 候选倍数
            mmr: {
                enabled: false,       // 启用 MMR
                lambda: 0.7           // MMR 参数
            },
            temporalDecay: {
                enabled: false,       // 启用时间衰减
                halfLifeDays: 30      // 半衰期(天)
            }
        }
    },
    
    // 缓存配置
    cache: {
        enabled: true,                // 启用缓存
        maxEntries: 1000              // 最大缓存条目
    },
    
    // 存储配置
    store: {
        driver: "sqlite",             // 存储驱动(sqlite)
        path: "...",                  // 存储路径
        vector: {
            enabled: true,            // 启用向量存储
            extensionPath: "..."      // 向量扩展路径
        }
    },
    
    // 同步配置
    sync: {
        onSessionStart: true,         // 会话启动时同步
        onSearch: true,               // 搜索时同步
        watch: true,                  // 监听文件变化
        watchDebounceMs: 1500,        // 监听防抖时间
        intervalMinutes: 0,           // 同步间隔(分钟)
        sessions: {
            deltaBytes: 100000,       // 字节变化阈值
            deltaMessages: 50,        // 消息变化阈值
            postCompactionForce: true // 压缩后强制同步
        }
    }
}

1.5 执行流程

复制代码
memory_search 工具调用
    ↓
1. 解析查询参数
   ├─ query(必填)
   ├─ minScore(可选,默认 0.35)
   └─ maxResults(可选,默认 6)
    ↓
2. 加载记忆索引
   ├─ MEMORY.md
   └─ memory/*.md
    ↓
3. 生成查询嵌入向量
   ├─ 使用配置的提供商(OpenAI/Gemini 等)
   └─ 或本地模型
    ↓
4. 执行搜索
   ├─ 向量搜索(相似度匹配)
   ├─ 文本搜索(关键词匹配)
   └─ 混合排序(向量 70% + 文本 30%)
    ↓
5. 应用过滤
   ├─ minScore 阈值
   └─ maxResults 限制
    ↓
6. 返回结果

1.6 返回结果格式

成功

json 复制代码
{
  "results": [
    {
      "path": "MEMORY.md",
      "content": "音乐偏好:喜欢的歌都在 C:\\Users\\83760\\Music\\good 文件夹里",
      "score": 0.85,
      "line": 10
    },
    {
      "path": "memory/2026-03-28.md",
      "content": "特别喜爱:《Adagio of the Highland》- Bandari(班德瑞)",
      "score": 0.78,
      "line": 15
    }
  ],
  "query": "用户喜欢的音乐",
  "totalFound": 2
}

失败

json 复制代码
{
  "error": "Memory search is not enabled. Set memorySearch.enabled=true in config."
}

1.7 使用示例

用户我喜欢的音乐有哪些

大模型操作

json 复制代码
{
  "tool_call": {
    "name": "memory_search",
    "arguments": { 
      "query": "用户喜欢的音乐",
      "maxResults": 5
    }
  }
}

执行结果

json 复制代码
{
  "results": [
    {
      "path": "MEMORY.md",
      "content": "音乐偏好:喜欢的歌都在 C:\\Users\\83760\\Music\\good 文件夹里",
      "score": 0.85,
      "line": 10
    },
    {
      "path": "USER.md",
      "content": "特别喜爱:《Adagio of the Highland》- Bandari(班德瑞)",
      "score": 0.78,
      "line": 15
    }
  ],
  "query": "用户喜欢的音乐",
  "totalFound": 2
}

二、memory_get 工具

2.1 工具概述

功能 :获取指定文件的特定行
核心特性

  • 精确行范围读取
  • 用于 memory_search 后获取详情
  • 保持上下文小
  • 支持 MEMORY.md 和 memory/*.md

2.2 Schema 定义

位置:约第 5957 行(工具元数据)

javascript 复制代码
"memory_get": {
    "emoji": "📓",
    "title": "Memory Get",
    "detailKeys": ["path", "from", "lines"]
}

实际参数 Schema

javascript 复制代码
const MemoryGetSchema = Type.Object({
    path: Type.String({ description: "Path to the memory file" }),
    from: Type.Optional(Type.Number({ description: "Line number to start from" })),
    lines: Type.Optional(Type.Number({ description: "Number of lines to read" }))
});

2.3 执行代码

javascript 复制代码
function createMemoryGetTool(options) {
    return {
        label: "Memory Get",
        name: "memory_get",
        description: "Safe snippet read from MEMORY.md or memory/*.md with optional from/lines; use after memory_search to pull only the needed lines and keep context small.",
        parameters: MemoryGetSchema,
        execute: async (_toolCallId, args) => {
            const params = args;
            
            // 1. 解析路径(必填)
            const path = readStringParam$1(params, "path", { required: true });
            
            // 2. 解析起始行
            const from = typeof params.from === "number" && Number.isFinite(params.from) ? 
                Math.max(1, Math.floor(params.from)) : 1;
            
            // 3. 解析行数
            const lines = typeof params.lines === "number" && Number.isFinite(params.lines) ? 
                Math.max(1, Math.floor(params.lines)) : 10;
            
            // 4. 解析记忆目录
            const memoryDir = options?.memoryDir ?? path.join(options?.workspaceDir ?? process.cwd(), 'memory');
            
            // 5. 构建完整路径
            const fullPath = path.startsWith('memory/') ? 
                path.join(memoryDir, path.slice(7)) : 
                path.join(options?.workspaceDir ?? process.cwd(), path);
            
            // 6. 读取文件
            const content = await fs$1.readFile(fullPath, 'utf-8');
            const allLines = content.split('\n');
            
            // 7. 提取指定行
            const startIdx = from - 1;  // 转换为 0-based 索引
            const endIdx = Math.min(startIdx + lines, allLines.length);
            const selectedLines = allLines.slice(startIdx, endIdx);
            
            // 8. 返回结果
            return {
                content: [{
                    type: "text",
                    text: selectedLines.join('\n')
                }],
                details: {
                    path,
                    from,
                    lines: selectedLines.length,
                    totalLines: allLines.length
                }
            };
        }
    };
}

2.4 执行流程图

复制代码
memory_get 工具调用
    ↓
1. 解析路径(必填)
    ↓
2. 解析起始行(默认 1)
    ↓
3. 解析行数(默认 10)
    ↓
4. 构建完整路径
   ├─ memory/xxx.md → memory 目录
   └─ MEMORY.md → 工作区根目录
    ↓
5. 读取文件
    ↓
6. 提取指定行
    ↓
7. 返回结果

2.5 返回结果格式

成功

json 复制代码
{
  "content": [{
    "type": "text",
    "text": "音乐偏好:喜欢的歌都在 C:\\Users\\83760\\Music\\good 文件夹里\n\n特别喜爱:《Adagio of the Highland》- Bandari(班德瑞)"
  }],
  "details": {
    "path": "MEMORY.md",
    "from": 10,
    "lines": 2,
    "totalLines": 100
  }
}

失败

json 复制代码
{
  "error": "File not found: memory/2026-03-28.md"
}

2.6 使用示例

用户查看 MEMORY.md 第 10 行开始的 5 行内容

大模型返回

json 复制代码
{
  "tool_call": {
    "name": "memory_get",
    "arguments": { 
      "path": "MEMORY.md",
      "from": 10,
      "lines": 5
    }
  }
}

执行结果

json 复制代码
{
  "content": [{
    "type": "text",
    "text": "音乐偏好:喜欢的歌都在 C:\\Users\\83760\\Music\\good 文件夹里\n\n特别喜爱:《Adagio of the Highland》- Bandari(班德瑞)\n\n关于老大:\n- 名字:老大"
  }],
  "details": {
    "path": "MEMORY.md",
    "from": 10,
    "lines": 5,
    "totalLines": 100
  }
}

三、关键机制对比

3.1 功能定位

特性 memory_search memory_get
用途 语义搜索 精确读取
输入 查询字符串 文件路径 + 行范围
输出 多个匹配片段 指定行内容

3.2 使用场景

场景 推荐工具
查找相关信息 memory_search
获取详细内容 memory_get
组合使用 memory_search → memory_get

3.3 配置要求

特性 memory_search memory_get
嵌入模型 需要 不需要
向量存储 SQLite 不需要
文件同步 监听变化 直接读取

四、组合使用示例

4.1 典型工作流

复制代码
1. 用户提问:`我喜欢的音乐有哪些`
   ↓
2. 大模型调用 memory_search
   {
     "query": "用户喜欢的音乐",
     "maxResults": 5
   }
   ↓
3. 返回搜索结果
   [
     { "path": "MEMORY.md", "line": 10, "score": 0.85 },
     { "path": "USER.md", "line": 15, "score": 0.78 }
   ]
   ↓
4. 大模型调用 memory_get 获取详情
   {
     "path": "MEMORY.md",
     "from": 10,
     "lines": 5
   }
   ↓
5. 返回详细内容并回答用户

4.2 代码示例

javascript 复制代码
// 1. 搜索记忆
const searchResults = await memory_search({
    query: "用户喜欢的音乐",
    maxResults: 5
});

// 2. 获取详细内容
for (const result of searchResults.results) {
    const detail = await memory_get({
        path: result.path,
        from: result.line,
        lines: 5
    });
    console.log(detail.content[0].text);
}
相关推荐
crazy_wsp1 小时前
使用AI从0到1上线微信小程序
人工智能·微信小程序·小程序
AI科技星1 小时前
光子本源三元结构定理(《全域数学·物理原本》)【乖乖数学】
人工智能·机器学习·数学建模·数据挖掘·agi
逻辑君1 小时前
认知神经科学研究报告【20260023】
人工智能·神经网络·机器学习
无心水2 小时前
【Hermes:MCP 与工具实战】28、GitHub MCP 深度实战:PR 审查、Issue、自动汇报全搞定
人工智能·github·issue·openclaw·养龙虾·hermes·honcho
江南十四行2 小时前
Python生成器与协程:从迭代器到异步编程的进阶之路
开发语言·python
β添砖java2 小时前
深度学习(21)使用块的网络VGG
网络·人工智能·深度学习
数智联AI团队2 小时前
AI员工时代已来:企业如何选择靠谱的“AI团队”实现降本增效?
大数据·人工智能
Java后端的Ai之路2 小时前
大模型数据飞轮核心技术一篇讲透:原理、架构、企业级案例与2026最全实践指南
人工智能·python·架构·数据飞轮
周末也要写八哥2 小时前
代码中的注释的重要性(一)
人工智能·机器学习