Skip to content

feat(serving): replicated dynamo.vllm behind the Dynamo frontend + LiveKit 2xTP4 arm / 多副本 dynamo.vllm 与 LiveKit 2xTP4 配置 - #38

Open
DinhKhangHoang wants to merge 8 commits into
vng-benchmarkfrom
feat/serving-dynamo-vllm-replicas
Open

DinhKhangHoang wants to merge 8 commits into
vng-benchmarkfrom
feat/serving-dynamo-vllm-replicas

Conversation

@DinhKhangHoang

Copy link
Copy Markdown
Collaborator

Description

Serving YAMLs can run dynamo.vllm engines with replicas: N behind the Dynamo frontend (KV router). This PR adds the LiveKit 111868 arm on that path, plus a script that reads LiveKit results.

Engine/launcher (9bb5712)

  • render/schema: python3 -m dynamo.vllm is a Dynamo engine (framework vllm, router profile dynamo).
    • replicas > 1 with the Dynamo frontend is allowed for dynamo.vllm only, and only without a --kv-events-config of its own.
    • DYN_SYSTEM_PORTS / DYN_KV_EVENT_PORTS are reserved.
  • launch_hardware-hcm.sh reserves one Dynamo system port and one KV-event port per replica.
  • serve_generic.sh starts one engine per GPU slice, each with its own --kv-events-config.
    • It waits for each replica to become healthy.
    • aiperf scrapes every replica.
  • benchmarks/dynamo-vllm/Dockerfile: vllm/vllm-openai:v0.31.0 + ai-dynamo 1.6.0.dev20261018. This is the first ai-dynamo release that routes Gemma-4's hybrid KV groups.

LiveKit arm (bdc706b)

  • serving/gemma4-livekit-2tp4-dyn-kv-sa.yaml: Gemma-4-31B FP8, 2× TP4 dynamo.vllm (8×H200).
    • KV router with --router-prefill-load-scale=16 and hard session affinity.
    • Scenario custom-agentic-livekit111868-v1, c96.
  • Image vcr.vngcloud.vn/108942-public69/dynamo-stack/vllm-runtime:0.31.0-dyn1.6.0.dev20261018-g4strip. It is public; Dockerfile.g4strip documents the build.

Results tooling (73b483c, 21fa1e6, b48f97a)

  • utils/serving/livekit_ttft.py: TTFT per conc, split by a room's first turn vs later turns. First turns carry the whole system prompt uncached and set the p95 tail.
    • It reads dataset.txt to pick the plan CSV, then fetches it from the lock.
    • New lock entries livekit-111868-{v1,v2}-plan: same HF repo and revision as the traces, public.
  • The serving-bench skill §4 and serving-yaml-procedures (en/zh) now describe the artifacts a run really uploads:
    • no results/ subdir;
    • server.<i>.log per replica;
    • agg_bmk.json and the fields to read in it;
    • tp in artifact names = gpus;
    • readiness 503s before warmup are not failures.
  • A fresh agent read run 39270751257 through the skill without workarounds.

Evidence: run 39270751257, c96, on hardware-hcm-8x_02.

  • 0 / 16,822 errors.
  • TTFT p95 0.64 s: first turns 0.79, later turns 0.60.
  • GPU prefix-cache hit 86.7%; the two workers split prompt tokens 52/48.
  • This matches the same config on Slurm (0.66 / 0.64 / 0.65 s). The run used the pre-patch image; the -g4strip image passed a tool-call smoke test on Slurm.

Related Issue

ai-dynamo/dynamo#16781 (upstream bug the -g4strip image patches)

Type of Change

  • Bug fix
  • New feature
  • Configuration change
  • Documentation update
  • Other (please describe)

Checklist

  • I have tested my changes locally
    • utils/test_serving_{livekit_ttft,fetch_dataset,to_matrix,router,render,launcher_hcm}.py pass.
    • test_serving_schema.py passes except test_router_needs_hardware_hcm_runner / test_storage_needs_hardware_hcm_runner, which already fail on vng-benchmark (stale message after the rtx6000pro runner was added).
  • I have updated documentation if necessary
  • perf-changelog: not added. Serving YAMLs are dispatched via utils/serving/dispatch.sh, not the changelog sweep, and earlier serving/*.yaml commits carry no entry either.
  • /reuse-sweep-run: N/A (no sweep).
中文

Serving YAML 现可在 Dynamo frontend(KV router)后以 replicas: N 运行 dynamo.vllm 引擎。本 PR 在此路径上新增 LiveKit 111868 配置,以及读取 LiveKit 结果的脚本。

  • 引擎与启动:
    • render/schema 支持 dynamo.vllm。
    • launch_hardware-hcm.sh 与 serve_generic.sh 为每个副本分配独立的 system port 与 KV-event port。
    • 新增 benchmarks/dynamo-vllm/Dockerfile。
  • LiveKit 配置: gemma4-livekit-2tp4-dyn-kv-sa.yaml,2× TP4,KV router + hard session affinity,c96。
  • 结果工具:
    • utils/serving/livekit_ttft.py 按房间首轮与后续轮次拆分 TTFT,plan CSV 从锁文件获取。
    • serving-bench skill 与 procedures 文档(中英)已按实际产物更新。
  • 验证: run 39270751257,c96,0 错误。
    • TTFT p95 0.64 s:首轮 0.79,后续 0.60。
    • 缓存命中 86.7%,与 Slurm 结果一致。
  • 测试: 新增与相关测试通过。test_serving_schema.py 的两个失败在 vng-benchmark 上已存在。

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown

Thanks for the contribution!

  • Review: If this PR changes files owned by someone other than a repository admin or @SemiAnalysisAI/core, ask one eligible CODEOWNER to complete the latest PR_REVIEW_CHECKLIST.md before contacting a core maintainer on Slack. Follow the template exactly, including As a PR reviewer and CODEOWNER, I have reviewed this and have, so sign-off verification triggers.
  • PR verification: Sweeps only run on labeled PRs. Add full-sweep-fail-fast (strongly recommended); use full-sweep-enabled only when matrix jobs should continue after a failure.
  • After merging: PR authors must ensure all GitHub Actions jobs pass. Transient failures often pass on rerun; see how to rerun failed jobs.
中文

感谢你的贡献!

  • **审阅:**如果 PR 修改的文件归属于仓库管理员及 @SemiAnalysisAI/core 之外的 CODEOWNER,请先联系一位有资格的 CODEOWNER 填写最新的 PR_REVIEW_CHECKLIST.md,再通过 Slack 联系核心维护者。必须严格遵循模板,并保留 As a PR reviewer and CODEOWNER, I have reviewed this and have,才能触发签核验证。
  • **PR 验证:**扫描仅在带有标签的 PR 上运行。强烈建议添加 full-sweep-fail-fast;仅当需要矩阵任务在失败后继续运行时才使用 full-sweep-enabled。
  • **合并后:**PR 作者必须确保所有 GitHub Actions 任务通过。临时性失败通常可以通过重新运行恢复;参见重新运行失败任务的说明。

DinhKhangHoang and others added 7 commits October 21, 2026 02:57
A serving YAML can now run `python3 -m dynamo.vllm` as its engine with
`replicas: N` behind `python3 -m dynamo.frontend`:

- render: dynamo.vllm is a Dynamo engine (framework vllm, router profile dynamo).
- schema: replicas > 1 with the Dynamo frontend is allowed for dynamo.vllm only,
  without a --kv-events-config of its own; DYN_SYSTEM_PORTS and
  DYN_KV_EVENT_PORTS are reserved.
- launch_hardware-hcm.sh: one Dynamo system port (<= 32767) and one KV event
  port per replica, for the bench step only.
- serve_generic.sh: one engine per GPU slice, each with its own system port and
  --kv-events-config; health wait per replica; aiperf scrapes every replica.
- benchmarks/dynamo-vllm/Dockerfile: vllm/vllm-openai:v0.31.0 + ai-dynamo
  1.6.0.dev20261018 (first release that routes Gemma-4's hybrid KV groups).
- serving/gemma4-livekit-2tp4-dyn-kv-sa.yaml: LiveKit 111868 v1 on 2x TP4 with
  the KV router and hard session affinity, c96.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Khang Hoang <khanghd@greennode.ai>
The stock ai-dynamo-runtime leaks an empty `<|channel>thought\n<channel|>`
into content on the turn after a tool result when Gemma 4 thinking is off
(ai-dynamo/dynamo#16781). The -g4strip image reinstalls a patched runtime
that keeps the gemma4 reasoning parser on, matching vllm serve. Performance
is unchanged; Dockerfile.g4strip documents the build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Khang Hoang <khanghd@greennode.ai>
…turn

A LiveKit run's p95 is set by each room's first turn (whole system prompt
uncached), which aiperf's aggregate hides. livekit_ttft.py reads a run's
profile_export.jsonl per conc with the trace's plan CSV and prints TTFT
for first and later turns, the 5 s-timeout turns, and first turns by
uncached length. The plan is fetched from the dataset lock as
<dataset>-plan (v1 and v2 entries added, same HF repo as the traces);
--plan takes a local CSV.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Khang Hoang <khanghd@greennode.ai>
…ench skill

The English procedures page got the LiveKit results line in 73b483c; the
zh page and the serving-bench skill's Results section now say the same, so
an agent reading a LiveKit run reports first and later turns too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Khang Hoang <khanghd@greennode.ai>
A fresh agent reading run 39270751257 through the serving-bench skill had
to work around the Results section: the agentic artifact has no results/
subdir, replicas add server.<i>.log, the aggregate (agg_bmk.json) and its
fields were not named, tp in names is the YAML's gpus, readiness 503s
before warmup look like failures, livekit_ttft.py needs pyyaml and
huggingface_hub, and the time estimate left out the runner queue. The
skill and both procedures pages now say so; a second fresh-agent pass
read the run without workarounds on the skill side.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Khang Hoang <khanghd@greennode.ai>
The best 2x TP4 LiveKit arm from the rbench Slurm study (job 4382, c96
TTFT p95 0.53 s vs 0.64 for dyn-kv-sa): before a room's first turn the
client sends that prompt minus the unknown first utterance (64 tokens)
with max_tokens 1, and the engines run 8192-token steps with a 2048
long-prefill threshold. The warm-up takes the ~14k-token first prefill
off the user's path; the smaller steps cut the later-turn tail.

- lock: livekit-111868-v1-warm (+ -plan), trace and plan at HF
  b2b84e6c (mkwarm.py 64 3000; sha256 = the trace Slurm ran).
- scenarios: custom-agentic-livekit111868-v1-warm, in the golden check.
- serving: gemma4-livekit-2tp4-dyn-kv-sa-warm-chunk (c96).
- livekit_ttft.py: warm=1 plan rows leave every TTFT view and get
  their own line (p50..max, share done within 0.5/1/1.5/2 s), since a
  warm-up must finish before the first turn. On job 4382 it prints
  p95 0.53, warm-ups p50 0.63 / p95 1.11.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Khang Hoang <khanghd@greennode.ai>
…cation

launch_hardware-hcm.sh sizes its salloc from measured use (8 CPUs + 64 GB
per GPU plus the engines' host KV pools). A serving YAML can now set
host_cpus / host_mem_gb (whole job: engines, router, sidecars, aiperf) to
ask for something else; unset keeps that default.

The livekit warm-chunk arm asks for 64 CPU / 192 GB instead of the default
512 GB: rbench job 4382 (same arm, c96) peaked at ~70 GB RSS over its Slurm
steps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Khang Hoang <khanghd@greennode.ai>
@DinhKhangHoang
DinhKhangHoang force-pushed the feat/serving-dynamo-vllm-replicas branch from f1aa16e to 3d0e5ec Compare October 21, 2026 02:59
CI's Lint runs ruff@latest format --check on infx; five files had drifted.
The router/storage runner checks now name hcm-rtx6000pro_* as well, so the
two schema tests assert the updated message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Khang Hoang <khanghd@greennode.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant