Repository navigation
Replies: 2 comments
"阈值被输出上限拖下去"这个机制在代码里有对应结构——建议按"预算被两处争用"来写1. 我核到的相关结构(
|
|
Upvoting — we hit this in production and narrowed it to a one-line validator gap, The condition. // index.js:63-64
const headroomTokens = config.headroomTokens ?? 65536;
const maxTokens = config.maxTokens ?? headroomTokens;
// index.js:132-134
const thresholdTokens = Math.floor(Math.min(
contextWindow * thresholdRatio,
(contextWindow - reserved) - headroomTokens,
));and the shrink guard ( So the burn condition is exactly The boundary is worth pinning. Why it is easy to hit. Suggested fix. Derive the cap from the span rather than the absolute value: const maxTokens = Math.min(
config.maxTokens ?? headroomTokens,
Math.floor(shadowedRouteTokenCount * 0.5),
);Or, minimally, fail at construction instead of at the 601 guard: if (maxTokens >= thresholdTokens)
throw new TargetPressureConfigError(
`maxTokens (${maxTokens}) must be below thresholdTokens (${thresholdTokens}): ` +
`a summary capped at or above the span it replaces can never shrink it`);Either turns an unbounded, billed, per-step loop into a single actionable error — Happy to test a patch if that is useful. |
Uh oh!
There was an error while loading. Please reload this page.
Environment: DSH Desktop, client UA
deepseek-harness/0.2.0-rc.2,@deepseek-ai/dsh-compaction-basic0.1.7-rc.2. Local OpenAI-compatible model route:contextWindow: 262000.Symptom. One agent session compacted itself 42 times in 6.63 h (median gap 7.4 min, P10 3.0 min), spending 153 min (38.5% of the window) just generating summaries. Each cycle freed 6.6 K tokens net and re-triggered within 1–3 steps. Every compaction looked like a hang, so the user aborted 11 of 32 turns.
Mechanism (
dsh-compaction-basic/lib/index.js):With
contextWindow = 262000:maxTokens0)128000The route's declared output cap is subtracted from the same budget the compaction threshold is drawn from, so
maxTokens = 49%of the window drags the threshold down to 26% of the window. Post-compaction floor is thenretain 21,440 + system/tool envelope 23,551 + summary output— with measured summary output averaging 12,639, only ≈10.8 K tokens of working band remain, i.e. one step of tool results re-crosses the threshold.Four defects, in order of importance:
reserved ≥ contextWindow(L129) andreserved + headroom ≥ contextWindow(L131), both of which throw with actionable text.reserved + headroom = 193,536 < 262,000passes, and the configuration lands in the band where compaction cannot help. Nothing is logged; the agent just thrashes forever.retainTokensis validated only againstthresholdTokens(L134). There is no check thatthreshold − retaincan actually absorb(system + tool envelope + summary output), and no "compaction made no progress → stop" bail-out. Compare the overflow path, which does havemaxOverflowRetries. Measured: at 17:20:46 the summary wrote 15,473 tokens while removing 13,642 — compaction increased context by 1,831 tokens, and the loop continued.headroomTokensis an absolute 65,536 and doubles as the summarizer's output cap. On any window ≤ 200 K it unilaterally claims ≥ 25–33% of capacity, and it is the very quantity that pushesthresholddown. A capacity-relative default (e.g.min(65536, 0.1 * contextWindow)) would not create the trap.Reproducer (deterministic, no local GPU required). Register an adapter model with
contextWindow: 262000anddefaultMaxTokens: 128000; composecompaction-basicwith defaults; drive a session from ~55 K to ~70 K estimated tokens with ordinary tool results. Expected (and observed):compaction/startat essentially every step boundary,retainTokens = 21440,thresholdTokens = 68464, andsummary.outputTokens ≥ shadowedTokenCountwithin ~10 cycles. WithmaxTokensunset or ≤ 16,384 the same session compacts ~once per 130 turns and never re-fires.Suggested fix.
(a) At spec-resolution time, verify
thresholdTokens − retainTokens > envelopeTokens + expectedSummaryTokens(usepolicy.maxTokensas the worst case) and, if it fails, throw/warn with the same actionable wording as L131 ("reduce the effective request maxTokens or compaction headroomTokens, or configure a larger contextWindow").(b) Track net reduction per session and stop auto-compacting when consecutive attempts do not reduce pressure (mirroring
maxOverflowRetries).(c) Cap summary output by the available band rather than by
headroomTokens.All reactions