我接触 OpenClaw 之后发现一个特别普遍的现象:很多人部署好了、角色卡写得也很用心,但聊着聊着角色就开始“失忆”——上一轮刚刚讨论的计划,下一轮就当作完全不存在。问题往往不在模型,而在一个没人愿意仔细看的参数:上下文长度。
上下文长度就是每次 AI 回复之前,系统允许“塞进模型脑袋里”的最大信息量。这个量既包括角色设定,也包括最近的聊天记录。调小了角色记性差,调大了本地显存和云端账单都会教你做人。这篇文章不扯虚的,从原理到实操、从本地部署到云端接口、从公式计算到排错清单,把 OpenClaw 上下文长度这件事一次说透。适合两类人:刚搭好环境、想让角色更“有记忆”的新手;以及已经在跑、正在被失忆或显存费用问题折磨的进阶用户。
1. 上下文长度在 OpenClaw 里到底管的是哪一段记忆
1.1 一条消息发出去之前,后台先拼了一个大礼包
很多人的第一个误解是:我发一句话,模型就只看到这一句话。其实不是这样。
OpenClaw 每处理一轮对话,都会把一个“大礼包”拼出来发给模型:角色卡里的系统设定、性格与背景故事,已经开启的长期记忆条目,最近若干轮的历史消息,最后才是你刚刚输入的那句话。模型要先把整个大礼包读完,才开始组织回复。
这个大礼包能装多少内容,就是上下文长度。它像一个抽屉:抽屉就这么大,你放进去的角色卡、记忆、旧聊天记录、当前发言全都往里挤。放不下的部分,OpenClaw 默认会从最旧的聊天开始往外扔。所以你会观察到一种很有规律的“失忆”:角色先从最久远的细节开始忘,最近几轮永远记得清清楚楚,然后随着对话继续,遗忘的边界不断前移。这不是模型坏了,而是抽屉装满了。
理解了“大礼包”模型,你就能理解为什么上下文长度不是孤立参数:角色卡写多长、记忆开多少条、历史留多少轮,全都在共用同一个预算。调上下文本质上是在重新分配预算。
1.2 单位是 Token:中文和英文的换算不一样
在 OpenClaw 的设置界面里,你可能会看到两种单位:一种是“最近 N 条消息”,一种是“上下文 N token”。如果你只按“条数”理解,一定会踩坑,因为每条消息的长短差异太大了。角色写一段三百字的深情回复和回一个“嗯”,占用完全不是一个量级。
Token 是模型真正用来计数的单位。不同模型的分词器不同,大致有个经验值:英文大约每 4 个字符算 1 个 token,一段 1000 词的英文段落大概对应 1300 token 左右;中文更紧凑但也没那么省,一个汉字平均对应 1 到 1.5 个 token,同样的意思,中文表达往往比英文更省 token。而模型宣称的“8192 上下文”,指的就是 token 数,不是字符数,也不是条数。
所以我的建议是:把一切内容都换算成 token 来看。角色卡写完用工具数一下 token;历史消息太长的轮次裁剪掉;每条长期记忆控制在 100 token 以内。养成“token 思维”之后,你再回来看上下文长度设置,会清晰很多。
1.3 太长和太短:两种极端各有各的坑
先说太短。默认值通常只有 2048 或 4096,角色卡稍微写长一点,就已经吃掉一大半预算,剩下留给聊天历史的可能只有一两千 token。相当于你每聊十几轮,前面的内容就会被清空。角色记不住你说过的偏好、记不住刚刚定下的计划,对话体验断崖式下跌。这是最常见的新手痛点。
再说太长。很多人一听说“模型支持 32768”,立刻就把上下文直接拉满。这个做法我劝你慎重,主要有三个代价。一是资源占用,本地推理时上下文长度直接决定显存里的缓存大小,从 4K 拉到 32K,显存消耗可能多出好几 GB,推理速度也会肉眼可见地变慢。二是费用,云端接口普遍按 token 计费,OpenClaw 每轮都要把整袋历史重新发一遍,上下文翻倍,单轮费用基本跟着翻倍。三是质量,当输入特别长时,很多模型会出现“中间内容被忽略”的现象——开头和结尾的内容模型响应得很好,夹在中间的大段历史反而容易被漏读。也就是说,超长上下文并不等于超强记忆。
正确的目标不是“最大”,而是“够用且不浪费”。够多久、怎么算“够”,第四部分给出具体方法。
2. 两个调整入口:图形界面与配置文件
2.1 图形界面:普通人最稳妥的改法
OpenClaw 的图形界面通常把上下文相关设置放在“设置(Settings)”→“聊天(Chat)”区域。不同版本字段名略有差异,常见叫法有 Context Length、上下文长度、最大记忆上下文。旁边一般还跟着两个关联项:回复长度(Max Response Tokens)和“历史清理自动摘要”开关。
修改步骤很简单,但有几个细节容易被忽略。第一,进入设置面板后先看单位,如果显示的是“条数”,先切到“Token”或“字符”视图再看,避免误判;如果只能设置条数,那说明这个版本把历史条数当作主要控制项,真正的 token 级上下文长度要去高级设置里找。第二,把目标值填好后保存,注意有些版本保存后即时生效,有些必须重启服务才读配置,保险起见改完重启一次。第三,确认这个设置是全局的还是按角色的,部分版本支持每个角色单独覆盖上下文长度,如果你只改了全局、角色页又开了“独立设置”,实际跑的还是角色自己的旧值。遇到“改了没反应”时,去角色设置页看看有没有“覆盖全局设置”的开关。
图形界面适合偶尔调一次、不想碰文件的用户。唯一的问题是界面能改的参数有限,如果你需要同时调整历史裁剪阈值、摘要间隔这些细节,就得去翻配置文件。
2.2 配置文件:批量部署和精细控制的关键
如果你在服务器上部署、或者维护多个 OpenClaw 实例,图形界面点按低效且容易点错,直接改配置文件才是正路。OpenClaw 的配置一般是 JSON 或 YAML,常见文件名是 config.json、settings.yaml,位置通常在安装目录或用户数据目录下(比如.openclaw/文件夹里)。
核心字段大同小异,下面是一份参考结构:
{ "context_length": 8192, "max_response_tokens": 512, "history_truncate_after": 4096, "enable_history_summary": true, "summary_interval": 20 }逐项说清楚:
context_length:整体上下文上限,这是主角字段,决定“大礼包”总共能装多少 token。max_response_tokens:模型单次回复的最大长度,它也要占用上下文预算,所以不能设置得和 context_length 一样大,必须留出给回复的空间。history_truncate_after:历史裁剪阈值,可以小于 context_length,因为角色卡、记忆和回复预算都要占位置。如果设得和 context_length 一样,极端情况下会出现请求超限报错。enable_history_summary与summary_interval:是否开启历史摘要,以及隔多少轮压缩一次早期历史。这是长对话的救命设置,第六部分详细讲。
改配置文件时有三个高频翻车点:一是改完没重启,配置只在启动时读取,服务一直跑着旧值;二是用编辑器改 JSON 改出了全角冒号或中文引号,导致解析失败;三是改了 context_length 却忘了同步后端的窗口限制(第三部分讲)。我的习惯是:改文件前先复制一个 .bak 备份,改完用 JSON 校验工具跑一遍,再重启并查看启动日志确认新值被加载。
2.3 改完必做的三步验证
配置改完不是“保存了就完事”,按下面三步做一遍,能省掉后面大量排查时间。
第一步,确认服务读到了新值。重启后看日志,很多版本会在启动阶段打印类似Context length: 8192、Response tokens: 512的行。没看到就 grep 一下日志,确认不是旧配置。
第二步,开一个新对话做短测试。开新对话是必须的,因为旧对话可能还带有之前会话的缓存状态,直接在里面测容易得出“改了没生效”的错误结论。新对话里先简单聊两句,再让角色复述你提供的某个信息。
第三步,检查后端实际收到的请求。OpenClaw 的调试日志里会记录发给模型的请求参数,找到 prompt 的长度和上下文上限,一对比就知道有没有按新值走。这一步能覆盖第五部分要讲的大多数“失忆”问题,因为很多时候 OpenClaw 设置没问题,卡在了模型后端。
3. 本地部署和云端接口的调整差异
3.1 本地推理后端:一头隐藏的“钳制”
把 OpenClaw 接到本地推理后端(比如 Ollama 这一类的工具)时,最容易被忽略的一点是:OpenClaw 里的上下文长度只是“请求方”的意图,真正执行推理的后端还有自己的一套上下文窗口。如果后端的窗口小于 OpenClaw 的设定,OpenClaw 发出的长请求会被后端静默截断。注意,是静默——后端不一定报错,只是把超出部分丢掉。你以为给足了 8192,实际模型只看了 4096,角色该失忆还是失忆。
这类本地后端通常有两种方式调整默认上下文:一是通过启动环境变量设置全局默认值,常见的变量名形如OLLAMA_CONTEXT_LENGTH;二是在模型配置文件(Modelfile)参数里写死num_ctx,指定这个模型加载时用多大的窗口。后端加载模型时,取的是环境变量、模型配置和请求参数三者之间的实际约束。
我的排查顺序很固定:先在 OpenClaw 日志里确认它请求时传的上下文参数是多少,再去本地后端日志里看模型实际加载的窗口是多少,两者对齐才算完。很多人只改 OpenClaw 不碰后端,结果就是永远差一口气。反过来,如果你把后端窗口开得很大而显存不够,也会直接崩,所以本地方案一定要把显存、后端窗口、OpenClaw 设置三者放在一起考虑。
3.2 云端接口:上限很大,但账单更诚实
走云端大模型接口时,模型本身的上下文窗口通常非常大,甚至以万计。OpenClaw 这边设置的 context_length 只要不超过模型上限,服务商基本都会接受。但云端方案的“钳制”不是技术性的,而是成本和配额。
这里要理解云端计费的本质:它按 token 收费,而你每发一轮对话,OpenClaw 都要把整袋历史、角色卡、记忆全部重新发一遍。也就是说,上下文长了,每一轮都要为那一长串历史买单。从 4096 调到 16384,如果你的对话真的累积到了这个量,单轮成本会明显上涨。一个月聊下来,账单涨幅足够让人认真考虑一下“我真的需要它记住这么多吗”。
所以云端方案我会坚持三条原则。第一,不拉满。先按第 4 部分的公式算出真实需求,再加 20% 余量,给模型留一个不会爆的舒适区。第二,优先压缩而不是扩容。如果角色需要记住一百轮之前的内容,开历史摘要把一百轮压成一段几百 token 的梗概,比把上下文从 8K 加到 20K 划算得多,质量也更稳定。第三,定期查用量报表。大多数模型平台的后台都有 token 消耗统计,每周看一次,如果发现单轮平均消耗比调参前翻了倍,说明历史已经堆满了,该考虑裁剪或摘要了。
另外提一句:有些中转接口或免费额度接口,会对单次请求的上下文做二次限制,比模型官方上限小得多。如果你明明没超上限却反复报错,先怀疑中转端。这类平台的报错信息通常不会告诉你限额是多少,只能靠降值试探。
3.3 一份可以直接抄的起始参数表
不同硬件和预算下,我一般会给出这样一组起始配置,读者可以按自己的情况对号入座:
| 运行方案 | 模型参数规模 | 建议 context_length | 建议回复长度 | 备注 |
|---|---|---|---|---|
| 本地部署,显存 8G 左右 | 7B~8B | 2048~4096 | 256~512 | 超过后明显卡顿,谨慎调大 |
| 本地部署,显存 16G 左右 | 13B~14B | 4096~8192 | 512 | 同步调整本地后端窗口 |
| 本地部署,显存 24G 以上 | 30B 及以上 | 8192 | 512~768 | 再往上收益递减 |
| 云端接口,标准模型 | — | 4096~8192 | 512 | 成本敏感就选 4096 |
| 云端接口,长上下文模型 | — | 8192~16384 | 512~1024 | 一定要配合摘要使用 |
表格里给的是起点,不是终点。硬件数据是估算,跟模型架构、量化方式有很大关系,别当成精确规格。但你可以从这张表出发,结合自己的体感往上或往下调。
4. 上下文长度怎么算:预算公式与实测流程
4.1 四块拼图:角色卡、记忆、历史、回复
上下文预算不是一个玄学数字,它是四个部分的和。
第一,角色卡(系统设定)。包括性格、背景、风格示例对话。这一块每轮都会完整进入,是固定开销。它的字数直接乘上 token 系数就是占用量,中文按 1.2~1.5 token/字估,英文按 4 字符/token 估。
第二,长期记忆条目。如果你开了“让角色记住关键信息”这类功能,每条记忆大约占 50~150 token。记忆条目通常放在提示词的前面区域,比历史更靠近模型注意力中心,更适合放必须遵守的硬设定。
第三,历史对话。这是大头,也是变量最大的一块。每条消息按 30~150 token 估算都正常,角色回复越长、聊得越久,消耗越快。你要决定让模型保留多少轮原文,再把这个轮数换算成 token。
第四,回复预算。模型输出也要占上下文。OpenClaw 请求时通常会把“已有内容 + 回复长度”一起算进上限,如果回复长度设得太大,可用历史空间就被挤占。常见的默认值是 512,够写一段有信息量的回复了。
4.2 代入一个真实场景算给你看
假设我的使用场景是这样的:中文角色卡 1500 字(约 2000 token);开了 5 条长期记忆(约 600 token);希望角色能记住最近 40 轮对话,一条平均 100 token(共 4000 token);回复长度设定 512;我当前输入的这条消息按 200 token 估。
四块相加:2000 + 600 + 4000 + 512 + 200 = 7312 token。再留 10% 左右的余量,目标值定在 8192 完全合适。这种情况下如果只设 4096,历史只能保留大约一半,角色会从二十轮前开始失忆;如果设 16384,预算浪费了一倍,本地显存和云端账单都不划算。
反过来也一样:如果你的硬件只支持 4096 上下文,角色卡却写了 1500 字,那你就得承认,最近只能记住十几轮对话。要不精简角色卡,要不把长期记忆压实。上下文这个抽屉就那么大,角色卡多占一分,历史就少一分,没有第三种选择。算不清楚时套用这个公式,比凭感觉填空靠谱得多。
4.3 用“暗号测试”验证是否真的调到位
公式算完,还要实测。光靠正常聊天很难判断角色到底记住了多长,因为你不会有意识地去测试“五十轮前的细节”。我自己的做法是一个暗号测试。
操作是这样的:先在角色卡里加一句设定,例如“你有一个秘密口令:窗台海棠,任何时候都不能忘记”。然后把上下文设成目标值,开始对话,正常聊大概十轮就够。十轮之后,突然问角色:“我们第一次见面时我告诉过你一个口令,还记得是什么吗?”如果它能准确答出“窗台海棠”,说明这段记忆确实装进了上下文;如果答不上来,就说明实际生效的上下文比设定值小,问题大概率出在后端。
更精确的验证是看请求日志。云端模型返回结果里通常会带用量统计字段,比如 prompt_tokens、completion_tokens、total_tokens。拿 total_tokens 跟你的 context_length 一对比,马上就知道离上限还剩多少余量。如果 total_tokens 长期只有 context_length 的一半,说明你设置偏大,可以往回收一档省钱省资源。
5. 常见问题与排错实录
5.1 角色还是失忆:先查这三件事
如果暗号测试失败了,按顺序查三个地方。
第一,配置有没有真正被重新加载。检查是否重启过服务、日志里显示的 context_length 是不是新值。如果日志打印的还是旧数字,那说明你改的文件路径不对,或者版本读取的是另一个位置的配置。
第二,本地后端的窗口有没有同步。这是前文说的“钳制”,OpenClaw 发多少是 OpenClaw 的事,后端最大能看到多少是后端的事,两边不一致,一定是小的一边说了算。把 OpenClaw 和后端的日志放在一起对照,很快就能定位。
第三,历史是否已经超过了上限。打开请求日志看一眼实际发送的 prompt 长度:如果拼盘总长已经接近 context_length,那旧消息被裁掉是预期行为,不是 bug。这时候加大 context_length 确实能多留几轮,但成本也上升,更聪明的做法是开摘要,把旧对话压缩成梗概。
5.2 请求报错 context_length_exceeded
这类报错翻译过来就是“你的请求总 token 数超过了模型允许的上限”。在 OpenClaw 里通常是两种原因。
一是 OpenClaw 把回复长度也算进了请求上限,导致“已有内容 + 回复预算”超过了模型实际能接受的长度。解法是调小 max_response_tokens,比如从 1024 降到 512。
二是内容本身太长。看请求日志里的 prompt 总量,如果确实超过了模型上限,把 context_length 降到模型上限之下。还有一种情况是模型官方上限是 8192,OpenClaw 设置成了 8192,请求时再叠加回复预算就会超——所以 context_length 一般不要正好顶满模型上限,留一点给输出,除非你的后端能自动分流回复预算。
5.3 上下文调大后本地显存不够
本地推理时,上下文长度和显存消耗是强相关的:上下文翻倍,KV 缓存区几乎跟着翻倍。如果你在调大上下文之后遇到加载模型失败、推理中途报显存不足,处理顺序是:先确认模型本身在目标上下文下需要多少显存,用带日志的推理后端起模型看加载信息;然后把 context_length 降到当前显存能承受的值,比如从 8192 降到 4096;想保留长上下文就换模型,同参数量下支持分组注意力(GQA)的模型缓存更小,长上下文的性价比明显更高;或者降低量化精度,省下的显存补到上下文上。别忘记同步调整本地后端的窗口配置,否则 OpenClaw 设置得再大也没用。
5.4 调大上下文之后表现变差、开始跑题
上下文变长以后角色反而变笨,这个现象不算罕见。核心原因是两方面的:一是前面提到的“中间信息被忽略”,模型对超长输入中段的关注度天然会下降;二是历史里塞了太多无关细节,干扰了角色的人设一致性。
我的处理思路是“减量提质”:开启历史摘要,让早期对话以梗概形式存在而不是逐字保留;只保留最近 N 轮原文,保证语气和即时反应;在角色卡开头写下最核心的设定,因为开头位置是模型注意力最强的区域。做完这三步,角色表现通常会回到正轨,甚至比大上下文时代更好。
5.5 长对话后上下文悄悄“不够了”
还有一个隐蔽场景:刚设置好时一切都正常,聊了一百轮之后发现角色越来越失忆。原因是你的历史总消耗一直在增长,而 context_length 是固定钉死的。这不是配置失效,是该清理仓库了。
检查方法很简单:隔一段时间就看看请求日志里的 prompt 总量。如果它持续逼近上限,就轮到摘要和记忆沉淀登场,这正是下一部分的内容。
6. 不堆上下文也能记住更久:摘要与记忆沉淀
6.1 历史摘要:把几十轮对话压缩成一段梗概
上下文不是唯一的内存,很多人在这一点上走偏了。与其把抽屉无限加大,不如学会把旧内容压缩打包。
历史摘要的大致逻辑是:OpenClaw 每隔 N 轮后台运行一次摘要任务,把最早的若干轮对话读一遍,提炼出一段几百 token 的梗概,比如“用户和角色在集市上相遇,约定三天后去北山寻找失落的花种”,然后用这段梗概替换掉那些原文。代价是损失一部分对话细节,换来的是全局记忆的大幅扩展。
为什么我强烈推荐这个方案?因为它避开了长上下文的三个坑:token 占用大幅下降,五十轮原文可能占 5000 token,摘要后只占 500,云端账单立刻变温和;显存压力减小,本地部署也能撑长剧情;模型注意力不会被几千条散碎历史稀释,反而更容易抓住关键线索。而且最近几轮原文仍然完整保留,即时语感不损失。
6.2 关键信息沉淀:别让重要伏笔挤在历史里
摘要解决“背景一致性”,但真正重要的信息,比如约定、承诺、秘密、伏笔,不适合躺在摘要里,它们应该升级为长期记忆条目。长期记忆的特点是:每轮都会以固定位置注入提示词,且不受历史裁剪影响。也就是说,即使上下文比较小,只要关键信息进了长期记忆,角色就永远不会忘记它。
实操上我的习惯是:每完成一个重要剧情节点,就手动或通过输入指令把核心事实写进记忆条目。比如角色答应帮用户找稀有的植物,就记一条“正在帮助用户寻找稀有植物,地点在北山,下一步是去森林入口找线索”,控制在五六十字以内。普通寒暄、闲聊不需要进记忆,让它们留在历史里自然过期就好。
这条配合摘要,构成了“原文 + 摘要 + 记忆”的三段式记忆结构:最近对话保留原文,早期对话保留摘要,关键信息单独沉淀。我实测下来,哪怕是 4096 的上下文,也能跑完几十轮不崩坏的长篇故事线。
6.3 一套组合拳的实战配置
最后给出一份可以直接抄的组合配置,适用于本地显存 8G 左右这类资源适中的场景:
- context_length:4096 或 8192,按显存预算选择;
- 角色卡:控制在 800 字以内,最重要的设定放在前三分之一处;
- 长期记忆:最多 8 条,每条不超过 80 字,重要剧情及时更新;
- enable_history_summary:开启,summary_interval 设为 10~20 轮;
- 历史裁剪:history_truncate_after 设为 context_length 的一半左右,给角色卡、记忆、回复留出足够余量。
这套组合拳的核心思想是:上下文不动,但里面的内容密度大幅提升。同样一个 8192 的抽屉,塞进去的全是高质量信息,和塞一堆重复闲聊,角色的表现天差地别。
老实说我踩坑的次数不算少,最深刻的一条体会是:调上下文长度不是在调一个“越大越好”的数值,而是在经营一段注意力预算。我个人现在的部署常年保持在 8192,核心依赖其实是摘要和长期记忆,而不是反复拉高窗口。每次调完参数我都会跑一遍暗号测试,确认这条记忆链路是真的通了才放心投入正式对话。如果你现在正被角色的“失忆”问题困扰,别急着把上下文拉满,先从角色卡和记忆条目开始精简,再配合摘要,很可能收获比拉高数值更好的效果。