Repository navigation
[TRTLLM-16460][feat] agent-flow: trtllm_modeling_v2 workflow for gated ModelingV2 onboarding and perf tuning - #20145
Wanli-Jiang wants to merge 70 commits into
Conversation
| @@ -0,0 +1,129 @@ | |||
| --- | |||
| name: staircase-modeling-disagg | |||
| description: Load when a target must work under disaggregated serving — prefill on one engine, decode on another, with per-sequence state transferred between them. The modeling duty is that EVERY piece of per-sequence state prefill produces is in the transferable set, which for a hybrid model is not just the attention KV pages. | |||
There was a problem hiding this comment.
Thanks for putting all these together.
-
Lets try to rename staircase to "trtllm_modeling_v2"?
-
One open question. Shall each feature have its own skill or it should be part of the main skill with reference doc on how each feature shall be implemented?
There was a problem hiding this comment.
updated codes and comments in #20145 (comment)
|
I am still understanding and reviewing the code in the workflow section. Regarding the "skills" section, I do not recommend incorporating these skills into the repo. The previous experience of the modeling agent tells us that, first, detailed skills may limit the model's performance. Second, the large amount of information carried in the skills is difficult to maintain, and errors and outdated information will become difficult to manage. We can first place them in an internal small repo. If there are clear AB tests proving that this is effective, then we can incorporate them into the repo. |
…emble, gate and deliver a model onboarding The staircase-onboard agent-flow workflow: a plan phase that surveys the checkpoint and drafts a staircase of units, per-unit assembly by an assembler agent with kernel and modeling smiths, boot/accuracy/acceptance/witness gates at every parallel member, a bounded remediation cycle, and delivery checks. Includes the agent-flow runtime package (turn and command executors: in-process, file dispatch, local, slurm, spool, delegated) that the workflow routes its turns and gate commands through, the role prompts, the materialized skills, and the package's tests. Squashed from user/williamj/staircase-polish @ c8109d6f90 (42 commits): - [feat] agent-flow: staircase-onboard workflow - [refactor] agent-flow: runtime package for turns and commands - [refactor] agent-flow: route staircase turns and gate commands through the runtime - [feat] staircase: close UNCOVERED with a bounded remediation cycle - [feat] agent-flow: run gates on a cluster only an agent can reach - [feat] staircase: gate every member, survey the demands, admit a new architecture - [fix] staircase: a checkpoint carrying its own implementation is an unsupported architecture - [fix] staircase: the accuracy gate cannot spell the topology the boot gate spells - [fix] staircase: the acceptance gate measured a speculator the unit was not built for - [fix] staircase: make the multi-rank launch and the supply survey actually work - [fix] staircase: the acceptance gate needs a stock path, which a new architecture does not have - [fix] staircase: see the registry's own unsupported-architecture message - [perf] staircase: stop spending assembler turns on restarts, and make a gate say what it measured - [feat] staircase: recover six improvements stranded in a sibling checkout - [fix] staircase: a member overlay must not be written into the source tree - [doc] staircase: carry the findings a real run produced - [chore] staircase: classify the in-tree Triton custom op - [feat] staircase: host offload names its capturable precedent - [feat] staircase: dspark, bounded-replay and kv_quant feature kinds - [fix] staircase: a gate test must not find the checkout that holds TMPDIR - [fix] staircase: the survey must read the in-tree catalog index - [fix] staircase: an unknown model_type is a new architecture too - [feat] staircase: defer feature-only smith failures to their unit - [fix] staircase: a resume collects the answers the dead process never read - [fix] staircase-onboard: commit.sh signs off (DCO) under git's own identity - [fix] staircase-onboard: kernel-source registry claims the run's Triton quantization ops - [fix] staircase-onboard: disagg equivalence witness runs a real, synchronised leg B (F021a-g) - [fix] staircase-onboard: a registration shim without a target counts as an unsupported architecture - [fix] staircase-onboard: an assembler blocked on knowledge_gap or environment can be re-entered - [fix] staircase-onboard: the acceptance gate measures a declared long-answer workload - [fix] staircase-onboard: token-comparing witness legs can run at batch 1 - [fix] staircase-onboard: the equivalence witness hands leg B an absolute prompts path - [feat] staircase-onboard: witness blocks can set an environment for both legs - [feat] staircase: ask targets for their runtime-value dump on every gate and witness run - [chore] agent-flow: reword two codespell findings in staircase_onboard - [chore] agent-flow: one-line docstring summaries in the staircase_onboard tests - [chore] agent-flow: NVIDIA copyright headers on the staircase_onboard files - [fix] staircase-onboard: kernel-source registry claims the four new Triton custom ops - [chore] Apply pre-commit formatting to the DeepSeek-V4.1 changes - [feat] staircase: place targets at models/<family>/<checkpoint>__<arch>__<parallel>/ - [chore] staircase: stop tracking the sandbox's session placeholders - [fix] staircase: no committed file names one operator's home or scratch path Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…certification of what a target claims task.yaml declares a serving envelope and a feature-combination matrix; preflight derives the gate tuples and the certified set from them (replacing 'the tuples the gates happened to run'). Adds the capacity-constant audit of the target against the envelope, the per-call-site smith brief and mandatory integer-width probes in kernel-verify, a typed certification_gap decision fanned out to verify smiths by the orchestrator, early delivery checks run as warnings after planning and after every unit, and a preflight refusal of a speculation algorithm the gates' launch path cannot run. Squashed from user/williamj/staircase-polish @ c8109d6f90 (7 commits): - [feat] staircase: declare the serving envelope and feature matrix, derive the certified set from them - [feat] staircase: audit the target's capacity constants against the serving envelope - [feat] staircase: smith brief per call site, and mandatory integer-width probes in kernel-verify - [feat] staircase: typed certification_gap decision, fanned out to verify smiths by the orchestrator - [feat] staircase: run the delivery checks that need no finished target early, as warnings - [fix] staircase: envelope follow-ups found replaying the DeepSeek-V4.1 spec - [feat] staircase: preflight refuses a speculation algorithm the gates' launch path has no branch for Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
… prompt snapshots; no model-specific data in the workflow Adapts the workflow to upstream agent-flow: per-role backend/model routing through an agents block (NVIDIA#19522), the backend/model named on externally dispatched turns, composed role prompts snapshotted into the workspace (NVIDIA#19715), the oversized-system-prompt spill (NVIDIA#19766). Fixes concurrent file-dispatch turns sharing a request id. Moves the DeepSeek-V4.1 specifics out of skills, registries and the example spec into a worked example that is never materialized, and replaces tests that read a model PR's files with fixtures. Squashed from user/williamj/staircase-polish @ c8109d6f90 (13 commits): - [fix] staircase: concurrent dispatch turns never share a request id - [feat] staircase: per-role backend and model routing through the agents block - [feat] staircase: a dispatched turn names the backend and model its role is configured for - [feat] staircase: snapshot the composed role prompts into the workspace - [test] staircase: a role's oversized system prompt reaches the CLI through the spill - [test] staircase: check the quickstart DSPARK contract against a fixture - [fix] staircase: claim tree-local Triton custom-op files by content, not by name - [chore] staircase: the example spec and the schema's messages name no checkpoint - [feat] staircase: move DeepSeek-V4.1 specifics out of the feature skills into a worked example - [fix] staircase: delivery accepts the op-matrix test a multi-rank catalog entry has on main - [test] staircase: the same-process retry test answers only once the retry holds the request - [doc] staircase: README sections for the envelope, the evidence ledger and commit hygiene - [doc] staircase: README sections for the gates and the execution substrate; no placeholder left Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…-embargo hooks, unit overlap and delivery audit commit.sh commits as the repository user with a matching DCO sign-off and refuses untracked links, sandbox placeholders and paths outside the policy; the pre-merge pack (staircase-onboard premerge lint|ci|copyright|hygiene|split|resign|pr-open|pack); source_embargo enforced by PreToolUse/PostToolUse hooks with an attempt log (prompt instruction for backends without hooks); opt-in --overlap-units that starts the next unit's assembler in its own worktree (F027); and a delivery tail that audits the run's commits and writes the pre-merge pack. Squashed from user/williamj/staircase-polish @ c8109d6f90 (8 commits): - [feat] staircase: commit helper signs as the repository user and refuses links, placeholders and stray paths - [feat] staircase: pre-merge pack as `staircase-onboard premerge <step>` - [feat] staircase: enforce source_embargo with PreToolUse/PostToolUse hooks and log every attempt - [feat] staircase: opt-in --overlap-units starts the next unit's assembler in its own worktree (F027) - [feat] staircase: delivery audits the run's commits and ends with the pre-merge pack - [doc] staircase: name the worked example's embargo in the package: spelling - [fix] staircase: package: embargo entries stay inside the package and read as reference material - [fix] staircase: the AST proof's label for a file that does not parse is spelled "unparsable" Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…dation and reports generated from it An append-only ledger of gate verdicts keyed by tree, member, config and covered code paths; verdicts invalidated by later commits are queued for re-run and the final regression is bound to the delivered tree. progress.json/html and the final report's gate tables are generated from the ledger. Decision files are <unit>-<role>-<turn>.yaml and never overwritten (F033), journal ordinals are atomic, and catalog/index.yaml is generated from per-entry fragments (F013/F014). Squashed from user/williamj/staircase-polish @ c8109d6f90 (10 commits): - [feat] staircase: append-only evidence ledger for gate verdicts - [feat] staircase: stale-verdict invalidation, re-run queue and final-regression binding - [feat] staircase: generate progress.json/html and the final report's gate tables from the ledger - [fix] staircase: decision files are <unit>-<role>-<turn>.yaml and never overwritten (F033) - [fix] staircase: Journal.next_ordinal is atomic across threads and processes - [feat] staircase: generate catalog/index.yaml from per-entry fragments (F013/F014) - [feat] staircase: the ledger records envelope probes, early checks and delivery checks - [feat] staircase: a verdict's config fingerprint includes each role's backend and model - [feat] staircase: the pre-merge pack states the final-regression binding and how to re-check it - [fix] staircase: catalog index sync is serialized and never undoes a commit that landed Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
… statistical accuracy, per-prompt acceptance, step witness Accuracy floors from the anchor's standard error with a cross-member finding; a per-prompt acceptance gate on a natural-text workload; a scheduler-equivalence witness with an optional step-trace hook; boot workloads declared in task.yaml and matched on generated text (a real image for multimodal); launch-path accuracy smoke through each unit's own deployment entry; token witnesses with declared workloads at every member; and `staircase-onboard gate <name>` to run one gate or witness standalone. Squashed from user/williamj/staircase-polish @ c8109d6f90 (10 commits): - [feat] staircase: statistical accuracy floors and a cross-member finding - [feat] staircase: per-prompt acceptance gate on a natural-text workload - [feat] staircase: scheduler-equivalence witness with an optional step-trace hook - [fix] staircase: the envelope's acceptance evidence follows the speculation predicate - [feat] staircase: boot workload declared in task.yaml, matched on generated text, with a real image for multimodal - [feat] staircase: launch-path accuracy smoke through each unit's own deployment entry - [feat] staircase: token witnesses declare their workload and refuse continuations too short to compare - [feat] staircase: `staircase-onboard gate <name>` runs one gate or witness standalone - [feat] staircase: feature witnesses run at every member, cheapest first - [feat] staircase: delivery re-runs the new gate kinds, and the ledger records the statistical floor Formatting and lint fixes folded in for this commit's files: - [chore] staircase: apply pre-commit formatting (4 files) Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
… --tree jobs, deadlines, sessions and external driver A spool scheduler (priority queue and device slots) replaces the flock protocol, with the legacy watcher kept behind STAIRCASE_SPOOL_WATCHER=legacy; --tree jobs and refusal of mixed-checkout results; atomic native rebuilds announced to every session; sessions declared in task.yaml with planned hand-over; deadlines counted from job start, no-progress detection, host-memory admission and a watchdog; and the external-transport driver as `staircase-onboard driver`. Squashed from user/williamj/staircase-polish @ c8109d6f90 (11 commits): - [feat] staircase: spool scheduler replaces the flock protocol - [feat] staircase: --tree jobs and refusal of mixed-checkout results - [feat] staircase: atomic native rebuild announced on every session - [feat] staircase: sessions declared in task.yaml, rendered entries and planned hand-over - [feat] staircase: deadlines from start, no-progress detection, host-memory admission, watchdog - [fix] staircase: a spool receipt is read only once it holds an exit code - [feat] staircase: the external-transport driver as `staircase-onboard driver` - [doc] staircase: execution substrate in README, BUILD_AND_TEST and TROUBLESHOOTING - [feat] staircase: STAIRCASE_SPOOL_WATCHER=legacy keeps the flock watcher as an escape hatch - [fix] staircase: the driver names the decision file exactly as the request does, and never overwrites one - [fix] staircase: only the CLI starts the orchestrator heartbeat thread Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…ayout: OpWrapper entries, a target's own ops/, phase targets Brings the workflow onto the modeling_v2 conventions of NVIDIA#19977, which this branch sits on. Catalog entries are OpWrapper classes whose ARCHS and CELLS are the executable contract: the survey reads certification from them, delivery checks them (and a target's own ops/<category>/ entries with their tests), and the smith and kernel skills write them, in the shared catalog or the target's ops/. Delivery checks the target as Prefill/DecodeTarget over a ModelingV2Core with a ModelWeights table, the modeling skills and the role prompts describe that target, the gates turn on the step-contract check, and the capacity audit leaves a target's ops/ to their cells. Squashed from user/williamj/staircase-polish @ c8109d6f90 (11 commits): - [fix] staircase: catalog index migration keeps the dividers of categories with no entry yet (NVIDIA#19977 catalog layout) - [fix] staircase: delivery checks catalog entries as executable contracts, and a target's own ops/ (NVIDIA#19977 catalog layout) - [fix] staircase: the survey reads an entry's certification from its ARCHS and CELLS, and lists other targets' ops/ as promotable (NVIDIA#19977 catalog layout) - [fix] staircase: kernel-source registry, smith brief and capacity audit name the entry, not a contract file (NVIDIA#19977 catalog layout) - [fix] staircase: smith and the kernel skills write OpWrapper entries in the shared catalog or the target's ops/ (NVIDIA#19977 catalog layout) - [fix] staircase: a smith dispatch names the target whose ops/ an ops/ entry goes in (NVIDIA#19977 catalog layout) - [fix] staircase: delivery checks the target the NVIDIA#19977 way (NVIDIA#19977 target layout) - [fix] staircase: modeling skills teach the target layer, bound entries and the weight table (NVIDIA#19977 target layout) - [fix] staircase: assembler, reviewer, planner and auditor prompts describe the NVIDIA#19977 target (NVIDIA#19977 target layout) - [fix] staircase: gates turn on the targets' step-contract check (NVIDIA#19977 target layout) - [fix] staircase: the capacity audit leaves a target's own ops/ to their cells (NVIDIA#19977 target layout) Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
… tier the survey measures FlashInfer is a pinned dependency, but the tree wraps a handful of its kernels as trtllm ops, and the workflow saw only those: the sourcing ladder and the survey knew torch.ops.trtllm and nothing else of the library. Adds tier 3 (a FlashInfer callable called directly) between the in-tree callable and native torch, a survey that reads the installed package's public API off disk and records which callables the engine already references, a flashinfer_api kernel source, and the skills and prompts that search FlashInfer before a writing tier or a ceiling. Against flashinfer-python 0.6.18: 558 public callables, 510 of them referenced nowhere in the engine. Squashed from user/williamj/staircase-polish @ c8109d6f90 (1 commits): - [feat] staircase: FlashInfer's public API is a sourcing tier the survey measures Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…d BUILD_AND_TEST for the polished workflow Operator documentation for everything above, and LESSONS.md, which replaces the raw findings of two onboarding runs with 34 lessons, each naming the in-tree mechanism that now prevents it. Also points the repository guide (AGENTS.md) at the environment failures that read as model failures. Squashed from user/williamj/staircase-polish @ c8109d6f90 (4 commits): - [doc] point the repo guide at the failures that are not the model's - [doc] staircase: README for per-role routing, prompt snapshots and worked examples - [doc] staircase: replace the raw run findings with LESSONS.md - [doc] staircase: LESSONS.md credits the mechanisms that landed with the hygiene and preflight work Also carries the documentation edits made by the commits squashed into the earlier commits: BUILD_AND_TEST.md, README.md, TROUBLESHOOTING.md. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…b's session nsys profile (and any setsid'd server) is re-parented to init once the job's leader exits; job_processes() then no longer sees it, so a cancel or the leftover reaper never killed it and the next job ran on a GPU a stranded server still held. Find such processes by the STAIRCASE_SPOOL_JOB / STAIRCASE_SPOOL_WATCHER markers in their environment once the verdict is set. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…uner campaign
A performance stage for modeling_v2 targets, chained after deliver
(perf.enabled) or standalone (staircase-onboard tune / --stage tune):
ground truth (target, stock reference, noise repeats), the config ladder
(Python: runtime rungs measured in parallel across spool sessions, judged
against same-host controls, winners stacked), and a campaign of tuner turns
(one hypothesis per worktree; the orchestrator measures e2e, applies the keep
rule and the accuracy gate, and cherry-picks keeps onto tune/best).
Adds the tuner role, prompt and staircase-perf-tuning skill, the perf block,
tune/{bench,ladder,records,campaign,requests,worktree,microbench,
gate_accuracy,stage,cli}.py and staircase-onboard perf {ladder,campaign,table}.
Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…the LLM-API argument in every gate Target selection is the LLM-API argument modeling_v2 (default "off"); nothing in the engine reads TRTLLM_MODELING_V2 any more. The gates only exported the switch, so boot, acceptance, witness and accuracy gates served the built-in model while recording the verdict as the target's. eval_command now merges modeling_v2: <mode> into the member's options YAML and the engine driver passes it to the quickstart's LLM(...). Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…ked candidates, session-mode nsys What the first real campaign (Qwen3.8-Flash-Next-NVFP4, 1x GB300) needed: - judge every measurement against a control from its own host: GB300 nodes differed by up to 4% at concurrency 1 for identical configs, and the ladder rejected a +4.8% rung on node effect; - evaluate a candidate stacked on the current best tree (eval worktree), re-stacking when a keep moves it; include a parent candidate's commits; - submissions through an inbox so only the campaign loop writes its state; idempotent spool submission; serialized worktree creation; - nsys session mode (nsys launch + external start/stop) and nsys_summary.py for per-step attribution; bench.py tears down its server on SIGTERM and refuses a busy device; - LESSONS 35-39, troubleshooting entries, the perf block in task.example.yaml. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…d host; re-stack on any move A control of another config (or host) must never stand in for this one: the control label carries the config digest, a candidate measured at an older config is re-measured (its measurement kept as attribution only), a missing same-host control is measured before judging, and a candidate whose best tree moved is re-stacked before it is queued. Commits the best tree already carries (by patch identity) are not applied again; eval worktrees are reused instead of re-created. Test: test_a_config_change_re_measures_against_a_control_of_that_config_and_host. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…-dry-run for the tune entry The task schema refused a top-level perf block, so the tune stage could not be configured through task.yaml at all; it is now a known key validated by tune.stage.validate_perf_block. --dry-run stops after preflight for the tune entry too. Workflow tests cover the standalone entry, chaining after delivery, re-entry of a delivered run, and dry-run. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…s with an earlier keep Candidates written in parallel from one base collide in the forward file once one is kept; the textual conflict is not a verdict. The stage dispatches one rebase turn (render_rebase_request) and re-evaluates the rebased candidate on the best tree. Test: test_a_candidate_that_conflicts_with_a_keep_is_rebased_and_retried. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…est when a keep lands; record the measured tree A keep moves the best tree; every other candidate measured on the old one would be re-measured anyway, so its job is cancelled and it re-stacks on the next pass. bench.py records the tree the scheduler put first on the path (STAIRCASE_TREE) rather than the --tree argument. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…plays at their launch Graph-replayed kernels carry no runtime correlation; attributing them by GPU start charged each replay to whichever step the host was in when it ran and reported idle that was not there (31% vs a measured 1.7% at batch 128). Group graph kernels into replays by graphId, place the k-th replay at the k-th cudaGraphLaunch, and judge a graph step on its replay's span. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…host's control of the new best The kept candidate's e2e label measured exactly the new best tree at the current config on its host; register it as that host's control instead of measuring it again. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…ted; correct spoolctl syntax in the docs A candidate re-stacked on a new best after passing its gate was kept on the old gate result, so the combined tree went ungated. Gate results now live under gates/<slug>-<tree sha>. The request template and the skill reference spelled 'spoolctl.py launch --spool S'; the global option precedes the subcommand. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…ee, measure and gate them once Kept one at a time, each keep forced every other winner to re-measure on the moved best (four winners: four serial rounds). Winners now wait for the other measurements on the same best; several are stacked in one eval tree, measured once against the same-host control and kept together if the stack holds each metric's best single gain within the loss floor and passes one accuracy gate. Otherwise the strongest single winner is kept and the rest re-stack. Test: test_winners_on_one_best_are_stacked_measured_and_gated_once. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…h the largest summed gain; rebase the rest onto the batch while it is measured Winners written in parallel collide in the forward file. The batch picked winners greedily by gain, so one large winner could exclude three smaller ones that stack together. Stacking is now simulated in the object store (merge-tree + commit-tree, no checkout) and the compatible set with the largest summed gain is measured. Winners left out are marked conflict with rebase_onto tune/eval-batch pinned to the batch commit; a rebased candidate waits for the batch and stacks on the new best once it is kept, or is sent back to rebase onto tune/best when it is not. Tuner turn prompts now pin grep/find to explicit search roots so embargoed lines never surface from a repository-wide search. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…l checkout instead of a fresh worktree A fresh eval worktree checks out the whole tree (2-4 minutes on Lustre) inside the campaign step. A kept, reverted or dropped candidate's eval checkout is moved and re-pointed with checkout -B / reset --hard / clean instead. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…ofiling the moved best tree The campaign ended when its one roadmap was spent, even with iteration budget left; the kept candidates had moved the profile it was ranked on. A second roadmap turn (perf.campaign.max_roadmaps, default 2) re-profiles the best tree and is told which slugs were tried and where their follow-ups are recorded. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…asurement, behind it on the same node A new best tree queued a control on every free node before any candidate was measured (five node-runs for three candidates). A measurement now goes to a free node whose host already has a control, else behind that node's control; nodes no measurement needs stay free. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…ates and batch runs by their real job names Gate jobs are named gate-<slug>-<tree sha> (and gate-batch-<sha>); the resume path adopted gate-<slug>, so a restarted loop neither waited on nor could cancel the gates already running. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…re-run, and reused eval checkouts drop ignored caches qsa-rowtile-union-compaction (WIN +1.8% con128) was reverted because its gate's test suite failed to collect: the reused eval checkout carried __pycache__ from its old path and pytest imported stale modules. Reuse now cleans ignored files (the native links are re-made), and gate_accuracy reports ERROR (pytest rc 2-5) instead of FAIL, which the campaign re-runs once instead of reverting. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…l name where hypotheses come from The campaign's sources -- the config ladder, per-step-class profiles, fusion and ordering patterns, FlashInfer as installed (the preflight's surface.md inventory), this repository's perf commits on similar modules, the sister engines, and the recorded kernel choices -- were spread over the stage, the skill references and the operator's notes. The skill now has one table mapping each source to where it lives in the stage, and every tuner request carries a 'Sources to check' block with the concrete paths and the git query. The profiling section reflects session-mode nsys and per-step-class summaries. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…o to the shared catalog Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…refix A second campaign in one repository collided on tune/best, as the stage did before it got run-scoped branches; perf.campaign.branch_prefix sets it. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…uments The gate's trtllm-eval arguments were the Qwen defaults (thinking off, 512 output tokens). A reasoning model such as gpt-oss-120b scores 53 on gsm8k under them (answers cut off), against 90 with its own settings. perf.campaign.accuracy.eval_args (stage) / campaign.eval_args (CLI) passes the model's settings through. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…ecisions record them
The roadmap request now carries the same 'Sources to check' block as a
candidate request (installed FlashInfer inventory, kernel_choices.json,
repository perf commits, sister engines) and asks each roadmap item for
its sources. Decision files carry sources: [{source, ref, outcome}],
kept in the campaign ledger per candidate.
Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
Covers step classes, graph replays charged to the launching step (not the step the host is in when the GPU runs them), kernel families and busy time. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…eline is the first control A follow-up campaign on an already tuned config disables the ladder; its ground baseline measured the best tree at the same configs, so the campaign adopts it (and its repeats) as same-host controls. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…s and the embargo A roadmap turn had to discover the best tree, configs, spools, env script and model on its own, and its request did not list the source embargo. It now carries the same facts a candidate request does. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…'s host Ground spread t-baseline and its repeats across sessions, so the noise floor measured host-to-host spread: on the Qwen3.8 follow-up it read 0.77% (keep threshold 2.3%) and a low first run on the second host became that host's control, inflating a candidate's delta to +2.6% where the same-host wrap measured +1.3%. The baseline and the stock reference still run side by side; the repeats then follow the baseline onto its session. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…nel ledger Every roadmap turn now also writes perf_optimize's kernel ledger: each kernel down to a GPU-time coverage target answers elimination / faster / fusion / overlap with a roadmap slug or an evidenced dismissal. The stage validates it with perf_optimize's own load_ledger + cross_validate, gives one fix turn carrying the validator's findings, records the coverage in the campaign ledger, and proceeds either way (campaign.kernel_ledger: require | off; campaign.kernel_coverage_pct, default 80). Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
… start before its session With a session_spool environment the task validation requires the spool directory, so the orchestrator could not be started until its compute session had imported the image (5-10 min). --wait-for-spool MINUTES waits for the spool to appear; validation still owns the verdict. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…currency point The warmup ran 16 prompts at concurrency 16, so the batch shapes of the con128 point were first built inside its measured window on a fresh session: on three GB300 sessions the first con128 measurement read 1.5-2.2% below later ones on the same host while con1 matched. The warmup now runs at the largest point with twice its prompts (OSL 64). Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…skills copy Materializing the packaged skills removed and re-copied them on every start; when the workspace's .claude/skills is read-only to the process (a sandbox protects it) the silent rmtree left the copy in place and copytree failed, so the run could not resume. An identical copy is now kept as is. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…s result is re-queued An adopted receipt can report rc 0 while the label's result directory is gone; the stage then failed with 'the baseline could not be measured'. A missing meta.json now re-queues the label like any other failed run. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…de by side The campaign created each candidate's worktree in its main loop and git worktree add held the repo lock through the checkout, so three tuner turns started minutes apart on a parallel filesystem. Registration (--no-checkout) keeps the lock; the checkout runs outside it in the turn's own thread. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
… is rebuilt An orchestrator stopped mid 'git worktree add' left the tree locked 'initializing' without an index, and the next start handed it to a tuner as is (no tensorrt_llm/). open_candidate now checks the tree is complete and otherwise unlocks, removes and re-creates it. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…ed together A NEUTRAL whose gain is real (some metric above both the noise band and near_min, default min_gain/4) and that loses nothing is held as 'near' instead of reverted. When a best tree has no winners and nothing left to measure, its compatible near misses are stacked through the batch path and judged by the same keep rule and gate; a stack that does not clear them reverts its members (no single is gated). campaign.stack_near (default true) and campaign.near_min configure it. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…t-for-spool Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…lap benches at layer scope Ground warns when noise_repeats < 2 (two samples read 0.32% at con128 where the host ranged 1.2% over the run). The perf skill's Ordering note asks overlap candidates to benchmark a whole decoder layer with the other side-stream users, and to keep side-stream work to few, wide CTAs. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…merged The delivery audit still checked the pre-merge NVIDIA#19977 contract: entries defining raw_call, targets deriving from Target, a ModelWeights table, every entry listed in catalog/index.yaml, and routing naming the target by its absolute module path. As merged, an entry's op call is __call__, targets and weight tables have no base class (a class with a WEIGHTS table, exposed as MODEL_WEIGHTS), there is no catalog index, and routing imports the target relative to its family package. The real gpt-oss and DeepSeek targets now pass every check (25 and 43). Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
modeling_v2 as merged keeps no catalog/index.yaml: an entry is one OpWrapper per file under catalog/<category>/. The staircase still generated that index from per-entry fragments and synced it before every turn and at delivery. The generator (catalog_index.py) and its hook are removed, and the survey probe lists the shared entries from the catalog files themselves (summary from the module docstring) and reads an entry's op from __call__. On this tree it reports the 8 shared entries and 11 target-owned ops with their cells and receipts. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…erged The smith, assembler, reviewer, auditor and plan prompts now describe the modeling_v2 layout on main: an entry is one OpWrapper subclass whose __call__ takes every argument explicitly, the catalog is its entry files, the core's _select_target picks a plain PrefillTarget or DecodeTarget, and the weight table is a W role class plus a WEIGHTS table and MODEL_WEIGHTS. Target selection is the LLM-API argument modeling_v2; the gates keep exporting TRTLLM_MODELING_V2 and the harness hands it to the constructor. test_prompts now refuses the retired draft names in any prompt, and the kernel-source attribution test reads the trtllm ops from the catalog and target ops/ files instead of skipping for want of an index. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
… as merged The modeling, kernel and feature skills, their references, and the README, LESSONS, BUILD_AND_TEST and TROUBLESHOOTING guides now match modeling_v2 on main: entries are called through __call__ with every argument at the call site, the catalog is its entry files with no index, the core's _select_target picks a plain PrefillTarget or DecodeTarget, and the weight table is a W role class with WEIGHTS and MODEL_WEIGHTS. Resolution is described as main does it: route returns the target class, the loader carries it on ModelConfig.modeling_v2_target, and nothing registers under a synthetic name. Target selection is the LLM-API argument modeling_v2; the gates export TRTLLM_MODELING_V2 and the harness passes it on. The multi-rank reference places the topology check in routing.py, since a target carries no configuration asserts. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
ruff-format over the tune stage and its tests, and the remaining ruff findings fixed by hand: one-line docstring summaries (D205), wrapped long lines (E501) and descriptive names for `l` (E741). No behaviour change; the rendered tuner requests and turn prompt are byte-identical. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
…modeling_v2 Package agent_flow.workflows.trtllm_modeling_v2, CLI trtllm-modeling-v2, TrtllmModelingV2Workflow, build_trtllm_modeling_v2_prompts, and skills trtllm-modeling-v2-* (the repo's trtllm- skill prefix). The workflow's own environment variables become MV2FLOW_*: TRTLLM_MODELING_V2* stays the engine's and the gates' switches, and MV2_* is MVAPICH2's. Internal temp dirs, locks, log tags and job names use mv2flow-; delivery branches are trtllm-modeling-v2/<slug>. "Staircase" remains only as the shape of a plan (core first, then one feature per unit) and in two quoted historical errors. Signed-off-by: Wanli Jiang <35160485+Wanli-Jiang@users.noreply.github.com>
ad3e732 to
6490d8b
Compare
|
Thanks both for the reviews. I've force-pushed an updated branch: it is rebased onto main now that #19977 has merged (so only this PR's own commits remain), aligned with modeling_v2 as merged, and it adds the
Both concerns are fair, and this week gave a concrete example of the second: aligning with modeling_v2 as merged meant rewriting 32 skill documents. Some context on how these skills differ from
Proposal, and I'd like your view before I change the code:
I lean towards (a) for this PR plus the A/B as a follow-up, but would go with (b) if you'd rather keep the detailed text out of the repo until there is data. Which do you prefer? |
@coderabbitai summary
Description
What
trtllm_modeling_v2istrtllm_modeling_v2(previouslystaircase-onboard; renamed following review) is an agent-flow workflow with two stages:tensorrt_llm/_torch/_experimental/modeling_v2/models/<family>/<checkpoint>__<arch>__<parallel>/, built from catalog entries and the target's ownops/. The target is trusted because it passes accuracy gates, not because it shares abstractions with other models.The modeling_v2 catalog, targets and router are already in tree (#19977); this PR is the agent half. An onboard run has five phases:
Everything is driven by one
task.yaml;perf.enabled: truechainstuneafter delivery, andtrtllm-modeling-v2 tuneruns it standalone on a delivered target.Why: onboard
The workflow has onboarded two checkpoints end to end. A MiMo-V2.6 run produced findings F001–F011 and a retrospective; a DeepSeek-V4.1-Flash-NVFP4 run (8 units, about 51 h) produced F001–F051 and a reflection.
In the second run, 9 defects escaped every gate and were found later by hand:
trtllm-serve(F040).The run also cost 6 session deaths, lock starvation on the shared GPU slots, and about 30 manual claim/dispatch/unlock interventions (F010–F012, F025, F031–F032, F044, F046). Records contradicted each other (F033), and commits carried sandbox placeholders and DCO identity mismatches (F002, F022, F043).
This PR ships the workflow together with the fixes for those findings, condensed into
LESSONS.md: each lesson with its symptom, its cause, the in-tree mechanism that now prevents it, and any gap still open.Why: tune, and what it did on one model
A correct target is not a fast one: the onboarded Qwen3.8-Flash-Next-NVFP4 target (1× GB300, ISL 8192 / OSL 1024, CUDA graphs on, MTP off) started at 0.83× the in-tree model at concurrency 1 (both on their default kernels). The tune stage then ran on it for about 28 h: 30 candidates, 19 kept, 2 delivered as kernel entries. Every keep passed the target's test suite, the modeling_v2 contract tests and gsm8k (anchor 96.36; kept scores 95.91–96.66).
A concurrency sweep afterwards, all three variants on each of 3 hosts (output tok/s/GPU, max_batch_size 128):
modeling_v2: off, default kernels)The in-tree model in this sweep runs the engine's default kernel switches:
moe_config.backend: AUTO, which picks the CUTLASS MoE for this checkpoint, andTRTLLM_LOW_M_GEMM_BACKENDoff. Withmoe_config.backend: TRTLLMandTRTLLM_LOW_M_GEMM_BACKEND=auto, the kernel families the tuned target also uses, the in-tree model reaches 245.6 tok/s/user at concurrency 1 and 3,342 tok/s/GPU at 128 (gsm8k 95.94). Measured on 3 hosts with the tuned target on each (the last row on 2 of them); the ratios are same-host:moe_config.backend: TRTLLMandTRTLLM_LOW_M_GEMM_BACKEND=autoSo most of the gap to the default in-tree model is its kernel selection; what the in-tree model cannot switch to (the target's fusions and kernels below) is worth 1.11× at concurrency 1 and 1.28× at 128. The tune stage does not yet search the reference model's own switches; that is a follow-up below.
Most of the gain is fusion (hyper-connection sites, MoE routing/finalize into neighbouring kernels, PLE), kernel sourcing (FlashInfer GDN and low-M GEMMs, a row-tiled sparse-attention prefill kernel) and one config-ladder rung. The tuned target code is not part of this PR; it lives on its own branch.
What changed (by area)
runner, prompts, the materialized skills, and the gates and witnesses. It also adds the agent-flowruntimepackage: turn executors (in-process, file dispatch) and command executors (local, slurm, spool, delegated).serving_envelopeandfeature_matrixintask.yaml; the certified set is derived from them, not from the gate tuples. A capacity-constant audit (F045); integer-width probes in kernel-verify and a smith brief per call site (F042, F047); a typedcertification_gapdecision fanned out to verify smiths (F019, F020, F026, F028); early delivery checks as warnings (F041); a preflight refusal of any speculation algorithm the launch path cannot run.agents:block (#19522), with Codex roles fixed in-process. Prompt snapshots (#19715), the spill check (#19766), duplicate request ids in file dispatch fixed. Model specifics live inexamples/, which a run never materializes.commit.shcommits and signs off as the repo user and refuses symlinks, placeholders and out-of-policy paths (F002, F022, F043).trtllm-modeling-v2 premerge lint|ci|copyright|hygiene|split|resign|pr-open|pack;source_embargoenforced with PreToolUse/PostToolUse hooks and an attempt log; opt-in--overlap-units(F027); a delivery tail that audits the run's commits.trtllm-serveand the disagg proxy; witnesses at every member;trtllm-modeling-v2 gate <name>.--treejobs with mixed-checkout results refused (F044); atomic native rebuilds (F025); sessions declared intask.yamlwith planned hand-over; deadlines from job start plus a watchdog; multi-nodemn_*launchers; the external-transport drivertrtllm-modeling-v2 driver(F010, F017, F030).OpWrapperclasses called through__call__with every argument at the call site;CELLSandARCHSare the executable contract, read by the survey and checked by delivery (shared catalog and a target's ownops/). The catalog is its entry files (no index). Delivery checks the core's_select_targetover plainPrefillTarget/DecodeTargetclasses, aW-row weight table withMODEL_WEIGHTS, and routing that returns the target class. Target selection is the LLM-API argumentmodeling_v2; gates pass it through the harness and setTRTLLM_MODELING_V2_VALIDATE=1for the step-contract check.__call__. The survey reads the installed package's public API off disk (no import, no GPU) and records which callables the engine already references. Against flashinfer-python 0.6.18: 558 public callables, 510 referenced nowhere in the engine.tune/: ground truth (baseline, in-tree reference, identity repeats as the noise floor), the config ladder, and the candidate campaign (one hypothesis = one worktree = onetunerturn; same-host controls; stacked evaluation of compatible winners and of near misses; speculative rebases; the keep gate = target suite + contract tests + gsm8k).bench.py(LLM-API yaml configs,--nsyssession-mode capture),nsys_summary.py(per step class, CUDA-graph replays placed at their launch),microbench.py, a FlashInfer/kernel-ledger roadmap requirement, and theperftooling CLI.LESSONS.md; a short "environment failures that read as model failures" table inAGENTS.md.Outside
agent-flow/agent_flow/workflows/trtllm_modeling_v2/and its tests, the PR touches only:agent-flow/agent_flow/runtime/(new package; the oldruntime.pybecomesruntime/portal.py) andagent-flow/tests/runtime/;agent-flow/pyproject.toml: thetrtllm-modeling-v2entry point, package-data, and an E501 per-file ignore for prompt tables;agent-flow/README.md: one sentence;AGENTS.md: one table.There are no changes under
tensorrt_llm/,cpp/ortests/, and no new dependencies.Naming
Following review, the workflow is
trtllm_modeling_v2(package),trtllm-modeling-v2(CLI),TrtllmModelingV2Workflow, and skillstrtllm-modeling-v2-*(the repo'strtllm-skill prefix). The workflow's own environment variables useMV2FLOW_*, so they never share a namespace with the engine'sTRTLLM_MODELING_V2*switches (and stay clear of MVAPICH2'sMV2_*). In the code, "staircase" now appears only in two quoted historical error messages; in prose it is just the shape of a plan (core first, then one feature per unit).How to run
Test Coverage
All tests are CPU-only and need neither GPUs nor model weights. Pass
PYTHONPATH=agent-flowwhen an editable install points at another checkout.pytest agent-flow/tests/workflows/trtllm_modeling_v2: 1870 passed, 2 skipped, including the tune suites (test_tune_stage,test_tune_ladder,test_tune_bench,test_tune_nsys_summary,test_tune_worktree_parallel, ...), the gate, ledger and substrate suites (with the substrate's fault injection),test_deliveryagainst the in-tree gpt_oss and DeepSeek-V3 targets, andtest_prompts, which refuses the pre-merge modeling_v2 names in any role prompt.pytest agent-flow/tests(all agent-flow workflows, guarding the sharedruntimepackage): 3524 passed, 5 skipped..pre-commit-config.yamlover every file this PR changes (origin/main..HEAD): all hooks pass.GPU validation. The tune stage ran end to end on Qwen3.8-Flash-Next-NVFP4 (above) and was started on gpt-oss-120b (one keep, gsm8k pass, before it was stopped). The onboard gates were exercised end to end by the two onboarding runs that produced the findings; the historical-defect replay and a pilot onboarding run on this branch are follow-ups.
Known limitations and follow-ups
tunemeasures but never blocks delivery.TRTLLM_LOW_M_GEMM_BACKEND, for the in-tree reference. A reference-side ladder, gated on accuracy, is a follow-up.tune --stopthat cancels its jobs and writes the partial summary.--overlap-units, off by default).dsparkspec stops at preflight with an explicit message.PR Checklist
Please review the following before submitting your PR:
PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.
PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.
Test cases are provided for new code paths (see test instructions)
If PR introduces API changes, an appropriate PR label is added - either
api-compatibleorapi-breaking. Forapi-breaking, includeBREAKINGin the PR title.Any new dependencies have been scanned for license and vulnerabilities
CODEOWNERS updated if ownership changes
Documentation updated as needed
Update tava architecture diagram if there is a significant design change in PR.
The reviewers assigned automatically/manually are appropriate for the PR.
Please check this after reviewing the above items as appropriate for this PR.