bug: context compaction gate undercounts tool-heavy turns and never fires before the context wall

当 Open WebUI 在单轮对话里连续触发大量工具调用(tool-calling)时,上下文压缩(context compaction)只在每轮开始前检查一次,工具循环中途不再复查,于是请求会在循环内悄悄超过模型上下文上限,最终以 HTTP 400 报错结束。优先排查方向是"压缩触发时机",而不

快速结论:当 Open WebUI 在单轮对话里连续触发大量工具调用(tool-calling)时,上下文压缩(context compaction)只在每轮开始前检查一次,工具循环中途不再复查,于是请求会在循环内悄悄超过模型上下文上限,最终以 HTTP 400 报错结束。优先排查方向是”压缩触发时机”,而不是 token 统计是否算错。

适用环境:Open WebUI rolling :main(Issue 复现时);本地 llama.cpp 后端,--n_ctx 262144;已在 0.11.0 及以上版本确认工具轮次的 token 统计行为有所变化。Issue 未提供 Python / CUDA / 显卡 / 操作系统等具体版本,故不列出。

最快修复方案:暂无确认的一步修复方案。Issue 维护者给出的可用规避手段是把 CHAT_RESPONSE_MAX_TOOL_CALL_ITERATIONS 设置得远低于其默认值 256,从而限制单轮内工具结果堆积的总量。

注意事项:该 Issue 已被关闭并标记为 #27599 的重复项。维护者明确表示原报告中的”测量错误”判断在当前 main 上不成立——工具输出已计入 token 估算,proposed fix 还会造成重复计数。降低工具迭代次数只是缓解手段,会牺牲单轮可执行的工具调用深度;对单个工具结果大小设上限是另一个独立需求,需另行开 Issue。

问题场景

用户在 Open WebUI 中使用带工具调用能力(function calling / tool calling)的对话,配合本地 llama.cpp 后端。某一轮对话中助手连续产生大量工具调用结果,例如一次会话里生成了 34 个 function_call_output 项、合计约 4.6 MB 内容。该轮开始时 token 数仍低于压缩阈值,压缩逻辑没有触发;随着工具循环继续执行,上下文在循环内部膨胀并越过模型窗口上限,下一次模型请求直接返回 HTTP 400。复现环境为 chat.context_compaction.enable=true,threshold=200000,retention=40。

报错原文

bug: context compaction gate undercounts tool-heavy turns and never fires before the context wall
HTTP 400 "request exceeds the available context size (262144)"

原因分析

真正原因是压缩检查的时机问题,而非 token 计量问题。上下文压缩只在一轮对话开始、第一次模型调用之前检查一次,之后工具调用循环运行期间不再复查(对应 Issue #27599)。当一轮起始时上下文低于阈值,随后在工具循环内持续增长并超过模型上下文窗口,就没有任何环节在超限请求发出前拦截它,最终由模型侧返回 HTTP 400。

原报告认为 _exceeds_token_threshold 漏算了 message["output"] 里的工具输出,但维护者在当前 main 上回放后否定了这一判断:工具输出已经包含在 token 估算中,且自 0.11.0 起,工具轮次记录的 usage 会保留该轮最后一次模型调用的 prompt 大小。因此按原报告提议的修复方式反而会重复计算 tool output。统计口径相关的 #27031 是相反方向的失效模式(过度计数、过早压缩),与本问题不同。

环境排查

  • 确认 Open WebUI 版本,Issue 复现时为 rolling :main,维护者指出 0.11.0 起工具轮次的 usage 记录行为已变化。
  • 确认后端模型上下文窗口,复现时 llama.cpp 使用 --n_ctx 262144
  • 确认是否启用了 context compaction,以及 threshold / retention 取值(复现时为 200000 / 40)。
  • 检查 CHAT_RESPONSE_MAX_TOOL_CALL_ITERATIONS 当前取值,默认 256。
  • 观察触发失败的那一轮是否包含大量工具调用结果,以及失败发生在轮次开始还是工具循环中途。

解决步骤

  1. 先确认问题是否发生在工具调用轮次中途超限,而不是轮次开始时就已超阈值——这是区分本问题与 #27031 的关键。
  2. CHAT_RESPONSE_MAX_TOOL_CALL_ITERATIONS 调整为远低于默认值 256 的数值,限制单轮内可堆积的工具调用次数。这是 Issue 中维护者给出的规避方案,属于缓解而非根治。
  3. 对工具输出体积做业务侧控制:减少单次工具返回内容的大小,避免单轮累积出百万级 token。单个工具结果的大小上限目前需要单独提 Issue 请求。
  4. 关注 #27599 的进展,该 Issue 负责”压缩何时运行”的问题,是本次重复关闭的归属项。
  5. 不要按原报告提议修改 _exceeds_token_thresholdget_chat_context_usage 去叠加工具输出,维护者已说明这会导致重复计数。

验证方法

在降低 CHAT_RESPONSE_MAX_TOOL_CALL_ITERATIONS 后,重放同一段工具密集对话,观察是否还会在工具循环中途发出超出上下文窗口的请求并返回 HTTP 400。若不再出现该错误,说明单轮上下文增长已被限制在窗口内。注意这只能验证规避手段有效,并不能验证压缩逻辑本身已修复——根治需等待 #27599。

参考来源

open-webui/open-webui #30268(关闭为 #27599 的重复项)

相关:#27599(context compaction never triggers mid-turn)、#27031(usage token 求和导致过早压缩)、#29872(sub-agent 工具循环不复查压缩)。

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 24669

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注