@@ -170,7 +170,7 @@ both are set per group.
170170Router sits in front of inference backend workers (SGLang, vLLM, TensorRT-LLM) and decides
171171which worker serves each request based on routing policy.
172172
173- Below is an example for running ` Qwen/Qwen3.8-Flash-Next ` on ` H200 ` :
173+ Below are examples for running ` Qwen/Qwen3.8-Flash-Next ` with SMG and ` zai-org/GLM-4.5-Air-FP8 ` with Dynamo on ` H200 ` :
174174
175175=== "SMG"
176176
@@ -234,77 +234,64 @@ Below is an example for running `Qwen/Qwen3.8-Flash-Next` on `H200`:
234234
235235 ```yaml
236236 type: service
237- name: qwen38-flash-next -dynamo
237+ name: glm-45-air -dynamo
238238
239239 env:
240240 - HF_TOKEN
241- - MODEL_ID=Qwen/Qwen3.8-Flash-Next
241+ - MODEL_ID=zai-org/GLM-4.5-Air-FP8
242242
243243 groups:
244- - replicas: 1
245- docker: true
244+ # The frontend and the workers discover each other via etcd
245+ - name: etcd
246+ replicas: 1
246247 commands:
247- - apt-get update
248- - apt-get install -y python3-dev python3-venv
249- - python3 -m venv ~/dyn-venv
250- - source ~/dyn-venv/bin/activate
251- - pip install -U pip
252- - pip install "ai-dynamo[sglang]==1.1.1"
253- - git clone https://github.com/ai-dynamo/dynamo.git
254- # Brings up the NATS / etcd compose stack and runs the Dynamo HTTP frontend.
255- - docker compose -f dynamo/dev/docker-compose.yml up -d
256248 - |
257- python3 -m dynamo.frontend \
258- --http-host 0.0.0.0 --http-port 8000 \
259- --discovery-backend etcd --router-mode kv \
260- --kv-cache-block-size 64
249+ curl -fsSL https://github.com/etcd-io/etcd/releases/download/v3.5.33/etcd-v3.5.33-linux-amd64.tar.gz \
250+ | tar -xz -C /usr/local/bin --strip-components=1 etcd-v3.5.33-linux-amd64/etcd
251+ - |
252+ etcd \
253+ --data-dir /tmp/etcd \
254+ --listen-client-urls http://0.0.0.0:2379 \
255+ --advertise-client-urls http://$DSTACK_MASTER_NODE_IP:2379
261256 resources:
262- cpu: 4
257+ cpu: 2
258+
259+ - name: frontend
260+ replicas: 1
261+ # The vLLM image provides vLLM's GLM tool call and reasoning parsers
262+ image: nvcr.io/nvidia/ai-dynamo/vllm-runtime:1.5.1
263+ commands:
264+ - export ETCD_ENDPOINTS=http://${{ groups[0].replicas[0].IP_ADDRESS }}:2379
265+ - |
266+ python3 -m dynamo.frontend \
267+ --http-port 8000 \
268+ --router-mode kv \
269+ --dyn-chat-processor vllm \
270+ --enable-auto-tool-choice \
271+ --tool-call-parser glm45 \
272+ --reasoning-parser glm45
263273 router:
264274 type: dynamo
275+ resources:
276+ cpu: 4
265277
266- - replicas: 2
267- python: "3.12"
268- nvcc: true
278+ - name: worker
279+ replicas: 2
280+ image: nvcr.io/nvidia/ai-dynamo/vllm-runtime:1.5.1
269281 commands:
270- # dstack injects DSTACK_ROUTER_INTERNAL_IP after the router replica
271- # is provisioned. Compose the etcd/NATS endpoints from it.
272- - export ETCD_ENDPOINTS="http://$DSTACK_ROUTER_INTERNAL_IP:2379"
273- - export NATS_SERVER="nats://$DSTACK_ROUTER_INTERNAL_IP:4222"
274- # Set to enable /health endpoint required by dstack probes.
275- - export DYN_SYSTEM_PORT="8000"
276- # Wait until the router's etcd and NATS ports are actually accepting connections.
277- - |
278- until curl -fsS "http://$DSTACK_ROUTER_INTERNAL_IP:2379/health" \
279- && curl -fsS "http://$DSTACK_ROUTER_INTERNAL_IP:8222/healthz"; do
280- echo "waiting for etcd/NATS on $DSTACK_ROUTER_INTERNAL_IP..."; sleep 3
281- done
282- - pip install "ai-dynamo[sglang]==1.1.1"
282+ - export ETCD_ENDPOINTS=http://${{ groups[0].replicas[0].IP_ADDRESS }}:2379
283+ # vLLM binds the KV events endpoint only if it's a wildcard address, otherwise it connects
283284 - |
284- python3 -m dynamo.sglang \
285- --model-path $MODEL_ID \
286- --served-model-name $MODEL_ID \
287- --discovery-backend etcd \
288- --host 0.0.0.0 \
289- --page-size 64 \
290- --tp $DSTACK_GPUS_NUM \
291- --ep $DSTACK_GPUS_NUM \
292- --mem-fraction-static 0.85 \
293- --chunked-prefill-size 8192 \
294- --linear-attn-prefill-backend flashinfer \
295- --linear-attn-decode-backend flashinfer \
296- --mamba-ssm-dtype bfloat16 \
297- --reasoning-parser auto
285+ python3 -m dynamo.vllm \
286+ --model $MODEL_ID \
287+ --max-model-len 65536 \
288+ --kv-events-config '{"publisher":"zmq","topic":"kv-events","endpoint":"tcp://*:20080","enable_kv_cache_events":true}'
298289 resources:
299- gpu: H200:4
290+ gpu: H200
291+ disk: 200GB..
300292
301293 port: 8000
302- model: Qwen/Qwen3.8-Flash-Next
303-
304- probes:
305- - type: http
306- url: /health
307- interval: 15s
294+ model: zai-org/GLM-4.5-Air-FP8
308295 ```
309296
310297 </div>
@@ -418,84 +405,77 @@ Below is an example for running `zai-org/GLM-4.5-Air-FP8` on `H200`:
418405 - MODEL_ID=zai-org/GLM-4.5-Air-FP8
419406
420407 groups:
421- - replicas: 1
422- docker: true
408+ # The frontend and the workers discover each other via etcd
409+ - name: etcd
410+ replicas: 1
423411 commands:
424- - apt-get update
425- - apt-get install -y python3-dev python3-venv
426- - python3 -m venv ~/dyn-venv
427- - source ~/dyn-venv/bin/activate
428- - pip install -U pip
429- - pip install "ai-dynamo[sglang]==1.1.1"
430- - git clone https://github.com/ai-dynamo/dynamo.git
431- # Brings up the NATS / etcd compose stack and runs the Dynamo HTTP frontend.
432- - docker compose -f dynamo/dev/docker-compose.yml up -d
433412 - |
434- python3 -m dynamo.frontend \
435- --http-host 0.0.0.0 --http-port 8000 \
436- --discovery-backend etcd --router-mode kv \
437- --kv-cache-block-size 64
413+ curl -fsSL https://github.com/etcd-io/etcd/releases/download/v3.5.33/etcd-v3.5.33-linux-amd64.tar.gz \
414+ | tar -xz -C /usr/local/bin --strip-components=1 etcd-v3.5.33-linux-amd64/etcd
415+ - |
416+ etcd \
417+ --data-dir /tmp/etcd \
418+ --listen-client-urls http://0.0.0.0:2379 \
419+ --advertise-client-urls http://$DSTACK_MASTER_NODE_IP:2379
438420 resources:
439- cpu: 4
421+ cpu: 2
422+
423+ - name: frontend
424+ replicas: 1
425+ # The vLLM image provides vLLM's GLM tool call and reasoning parsers
426+ image: nvcr.io/nvidia/ai-dynamo/vllm-runtime:1.5.1
427+ commands:
428+ - export ETCD_ENDPOINTS=http://${{ groups[0].replicas[0].IP_ADDRESS }}:2379
429+ - |
430+ python3 -m dynamo.frontend \
431+ --http-port 8000 \
432+ --router-mode kv \
433+ --dyn-chat-processor vllm \
434+ --enable-auto-tool-choice \
435+ --tool-call-parser glm45 \
436+ --reasoning-parser glm45
440437 router:
441438 type: dynamo
439+ resources:
440+ cpu: 4
442441
443- - replicas: 4
444- python: "3.12"
445- nvcc: true
442+ # Only prefill workers publish KV events, as Dynamo's decode routing ignores prefix overlap
443+ - name: prefill-worker
444+ replicas: 4
445+ image: nvcr.io/nvidia/ai-dynamo/vllm-runtime:1.5.1
446446 commands:
447- # dstack injects DSTACK_ROUTER_INTERNAL_IP after the router replica
448- # is provisioned. Compose the etcd/NATS endpoints from it.
449- - export ETCD_ENDPOINTS="http://$DSTACK_ROUTER_INTERNAL_IP:2379"
450- - export NATS_SERVER="nats://$DSTACK_ROUTER_INTERNAL_IP:4222"
451- # Set to enable /health endpoint required by dstack probes.
452- - export DYN_SYSTEM_PORT="8000"
453- # Wait until the router's etcd and NATS are healthy.
447+ - export ETCD_ENDPOINTS=http://${{ groups[0].replicas[0].IP_ADDRESS }}:2379
448+ - export VLLM_NIXL_SIDE_CHANNEL_HOST=$DSTACK_MASTER_NODE_IP
449+ # vLLM binds the KV events endpoint only if it's a wildcard address, otherwise it connects
454450 - |
455- until curl -fsS "http://$DSTACK_ROUTER_INTERNAL_IP:2379/health" \
456- && curl -fsS "http://$DSTACK_ROUTER_INTERNAL_IP:8222/healthz"; do
457- echo "waiting for etcd/NATS on $DSTACK_ROUTER_INTERNAL_IP..."; sleep 3
458- done
459- - pip install "ai-dynamo[sglang]==1.1.1"
460- - |
461- python3 -m dynamo.sglang \
462- --model-path $MODEL_ID --served-model-name $MODEL_ID \
463- --discovery-backend etcd --host 0.0.0.0 \
464- --page-size 64 \
465- --disaggregation-mode prefill --disaggregation-transfer-backend nixl
451+ python3 -m dynamo.vllm \
452+ --model $MODEL_ID \
453+ --max-model-len 65536 \
454+ --disaggregation-mode prefill \
455+ --kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_producer"}' \
456+ --kv-events-config '{"publisher":"zmq","topic":"kv-events","endpoint":"tcp://*:20080","enable_kv_cache_events":true}'
466457 resources:
467458 gpu: H200
459+ disk: 200GB..
468460
469- - replicas: 8
470- python: "3.12"
471- nvcc: true
461+ - name: decode-worker
462+ replicas: 8
463+ image: nvcr.io/nvidia/ai-dynamo/vllm-runtime:1.5.1
472464 commands:
473- - export ETCD_ENDPOINTS="http://$DSTACK_ROUTER_INTERNAL_IP:2379"
474- - export NATS_SERVER="nats://$DSTACK_ROUTER_INTERNAL_IP:4222"
475- - export DYN_SYSTEM_PORT="8000"
476- - |
477- until curl -fsS "http://$DSTACK_ROUTER_INTERNAL_IP:2379/health" \
478- && curl -fsS "http://$DSTACK_ROUTER_INTERNAL_IP:8222/healthz"; do
479- echo "waiting for etcd/NATS on $DSTACK_ROUTER_INTERNAL_IP..."; sleep 3
480- done
481- - pip install "ai-dynamo[sglang]==1.1.1"
465+ - export ETCD_ENDPOINTS=http://${{ groups[0].replicas[0].IP_ADDRESS }}:2379
466+ - export VLLM_NIXL_SIDE_CHANNEL_HOST=$DSTACK_MASTER_NODE_IP
482467 - |
483- python3 -m dynamo.sglang \
484- --model-path $MODEL_ID --served-model-name $MODEL_ID \
485- --discovery-backend etcd --host 0.0.0.0 \
486- --page-size 64 \
487- --disaggregation-mode decode --disaggregation- transfer-backend nixl
468+ python3 -m dynamo.vllm \
469+ --model $MODEL_ID \
470+ --max-model-len 65536 \
471+ --disaggregation-mode decode \
472+ --kv- transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_consumer"}'
488473 resources:
489474 gpu: H200
475+ disk: 200GB..
490476
491477 port: 8000
492478 model: zai-org/GLM-4.5-Air-FP8
493-
494- # Custom probe is required for PD disaggregation.
495- probes:
496- - type: http
497- url: /health
498- interval: 15s
499479 ```
500480
501481 </div>
0 commit comments