最近在翻OpenClaw的源码翻到记忆系统那块的时候愣住了。这玩意的整套RAG——向量索引、全文检索、嵌入缓存——全塞在一个SQLite文件里。没有Pinecone没有Weaviate没有任何外部向量数据库。我第一反应是这也太糙了吧看完实现之后改主意了。不是糙是想明白了才这么干的。先说背景为什么AI需要记忆你跟ChatGPT聊过的都知道AI是没有长期记忆的。你昨天告诉它你喜欢用TypeScript今天它又问你一遍。OpenClaw要解决的就是这个问题。它让AI Agent能记住你之前聊过什么、做过什么决定、偏好是什么下次对话的时候直接调出来。这就需要一套检索系统——把你的历史信息存起来需要的时候快速找到最相关的那几条。业内叫RAGRetrieval-Augmented Generation检索增强生成。大部分团队做RAG的标配是向量数据库 嵌入模型 一堆胶水代码。OpenClaw的做法是把这些全打包进SQLite。一个SQLite凭什么能干这事因为SQLite不只是那个轻量级数据库。加上sqlite-vec扩展它能做向量KNN搜索。加上FTS5模块它能做全文检索。两个加在一起就是一个麻雀虽小五脏俱全的RAG引擎。OpenClaw在SQLite里建了6张表分工非常清楚meta表存配置元数据比如用的哪个嵌入模型、向量维度多少文本被切成小块存在chunks表每块带着embedding向量向量索引在chunks_vec虚拟表里用sqlite-vec做KNN查询全文索引在chunks_fts虚拟表里用FTS5做关键词匹配files表追踪哪些文件索引过了通过对比内容哈希和mtime判断要不要重新处理embedding_cache表缓存嵌入结果同样的文本不重复调API没有多余的东西。我看过不少RAG实现表结构动辄十几张各种冗余字段。OpenClaw这6张表的设计看得出是想清楚了才动手的。最精妙的部分混合检索单纯用向量搜索有个问题——你搜JWT认证这种精确术语的时候语义检索经常不如关键词好使。反过来你问之前讨论的那个安全方案这种模糊描述关键词又搞不定。OpenClaw的解法是两路同时跑然后五步合并取并集→加权求和向量0.7 关键词0.3→时间衰减→排序→MMR去重时间衰减这个设计我特别喜欢——30天前的内容得分自动减半但核心决策文档标记为常青永不衰减。你一个月前的会议记录确实不该和昨天的笔记抢位置。MMRMaximal Marginal Relevance是防止返回一堆高度重复的结果。前两条已经选了JWT相关内容第三条即使JWT分数也高也会让位给一条关于OAuth的不同视角。整条管线的权重、衰减速率、MMR参数全部可配。想要纯向量搜索textWeight设0。想关时间衰减一个开关。这种默认好用、细节可调的设计风格贯穿整个OpenClaw。嵌入模型的降级策略这块也值得说一下。OpenClaw支持6种嵌入提供商——OpenAI、Gemini、Voyage、Mistral、本地Ollama、还有完全离线的GGUF模型。设成auto模式时它会按优先级自动往下找本地有GGUF模型文件直接用零网络依赖。没有看谁有API key就用谁OpenAI、Gemini、Voyage、Mistral挨个试。全都没有没关系退化成纯全文检索模式不做语义理解但照样能搜。不是报错崩溃是一级一级往下降。这比我见过的大多数RAG框架都优雅——很多项目embedding配不好直接就挂了。有个细节Ollama故意被排除在auto之外。因为auto模式不该假设你本地开着一个Ollama服务要用得手动指定。这种克制我觉得是对的。为什么不用向量数据库这是我看完源码之后想得最多的问题。Pinecone、Milvus、Qdrant这些专业向量数据库处理几千万条数据没问题。但OpenClaw面对的场景是什么个人AI助手每个用户几百篇笔记顶多几千个文本块。用向量数据库就意味着要单独部署一个服务、要维护连接池、要处理服务挂了的情况、每个月还要付费。SQLite呢数据就在一个文件里备份就是复制文件迁移就是拷走ACID事务保证一致性。不需要运维不需要网络不需要付钱。OpenClaw的源码注释里说得很直白牺牲分布式扩展性换取零服务器依赖和极低运维复杂度。对于个人工具这个场景这就是正确的取舍。不是每个钉子都需要用向量数据库这把锤子。几个可以直接拿走的实践翻源码的时候记了几个有意思的工程细节本地嵌入模型的向量要做L2归一化。OpenClaw对本地GGUF模型、Gemini、Ollama返回的向量做了归一化处理归一化后余弦相似度等价于内积sqlite-vec的L2距离搜索直接就是余弦排序。OpenAI、Voyage这些远程API本身就返回归一化过的向量所以不需要再处理。这个区分很细但说明作者对每家API的行为都摸清楚了。嵌入缓存按四元组做主键(provider, model, provider_key, content_hash)。换了模型不会命中错误缓存换了API endpoint也不会。见过不少项目在这里翻车——切模型后旧缓存污染新索引。中文BM25要过滤单字。“的”、“了”、是这种单个汉字基本没区分度直接跳过。关键词上限12个就够了。OpenClaw的QMD后端专门写了一个normalizeHanBm25Query函数处理这个在外部检索引擎做中文搜索时自动生效。文件去重用realpath。符号链接可能导致同一个文件被索引两遍fs.realpath()解析真实路径后用Set去重。小细节但说明作者踩过这个坑。说到底OpenClaw这套记忆系统给我最大的启发不是技术层面的——SQLite FTS5 sqlite-vec这个组合并不新鲜。真正让我佩服的是克制。在一个大家都在往项目里塞Redis、Kafka、向量数据库的时代OpenClaw选了最简单的技术栈然后在检索策略上下足了功夫。五步混合管线、时间衰减、MMR去重——这些才是真正决定搜索质量的东西跟你用什么数据库关系不大。做AI产品的同行可以想想你的RAG系统真的需要那么重的基础设施吗
最火的AI Agent框架OpenClaw,记忆系统居然只用了一个SQLite
最近在翻OpenClaw的源码翻到记忆系统那块的时候愣住了。这玩意的整套RAG——向量索引、全文检索、嵌入缓存——全塞在一个SQLite文件里。没有Pinecone没有Weaviate没有任何外部向量数据库。我第一反应是这也太糙了吧看完实现之后改主意了。不是糙是想明白了才这么干的。先说背景为什么AI需要记忆你跟ChatGPT聊过的都知道AI是没有长期记忆的。你昨天告诉它你喜欢用TypeScript今天它又问你一遍。OpenClaw要解决的就是这个问题。它让AI Agent能记住你之前聊过什么、做过什么决定、偏好是什么下次对话的时候直接调出来。这就需要一套检索系统——把你的历史信息存起来需要的时候快速找到最相关的那几条。业内叫RAGRetrieval-Augmented Generation检索增强生成。大部分团队做RAG的标配是向量数据库 嵌入模型 一堆胶水代码。OpenClaw的做法是把这些全打包进SQLite。一个SQLite凭什么能干这事因为SQLite不只是那个轻量级数据库。加上sqlite-vec扩展它能做向量KNN搜索。加上FTS5模块它能做全文检索。两个加在一起就是一个麻雀虽小五脏俱全的RAG引擎。OpenClaw在SQLite里建了6张表分工非常清楚meta表存配置元数据比如用的哪个嵌入模型、向量维度多少文本被切成小块存在chunks表每块带着embedding向量向量索引在chunks_vec虚拟表里用sqlite-vec做KNN查询全文索引在chunks_fts虚拟表里用FTS5做关键词匹配files表追踪哪些文件索引过了通过对比内容哈希和mtime判断要不要重新处理embedding_cache表缓存嵌入结果同样的文本不重复调API没有多余的东西。我看过不少RAG实现表结构动辄十几张各种冗余字段。OpenClaw这6张表的设计看得出是想清楚了才动手的。最精妙的部分混合检索单纯用向量搜索有个问题——你搜JWT认证这种精确术语的时候语义检索经常不如关键词好使。反过来你问之前讨论的那个安全方案这种模糊描述关键词又搞不定。OpenClaw的解法是两路同时跑然后五步合并取并集→加权求和向量0.7 关键词0.3→时间衰减→排序→MMR去重时间衰减这个设计我特别喜欢——30天前的内容得分自动减半但核心决策文档标记为常青永不衰减。你一个月前的会议记录确实不该和昨天的笔记抢位置。MMRMaximal Marginal Relevance是防止返回一堆高度重复的结果。前两条已经选了JWT相关内容第三条即使JWT分数也高也会让位给一条关于OAuth的不同视角。整条管线的权重、衰减速率、MMR参数全部可配。想要纯向量搜索textWeight设0。想关时间衰减一个开关。这种默认好用、细节可调的设计风格贯穿整个OpenClaw。嵌入模型的降级策略这块也值得说一下。OpenClaw支持6种嵌入提供商——OpenAI、Gemini、Voyage、Mistral、本地Ollama、还有完全离线的GGUF模型。设成auto模式时它会按优先级自动往下找本地有GGUF模型文件直接用零网络依赖。没有看谁有API key就用谁OpenAI、Gemini、Voyage、Mistral挨个试。全都没有没关系退化成纯全文检索模式不做语义理解但照样能搜。不是报错崩溃是一级一级往下降。这比我见过的大多数RAG框架都优雅——很多项目embedding配不好直接就挂了。有个细节Ollama故意被排除在auto之外。因为auto模式不该假设你本地开着一个Ollama服务要用得手动指定。这种克制我觉得是对的。为什么不用向量数据库这是我看完源码之后想得最多的问题。Pinecone、Milvus、Qdrant这些专业向量数据库处理几千万条数据没问题。但OpenClaw面对的场景是什么个人AI助手每个用户几百篇笔记顶多几千个文本块。用向量数据库就意味着要单独部署一个服务、要维护连接池、要处理服务挂了的情况、每个月还要付费。SQLite呢数据就在一个文件里备份就是复制文件迁移就是拷走ACID事务保证一致性。不需要运维不需要网络不需要付钱。OpenClaw的源码注释里说得很直白牺牲分布式扩展性换取零服务器依赖和极低运维复杂度。对于个人工具这个场景这就是正确的取舍。不是每个钉子都需要用向量数据库这把锤子。几个可以直接拿走的实践翻源码的时候记了几个有意思的工程细节本地嵌入模型的向量要做L2归一化。OpenClaw对本地GGUF模型、Gemini、Ollama返回的向量做了归一化处理归一化后余弦相似度等价于内积sqlite-vec的L2距离搜索直接就是余弦排序。OpenAI、Voyage这些远程API本身就返回归一化过的向量所以不需要再处理。这个区分很细但说明作者对每家API的行为都摸清楚了。嵌入缓存按四元组做主键(provider, model, provider_key, content_hash)。换了模型不会命中错误缓存换了API endpoint也不会。见过不少项目在这里翻车——切模型后旧缓存污染新索引。中文BM25要过滤单字。“的”、“了”、是这种单个汉字基本没区分度直接跳过。关键词上限12个就够了。OpenClaw的QMD后端专门写了一个normalizeHanBm25Query函数处理这个在外部检索引擎做中文搜索时自动生效。文件去重用realpath。符号链接可能导致同一个文件被索引两遍fs.realpath()解析真实路径后用Set去重。小细节但说明作者踩过这个坑。说到底OpenClaw这套记忆系统给我最大的启发不是技术层面的——SQLite FTS5 sqlite-vec这个组合并不新鲜。真正让我佩服的是克制。在一个大家都在往项目里塞Redis、Kafka、向量数据库的时代OpenClaw选了最简单的技术栈然后在检索策略上下足了功夫。五步混合管线、时间衰减、MMR去重——这些才是真正决定搜索质量的东西跟你用什么数据库关系不大。做AI产品的同行可以想想你的RAG系统真的需要那么重的基础设施吗