Skip to content

mergeRangesToThreshold 输出低于 gate 阈值的尾部批次,破坏「列出即可压缩」不变量 #309

Description

@ranxianglei

来源: ranxianglei/billion-context#847 (ranxianglei/billion-context#847) 分析 持续压缩失败、模型反复提交同一被拒范围 时发现

现象

billion-context #847:模型连续 7 次提交同一范围,每次都被 gate 拒绝(Total compressible content too small (1734 chars across 1 range(s), min 5000)),而 nudge/acp_status 全程把该范围列为可压缩(pendingT1 ≈ 40K 一直存在)。最终 usage 76%→89%,上游流截断。

根因

mergeRangesToThreshold(0.0.74 dist/index.js:2129-2145):把相邻 range 合并到 batchChars >= minChars 为止,但循环结束时无条件 push 尾部残余批次,即使其 batchChars < minChars:

if (batch.length > 0) result.push(mergeBatch(batch));

因此 nudge 的 "Compressible ranges" 列表(recommendNoderecommendedRanges,dist/index.js:~2505-2540,注入点 :3083)会包含压不动的范围。不变量「凡被列为可压缩的范围都一定压得动」被破坏。

加剧因素:viableRanges(chunk-QPVKTDYF.js:387-390)的门槛是 VIABLE_RANGE_MIN_TOKENS = 200 tokens(≈800 chars),与 gate 的 compress.minCompressRange(默认 5e3,chars)单位和数值都不一致——两个门槛、两种单位,消费方无法只靠一个过滤就对齐 gate。

影响

  • 模型按列表选范围 → 必然被拒 → 失败调用+错误留在上下文尾部 → 模型模仿重试 → 死循环(#847 实测 7 次/13 分钟)。
  • 所有依赖 recommendedRanges 的消费方(nudge、acp_status、preflight 式自动压缩)都被误导。

建议修复

  1. 尾部批次若 < minChars:并入前一个批次(允许超阈值),或不输出。
  2. 统一门槛:让 viableRanges 与 gate 共用同一阈值与单位(chars),或废弃双门槛之一。
  3. 加一条回归测试:recommendedRanges 输出的每个 range 必须满足 gate 的 chars 下限(当前默认配置下必挂)。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions