Skip to content

长会话上下文超限时自动压缩未触发,请求发送远超活跃 token 数,持续 HTTP 400 #269

Description

@scuer-ls

现象描述

在长会话中持续工作(多轮文件修改)后,模型请求开始持续失败,报错:

Request failed: HTTP 400: This model's maximum context length is 1048576 tokens.
However, you requested 4979364 tokens (4979364 in the messages, 0 in the completion).
Please reduce the length of the messages or completion.

关键矛盾

  • 会话索引(sessions-index.json)中记录的该会话 activeTokens 约为 524,396(未超过模型上限)
  • 但实际发出的请求消息量达到 4,979,364 tokens(约为 activeTokens 的 9.5 倍)
  • 说明请求构造时把全部历史消息(含未压缩部分)都发送给了 API,而自动压缩没有生效

复现路径

  1. 在长会话中进行大量文件读取/修改(会话消息文件约 9.6MB)
  2. 上下文持续累积,接近模型上限(1,048,576)
  3. 模型请求开始返回 HTTP 400 上下文超限
  4. 此后每次重试均失败,自动压缩(compaction)似乎从未触发

预期行为

根据会话持久化文档,上下文过长时应触发压缩流程:

  • 将较早消息生成摘要并标记 compacted: true
  • 后续请求只发送未压缩消息 + 摘要

预期是压缩后请求应能恢复成功,而不是持续 400。

实际行为

  • 压缩未触发(或触发了但请求本身失败)
  • 请求携带全部历史,token 数远超活跃上下文统计值,持续 400
  • 用户只能通过开启新会话来规避,原会话无法继续

疑似根因

  1. 压缩流程依赖模型请求:生成摘要本身需要调用模型 API;若上下文已超限,压缩请求同样会 400,形成死循环。
  2. 请求构造未做兜底:发送前未检查消息总 token 是否超过模型上限,也未强制截断/压缩。
  3. activeTokens 统计与请求实际 token 数存在数量级差异,统计口径可能漏掉了部分历史。

建议修复

  1. 请求构造前校验总 token 数,超过上限时强制触发压缩(优先于发送请求)
  2. 压缩摘要生成失败时提供降级策略(例如直接丢弃最早 N 条消息,或仅保留最近 M 条)
  3. 压缩流程不应依赖"上下文未超限"这一前提,避免死循环

复现环境

  • Deep Code CLI(npm 全局安装,最新版)
  • 模型:deepseek-v4-flash(OpenAI 兼容接口)
  • 会话消息文件大小:约 9.6MB(85 条用户消息 / 355 条 assistant / 310 条 tool)
  • 本地已存在 7 个 failed 状态会话,其中 1 个为上下文超限所致(activeTokens 524,396),其余 6 个 activeTokens <
    30,000(可能为其他原因)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions