multi-agent-lab / docs /adr /0014-modal-model-serving.md
agharsallah
feat: unify model catalogue and self-hosted routing
9dd6dab
|
Raw
History Blame Contribute Delete
2.95 kB
# ADR-0014: Serve Small Models on Modal, One App Per Provider
## Status
Accepted. **Amended by [ADR-0019](0019-single-model-catalogue-no-cloud-path.md):**
the model catalogue moved to the stdlib-only `modal/catalogue.py` (single source of
truth, shared with the engine); `registry.py` is now a back-compat re-export, and
the engine binds endpoints from the catalogue + `MODAL_WORKSPACE` rather than
`OPENAI_BASE_URL`.
## Context
The engine routes agent roles to small models through an OpenAI-compatible
interface, but until now there was no hosted backend behind it — only the local
deterministic stub. We need real small models (all under the 32B cap, with a
≤4B Tiny Titan tier) served as APIs the engine can call, without coupling the
engine to any single inference vendor.
We want the serving layer to be scalable (autoscaling, pay-per-use), extensible
(adding a model or provider should be trivial), and configurable per task (GPU,
context length, concurrency, tool/reasoning parsers, multimodal limits).
## Decision
Add a `modal/` folder that serves models on Modal as serverless,
OpenAI-compatible endpoints (vLLM behind an autoscaling web server).
- **One Modal app per provider** (`nvidia-llms`, `openbmb-llms`, `google-llms`).
Providers deploy, scale, and fail independently.
- **One reusable serving path** in `service.py` (`ModelConfig` + `register_model`)
shared by every app, so the vLLM/Modal best practices are written once.
- **Configuration is data** in `registry.py`: a model is one `ModelConfig`; a
provider is one app file. This mirrors the project's "config, not code"
invariant (ADR-0011).
- Weights and the vLLM compile cache live in **shared Volumes**, so a model
pulled once is warm across every provider app.
## Consequences
- The engine talks to any endpoint via the OpenAI SDK by setting
`OPENAI_BASE_URL`; model roles (`MODEL_TINY/FAST/BALANCED/STRONG`) map to the
endpoint whose size fits the role.
- Vendor isolation: a provider can be added, retuned, or removed without
touching the others or the engine.
- Gated repos (Gemma, the Nemotron repos used here) require a Hugging Face token
in the `huggingface-secret` Modal Secret; ungated models deploy without it.
- Endpoints are public by default; bearer-token auth is opt-in at deploy time
(`MODAL_LLM_REQUIRE_AUTH=1`) and supplied via the `llm-api-key` Secret as the
`VLLM_API_KEY` env var — secrets are never hard-coded.
- The API is OpenAI-compatible: each endpoint self-documents at `/docs` and
`/openapi.json`, and a checked-in `modal/openapi.yaml` (3.1) plus
`modal/docs/openapi.md` document the shared surface.
- vLLM tool/reasoning parser names are version-specific and left conservative;
enable per model once verified against the deployed vLLM version.
- Modal's docs index is mirrored at `modal/docs/modal-llms.txt` and refreshed
when the pinned vLLM/Modal versions change (ADR-0004, document-as-we-build).