• Stefy Lanza (nextime / spora )'s avatar
    lora: a trained text adapter can reach a pod, and be picked per request (v0.3.36) · 3a46f9a8
    Stefy Lanza (nextime / spora ) authored
    A QLoRA trained for a client sat on disk for ten days while a second service
    rented its own A40 every morning, pushed the adapter over SSH and proxied to it.
    The path that should have carried it was written but had never been run end to
    end, and five things were in the way.
    
    * `ensure_text_loras` DROPPED a PEFT directory — "publish it to HuggingFace" —
      which is the shape every trainer writes. It now travels as one deterministic
      tar (sorted names, fixed uid/gid/mtime, so the content id is stable) and is
      unpacked by the blob store, because vLLM loads an adapter from a directory:
      adapter_config.json carries the rank and target modules, and a bare
      .safetensors is not loadable.
    
    * the adapter was re-read and re-hashed ON EVERY REQUEST. A Target is rebuilt per
      request, so `lora_entry` was set again each time; the bytes were never re-sent
      (the store is content-addressed) but 159 MB was read and hashed, and the pod
      asked, only to learn it already had it. Cached per (pod, path, size+mtime), so
      a retrained adapter at the same path is still sent again.
    
    * `_lora_args` passed a CONTENT ID straight through, producing
      `--lora-modules name=sha256:…`, which vLLM cannot open. On a pod that is the
      only form the adapter has.
    
    * an engine launched for a base model carried none of its adapters. vLLM
      registers them at launch and one vLLM serves one base, so the pod a shared pool
      rented for the base alone could never serve an adapter of it — the whole point
      of sharing the pool. Every model naming the same base now contributes its
      adapter under its own model id, which is the name requests ask for, so two
      versions can be A/B'd on one GPU with no reload.
    
    * `--max-loras` was never set. At its default of 1, requests naming different
      adapters cannot share a batch and serialise instead: the cost lands on latency,
      not on an error.
    
    Extracting a bundle is a write from network bytes, so member names are checked
    for escapes before anything is unpacked, and tar's data filter is used as well.
    Co-Authored-By: 's avatarClaude Opus 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01PxYHWbCAjjjD7A1rhFKtaW
    3a46f9a8
loras.py 131 KB