Baseten Inference Stack
How we went from "the LLM engine does everything" to a disaggregated encoder with hierarchical response caching. Click the scenarios in each diagram.
Background
MoonViT + mm_proj turn pixels into a tensor of LLM-space embeddings. That's the whole interface — which is what makes everything after this slide possible.
mm_hash identifies content, not URLs
video = same path, chunked frames
Why this matters. The vision tower's only contract with the LLM is "hand me N embeddings and where to put them." Anything with that contract can run anywhere — and anything content-addressed can be cached.
Stage 1
Vision tower, prefill, and decode share one process and one set of GPUs. The engine's native multimodal path (engine_native_passthrough) fetches raw URLs and encodes in the same loop that generates tokens.
The problem. The vision tower is compute-bound and saturates whatever GPU it lands on — so every image steals SM time from token generation, and the encoder can only scale by scaling the whole B200×8 engine with it.
Stage 2
The vision tower + mm_proj move into their own service, multimodal-encoder, on small cheap GPUs. The frontend calls it once per media item and splices the returned embeddings into the token stream; the LLM engine never sees a pixel.
{mm_hash, mm_kwargs: mm_embeds · grid_thws · length}
HTTP or Dynamo RPC transport
E and P/D scale independently
validation + SSRF checks off the hot path
What we bought. Encode capacity is now a knob: a fleet of single-GPU encoders in front of the big engines, each loading only the vision + embedding shards. mm_hash flows with the tokens into KV-aware routing, so repeated images also land on workers that already hold their KV blocks.
Stage 3
Encoding is deterministic and responses are big (~50 MB for a 4K image) — ideal cache material. response-cache-nginx (OpenResty + Lua) is a transparent response cache deployed at two levels: one in the cluster where the model runs, one shared next to the encoder.
proxy_cache_lock coalesces identical concurrent encodes
entries valid 24 h, only 200s cached
The full hierarchy a repeated image can hit before any GPU work:
Under the hood. Each cache level can scale out: a stateless router consistent-hashes the key over sticky tmpfs shards, so a 50 MB entry lives on exactly one shard, the same key always lands there, and adding a replica only remaps ~1/n of keys.
End state. One deterministic function (pixels → embeddings), pulled out of the engine, put behind content-addressed caches. The engine decodes tokens; the encoder fleet encodes; nginx makes sure each unique image is encoded roughly once.