Files

100 lines
3.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Model specifications for sgl-router e2e tests.
Adapted from SMG's e2e_test/infra/model_specs.py. The same dict-of-dicts
shape (so test code reads the same) but the entries are narrower —
sgl-router tests today target small/medium models only; the larger
function-calling / reasoning models from SMG are out of scope.
Each entry:
- model: HuggingFace path or local path (env-resolved)
- memory_gb: estimated single-GPU footprint
- tp: tensor-parallel size (= GPUs needed)
- features: feature tags for filtering
- worker_args: optional extra `sglang.launch_server` flags
"""
from __future__ import annotations
import os
# Local-cache root for CI / cluster nodes that pre-download HF weights.
# Mirrors the SMG `ROUTER_LOCAL_MODEL_PATH` env var.
ROUTER_LOCAL_MODEL_PATH = os.environ.get("ROUTER_LOCAL_MODEL_PATH", "")
def _resolve_model_path(hf_path: str) -> str:
"""Prefer a local copy of the model when one exists under
``ROUTER_LOCAL_MODEL_PATH``; otherwise fall back to the HuggingFace ID.
"""
if ROUTER_LOCAL_MODEL_PATH:
local_path = os.path.join(ROUTER_LOCAL_MODEL_PATH, hf_path)
if os.path.exists(local_path):
return local_path
return hf_path
# Every worker in this suite exists to answer a handful of 8–1024-token router
# assertions, so the engine's serving defaults are actively wrong here. At
# ``--mem-fraction-static 0.83`` the KV pool claims whatever the card has minus
# a slack of ``free_memory_at_dist_init * (1 - mem_fraction_static)`` — on an
# idle 80 GB H100 that is ~60 GB of KV (556K tokens for a 0.6B model) against
# ~13 GB of slack, and the activation working set for the default
# ``chunked_prefill_size=8192`` already accounts for nearly all of it. The
# prefill CUDA graph then has nothing left to capture its 58 num-token buckets
# into, dies part-way through with ``CUDA error: out of memory`` inside
# ``graph.capture_end()``, and the worker exits during startup — surfacing as a
# router e2e failure that has nothing to do with the router. Bounding the pool
# and skipping the prefill graph removes the whole class; it also cuts the
# per-spawn capture time, which this suite pays once per test.
CI_WORKER_ARGS: list[str] = [
"--mem-fraction-static=0.6",
"--cuda-graph-backend-prefill=disabled",
]
MODEL_SPECS: dict[str, dict] = {
# Fast-start tiny model for convergence / decode-affinity / stale-request
# tests. Single GPU, ~2 GB weights, sub-30s start on a warm cache.
"qwen3-0.6b": {
"model": _resolve_model_path("Qwen/Qwen3-0.6B"),
"memory_gb": 4,
"tp": 1,
"features": ["chat", "streaming"],
"worker_args": CI_WORKER_ARGS,
},
# Standard small chat model — matches SMG's `llama-1b` entry.
"llama-1b": {
"model": _resolve_model_path("meta-llama/Llama-3.2-1B-Instruct"),
"memory_gb": 4,
"tp": 1,
"features": ["chat", "streaming"],
"worker_args": CI_WORKER_ARGS,
},
# Primary 8B chat model — matches SMG's `llama-8b`.
"llama-8b": {
"model": _resolve_model_path("meta-llama/Llama-3.1-8B-Instruct"),
"memory_gb": 16,
"tp": 1,
"features": ["chat", "streaming"],
"worker_args": CI_WORKER_ARGS,
},
}
def get_model_spec(model_id: str) -> dict:
"""Return the spec dict for ``model_id``; KeyError if absent."""
if model_id not in MODEL_SPECS:
raise KeyError(
f"Unknown model: {model_id}. Available: {list(MODEL_SPECS.keys())}"
)
return MODEL_SPECS[model_id]
def get_models_with_feature(feature: str) -> list[str]:
"""Filter model IDs by feature tag (e.g. ``streaming``, ``chat``)."""
return [
model_id
for model_id, spec in MODEL_SPECS.items()
if feature in spec.get("features", [])
]