Playbook 2 – Turning Spark Arena Models into a Unified Multi‑Mode Assistant with LiteLLM + Open WebUI
Since my original post, things have evolved a lot. Spark Arena and the GB10 community have gone from “here are some cool models” to a full recipe + leaderboard ecosystem that makes it trivial to stand up Nemotron‑3‑Nano NVFP4, GLM‑4.7‑Flash‑AWQ, Qwen3‑Coder‑Next‑FP8, Qwen‑Instruct‑80B and more on a single or dual DGX Spark. The net effect is a quantum leap in developer velocity: instead of burning hours on flags and container wiring, we can treat these as reliable building blocks and focus on UX, routing, and product behavior.
Huge thanks to Raphael Amorim (@raphael.amorim), @eugr, and everyone working on spark‑vllm‑docker, llama‑benchy, and Spark Arena itself — Playbook 2 is entirely about what you can build on top of their work, not yet another way to launch a model.
What follows is how, on a single Spark (usually one primary Spark Arena model up at a time), you can use LiteLLM + Open WebUI to turn that into a clean, multi‑mode assistant stack with natural model names like NeMo Expert, GLM Expert, Qwen Coder Fast, Phi Fast, Grok-4, etc. LiteLLM resolves everything; Open WebUI just shows these names in the dropdown.
1. Architecture: Open WebUI → LiteLLM → Spark Arena + hosted
The architecture is intentionally simple:
-
Open WebUI
-
Talks only to LiteLLM via an OpenAI‑compatible endpoint.
-
In
start_core_services.yml:environment: OPENAI_API_BASE_URL: http://litellm:4000/v1 OPENAI_API_KEY: simple-api-key
-
-
LiteLLM proxy/router
-
Runs as a small service next to Open WebUI:
services: litellm: image: ghcr.io/berriai/litellm:main-latest container_name: litellm restart: always command: --config /app/config.yaml --num-workers 4 ports: - "4000:4000" volumes: - ./litellm_config.yaml:/app/config.yaml:ro env_file: - /home/mark/vllm/model-configs/env.env networks: [llm-net] -
Reads a single
litellm_config.yamlthat defines all local and hosted models plus routing rules.
-
-
Spark Arena vLLM backends + hosted APIs
- One primary big chat model via Spark Arena (Nemotron‑3‑Nano or GLM‑4.7 or Qwen‑Instruct) at a time, plus Qwen‑Coder and a small router like Phi‑4‑mini.
- Hosted backups: Grok‑3/4, Qwen‑Max/Qwen3 cloud, GLM‑4.7 cloud, NVIDIA Llama‑3‑70B, etc.
Open WebUI only sees model names from LiteLLM – e.g., NeMo Expert, GLM Expert, Qwen Coder Fast, Phi Fast, Grok-4 – and LiteLLM resolves them to whichever backend is actually running.
2. LiteLLM model_list: real model names, real modes
Your recipes from Spark Arena already defines the modes you need, using concrete model names.
Local Nemotron‑Nano profiles
# ── LOCAL NEMOTRON NANO (optimized for speed) ──
- model_name: "Base" # Native (thinking ON)
litellm_params:
model: openai/nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4
api_base: http://host.docker.internal:8000/v1
api_key: os.environ/NEMOTRON_API_KEY
temperature: 0.4
top_p: 0.9
max_tokens: 8192
extra_body: {}
chat_template_kwargs:
enable_thinking: true
- model_name: "Fast"
litellm_params:
model: openai/microsoft/Phi-4-mini-instruct
api_base: http://phi-judge:8000/v1
api_key: simple-api-key
temperature: 0.2
top_p: 0.9
max_tokens: 8192
timeout: 30
initial_messages:
- role: system
content: |
You are a fast, local judge / evaluator / classifier.
extra_body: {}
- model_name: "Expert" # Balanced reasoning
litellm_params:
model: openai/nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4
api_base: http://host.docker.internal:8000/v1
api_key: os.environ/NEMOTRON_API_KEY
temperature: 0.6
top_p: 0.98
max_tokens: 16384
timeout: 300
extra_body: {}
chat_template_kwargs:
enable_thinking: true
effort: "medium"
- model_name: "Heavy"
litellm_params:
model: openai/nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4
api_base: http://host.docker.internal:8000/v1
api_key: os.environ/NEMOTRON_API_KEY
temperature: 1.0
top_p: 1.0
max_tokens: 32768
timeout: 600
stream_timeout: 240
extra_body: {}
chat_template_kwargs:
enable_thinking: true
- model_name: "Code"
litellm_params:
model: openai/nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-NVFP4
api_base: http://host.docker.internal:8000/v1
api_key: os.environ/NEMOTRON_API_KEY
temperature: 0.2
top_p: 0.95
max_tokens: 16384
timeout: 300
stream_timeout: 180
extra_body: {}
chat_template_kwargs:
mode: code
enable_thinking: true
clear_thinking: false
GPT‑OSS‑120B profiles
# ===================GPT OSS 120B ==========================================
- model_name: "Fast"
description: Ultra-fast classifier / router / moderator – short & strict
litellm_params:
model: openai/gpt-oss-120b
api_base: http://host.docker.internal:8010/v1
api_key: sk-1234
temperature: 0.2
top_p: 0.9
max_tokens: 2048
timeout: 12
initial_messages:
- role: system
content: |
You are a fast, local classifier/router/moderator.
- model_name: "Expert"
description: Balanced reasoning – good default quality/speed trade-off
litellm_params:
model: openai/gpt-oss-120b
api_base: http://host.docker.internal:8010/v1
api_key: sk-1234
temperature: 0.55
top_p: 0.95
max_tokens: 32768
timeout: 400
extra_body: {}
chat_template_kwargs:
enable_thinking: true
effort: medium
- model_name: "Heavy"
description: Maximum reasoning depth & longest allowed outputs
litellm_params:
model: openai/gpt-oss-120b
api_base: http://host.docker.internal:8010/v1
api_key: sk-1234
temperature: 0.75
top_p: 0.98
max_tokens: 65536
timeout: 1200
stream_timeout: 600
extra_body: {}
chat_template_kwargs:
enable_thinking: true
effort: maximum
- model_name: "Code"
description: Programming & technical tasks – prefers clean output
litellm_params:
model: openai/gpt-oss-120b
api_base: http://host.docker.internal:8010/v1
api_key: sk-1234
temperature: 0.15
top_p: 0.85
max_tokens: 32768
timeout: 600
extra_body: {}
chat_template_kwargs:
mode: code
enable_thinking: true
clear_thinking: true
2.5. How “modes” map to temperature / length / effort
The different “modes” (Fast, Expert, Heavy, Code) are just concrete per‑model profiles with carefully chosen parameters in litellm_config.yaml:
-
Temperature
- Fast / classifier modes (
Fast) use low temperature (around 0.15–0.2) and tightertop_pfor short, stable, deterministic outputs (routing, judging, quick edits). - Expert modes (
Expert) sit in the 0.4–0.6 range with slightly highertop_pfor balanced reasoning and creativity. - Heavy modes (
Heavy) use higher temperature and relaxedtop_pso they can explore more options when you explicitly want deep thinking or long, open‑ended answers.
- Fast / classifier modes (
-
max_tokens / timeouts
- Fast modes cap
max_tokenslow and use short timeouts to enforce quick responses and trigger fallbacks when a request clearly needs more room. - Expert modes increase
max_tokensand timeouts to comfortably handle most daily chat and analysis. - Heavy / Max modes increase
max_tokensaggressively and extendtimeout/stream_timeoutto cover long documents, full files, and multi‑step reasoning.
- Fast modes cap
-
effort / thinking flags
- Nemotron and GPT‑OSS profiles use
enable_thinking: trueandeffort(medium,maximum) where supported to hint how hard to “think” internally before answering. - Code profiles set
mode: code(and sometimesclear_thinking) to bias toward clean code blocks and minimal chatter.
- Nemotron and GPT‑OSS profiles use
When you pick Fastvs Expert vs Heavy vs Code, you’re really choosing a bundle of temperature + length + timeout + prompt discipline that you’ve pre‑curated for that model’s sweet spot, from Hugging Face, UnSloth model cards etc.
- Routing and fallbacks (concrete names, Grok‑4 fallback)
The final piece is the routing_strategy and router_settings. Using the same mode names "Fast" "Expert" for GL, Nemotron Nano etc with a simple, explicit fallback chain ending at Grok-4 results a clean UI and model dropdown menu.
# ── ROUTING & SETTINGS ───────────────────────────────────────────────────────
routing_strategy: usage-based-routing
router_settings:
max_tokens_threshold: 4096
fallback_on_max_tokens: true
retry_on_failure: true
num_retries: 2
timeout: 60
# Corrected fallbacks – each fallback entry must list the model names that
# should be used when the primary model fails or when the token limit is hit.
fallbacks:
- "Fast":
fallback_to: ["Fast","Expert", "Heavy"]
- "Expert":
fallback_to: ["Expert","Heavy"]
- "Heavy":
fallback_to: ["Heavy","Grok-4"]
# Context‑window fallback mappings – ensure that when the primary model’s
# context window is exhausted, the system falls back to a model with a
# larger window.
context_window_fallbacks:
"Fast": ["Expert", "Heavy"]
"Expert": ["Heavy"]
"Heavy": ["Heavy", "Grok-4"]
You keep one version of this block active at a time, depending on which Spark Arena recipe is your primary. Either way:
- Fast classifiers escalate into their corresponding Expert/Heavy modes and then
Grok-4. - The primary local assistant (
Expert) escalates to its Heavy profile and thenGrok-4. - Code‑oriented models fall back to Qwen‑Coder profiles and, if needed,
Grok-4.
No generic labels; everything is grounded in real model_name strings from your config, with Grok-4 as the single hosted backstop.
4. Phi Mini in the stack – the fast tier
Phi Fast runs Microsoft’s Phi‑4‑mini‑instruct as a dedicated small, fast tier, wired as its own vLLM instance on phi-judge:8000. Large quantized models like Nemotron‑3‑Nano NVFP4, GLM‑4.7‑Flash‑AWQ, and Qwen3‑Coder‑Next‑FP8 typically use < 62% of DGX Spark’s VRAM in their Spark Arena recipes, which leaves comfortable headroom to keep Phi‑4‑mini loaded at the same time together with Qdrant, embedding model and reranking model etc.
This gives you:
- Sub‑second, ultra‑cheap responses for classification, routing, moderation, and quick Q&A.
- A local‑only Fast tier:
Fastis always tried first for short/simple tasks, and only escalates toExpert/Heavy/ Grok-4when it hits timeouts, token limits, or context constraints via the routing rules above.
You get snappy, resilient behavior without complicating Open WebUI at all; it just exposes Fast as another model, and LiteLLM handles the routing.
5. What this gives you in practice
On a single DGX Spark:
- Spark Arena recipes give you vLLM deployments for Nemotron, GLM, Qwen‑Coder, Qwen‑Instruct.
- LiteLLM wraps those (plus small locals like Phi‑4‑mini and hosted models like Grok‑4, Qwen‑Max/Qwen3, Llama‑3‑70B) into a single OpenAI‑compatible endpoint with per‑model routing and fallbacks using real model names.
- Open WebUI talks only to LiteLLM and simply lists
Fast,Expert,Heavy,Code, etc. — nothing abstract, no alias layer.
The result is a hosted‑grade, multi‑model assistant experience with simple, concrete model choices and robust failover, running entirely on your hardware, with Spark Arena doing the heavy lifting underneath.
Auto mode will be added at a future date to automatically route to these basic modes, MoE and compound cloud/local MoE modes.
@raphael.amorim, @eugr thank you for providing the community Spark Arena, recipes etc, it is great having a foundation to build on! There is still more work to do here integration of Modes and Auto Mode, lets think about developing a community front end for the model in Spark Arena Models to provide a complete solution for Spark Users. I do like the openWebUI front end it does provide a lot of flexibility for customization. I do really like Qdrant as a backend vector database for openWebUI. The backend with RAG and pipelines are very simple and work well once you work out how to code them but very hard to get going the first time when you are trying to configure everything. I will post more on RAG and building RAG corpus at a future date.
Many thanks,
Mark