Degenerate repetition at tool-call decision points in long agentic contexts (portable reproducer; 3 serving stacks incl. Ollama cloud 6/6)

#58
by rasatpetabit - opened

In long, tool-heavy agentic conversations, Flash-0731 probabilistically fails at the point a tool call should be emitted: it produces a short action-announcement ("Run.", "Let me run it.") and repeats it until aborted or token-capped.

We hit this in production (onsets observed from 92k to 350k context) and carried it to what we believe is checkpoint-level proof: one fixed, fully sanitized ~240k-token conversation reproduces the collapse on three serving stacks that share no code or hardware:

Serving stack Trials Strict loops
Ollama cloud, deepseek-v4-flash:0731-cloud 6 6/6 (61-97x "Run.", all capped)
Alibaba DashScope intl, deepseek-v4-flash 6 2/6 (remaining 4 emitted 6-19x "Run." before the call)
Community SM80 vLLM (8x A100) 6 4/6

Reproducer payload + one-file classifier: https://gist.github.com/rasatpetabit/64ea43e9795bdb8844ba590155ae9f87

Sampling: temperature 1.0, top_p 0.95, no penalties, tool_choice=auto. Ruled out on our stack: speculative decoding (loops with DSpark removed), chat template (loops when encoded with the reference encoding_dsv4.py as a raw completion), prefix-cache state, seeds. Gross retrieval stays intact while it fails (24/24 planted-fact recall at 351k depth) - the failure is specific to the emit-a-tool-call decision. Related: ggml-org/llama.cpp#26694 (Flash GGUF/Metal), QwenLM/qwen-code#4695 (V4-Pro on DashScope, with a dose-response showing in-context self-reinforcement: >=20 prior repeat-examples -> 87% failure, 0-10 -> 0/12).

One research clue: synthetic conversations matching the failing payload's shape (depth, 51 tools, structure, priming) produced 0/22 loops - the attractor appears to require realistic content statistics.

Interim mitigations that help operators: frequency_penalty >= 0.1 suppresses verbatim loops (but collapses can re-emerge with per-line lexical variation); serving-side repetition detection with resample-on-detect; stripping loop text from resubmitted history. Full report with receipts sent to service@deepseek.com on 2026-08-14 - happy to share everything privately. Contact: ras@petabitscale.com

Independent confirmation on a self-hosted vLLM 0.25.2 deployment (2x DGX Spark GB10, TP=2, 1M ctx): reproduced at 245-257k-token depth at temperature 1.0 / top_p 1.0, so this is not a greedy-decoding artifact.

Two observations that may help others hitting this:

  1. In tool-calling agents the loops fragment. The model emits 1-8k chars of cycled action-sentences ("Let me do it. Let me run it. Emitting now."), a tool call interrupts, then the next completion loops again. Each fragment is small, so output-length-based loop detection misses it entirely - while the replayed transcript still accumulates every instance. Sessions degraded from brief stutters to 40-minute turns as history contamination grew, consistent with the in-context snowball described here.

  2. The "strip loop text from resubmitted history" mitigation works, measured. We implemented it as a gateway-side pre-call scrub (collapse consecutive and short-cycle duplicate sentences within assistant messages of the submitted history only; user/tool messages untouched; one copy of each sentence survives), plus frequency_penalty=0.1 applied only when scrubbing actually removed text. On live sessions this removed 1-8k chars per request and broke the escalation without restarting the session. Detection tip for the fragmented shape: flag when any <=80-char normalized sentence repeats >=8 times and repeats are >=40% of the text's sentences.

Hope the report reaches the training side - happy to share more traces if useful.

I've been seeing this, too. Still present in DeepSeek V4.1 Flash through the API (OpenRouter → DeepSeek BYOK)

Sign up or log in to comment