OpenClaw 7.1 升 8.2,我踩了十来个坑,最后靠换一台机器把记忆搜索救回来
写在前面
昨天我把跑着的 OpenClaw 从 7.1 升到了 8.2,本意是修一个老毛病——记忆搜索失效。结果这一天过得极其充实:没有 sudo 密码怎么重建容器、本地嵌入的 batch 512 硬限制、索引越补越脏、最后整个会话卡死到只能重启网关才缓过来。
这篇把整条线摊开讲。升级本身不难,难的是中间那十几个坑,每个都像是设计好的一样等着你。
先交代背景,免得后面看不懂:我跑 OpenClaw 的是一台 2 核、3.6G 内存的云主机(tecent-vps),Docker 容器方式部署。另一台 debian 小主机(4 核)专门跑各种服务,包括后面要提到的向量服务。最后一台 bwh-vps 做前端。三台机分工,这格局后面有用。
1. 为什么升:一个"睡懒觉"的记忆搜索
先说为什么要折腾。
OpenClaw 有个记忆系统,会把过往对话的内容向量化存起来,下次你再问相关的东西,它能把旧对话翻出来当上下文。这套东西在 7.1 上跑得好好的,属于"进程内"直接嵌入——就是程序自己把模型加载进内存里算向量,不需要额外起一个服务。
但升级到 8.2 之后,这套"进程内"的机制整个没了。8.2 跨过了 8.1(也就是 OpenClaw 2.0),是个大版本,架构重做了一遍。本地嵌入被重构成"托管 server"模式,旧配置 config:{} 直接不生效,记忆搜索一下就哑了。
这就是升级的导火索:我想修好它,结果一头扎进去出不来。
2. 第一个坑:镜像拉不下来,429 限流
升级第一步就卡住。Docker Hub 拉 OpenClaw 的镜像,报 429 Too Many Requests。
国内直连 Docker Hub 本来就慢,赶上限流更是拉不动。解法是把 FROM 换成国内加速镜像:
FROM docker.m.daocloud.io/openclaw/openclaw:latest
这种加速镜像把官方镜像同步了一份,拉取快得多。这个属于常规操作,不算难。
3. 第二个坑:没有 sudo 密码,容器建不起来
真正麻烦的在这。我要重建容器,但构建目录的属主不对,docker compose up -d --build 会失败。而我这台机子的 admin 用户没有 sudo 密码——或者说,我不知道密码。
没有 sudo,很多"常规解法"都失效了。但这台机子有个例外:admin 在 docker 组里。有 docker 组权限,就能直接跑 docker 命令,包括用 docker 的卷挂载来"偷"改宿主机的文件权限。
于是我用了一个绕法,用 docker 起一个临时 alpine 容器,把构建目录的属主改成容器要用的 uid:
docker run --rm -v /opt/stacks/openclaw:/d alpine chown -R 1001:1001 /d
把 /opt/stacks/openclaw 挂载进去,在容器里用 root 把整个目录 chown 成 1001:1001,退出即删。这样绕过了 sudo,因为跑这条命令只需要 docker 组的权限。
数据目录也一样要管:/home/admin/.openclaw 属主必须跟容器里的运行用户对上,否则容器起来也没权限读写。确认 admin 的 uid 正好是 1001,跟容器的 user:1001:1001 匹配,这关才算过。
4. 第三个坑:本地嵌入整个换了玩法
容器起来了,8.2 能跑,但记忆搜索是坏的。因为 8.2 把旧的"进程内 node-llama-cpp 运行时"退役了,改成用 @openclaw/llama-cpp-provider 这个新插件,配合一个"托管"的 llama-server。
也就是说,本地嵌入不再是自己塞进程序里,而是要起一个独立的 llama-server 进程,OpenClaw 通过 HTTP 去调它。装插件的时候要带两个参数:
openclaw plugins install @openclaw/llama-cpp-provider --force --accept-capabilities
--accept-capabilities 是承认这个插件需要的权限,--force 是强制覆盖。
配置这一步有个坑:得跑交互式命令 openclaw configure --section model,里面要用方向键和回车一路选「Local llama.cpp → Managed local server → Yes」。这在 SSH 里特别容易卡死——交互式界面在 SSH 里看不到、也按不动,而且 exec 一超时整个会话就没了。我的经验是必须用 pty 加后台进程的方式操作,还得模拟方向键和回车,很折腾。
5. 第四个坑:llama-server 起不来,缺一个库
配好了,但 llama-server 启动失败。
报错追下去发现是容器里缺 OpenMP 的运行库(libgomp1)。llama.cpp 这类本地推理库依赖 OpenMP 做并行,没有就跑不起来。用 root 进容器补上:
docker exec -u 0 openclaw apt-get install -y libgomp1
这里有个隐患要提醒:这个操作只对当前容器生效,一旦容器重建,这个库又没了,得重新装。所以正确做法是把它写进 Dockerfile,而不是手动装。我当时是手动装的,记了个备忘。
6. 第五个坑(最大的):batch 512 硬限制
llama-server 起来了,本地嵌入也连上了,本以为完事。结果一跑记忆搜索就报错:
input is too large to process. increase the physical batch size (current batch size: 512)
什么意思呢?OpenClaw 把记忆切块成一段段文本去算向量,每段 754 个 token,但托管起来这个 llama-server 的物理 batch 只有 512。754 超过了 512,直接拒了。
问题是这个 batch 512 是 OpenClaw 核心启动嵌入进程时写死的,根本没法通过配置改。我试了三种常规办法,全都不行:
- 在
models.ini里加ubatch-size——没用,OpenClaw 会重写这个文件,而且嵌入进程根本不读它。 - 在
localService.args里加--ubatch-size参数——没用,嵌入进程不继承这些参数。 - 改插件常量
LLAMA_CPP_EMBEDDING_UBATCH_SIZE=2048——还是没用,这个常量只影响 models.ini,碰不到核心启动的嵌入进程。
三条路全堵死。到这里我基本确认,8.2 托管嵌入的 batch 512 是一个绕不过去的限制,至少在这个版本、这个配置下改不了。要么认了,要么换方案。
7. 索引越补越脏,卡死整个会话
本地嵌入这头还没解决,另一头又出事了。
因为嵌入反复失败重试,记忆索引越来越脏。查状态的时候看到 16/67 files · 35 chunks · Dirty: yes——一堆文件没索引上,还标了脏。我试着 openclaw memory status --index 去补,结果因为嵌入服务一直报错,越补越乱。
更糟的是,这个反复失败的重试把会话的预处理拖垮了。正常情况会话开始前的准备只要 5 秒,因为嵌入卡住,被拖到 160 到 230 秒。后台的任务等了 630 秒没进展就超时,可恢复机制还误判"正在回复",迟迟不肯中断。最后整个会话彻底卡死,只能重启网关才缓过来。
这条链我理了很久才想明白:根子就是 embedding 反复失败,下游全是被它拖死的。而自愈机制(超时、恢复、中断宽限)全是内置写死的,配置里没有对应项,也没有手动强制中断的命令。想根治,只能让 embedding 别老失败。
8. 换方案:把向量算到另一台机器上
三条本地配置的路都堵死之后,我决定换思路——不在这台 3.6G 内存的机器上硬扛了,把向量计算挪到局域网里另一台 debian 小主机上去。
这台 debian 本来就在跑一个 llama-server(给别的服务用),干脆让它兼职提供 embedding 服务。OpenClaw 这边把记忆搜索的 provider 改成 openai 兼容的远程调用:
memory:
search:
provider: openai-compatible
remote:
baseUrl: http://100.79.32.111:8080/v1/
model: embeddinggemma-300m
关键点是这个地址是局域网内的,数据不出自己家,隐私没问题,但算力、batch 限制这些都由那台机器扛了。
改完实测:各种大小的文本块(232、540、605、802、1442、1642 token)全部成功,没有 batch 限制。困扰了一天的嵌入问题,换台机器就没了。
9. 索引重建,量大了是真要命
切到远程之后,重新跑索引重建:
补完前:16/67 files · 35 chunks · Dirty: yes
补完后:20/20 files · 200 chunks · Dirty: no
这才两百个 chunk,跑起来都要费一阵。如果记忆量是几千几万个 chunk,重建就是全量重算向量,时间随量线性涨,短时间内根本跑不完。
这也是想升级的人要提前想清楚的:8.2 把存储从 JSON 文件整个迁到了 SQLite,不管嵌入用哪种方式,索引都得重新向量化、重建。迁移是躲不掉的,差别只在向量化模型够不够强——本地 CPU 慢慢算,和远程 GPU/API 高吞吐并行算,速度天差地别。我这台小内存机器就是吃了本地算的亏。
顺带说一句,"保留索引身份"这个词容易误解。8.2 文档说本地嵌入 provider 和索引身份会保留,意思是你在不同嵌入模型之间切换时,系统不会以为你是新用户、索引身份不丢。但它不代表索引内容免重建——存储底子都换了,重建躲不掉。
10. 那能不能回到老式记忆搜索?
有人会问,能不能在 8.2 上把 7.1 那种"进程内 node-llama-cpp"的老方式恢复出来?
答案是不行,那个运行时在 8.2 里已经被删了,不是没找到开关,是底层没有了。但"本地记忆搜索"这件事本身,8.2 还是支持的——通过托管 llama-server 的 managed mode,官方文档也确认保留了历史 local provider。
我们之所以没走这条路,纯粹是这台 tecent-vps 内存太小(3.6G),托管模式还要装 Gemma 4 聊天模型(5G)+ EmbeddingGemma(0.3G),内存扛不住,加上那个 batch 512 的限制。不是机制上做不到,是这台机器扛不动。换个内存大的机器,本地嵌入照样能用。
11. 备份救了我
整个过程我做了两重备份,事后看非常值:
- 一个
openclaw.json.bak配置备份,手动存的。 - 一个全量 backup 打包
openclaw-backup-20260903.tar.gz,升级前打的。
中间有几回改配置改到心里没底,全靠能回滚才敢继续往下试。自托管这玩意儿,没有备份兜底,真不敢这么折腾。建议所有要升级的人,先备份再动手。
最后
一天下来,升级本身没花多少时间,时间全耗在坑里。总结下来其实是三件事:
- 大版本跨越,架构变了要提前摸底。7.1 到 8.2 是跨了 2.0 的大版本,存储从 JSON 换 SQLite、嵌入从进程内换托管,这些升级前就该知道。
- 本地嵌入的 batch 512 是个绕不过的硬限制,小内存机器别硬扛,换个强点的向量来源更省事。
- 备份是底线。没有能回滚的东西,这种一天的折腾根本不敢开始。
如果问我值不值,我会说值。折腾完之后记忆搜索反而更稳了,而且理顺了整套架构。只是下次再有大版本升级,我会先看一眼 changelog,把该知道的坑提前记下来,而不是一头扎进去。