OpenClaw【四、记忆系统】

在 OpenClaw 2026 版本中,记忆与上下文管理(Memory & Context) 是其区别于普通聊天机器人的核心能力。它不仅仅是一个简单的“历史记录”,而是一个分层的、可检索的、支持自定义逻辑的知识库系统。

OpenClaw 的记忆架构分为三层:

  1. 短期记忆 (Short-term Memory):当前对话窗口的原始上下文(Token 限制内)。
  2. 长期记忆 (Long-term Memory / RAG):基于向量数据库的历史对话摘要和关键事实。
  3. 工作记忆 (Working Memory):当前任务执行过程中的临时状态(如:正在处理的文件名、上一步的报错信息)。

以下是配置详解自定义记忆逻辑实现的保姆级教程。


一、核心架构与配置 (config.yaml)

首先,你需要在 config.yaml 中启用并配置记忆模块。OpenClaw 默认支持多种向量数据库后端(Chroma, Milvus, FAISS, Qdrant)。

1. 基础配置示例

memory:
  # 是否启用长期记忆
  enabled: true
  
  # 向量数据库后端选择: 'chroma' (默认,轻量), 'milvus', 'qdrant', 'faiss'
  backend: chroma
  
  # 向量数据库连接配置
  vector_store:
    chroma:
      persist_directory: ./data/chroma_db # 本地持久化路径
      # 如果是远程服务:
      # host: localhost
      # port: 8000
      
  # 嵌入模型 (Embedding Model) - 用于将文本转化为向量
  # 推荐使用本地 Ollama 运行的 embedding 模型,如 nomic-embed-text 或 m3e
  embedding:
    provider: ollama
    model: nomic-embed-text:latest
    base_url: http://localhost:11434

  # 记忆检索策略
  retrieval:
    # 每次对话自动检索的最大相关片段数
    top_k: 5
    # 相似度阈值 (0-1),低于此值的内容不被视为相关
    threshold: 0.75
    # 时间衰减因子:越旧的记忆权重越低 (0.0-1.0)
    time_decay: 0.95

  # 记忆维护策略
  maintenance:
    # 当对话轮数超过此值时,触发自动摘要并存入长期记忆
    summary_threshold: 10
    # 自动清理超过 N 天的原始日志 (可选)
    retention_days: 30

二、记忆工作流程详解

理解流程是自定义逻辑的前提:

  1. 用户输入 -> 预处理 (清洗、脱敏)。
  2. 检索 (Retrieve):根据用户输入,在向量库中搜索 Top-K 相关历史记忆。
  3. 增强 (Augment):将检索到的记忆 + 当前对话 + 系统提示词 (System Prompt) 组装成完整的 Prompt。
  4. 生成 (Generate):LLM 基于完整 Prompt 输出回复。
  5. 存储 (Store)
    • 将当前对话追加到短期上下文。
    • 如果达到 summary_threshold,触发后台异步任务:调用 LLM 对近期对话进行摘要,提取关键实体(人名、地点、任务状态),存入向量库。

三、自定义记忆逻辑实现 (高级篇)

OpenClaw 允许开发者通过 Python 脚本完全接管记忆的写入读取遗忘逻辑。这是实现“个性化 AI”的关键。

场景:实现一个“用户偏好记忆”系统

目标:当用户说“我喜欢喝美式咖啡”时,AI 不仅记住这句话,还要将其标记为 PREFERENCE 类型,并在未来任何涉及饮料的对话中优先调用。

步骤 1:创建自定义记忆处理器

skills/custom/ 目录下创建 custom_memory.py

# skills/custom/custom_memory.py
from openclaw.memory.base import BaseMemoryHandler
from openclaw.core.llm import get_llm_client
from openclaw.utils.logger import logger
import json
from datetime import datetime

class UserPreferenceHandler(BaseMemoryHandler):
    """
    自定义处理器:专门处理用户偏好类记忆
    """
    
    def __init__(self, config):
        super().__init__(config)
        self.category_tag = "USER_PREFERENCE"
        self.llm = get_llm_client()

    async def should_save(self, message: str, context: dict) -> bool:
        """
        判断当前消息是否需要存入特殊记忆库
        逻辑:让 LLM 判断这句话是否包含用户偏好
        """
        prompt = f"""
        判断以下用户输入是否表达了明确的个人偏好(如喜欢/讨厌的食物、颜色、工作方式等)。
        如果是,返回 JSON: {{"is_preference": true, "content": "提取的核心偏好"}}
        如果不是,返回 JSON: {{"is_preference": false}}
        
        用户输入: {message}
        """
        response = await self.llm.generate(prompt, temperature=0.1)
        try:
            data = json.loads(response.strip())
            return data.get("is_preference", False)
        except:
            return False

    async def process_and_save(self, message: str, context: dict):
        """
        执行具体的保存逻辑
        """
        # 1. 提取结构化数据
        extract_prompt = f"从 '{message}' 中提取偏好主题和具体内容,格式为 JSON: {{'topic': '...', 'detail': '...'}}"
        extracted = await self.llm.generate(extract_prompt, temperature=0.1)
        
        # 2. 构建记忆元数据
        memory_entry = {
            "text": message,
            "metadata": {
                "type": self.category_tag,
                "timestamp": datetime.now().isoformat(),
                "source": "user_explicit",
                "extracted_data": json.loads(extracted)
            }
        }
        
        # 3. 写入向量库 (带特定标签)
        # OpenClaw 底层支持 add_documents 方法,可传入 metadata 过滤
        await self.vector_store.add_texts(
            texts=[message],
            metadatas=[memory_entry["metadata"]],
            ids=[f"pref_{datetime.now().timestamp()}"]
        )
        logger.info(f"💾 已保存用户偏好记忆: {message}")

    async def retrieve_relevant(self, query: str, top_k: int = 3):
        """
        自定义检索逻辑:优先检索偏好类记忆
        """
        # 使用 metadata 过滤,只查找 type=USER_PREFERENCE 的记录
        results = await self.vector_store.similarity_search(
            query=query,
            k=top_k,
            filter={"type": self.category_tag} 
        )
        return results

# 注册处理器
# 在 OpenClaw 启动时,需要在 config 或主程序中注册这个 Handler
# 通常在 main.py 或 plugins 入口
def register_custom_memory(app):
    handler = UserPreferenceHandler(app.config.memory)
    app.memory_manager.register_handler("preference", handler)
    logger.info("✅ 用户偏好记忆处理器已加载")
步骤 2:在主程序中注册自定义逻辑

修改 main.py 或在 plugins/__init__.py 中引入:

# main.py (片段)
from skills.custom.custom_memory import register_custom_memory

def start_openclaw():
    # ... 初始化配置 ...
    app = OpenClawApp(config)
    
    # 注册自定义记忆逻辑
    register_custom_memory(app)
    
    # 启动服务
    app.run()
步骤 3:在 Agent 提示词中调用自定义记忆

为了让 AI 真正“使用”这些记忆,需要修改 Agent 的 System Prompt (agents/default_agent.yaml)。

agent:
  name: "PersonalAssistant"
  role: |
    你是一个贴心的个人助理。
    
    【记忆使用指南】
    1. 在回答用户关于喜好、习惯的问题前,必须先查询 "USER_PREFERENCE" 类型的记忆。
    2. 如果检索到相关偏好(如用户喜欢美式咖啡),请在回答中自然融入,不要生硬地引用。
    3. 如果用户提出了新的偏好,请调用 save_memory 技能进行保存。

  # 动态注入检索结果的占位符 (OpenClaw 会自动替换 {{retrieved_memories}})
  system_prompt_suffix: |
    --- 相关历史记忆 ---
    {{retrieved_memories}}
    ------------------

四、高级技巧:记忆的生命周期管理

1. 主动遗忘 (Forgetting Mechanism)

为了防止向量库无限膨胀或记住过时信息(如“我明天要去北京”,但今天已经回来了),可以实现过期清理逻辑

  • 实现思路
    process_and_save 时,给记忆加上 expiry_date 元数据。
    创建一个定时任务(Cron Job),每天扫描向量库,删除 expiry_date < now 的记录。
# 伪代码示例
async def cleanup_expired_memories(vector_store):
    today = datetime.now()
    # 查询所有带有 expiry_date 且已过期的记录 ID
    expired_ids = await vector_store.query_metadata_filter(
        filter={"expiry_date": {"$lt": today.isoformat()}}
    )
    if expired_ids:
        await vector_store.delete(ids=expired_ids)
        logger.info(f"🗑️ 已清理 {len(expired_ids)} 条过期记忆")

2. 记忆摘要压缩 (Summarization Chain)

对于长对话,直接存原文会浪费 Token 且检索不准。OpenClaw 支持配置摘要链

  • 配置:在 config.yaml 中设置 maintenance.summary_model 为一个擅长总结的小模型(如 qwen2.5:1.8b),以节省成本。
  • 逻辑:每 10 轮对话,后台静默运行一次:“总结过去 10 轮对话的关键事实、待办事项和用户情绪,生成一段 200 字以内的摘要”,然后将摘要存入向量库,而非原始对话。

3. 多模态记忆 (Multimodal Memory)

2026 版 OpenClaw 支持将图片、截图的特征向量也存入记忆库。

  • 场景:用户发了一张冰箱的照片问“里面还有什么吃的?”。
  • 实现:使用 CLIP 或多模态 Embedding 模型(如 nomic-embed-vision)将图片转为向量。检索时,将用户的问题也转为多模态向量进行匹配,从而找回之前的图片记忆。

五、调试与验证

配置好自定义记忆后,如何验证是否生效?

  1. 查看向量库内容
    OpenClaw 提供了一个 CLI 工具查看记忆:

    python main.py --memory-view --filter "type=USER_PREFERENCE"
    

    这会列出所有被标记为偏好的记忆条目。

  2. 观察日志
    查看 logs/memory_ops.log,你会看到类似记录:

    [INFO] Retrieving memories for query: "我想喝点什么?"
    [INFO] Found 2 matches with score > 0.75
    [DEBUG] Injected context: "User prefers Americano coffee."
    
  3. 实战测试

    • 第一轮:“记住,我讨厌吃香菜。” -> 检查日志是否触发 should_save 并写入。
    • 第二轮(间隔几分钟后):“今晚吃什么好?” -> 观察 AI 回复是否主动避开香菜,并提及“记得你不喜欢香菜”。

六、总结

OpenClaw 的记忆系统不仅仅是“存下来”,而是“理解、筛选、重组”

  • 初级用法:配置 config.yaml 开启 Chroma + Ollama Embedding,享受自动的 RAG 能力。
  • 中级用法:调整 thresholdtop_k,优化检索精度。
  • 高级用法:编写 BaseMemoryHandler 子类,实现结构化提取主动遗忘多模态检索领域专用记忆库
posted @ 2026-03-17 16:05  蓝迷梦  阅读(95)  评论(0)    收藏  举报