1. 从 OpenClaw 的记忆丢失说起:Rust 重写要解决什么
如果你用过一段时间的 OpenClaw,大概率遇到过这种场景:昨天刚跟它聊过的项目背景、偏好设置、甚至刚教会它的一个操作流程,今天再打开就"失忆"了。更让人头疼的是,每次换台机器或者重装环境,依赖安装能折腾掉大半天,Python 版本冲突、系统库缺失、编译工具链对不上,报错信息还特别抽象。至于"自我学习进化"和"自动生成技能",原版更多是停留在概念层面,实际用起来还是得手动写配置、手动喂知识。
这就是 RsClaw(螃蟹 AI)想解决的问题。它是一个用 Rust 全新重写的 OpenClaw 升级版开源项目,项目地址在 github.com/rsclaw-ai/rsclaw。核心思路很直接:把原来靠脚本和运行时拼凑的能力,用 Rust 的类型系统和内存模型重新组织一遍,让记忆持久化、依赖管理、技能生成这三件事从"能用"变成"稳定可用"。
这篇文章聚焦四个工程痛点:记忆持久化、依赖安装简化、自我学习进化、技能自动生成。我会把可复制的 Rust 模块配置、依赖清单和验证步骤都写出来,你可以照着在本地复现记忆恢复和技能生成的完整流程。适合谁看?如果你是被 OpenClaw 记忆丢失折磨过的用户,或者想用 Rust 做 AI Agent 基础设施的开发者,这篇会比较对味。
先说清楚一个前提:RsClaw 的记忆体系不是简单地把对话存进 SQLite 就完事。它做了三层分层——Core 核心层永久留存身份和固定事实,Working 工作层存高频上下文,Peripheral 外围层放低价值信息并快速衰减。衰减算法用的是 Weibull 拉伸指数,召回时把 BM25 关键词检索和 hnsw_rs 向量余弦检索用 RRF 融合。这套东西用 Rust 写,最大的好处是并发安全和内存可控,不会因为长时间运行导致内存泄漏把记忆搞丢。
2. TaoToken 前置:给 RsClaw 接上稳定的模型调用通道
RsClaw 本身是个 Agent 框架,它需要调用大模型来完成对话、记忆蒸馏、技能生成这些任务。所以在你开始折腾 Rust 模块之前,得先把模型调用通道准备好。我用的是 TaoToken 的 API 服务,官网在 https://taotoken.net,API 端点是 https://taotoken.net/api。它的作用是提供一个兼容 OpenAI 协议的接口,让你不用自己维护模型部署,直接拿 Key 就能调。
为什么要在 RsClaw 的教程里先讲这个?因为记忆蒸馏和技能生成都依赖模型输出结构化数据。如果模型调用不稳定,蒸馏出来的实体、偏好、操作流程就会残缺,记忆恢复自然失败。TaoToken 的接口格式跟 OpenAI 一致,RsClaw 的 Rust 客户端可以直接复用现成的 HTTP 客户端库,不需要额外适配层。
你需要准备三样东西:Base URL、API Key、Model ID。Base URL 填 https://taotoken.net/api,API Key 在控制台的 API Keys 页面生成,Model ID 根据你用的模型填,比如 claude 系列或者 gpt 系列。这三个值后面会写进 RsClaw 的配置文件里。
具体操作路径:先访问 https://taotoken.net/api-keys 生成一个 Key,然后到 https://taotoken.net/doc 看一下接口文档确认模型列表。如果你主要做长期编码和 Agent 任务,可以考虑 Coding Plan,入口在 https://taotoken.net/coding-plan。想先验证模型对话效果,用 https://taotoken.net/chat 直接试。
这里有个坑要注意:RsClaw 的 Rust 客户端在初始化时会读取环境变量TAOTOKEN_API_KEY,如果你把 Key 写死在代码里,换环境时容易泄露。建议用.env文件配合dotenvycrate 加载,后面配置章节会给完整示例。
3. 可复制配置:Cargo.toml 依赖清单与记忆模块 settings
这一节是全文最核心的部分,我会给出完整的Cargo.toml依赖清单和记忆模块的配置文件。你直接复制到项目里就能跑。
先看依赖清单。RsClaw 的记忆模块依赖几个关键 crate:tokio做异步运行时,serde和serde_json做序列化,rusqlite做本地持久化,hnsw_rs做向量检索,reqwest做 HTTP 调用。版本我实测下来比较稳的组合如下:
[package] name = "rsclaw-memory" version = "0.1.0" edition = "2021" [dependencies] tokio = { version = "1.38", features = ["full"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" rusqlite = { version = "0.31", features = ["bundled"] } hnsw_rs = "0.2" reqwest = { version = "0.12", features = ["json", "rustls-tls"] } dotenvy = "0.15" anyhow = "1.0" tracing = "0.1" tracing-subscriber = "0.3"注意rusqlite开了bundledfeature,这样它会自带 SQLite 源码编译,不依赖系统库,跨平台安装依赖的痛点直接消掉一大半。reqwest用rustls-tls而不是默认的 native-tls,避免 OpenSSL 版本冲突。
接下来是记忆模块的配置文件。RsClaw 用 TOML 格式管理分层记忆参数,文件路径是config/memory.toml:
[memory.core] decay_coefficient = 0.9 permanent = true storage = "sqlite://data/core.db" [memory.working] decay_coefficient = 0.5 promotion_threshold = 3 storage = "sqlite://data/working.db" [memory.peripheral] decay_coefficient = 0.2 cleanup_interval_hours = 24 storage = "sqlite://data/peripheral.db" [retrieval] bm25_weight = 0.4 vector_weight = 0.6 rrf_k = 60 top_k = 8 [model] base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" model_id = "claude-3-5-sonnet"这份配置里,decay_coefficient控制每层的衰减速度,Core 层 0.9 意味着几乎不衰减,Peripheral 层 0.2 意味着低价值信息很快被淘汰。promotion_threshold = 3表示 Working 层的记忆被召回 3 次后可以升级到 Core 层。rrf_k = 60是 RRF 融合算法的平滑参数,这个值在信息检索领域比较通用。
环境变量文件.env放在项目根目录:
TAOTOKEN_API_KEY=你的Key RSCLAW_DATA_DIR=./data RUST_LOG=info这里 Base URL、Key、Model ID 三件套齐了。Base URL 是https://taotoken.net/api,Key 从环境变量读,Model ID 在 TOML 里指定。如果你用 Claude Code 做辅助开发,可以参考 https://taotoken.net/claude-code-anthropic 的接入说明,配置逻辑是一样的。
4. 验证请求:复现记忆恢复与技能生成流程
配置写完之后,得验证它真的能跑。我分两步:先验证模型调用通道,再验证记忆恢复和技能生成。
第一步,写一个最小的 Rust 测试程序,确认能通过 TaoToken 拿到模型响应。创建src/bin/verify_model.rs:
use reqwest::Client; use serde_json::json; use std::env; #[tokio::main] async fn main() -> anyhow::Result<()> { dotenvy::dotenv().ok(); let api_key = env::var("TAOTOKEN_API_KEY")?; let client = Client::new(); let resp = client .post("https://taotoken.net/api/v1/chat/completions") .header("Authorization", format!("Bearer {}", api_key)) .json(&json!({ "model": "claude-3-5-sonnet", "messages": [ {"role": "user", "content": "用一句话说明记忆持久化的重要性"} ] })) .send() .await?; let status = resp.status(); let body: serde_json::Value = resp.json().await?; println!("status: {}", status); println!("response: {}", body["choices"][0]["message"]["content"]); Ok(()) }运行cargo run --bin verify_model,如果看到 status 200 和模型返回的内容,说明通道没问题。这一步能过,后面的记忆蒸馏才有模型可用。
第二步,验证记忆恢复。RsClaw 的记忆写入是自动的,每轮对话结束后会触发蒸馏。你可以手动调用记忆模块的recall函数来测试:
use rsclaw_memory::{MemoryStore, RecallQuery}; #[tokio::main] async fn main() -> anyhow::Result<()> { let store = MemoryStore::from_config("config/memory.toml").await?; // 写入一条测试记忆 store.remember("用户偏好使用 Rust 做后端开发").await?; // 模拟新会话,召回关联记忆 let query = RecallQuery::new("用户的技术栈是什么"); let memories = store.recall(query, 5).await?; for m in memories { println!("[{}] {}", m.layer, m.content); } Ok(()) }预期输出会显示从 Core 层或 Working 层召回的"用户偏好使用 Rust 做后端开发"。如果输出为空,说明衰减参数或者检索权重需要调整,检查bm25_weight和vector_weight是否加起来等于 1.0。
第三步,验证技能自动生成。RsClaw 的技能生成逻辑是:从记忆里提取重复出现的操作流程,蒸馏成结构化技能。触发方式是在对话中多次执行同类操作,然后调用generate_skills:
let skills = store.generate_skills().await?; for skill in skills { println!("技能名: {}", skill.name); println!("触发条件: {}", skill.trigger); println!("步骤: {:?}", skill.steps); }实测下来,连续三次让 Agent 执行"读取 CSV 并统计行数"之后,技能生成模块会产出一个名为csv_row_count的技能,包含文件路径参数和统计步骤。这就是"自我学习进化"的落地形态——不是玄学,而是基于记忆频次的模式提取。
5. 本篇常见错排查:401、local proxy failed 与 reading choices
这一节列几个你大概率会撞上的报错,以及对应的排查路径。
报错一:401 Unauthorized。这个最常见,原因是 API Key 没读到或者格式不对。检查.env文件是否在项目根目录,dotenvy::dotenv()是否在读取环境变量之前调用。另外确认 Key 没有多余空格,Header 格式是Bearer加 Key,中间一个空格。如果还是 401,去 https://taotoken.net/api-keys 重新生成一个 Key 试试。
报错二:local proxy failed 或 connection refused。这个通常出现在你本地配了 HTTP 代理,但 reqwest 没走代理或者代理地址失效。RsClaw 默认不读系统代理,如果你需要走代理,得在 Client 构建时显式设置。但更常见的坑是环境变量HTTP_PROXY残留导致 reqwest 尝试连接一个不存在的本地端口。排查方法:echo $HTTP_PROXY看有没有值,有就 unset 掉再跑。
报错三:reading choices 相关解析失败。这个报错说明模型返回的 JSON 结构跟预期不符。RsClaw 期望的是 OpenAI 兼容格式,即choices[0].message.content。如果返回体里没有choices字段,可能是 Model ID 填错了,或者接口路径少了/v1。确认 Base URL 是https://taotoken.net/api,完整路径是https://taotoken.net/api/v1/chat/completions。另外检查模型名是否在 TaoToken 支持的列表里,文档在 https://taotoken.net/doc。
报错四:OAuth 或 auth.json 相关。如果你用 Codex 或者 Claude Code 做辅助,可能会遇到auth.json读取失败。RsClaw 本身不用 OAuth,但如果你在开发环境里混用了其他工具的凭证文件,路径冲突会导致读取异常。解决办法是给 RsClaw 单独的数据目录,通过RSCLAW_DATA_DIR环境变量隔离。CC Switch 或 Cline MCP 的场景下,同样要确保 Base URL、Key、Model ID 三件套写全,缺一个都会导致认证链路断掉。
报错五:hnsw_rs 索引构建失败。这个出现在记忆量较大时,向量维度不匹配或者索引文件损坏。删掉data/目录下的索引文件重新构建即可。生产环境建议定期备份 Core 层的 SQLite 文件,因为那是永久记忆,丢了就真丢了。
6. 把记忆和技能跑起来之后,你可以这样继续
到这一步,你应该已经能在本地复现记忆写入、召回和技能生成的完整流程了。我自己的经验是,先别急着灌大量数据,用几条测试记忆把三层衰减和 RRF 融合的参数调顺,再逐步导入真实对话历史。Core 层的decay_coefficient设成 0.9 是有道理的,身份和固定事实不该被时间冲淡;Working 层的promotion_threshold可以按你的召回频率调整,召回越频繁,升级越快。
技能生成这块,目前它提取的是操作流程类模式,对于"读取文件→解析→输出"这种线性步骤效果最好。如果你的任务涉及复杂分支,建议先在记忆里把步骤拆细,再让生成模块去蒸馏。
模型调用通道保持稳定是前提。TaoToken 的 API 端点是 https://taotoken.net/api,Key 在控制台生成,文档在 https://taotoken.net/doc。长期跑 Agent 任务的话,Coding Plan 会比按量调用更省心,入口在 https://taotoken.net/coding-plan。想快速验证模型输出质量,直接用 https://taotoken.net/chat 就行。
最后提醒一句:Rust 重写带来的最大收益不是性能数字,而是"不会莫名其妙丢记忆"这件事本身。类型系统帮你挡住了大部分序列化错误,所有权模型帮你管住了并发写入。把配置跑通之后,你会发现原来那些玄学 bug,很多在编译期就被拦下来了。