
1. 项目概述为什么我们需要一个“不上云”的记忆中枢最近在折腾AI Agent特别是OpenClaw这个框架发现一个挺有意思的痛点记忆管理。很多AI Agent项目包括一些开源的默认都把记忆比如对话历史、用户偏好、任务上下文往云服务或者某个中心化的数据库一扔了事。这听起来方便但细想问题不少。数据隐私和安全是首要顾虑谁也不想自己的私人对话或工作流细节在云端裸奔。其次是延迟和成本每次Agent回忆点东西都得跨网络请求响应慢不说API调用次数哗哗地涨。最关键的是当你想深度定制记忆的存储、检索逻辑或者把Agent嵌入到本地离线环境时云服务的黑盒子和固定接口就成了绊脚石。所以当看到“记忆不上云”这个提法时我立刻觉得击中了要害。这个项目的核心就是用mem9和TiDB这两个技术栈为OpenClaw打造一个完全私有化、高性能、可扩展的“记忆中枢”。简单来说就是把AI Agent那个最核心、也最敏感的“大脑皮层”——记忆系统牢牢攥在自己手里部署在自己的服务器或甚至高性能工作站上。Mem9是一个新兴的、专门为AI和向量检索场景设计的内存数据库它最大的特点是快能把海量的向量和标量数据放在内存里进行毫秒级相似度搜索。而TiDB则是业界知名的分布式NewSQL数据库强在一致性、高可用和水平扩展适合存储那些需要持久化、结构化关系强的元数据。OpenClaw是一个功能丰富的AI Agent开发框架。把它们仨组合起来目标就很清晰了用Mem9扛住AI Agent实时、高频的向量记忆检索压力用TiDB确保记忆的持久化、事务性和复杂查询能力共同为OpenClaw提供一个既快又稳、还完全自主可控的记忆后台。这不仅仅是换个数据库那么简单。它意味着你可以构建这样的Agent它能记住几个月前和你讨论过的项目细节向量记忆能追踪复杂工作流的状态结构化记忆所有这些数据都在你的防火墙内响应速度堪比本地应用并且随着业务增长你可以轻松扩展这个记忆系统。对于企业级应用、对数据敏感的研究或者单纯就是喜欢“一切尽在掌握”的极客来说这种方案吸引力巨大。接下来我就详细拆解一下这个组合方案的设计思路、实操要点以及我趟过的一些坑。2. 核心架构与组件选型解析2.1 为什么是Mem9 TiDB的组合在决定用Mem9和TiDB之前我评估过好几个方案。最常见的可能是直接用PGVectorPostgreSQL的向量扩展或者Chroma、Weaviate这类专门的向量数据库。PGVector生态好但纯内存性能优化和分布式方面不是专长Chroma等虽然易用但在需要处理混合负载向量复杂关系查询和强一致性要求的场景下有时显得力不从心。Mem9吸引我的点在于它的定位非常精准。它自称是“AI原生”的内存数据库底层为向量操作做了大量优化比如SIMD指令加速、高效的内存布局使得在亿级向量里做ANN近似最近邻搜索也能保持极低延迟。这对于AI Agent的“瞬时回忆”能力至关重要——当Agent需要根据当前对话上下文快速找到相关历史时几百毫秒的延迟都是不可接受的。Mem9通常作为内存缓存或主向量存储层数据可以异步持久化到后端。那为什么还要TiDB呢因为记忆不仅仅是向量。一个完整的记忆中枢至少包含两类数据向量记忆对话文本、文档片段经过Embedding后的向量用于语义检索。结构化记忆用户ID、会话ID、时间戳、记忆的元数据来源、类型、置信度、Agent的状态、任务流水线等。这些数据关系复杂需要事务支持比如记录一个任务步骤必须原子化需要复杂的JOIN查询还需要可靠的持久化。TiDB作为兼容MySQL协议的分布式数据库完美承接了这部分需求。它的水平扩展能力可以应对记忆数据量的持续增长强一致性模型保证了记忆状态的准确无误。更重要的是TiDB的生态完善监控、备份、迁移工具一应俱全降低了运维复杂度。所以这个架构的本质是“内存向量检索 分布式关系存储”的混合模式。Mem9负责高速的“感性回忆”相似性匹配TiDB负责严谨的“理性记录”结构化查询与持久化。两者通过一个设计良好的数据同步或关联机制比如共用一条唯一业务ID协同工作。2.2 OpenClaw的记忆接口与扩展点OpenClaw框架本身提供了一定的记忆抽象。要对接我们自建的记忆中枢关键是要理解它的记忆接口Memory Interface或相关的存储插件机制。OpenClaw的记忆模块通常期望提供几个核心能力save(memory_entity): 保存一条记忆可能包含文本、向量、元数据。search(query_embedding, top_k): 根据查询向量搜索最相关的记忆。get_by_session(session_id): 获取某个会话的所有记忆。delete(memory_id): 删除特定记忆。我们的任务就是实现一个自定义的MemoryBackend在这个后端内部根据记忆数据的类型和用途智能地路由到Mem9或TiDB。例如当保存一段对话文本时后台同时做两件事调用Embedding模型生成向量将向量存入Mem9将原始文本、会话ID、时间戳、以及对应的Mem9向量ID存入TiDB。当Agent需要回忆时先用当前上下文生成查询向量去Mem9做快速相似搜索拿到一组向量ID和相似度分数再用这些向量ID去TiDB查询完整的原始文本和元数据按分数排序后返回给Agent。这种设计实现了读写分离和负载分流向量检索的压力由Mem9承担复杂的关系查询和持久化由TiDB承担两者各司其职。3. 环境准备与核心组件部署3.1 TiDB集群的部署与配置要点对于私有化部署我推荐使用TiDB Operator在Kubernetes上部署这是目前管理生产级TiDB集群最优雅的方式。如果资源有限或想快速验证也可以使用TiDB Playground或单机版TiDB。1. 使用TiUP部署单机测试环境最快对于本地开发测试TiUP是最佳选择。它一键就能拉起一个包含PD、TiKV、TiDB的迷你集群。# 安装TiUP curl --proto https --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh source ~/.bashrc # 启动一个本地TiDB集群 tiup playground v7.5.0 --db 1 --pd 1 --kv 1 --tiflash 0执行后TiUP会输出MySQL连接信息通常TiDB服务在127.0.0.1:4000用户名root密码为空。用MySQL客户端就能连接。2. 关键配置与初始化连接上TiDB后我们需要为OpenClaw记忆中枢创建专用的数据库和用户。-- 创建数据库 CREATE DATABASE IF NOT EXISTS openclaw_memory CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 创建专用用户并授予权限 CREATE USER openclaw_user% IDENTIFIED BY YourStrongPassword123!; GRANT ALL PRIVILEGES ON openclaw_memory.* TO openclaw_user%; FLUSH PRIVILEGES; -- 切换到该数据库 USE openclaw_memory;注意生产环境务必使用强密码并考虑将%替换为具体的应用服务器IP地址以收紧网络策略。3. 设计记忆元数据表这是整个系统的“目录”。以下是一个核心表结构的示例CREATE TABLE memory_metadata ( id BIGINT AUTO_INCREMENT PRIMARY KEY, memory_id VARCHAR(64) NOT NULL UNIQUE COMMENT 业务唯一ID用于关联Mem9, session_id VARCHAR(64) NOT NULL COMMENT 所属会话ID, user_id VARCHAR(64) COMMENT 用户ID, content_text TEXT COMMENT 记忆的原始文本内容, content_embedding_id VARCHAR(128) COMMENT 存储在Mem9中的向量ID, memory_type ENUM(conversation, fact, procedure, preference) DEFAULT conversation, source VARCHAR(255) COMMENT 来源如api, upload, internal, confidence FLOAT DEFAULT 1.0 COMMENT 置信度或重要性分数, metadata JSON COMMENT 扩展元数据JSON格式, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_session (session_id), INDEX idx_user (user_id), INDEX idx_created (created_at), INDEX idx_memory_type (memory_type) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_general_ci;这张表是TiDB存储的核心。memory_id是桥梁链接了TiDB中的元数据和Mem9中的向量。JSON类型的metadata字段提供了灵活性可以存储自定义属性。3.2 Mem9的安装与向量空间配置Mem9的安装相对简单它通常以单个二进制或Docker镜像提供。我们关注的是如何配置它来存储OpenClaw的记忆向量。1. 通过Docker快速启动Mem9docker run -d \ --name mem9-server \ -p 8080:8080 \ # REST API 端口 -p 50051:50051 \ # gRPC 端口性能更好 -v /your/data/path:/data \ mem9/mem9:latest \ --data-dir /data \ --dimension 768 \ # 向量维度必须与你的Embedding模型匹配 --metric cosine # 相似度度量方式可选 cosine, l2, ip这里有几个关键参数--dimension 768必须与你选用的Embedding模型输出维度一致。例如text-embedding-3-small是1536bge-small-zh是512。配错了后续所有向量操作都会失败。--metric cosine相似度计算方式。对于文本语义搜索cosine余弦相似度是最常用的。-v /your/data/path:/data将数据目录挂载到宿主机防止容器重启后数据丢失。2. 创建向量集合CollectionMem9里类似表的概念叫“集合”。我们需要通过其API创建一个集合来存放记忆向量。# 使用curl调用Mem9的REST API curl -X POST http://localhost:8080/collections \ -H Content-Type: application/json \ -d { name: openclaw_memory_vectors, dimension: 768, metric: cosine, index_type: HNSW, # 使用HNSW索引在精度和速度间取得平衡 index_params: { M: 16, ef_construction: 200 } }HNSW是目前主流的近似最近邻索引M和ef_construction是构建索引的参数影响构建速度和检索精度。对于记忆检索场景中等参数即可例如M16,ef_construction200能在保证较高召回率的同时拥有不错的性能。3. 验证连接部署完成后分别验证TiDB和Mem9是否正常工作。# 验证TiDB mysql -h 127.0.0.1 -P 4000 -u root -e SHOW DATABASES; # 验证Mem9 curl http://localhost:8080/collections/openclaw_memory_vectors4. OpenClaw记忆后端的深度集成实现4.1 构建自定义Memory BackendOpenClaw通常允许通过插件或继承基类的方式扩展记忆后端。我们需要创建一个新的类比如叫HybridMemoryBackend它同时持有TiDB和Mem9的客户端连接。1. 项目结构与依赖假设你的OpenClaw项目使用Python。核心依赖包括pymysql或mysql-connector-python: 连接TiDB (兼容MySQL协议)grpcio和mem9-client(如果官方提供) 或直接使用requests: 与Mem9的gRPC或REST API交互某个Embedding库如openai,sentence-transformers(用于本地Embedding模型)首先安装依赖pip install pymysql grpcio requests sentence-transformers2. 后端核心类实现下面是一个高度简化的骨架代码展示了核心逻辑import json import pymysql import requests from typing import List, Dict, Any, Optional from sentence_transformers import SentenceTransformer class HybridMemoryBackend: def __init__(self, tidb_config: Dict, mem9_config: Dict, embed_model_name: str BAAI/bge-small-zh): # 初始化TiDB连接 self.tidb_conn pymysql.connect( hosttidb_config[host], porttidb_config[port], usertidb_config[user], passwordtidb_config[password], databasetidb_config[database], charsetutf8mb4, cursorclasspymysql.cursors.DictCursor ) # 初始化Mem9客户端这里以REST为例 self.mem9_base_url fhttp://{mem9_config[host]}:{mem9_config[port]} self.collection_name mem9_config[collection] # 初始化Embedding模型关键 self.embedder SentenceTransformer(embed_model_name) self.vector_dim self.embedder.get_sentence_embedding_dimension() print(fEmbedding model loaded, dimension: {self.vector_dim}) def _generate_embedding(self, text: str) - List[float]: 生成文本的向量表示 # 注意生产环境需考虑批处理以提升效率 embedding self.embedder.encode(text, normalize_embeddingsTrue) # 归一化便于cosine计算 return embedding.tolist() def save_memory(self, session_id: str, content: str, user_id: Optional[str]None, **metadata): 保存一条记忆到混合存储 # 1. 生成向量 vector self._generate_embedding(content) # 2. 生成唯一业务ID (例如UUID) memory_id self._generate_uuid() # 3. 先存Mem9 (向量) mem9_payload { id: memory_id, vector: vector, payload: {session_id: session_id} # 可以在Mem9也存少量关联信息 } resp requests.post( f{self.mem9_base_url}/collections/{self.collection_name}/points, json{points: [mem9_payload]} ) resp.raise_for_status() # 4. 再存TiDB (元数据) with self.tidb_conn.cursor() as cursor: sql INSERT INTO memory_metadata (memory_id, session_id, user_id, content_text, content_embedding_id, metadata) VALUES (%s, %s, %s, %s, %s, %s) cursor.execute(sql, (memory_id, session_id, user_id, content, memory_id, json.dumps(metadata))) self.tidb_conn.commit() return memory_id def search_memories(self, query_text: str, session_id: Optional[str]None, top_k: int5) - List[Dict]: 搜索相关记忆 # 1. 将查询文本转换为向量 query_vector self._generate_embedding(query_text) # 2. 在Mem9中搜索相似向量 search_payload { vector: query_vector, limit: top_k * 2, # 多取一些方便后续过滤 with_payload: True } if session_id: # 如果指定了session可以利用Mem9的过滤功能如果支持 search_payload[filter] {must: [{key: session_id, match: {value: session_id}}]} resp requests.post( f{self.mem9_base_url}/collections/{self.collection_name}/search, jsonsearch_payload ) resp.raise_for_status() vector_results resp.json()[result] # 3. 提取向量ID去TiDB获取完整元数据 memory_ids [item[id] for item in vector_results] if not memory_ids: return [] placeholders ,.join([%s] * len(memory_ids)) with self.tidb_conn.cursor() as cursor: sql fSELECT * FROM memory_metadata WHERE memory_id IN ({placeholders}) ORDER BY FIELD(memory_id, {placeholders}) # 注意这里简化了实际需要更复杂的排序结合Mem9返回的分数 cursor.execute(sql, memory_ids * 2) # 一个用于IN一个用于FIELD排序 tidb_rows cursor.fetchall() # 4. 合并结果将TiDB的元数据与Mem9的向量相似度分数结合 tidb_map {row[memory_id]: row for row in tidb_rows} merged_results [] for vec_item in vector_results: mem_id vec_item[id] if mem_id in tidb_map: merged {**tidb_map[mem_id], **{similarity_score: vec_item[score]}} merged_results.append(merged) if len(merged_results) top_k: break # 按相似度分数降序排列 merged_results.sort(keylambda x: x.get(similarity_score, 0), reverseTrue) return merged_results def _generate_uuid(self): import uuid return str(uuid.uuid4()) def close(self): self.tidb_conn.close()4.2 在OpenClaw中注册与配置后端接下来需要让OpenClaw框架使用我们刚写的HybridMemoryBackend。这通常需要在OpenClaw的配置文件如config.yaml或初始化代码中指定。1. 修改OpenClaw配置找到OpenClaw关于记忆存储的配置部分将其指向我们的自定义后端。具体配置方式取决于OpenClaw版本可能类似这样# config.yaml memory: backend: custom backend_class: your_module.HybridMemoryBackend backend_config: tidb: host: 127.0.0.1 port: 4000 user: openclaw_user password: YourStrongPassword123! database: openclaw_memory mem9: host: 127.0.0.1 port: 8080 collection: openclaw_memory_vectors embed_model: BAAI/bge-small-zh # 使用的Embedding模型2. 或在初始化代码中注入如果OpenClaw支持编程式配置可以在启动脚本中这样做from openclaw import OpenClaw from your_memory_backend import HybridMemoryBackend tidb_config {...} mem9_config {...} memory_backend HybridMemoryBackend(tidb_config, mem9_config) agent OpenClaw( memory_backendmemory_backend, # ... 其他配置 )5. 性能调优与生产环境考量5.1 Mem9向量检索的优化策略Mem9的性能核心在于索引构建和查询参数。在创建集合时设定的index_params只是第一步。1. 索引参数调优M影响索引的连通性和内存占用。值越大精度越高但构建越慢内存占用越多。对于记忆检索通常要求高召回可以设为24或32。ef_construction影响索引构建时的精度。值越大构建越慢但索引质量越高。通常200-400是合理范围。ef_search这是运行时最重要的参数。在搜索时指定影响搜索的精度和速度。值越大结果越精确但越慢。你需要根据业务容忍的延迟和所需的精度来权衡。可以通过一个简单的测试集来调整# 在搜索时指定ef_search search_payload { vector: query_vector, limit: top_k, params: {ef: 128} # 动态调整ef_search }对于大多数对话记忆检索ef_search在64-256之间通常能取得很好的平衡。2. 批量操作与连接池频繁的单条插入和搜索是性能杀手。务必实现批量操作。批量保存Agent运行一段时间后将累积的记忆批量写入而不是每次对话都写。使用gRPC接口如果Mem9支持优先使用gRPC而非REST APIgRPC在大量小数据包传输上效率高得多。客户端连接池为Mem9的REST客户端如requests.Session或gRPC通道配置连接池避免反复建立TCP连接的开销。5.2 TiDB的表设计与查询优化TiDB虽然是分布式数据库但良好的表设计仍是性能基石。1. 分区表应对海量记忆如果记忆数据量非常庞大例如数亿条可以考虑对memory_metadata表按created_at创建时间进行范围分区Range Partitioning。这样可以将历史冷数据与热数据物理分离提升查询和维护效率。ALTER TABLE memory_metadata PARTITION BY RANGE ( UNIX_TIMESTAMP(created_at) ) ( PARTITION p202401 VALUES LESS THAN (UNIX_TIMESTAMP(2024-02-01)), PARTITION p202402 VALUES LESS THAN (UNIX_TIMESTAMP(2024-03-01)), PARTITION p202403 VALUES LESS THAN (UNIX_TIMESTAMP(2024-04-01)), PARTITION pfuture VALUES LESS THAN MAXVALUE );2. 复合索引与覆盖索引根据你的查询模式建立合适的索引。除了示例中的单列索引高频的复合查询可能需要复合索引。-- 例如频繁按用户和会话查询最近记忆 CREATE INDEX idx_user_session_time ON memory_metadata (user_id, session_id, created_at DESC); -- 如果查询经常只返回部分列考虑使用覆盖索引 CREATE INDEX idx_session_cover ON memory_metadata (session_id, memory_id, content_embedding_id);使用EXPLAIN语句分析你的关键查询确保它们用上了索引避免全表扫描。3. 处理JSON字段的查询metadataJSON字段虽然灵活但直接查询其中的属性可能较慢。如果某些元数据字段查询非常频繁可以考虑将其提取出来作为单独的列或者使用TiDB 5.0支持的生成列Generated Column来建立索引。-- 例如假设metadata里有一个频繁查询的topic字段 ALTER TABLE memory_metadata ADD COLUMN topic VARCHAR(50) AS (JSON_UNQUOTE(JSON_EXTRACT(metadata, $.topic))) VIRTUAL, ADD INDEX idx_topic (topic);5.3 数据同步与一致性的保障在Mem9和TiDB的混合架构中保证数据一致性是一个挑战。我们采用的是“先Mem9后TiDB”的写入顺序但这并不能保证原子性Atomicity。1. 最终一致性策略对于记忆存储通常可以接受最终一致性。我们的策略是写入时先写Mem9向量成功后写TiDB元数据。如果写TiDB失败记录错误日志并尝试重试或者将失败任务放入一个可靠队列如TiDB Binlog Kafka进行异步补偿。由于Mem9中存储了关联的session_id即使TiDB暂时失败Agent的向量检索功能仍可工作只是无法通过TiDB做复杂的元数据关联查询。定期运行一个核对任务比较Mem9和TiDB中的数据修复不一致如Mem9中有但TiDB中无的记录。2. 引入分布式事务可选复杂度高如果业务要求强一致性可以考虑引入分布式事务协调器如Seata或者利用TiDB本身的事务能力将向量数据也存储在支持事务的向量扩展中但这可能牺牲Mem9的性能优势。对于绝大多数AI记忆场景最终一致性加上良好的错误处理和补偿机制是完全足够的。6. 运维监控与故障排查实录6.1 关键监控指标与告警设置一个稳定的私有记忆中枢离不开监控。1. TiDB监控使用TiDB自带的监控组件TiDB Dashboard、Prometheus Grafana监控以下核心指标数据库连接数tidb_server_connections查询延迟tidb_server_handle_query_duration_secondsTiKV Region状态tikv_region_status关注Leader分布是否均匀。存储空间tikv_store_size_bytes防止磁盘写满。告警设置慢查询如 2s告警、连接数过高告警、集群节点宕机告警。2. Mem9监控Mem9可能提供Prometheus metrics端点。需要关注内存使用率向量索引完全在内存中内存是关键资源。QPS每秒查询数与延迟mem9_qps,mem9_search_latency_ms。集合大小mem9_collection_vectors_count。告警内存使用率超过80%、搜索延迟P99超过设定阈值如200ms。3. 应用层监控在HybridMemoryBackend中埋点记录保存记忆的成功/失败率、平均耗时。搜索记忆的成功/失败率、平均耗时、返回结果数量。Embedding模型调用耗时。6.2 常见问题与解决方案速查表以下是我在搭建和测试过程中遇到的一些典型问题及解决方法问题现象可能原因排查步骤与解决方案Mem9插入向量失败报错“dimension mismatch”1. 创建集合时指定的维度与实际插入向量的维度不一致。2. Embedding模型输出维度变化。1. 检查mem9_config中dimension参数。2. 打印self.embedder.get_sentence_embedding_dimension()确认维度。3. 重建集合或使用与模型匹配的维度。TiDB连接超时或“Too many connections”1. 应用未使用连接池每次操作都新建连接。2. TiDBmax_connections设置过低。3. 连接未正确关闭导致泄漏。1. 在应用中使用数据库连接池如DBUtils。2. 检查TiDB全局变量SHOW VARIABLES LIKE max_connections;必要时调大。3. 确保每个数据库操作后正确关闭游标和连接使用with上下文管理器。记忆搜索速度突然变慢1. Mem9内存不足触发磁盘交换。2. TiDB表缺乏有效索引导致查询全表扫描。3. 网络波动。1. 检查Mem9所在服务器内存使用情况。2. 在TiDB中使用EXPLAIN ANALYZE分析慢查询SQL添加缺失索引。3. 检查网络延迟。保存记忆成功但后续搜索不到1. 数据一致性出现问题Mem9和TiDB未同步。2. 搜索时过滤条件如session_id错误。3. Embedding模型不一致如保存和搜索用了不同模型。1. 检查错误日志确认TiDB插入是否成功。运行数据核对脚本。2. 检查搜索代码中的过滤逻辑。3.确保保存和搜索使用完全相同的Embedding模型和参数特别是归一化设置。OpenClaw启动时报错找不到自定义Backend1. Python模块路径问题。2. 类名拼写错误。3. 依赖未安装。1. 确保your_module.HybridMemoryBackend的路径正确且__init__.py文件存在。2. 在OpenClaw启动前手动导入你的后端类进行测试。3. 检查pymysql,sentence-transformers等依赖是否已安装。向量相似度分数都很低召回不准1. Embedding模型不适合你的领域或语言。2. 文本预处理不一致如保存时做了清洗搜索时没有。3. Mem9的metric设置错误如用了l2但数据是cosine归一化的。1. 尝试更换或微调Embedding模型如从bge-small-zh换到bge-large-zh。2. 统一保存和搜索前的文本预处理流程去停用词、标准化等。3. 确认Mem9集合的metric与Embedding生成方式匹配通常cosine配归一化向量。6.3 备份与恢复策略TiDB备份使用Dumpling进行逻辑全量备份tiup dumpling -u root -P 4000 -h 127.0.0.1 --filetype sql -t 8 -o /path/to/backup使用BR(Backup Restore) 进行物理增量/全量备份适用于大规模数据。制定周期计划如每日全备每小时增备。Mem9备份由于Mem9数据可通过TiDB的content_embedding_id关联重建核心是备份其索引配置文件和数据目录。定期对Mem9的数据目录Docker挂载的/your/data/path进行快照备份。记录创建集合时使用的精确参数dimension,metric,index_params以便灾难恢复时重建。恢复流程恢复TiDB数据使用Lightning导入Dumpling备份或BR恢复。从备份中恢复Mem9数据目录。如果Mem9数据目录无法恢复则需要从TiDB中读取元数据重新生成所有文本的向量并批量重新插入到新创建的Mem9集合中。这强调了在TiDB中保存原始文本content_text的重要性。7. 进阶玩法与扩展思路搭建好基础系统后可以在此基础上探索更多增强功能。1. 记忆分层与冷却不是所有记忆都同等重要。可以实现一个记忆冷却策略高频访问的记忆留在Mem9热层。长期未访问的记忆将其向量从Mem9迁移到更经济的冷存储如支持向量的对象存储或磁盘型向量数据库只在TiDB元数据中标记存储位置。当Agent再次需要时再异步加载回Mem9。2. 记忆融合与摘要当某个主题的记忆片段过多时可以对它们进行自动摘要生成一条“融合记忆”存入避免搜索时返回过多冗余片段。这可以在后台使用另一个LLM来异步完成。3. 多模态记忆扩展目前的架构主要针对文本。如果要支持图像、音频的记忆可以使用多模态Embedding模型如CLIP生成统一向量。在TiDB的metadataJSON字段或新增列中存储文件的原始路径或对象存储链接。搜索时用多模态查询如一张图去Mem9搜向量再通过TiDB拿到对应的文件地址。4. 与OpenClaw Skill深度集成将记忆中枢的能力封装成OpenClaw的Skill。例如创建一个RecallMemorySkill让Agent可以主动调用类似“回忆一下我们上周讨论的关于项目架构的要点”这样的指令背后就是调用我们实现的search_memories方法。这个“记忆不上云”的方案把AI Agent最宝贵的记忆资产控制在了自己手中。它确实比直接调用云服务多了不少部署和运维的工作但换来的数据主权、性能提升和定制灵活性对于严肃的项目和产品来说这份投入是值得的。在实际使用中最关键的是把握好Mem9和TiDB的边界设计好数据同步和一致性策略然后就是持续的监控和调优。希望这份详细的拆解能帮你少走弯路。