• Stefy Lanza (nextime / spora )'s avatar
    ocr: resumption must respect the context window, and never extend a loop (v0.3.50) · 548c3ea1
    Stefy Lanza (nextime / spora ) authored
    Two defects that a throughput collapse on a live install made visible. With
    surya_max_tokens raised to 12288, 262 resumption segments spent 1.6M generated
    tokens in 80 minutes, 122 of them running the full cap dry, while 253 of those
    262 ended in "came back repeating itself".
    
    Resumption re-sends the text so far as INPUT, so the model's context window --
    not the continuation budget -- is the real ceiling. The budget did not know
    that: at a 12288-token cap, the third segment of a page asked for 12288 more on
    top of ~28,500 already in a 32,768-token window and was rejected outright. The
    page was then reported as one that could not be resumed AT ALL, discarding text
    already paid for.
    
      - surya_context_tokens, or 0 to read the server's own max_model_len from
        /v1/models. Configuration wins: an operator may serve a shorter window than
        the checkpoint advertises.
      - Each segment asks for the smaller of the cap and the room left, measured
        from what the server said the prompt cost (usage.prompt_tokens), not
        guessed; the guess covers the first resumption only.
      - Out of room stops, KEEPS what it has, and says so -- naming the fix that
        helps, which is a SMALLER max_tokens, not a bigger budget.
      - A refusal for length is not retried: the fallback resumption adds a user
        turn, so it is longer than the request just refused.
      - Not knowing the window changes nothing and guesses nothing.
    
    The second defect: a reply that trips surya's repeat detector hit the cap
    because it is LOOPING, not because the page is long. Resuming it can only
    extend the loop, and surya re-runs the whole page anyway -- so one page on that
    path cost four full generations. It is no longer resumed, and it is not marked
    truncated either: that is surya's retry to make, and "truncated" would send the
    caller looking for a bigger budget it cannot use.
    
    A fixed token cap is also an accidental repetition circuit-breaker, which is
    why raising it slowed the LOOPING pages by the ratio of the caps rather than
    every page. Documented in docs/ocr.md with the window arithmetic (2048 -> ~13
    segments, 12288 -> 2).
    
    Tests: 8 new (window clamp, stop-one-segment-early, length refusal not
    retried, unknown window, configuration over server, a cap below the 256-token
    floor is never mistaken for a full window, a looping reply is not resumed, a
    genuinely long page still is). 62 pass in the surya/blank-page suites; the
    floor-versus-cap bug was caught by the existing 44.
    Co-Authored-By: 's avatarClaude Opus 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01PxYHWbCAjjjD7A1rhFKtaW
    548c3ea1
routes.py 260 KB