• Stefy Lanza (nextime / spora )'s avatar
    longcat: VRAM accounting, a draining releaser, and video in the front queue (v0.2.32) · 409880f3
    Stefy Lanza (nextime / spora ) authored
    Step 3: make LongCat a citizen of the memory and swap machinery rather than a model that
    merely runs. Three gaps had to close.
    
    1. THE ESTIMATE. _get_model_used_vram_gb had no branch for a `longcat:` key, so it fell
       through to scanning the checkpoint — ~83 GB across variants, which would have asked
       the manager to evict the whole box on every request. Added beside the ds4/colibri/vllm
       early returns: measured if known, else the starting estimate.
    
    2. THE MEASUREMENT. No official VRAM figure exists for LongCat and the real peak moves
       with the variant, the stage and the offload mode, so the constant is a starting point
       and the service reports what it actually reached. It has to come from inside the
       worker: the pipeline loads lazily on the first request, so a host-side free-VRAM delta
       would also be counting whatever else was loading on the card. torch's
       max_memory_reserved is this process's own arenas — what the card genuinely cannot give
       to anything else. The HIGH-WATER mark is kept, because a draft run touches far less
       than a 720p refinement and reserving the smaller figure would under-evict later, and
       it is keyed per config_id/variant so an fp8 sibling cannot inherit a bf16 measurement.
    
    3. GIVING THE CARD BACK. register_external_vram_releaser with the documented
       fn(needed_gb) -> float contract (not voice_clone's zero-argument one, which raises
       TypeError inside eviction and is therefore never reclaimed). The drain matters more
       here than anywhere: acquire_stt_backend POPS the model pool, so _is_key_busy is
       permanently False for this model and Pass 1 of release_idle_vram would tear the
       subprocess down mid-generation and lose a multi-minute request. The releaser waits for
       in-flight work, bounded by longcat.evict_drain_timeout_s (300 s).
    
    Also: video can now take a slot in the front per-model queue. Every acquire site was
    guarded by `_task_kind(path) == "text"`, so max_instances on a video model did nothing at
    the front and nothing bounded concurrent generations but the engine and the swap gate.
    _queues_at_front() enables it for video when — and only when — the operator has set
    max_instances: doing it unconditionally would change behaviour for every existing video
    model and start returning 503 at queue_max_size, which is not something to impose on
    deployments that never asked. Applied at all four sites (direct, keepalive, both
    brokered), and the `is_text` local it replaced was left dead, so it is gone.
    
    21 tests, including the one that matters most: an eviction arriving mid-generation waits
    and the request still completes.
    Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_0182DhR1eFNPQyGmDrpHbedY
    409880f3
app.py 162 KB