ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

OpenHands 对话被 LLM 拒收?上下文窗口压缩完整指南

OpenHands 对话被 LLM 拒收?上下文窗口压缩完整指南 OpenHands 对话被 LLM 拒收上下文窗口压缩完整指南【免费下载链接】OpenHands OpenHands: AI-Driven Development项目地址: https://gitcode.com/GitHub_Trending/ope/OpenHandsOpenHands是一个 AI 驱动的编程助手项目它能替你跑终端、改代码、查文件。但很多人和它聊到一半会突然收到一条来自 LLM 的报错任务戛然而止。这篇文章带你从一条真实报错出发搞懂 OpenHands 是如何管理模型上下文窗口的以及你自己可以动手调哪些参数让长对话不再中途崩掉。一次卡壳的现场先看看你会撞上的东西。连续让 Agent 分析几个大文件、再追问了几轮之后回复框里弹出一句input length and max_tokens exceed context limit再往下翻会话日志可能还会看到另一条Conversation history longer than LLM context window limit翻译成人话你和它积累的所有对话 它准备生成的回复加起来已经塞不进模型的工作记忆了。任务没做完会话直接废掉这就是上下文超限context limit最典型的翻车现场。为什么会撞墙一个类比说清楚把上下文窗口想象成 Agent 的工作记忆白板每轮你说的话、它的回答、读过的代码都要抄写在上面模型每次思考前得把整块白板重新读一遍。白板面积是固定的不同模型不同Claude 3.7 这类模型有明确的 token 上限一旦抄写内容超过板面模型就只能拒绝开工。关键点在于白板只增不减——你不手动清它不会自己擦。所以长对话必然逼近上限除非项目帮你自动擦旧留新。OpenHands 做的正是这件事。开箱即用它默认就带了一套兜底好消息是你什么都不改也能跑OpenHands 默认内置了对话历史压缩能力业内一般叫condenser压缩器。它的思路很朴素——白板写满之前自动把早期轮次的内容压缩成摘要把最新几轮完整保留下来这样模型读到的上下文长度始终可控。这套默认行为在前后端都有体现默认设置里压缩是开启的并带一个默认保留上限condenser: { enabled: true, max_size: 240, // 压缩时保留的对话轮次上限 }这段默认值定义在 src/services/settings.ts 中。会话界面里有一条上下文水位线实时显示当前已用 token / 模型窗口大小。水位超过70%变黄、超过90%变红变红时界面上会浮现压缩一下的入口一键手动触发 condenser。这套阈值逻辑在 src/components/features/conversation/usage-panel/context-meter.tsx。手动压缩走的是同一个服务点击压缩后前端调用 use-compact-context-action.ts 里的动作把当前历史交给 condenser 摘要压缩完水位线肉眼可见地回落。换句话说默认状态下OpenHands 已经替你接住了大部分上下文超限场景你只需要知道它在哪、什么时候该看它一眼。手把手配置改哪几个参数想按自己的节奏调只需要动两三个字段全部写进设置里的agent_settings段Web 端在 Settings → Condenser 页面源码入口是 src/routes/condenser-settings.tsx配置文件对应config.template.toml的[agent]段参数作用建议enable_history_truncation超限后是否自动修剪历史而不是直接抛错终止保持truecondenser.enabled是否启用压缩器长对话场景保持truecondenser.max_size压缩后保留多少轮原始对话默认 240窗口小的模型调低最小可运行示例TOML[agent] enable_history_truncation true condenser NoOpCondenserConfig # 默认压缩器 [agent.condenser] enabled true max_size 240改完重启会话即可生效。如果你用 OpenRouter 这类聚合渠道某些模型不上报窗口大小界面上只会显示裸 token 数而没有百分比——这是已知现象不影响压缩本身只是水位线显示退化为纯数字。进阶写一个自己的压缩器默认的压缩策略是保最近、缩历史但如果你有特殊需求——比如希望代码块优先保留原文、只压缩闲聊——OpenHands 允许你挂自定义 condenser。接口很简单继承抽象基类实现一个compress方法接收历史、返回压缩后的历史。from openhands.memory.condenser.abstract_condenser import AbstractCondenser class CodeFirstCondenser(AbstractCondenser): def compress(self, history): # 自己定义规则代码片段原样保留自然语言摘要 return self._keep_code_compress_chat(history)然后把配置里的condenser指向这个类名即可。压缩器的扩展点集中在 openhands/memory/condenser/ 目录写之前先翻一遍abstract_condenser.py里的接口约定。怎么确认优化生效看这几个指标调完参数别凭感觉盯三个数就够了水位线颜色压缩前后上下文 meter 的百分比应明显回落如果压缩后还在 90% 红线附近说明max_size太大往下调。压缩触发频率长任务里如果压缩事件Condensation event几轮就来一次说明窗口被大文件读取得太满优先考虑拆任务而不是继续压低max_size。任务完成度压缩是为了让对话活下来代价是早期细节被摘要化。观察 Agent 是否还记得任务早期的约定如果失忆明显把max_size调高一些在不崩和不忘之间找平衡。整个检测—压缩—恢复的过程可以画成一条状态流对应的调优阈值就两个70% 的黄线提示你该手动压一下了90% 的红线是再不管就要崩了。避坑 FAQ问报错说超 4096 限制但我明明用的是大窗口模型答那个 4096 是max_tokens单次回复预留和输入加起来超了某个小窗口的老错误。先确认模型配置里挂的到底是哪个模型聚合渠道有时会静默回退到小模型。问我把自动修剪关了为什么还是被压缩答enable_history_truncation管的是超限后的应急修剪而 condenser 是提前预防两者独立。想要完全不被动压缩得把condenser.enabled也关掉——但长对话下不推荐。问压缩之后 Agent 忘了之前说的话算 bug 吗答不算这是摘要化的固有代价。关键事实文件路径、约束条件建议用明确的句子重复说一次它们更容易在摘要里存活。问手动点压缩和自动压缩有什么区别答走的是同一条服务链路区别只是触发时机——自动压缩由水位触发手动压缩由你在界面红区时主动发起。手动的好处是你可以选在一个任务阶段结束时压摘要边界更干净。问窗口大小显示为空或 0 怎么办答部分聚合渠道不返回窗口大小meter 会退化为只显示裸 token 数。这不是故障压缩逻辑照常工作只是百分比无法计算。一句话收尾如果你正在用 OpenHands 跑代码生成、文档分析这类需要长上下文的任务记住一件事默认开启压缩器 盯着 70%/90% 两条水位线就足以扛住绝大多数上下文超限场景接下来项目还会把压缩从被动擦白板走向预判趋势提前整理让长对话的连续性再上一个台阶。【免费下载链接】OpenHands OpenHands: AI-Driven Development项目地址: https://gitcode.com/GitHub_Trending/ope/OpenHands创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表