Repository navigation
feat(serving): Gemma 4 LiveKit prod config, 2x TP4 dynamo.vllm behind the Dynamo KV router / feat(serving):Gemma 4 LiveKit 生产配置,Dynamo KV router 后的 2x TP4 dynamo.vllm - #48
Open
DinhKhangHoang wants to merge 4 commits into
Conversation
…rontend The refactored serving flow started one Dynamo engine only: schema.py rejected replicas > 1 with dynamo.frontend, and job.sh / bench.sh had one system port. Two dynamo.vllm engines on one node also need their own vLLM KV event port, or the second ZMQ publisher fails to bind. - render.py: python3 -m dynamo.vllm is a Dynamo engine (framework vllm). - schema.py: replicas > 1 behind the Dynamo frontend for dynamo.vllm, without a --kv-events-config of its own; DYN_SYSTEM_PORTS / DYN_KV_EVENT_PORTS are reserved. - job.sh: one system port and one KV event port per replica. - bench.sh: each replica gets its GPU slice, DYN_SYSTEM_PORT and a ZMQ --kv-events-config; aiperf scrapes every system port; with several replicas bench.sh waits for each one's /health, since the frontend lists the model as soon as the first engine registers. One dynamo.sglang engine starts as before. 中文:在 Dynamo frontend 后运行多副本 dynamo.vllm。重构后的流程只启动一个 Dynamo 引擎(schema.py 拒绝 dynamo.frontend 搭配 replicas > 1)。现在 dynamo.vllm 可设 replicas > 1:每个副本有独立的 GPU 分片、system 端口和 vLLM KV event 端口,aiperf 抓取所有副本的指标,并在压测前等待每个副本 /health 就绪。 单个 dynamo.sglang 引擎的行为不变。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Khang Hoang <khanghd@greennode.ai>
…outer The setup we run in prod for customer 111868, on one 8x H200 node: two TP4 dynamo.vllm workers behind the Dynamo frontend KV router (prefill load scale 16, hard session affinity), image vllm-runtime:0.31.0-dyn1.6.0-g4p2-prod (vLLM 0.31.0 + vllm#57613, ai-dynamo 1.6.0 + dynamo#17486, unified parser route). livekit scenario (v1.1-warm), c96 and c150 (per-node prod load). 中文:新增 Gemma 4 LiveKit 生产配置:单台 8x H200 上两个 TP4 dynamo.vllm worker,前面是 Dynamo frontend KV router(prefill load scale 16、硬会话亲和), 镜像 vllm-runtime:0.31.0-dyn1.6.0-g4p2-prod。livekit 场景(v1.1-warm), 并发 96 和 150(单节点生产负载)。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Khang Hoang <khanghd@greennode.ai>
|
Thanks for the contribution!
中文感谢你的贡献!
|
DinhKhangHoang
marked this pull request as ready for review
November 3, 2026 00:08
|
Generally most InferenceX submissions don't need to add changes to the infx package. On the off chance they do, generally the diff is small. Please prompt your agent to clean your PR to keep your diff to only necessary & minimal changes too. We have an increased code quality bar for changes to the infx package. 中文大多数 InferenceX 提交通常不需要修改 infx 包。即使确实需要,改动通常也很小。请让你的 agent 清理 PR,使改动只包含必要且最小的内容。infx 包的改动有更高的代码质量要求。 |
bench.sh started every engine replica with DYN_SYSTEM_PORT, so plain vllm serve / sglang engines got it too, set to their HTTP port. Nothing reads it there, but it is wrong. The variable now goes only to Dynamo engines; test_bench.py checks that a vllm serve engine does not get it (fails on the previous bench.sh). bench.sh 之前给每个引擎副本都设置 DYN_SYSTEM_PORT,普通的 vllm serve / sglang 引擎也会拿到它(值为其 HTTP 端口)。虽然没有程序读取,但这是错误的。 现在只有 Dynamo 引擎会设置该变量;test_bench.py 检查 vllm serve 引擎不会 拿到它(在旧的 bench.sh 上会失败)。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Khang Hoang <khanghd@greennode.ai>
The unified parser route came only from the image's ENV. Setting it in router.env makes the route visible in the YAML and keeps it if the image changes to one on the 1.6.x default (the legacy route, which leaks reasoning after a tool response). 统一解析路径此前只来自镜像的 ENV。在 router.env 中显式设置后,YAML 中可以直接看到所用路径;即使换成默认使用旧路径的 1.6.x 镜像(工具返回 后会泄漏推理内容),也仍然走统一路径。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Khang Hoang <khanghd@greennode.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
This adds the Gemma 4 LiveKit prod setup (customer 111868) as a serving YAML. One 8x H200 node runs two TP4
dynamo.vllmworkers behind the Dynamo frontend KV router.The refactored flow could not run that setup yet.
schema.pyrejectedreplicas > 1withdynamo.frontend, andjob.sh/bench.shstarted one Dynamo engine with one system port. This is the same gap thegemma4-livekit-tp4-dyn-sgl-…-car128config works around by running one engine at half the concurrency. #38 had this change for the old tree; this ports it to the new one.Launcher (first commit)
render.py:python3 -m dynamo.vllmcounts as a Dynamo engine, with frameworkvllm.schema.py:replicas > 1behind the Dynamo frontend is allowed fordynamo.vllm, as long asservehas no--kv-events-configof its own.dynamo.sglangstays at one replica.job.sh: picks a system port and a KV event port for each replica.bench.sh: each replica gets its GPU slice, its ownDYN_SYSTEM_PORTand a ZMQ--kv-events-config. Without that, the second vLLM publisher can't bind. aiperf scrapes every system port.bench.shwaits for each one's/health. The frontend lists the model as soon as the first engine registers, so the old check alone would start the client with one worker up.dynamo.sglangengine starts exactly as before.Config (second commit):
configs/serving/gemma4-livekit-2tp4-dyn-vllm-prod.yamlvcr.vngcloud.vn/108942-public69/dynamo-stack/vllm-runtime:0.31.0-dyn1.6.0-g4p2-prod, public pull, used for both engine and router. It is vLLM 0.31.0 + ai-dynamo 1.6.0 plus:contentwhen thinking is off.DYN_PARSER_VERSION=2(unified parser route), also set inrouter.envso the route doesn't depend on the image. The legacy route leaks reasoning into content after a tool response and returns raw tool-call markup withtool_choice: none.--router-mode=kv --router-prefill-load-scale=16, hard session affinity (30 min),--router-min-initial-workers=2. aiperf sends its per-conversation id asx-dynamo-session-id.--max-num-batched-tokens 8192 --long-prefill-token-threshold 2048 --prefix-cache-retention-interval 4096.scenario: livekit(v1.1-warm),conc: [96, 150]. c150 is the per-node prod load (300 CCU on 2 nodes).Validation
to_matrix --check:gemma4-livekit-2tp4-dyn-vllm-prod custom-agentic-livekit111868-v1.1-warm (1200s) c96,150 cluster:hcm-hgx02.gn-benchmarkrun 41402074324 of this YAML on this branch (hcm-hgx02, 1200 s per point, aiperf warm-up phase excluded):Both replicas came up with their own KV event port, the frontend picked the v2 parser route (
parser_version=V2), and the server and router logs have no tracebacks.Tool-call and API edge smoke on the
-g4p2image (our Slurm job 8218, 340 requests, Dynamo vsvllm serve): row for row the same result as the-g4p1smoke the prod route was validated on (job 7594). vllm#57613 changes nothing on the API side.c96 is in line with what we had before on the V1 warm trace (p95 0.53 on the
-g4stripimage in CI run 39393810302, 0.55 on-g4p1in our Slurm job 7604). It is not a strict before/after, since v1.1-warm drops the short rooms.c150, the per-node prod load, is at p95 0.73 s, above the 0.5 s target. This PR is the config as it runs in prod; tuning for c150 is a separate step.
New tests:
test_bench.pyrunsbench.shwith two fakedynamo.vllmreplicas: GPU slices, KV event endpoints and metrics URLs.test_driver.pychecks thatjob.shgives each replica its own ports and that the frontend inherits none of them.中文
内容
新增 Gemma 4 LiveKit 生产配置(客户 111868):单台 8x H200 上两个 TP4
dynamo.vllmworker,前面是 Dynamo frontend KV router。重构后的流程此前无法运行该配置:
schema.py拒绝dynamo.frontend搭配replicas > 1,job.sh/bench.sh只启动一个 Dynamo 引擎、一个 system 端口。gemma4-livekit-tp4-dyn-sgl-…-car128配置正是用"单引擎、半并发"绕过这个限制。#38 在旧目录结构上做过同样的修改,本 PR 将其移植到新结构。启动器(第一个 commit)
render.py:python3 -m dynamo.vllm视为 Dynamo 引擎,framework 为vllm。schema.py:dynamo.vllm可以在 Dynamo frontend 后设置replicas > 1,前提是serve中没有自带--kv-events-config;dynamo.sglang仍限一个副本。job.sh:为每个副本选取 system 端口和 KV event 端口。bench.sh:每个副本有自己的 GPU 分片、DYN_SYSTEM_PORT和 ZMQ--kv-events-config,否则第二个 vLLM publisher 无法绑定端口。aiperf 抓取所有 system 端口的指标。多副本时会等待每个副本的/health,因为 frontend 在第一个引擎注册后就会列出模型。单个dynamo.sglang引擎的启动方式不变。配置(第二个 commit):
configs/serving/gemma4-livekit-2tp4-dyn-vllm-prod.yamlvcr.vngcloud.vn/108942-public69/dynamo-stack/vllm-runtime:0.31.0-dyn1.6.0-g4p2-prod(可匿名拉取),引擎与 router 共用。在 vLLM 0.31.0 + ai-dynamo 1.6.0 基础上加入:content。DYN_PARSER_VERSION=2(统一解析路径,同时在router.env中显式设置,不依赖镜像):旧路径会在工具返回后把推理内容放进 content,并在tool_choice: none时输出原始工具调用标记。--router-mode=kv --router-prefill-load-scale=16,硬会话亲和(30 分钟),--router-min-initial-workers=2。aiperf 以会话 id 作为x-dynamo-session-id发送。--max-num-batched-tokens 8192 --long-prefill-token-threshold 2048 --prefix-cache-retention-interval 4096。scenario: livekit(v1.1-warm),conc: [96, 150]。c150 为单节点生产负载(2 个节点承载 300 CCU)。验证
to_matrix --check:gemma4-livekit-2tp4-dyn-vllm-prod custom-agentic-livekit111868-v1.1-warm (1200s) c96,150 cluster:hcm-hgx02。本分支上该 YAML 的
gn-benchmark运行 41402074324(hcm-hgx02,每个点 1200 s,不含 aiperf warm-up 阶段):两个副本各自使用独立的 KV event 端口,frontend 选择了 v2 解析路径(
parser_version=V2),server 和 router 日志中没有 traceback。-g4p2镜像的工具调用与 API 边界 smoke(我们的 Slurm job 8218,340 个请求,Dynamo 对比vllm serve):与验证生产路径时-g4p1的 smoke(job 7594)逐行结果一致,vllm#57613 对 API 行为没有影响。c96 与此前 V1 warm trace 的结果一致(CI run 39393810302 上
-g4strip镜像 p95 0.53,我们 Slurm job 7604 上-g4p1为 0.55)。由于 v1.1-warm 去掉了较短的 room,这不是严格的前后对比。c150(单节点生产负载)p95 为 0.73 s,高于 0.5 s 目标。本 PR 是生产环境实际运行的配置,针对 c150 的调优另行处理。
新增测试:
test_bench.py用两个模拟的dynamo.vllm副本运行bench.sh,检查 GPU 分片、KV event 端点和指标 URL。test_driver.py检查job.sh为每个副本分配独立端口,且 frontend 不继承这些端口。AI model disclosure
Prepared with Claude Opus 5.5 (
claude-opus-5-5) in Claude Code: code, tests, config and this description. Reviewed by Khang Hoang.🤖 Generated with Claude Code