Run end-to-end commands from inferencex-e2e/, which owns pyproject.toml, uv.lock, and .python-version. Workflow dispatch generator arguments also resolve paths relative to that directory. The project-local .python-version selects its Python version.
In order to test configurations described in inferencex-e2e/configs, the primary workflow file used is .github/workflows/e2e-tests.yml. As input, this workflow takes in the CLI arguments for the python -m infx.matrix.generate command. The command usage is shown below:
usage: python -m infx.matrix.generate [-h] {full-sweep,test-config} ...
Generate benchmark configurations from YAML config files
positional arguments:
{full-sweep,test-config}
Available commands
full-sweep Generate full sweep configurations with optional
filtering by model, precision, framework, runner type,
and sequence lengths
test-config Generate full sweep for specific config keys.
Validates that all specified keys exist before
generating.
options:
-h, --help show this help message and exit
The full-sweep command generates benchmark configurations with optional filtering. You can specify --single-node, --multi-node, or both. If neither is specified, both types are generated.
usage: python -m infx.matrix.generate full-sweep
--config-files CONFIG_FILES [CONFIG_FILES ...]
[--runner-config RUNNER_CONFIG]
[--no-evals | --evals-only] [--all-evals]
[--smoke] [--trim-conc]
[--runner-node-filter RUNNER_NODE_FILTER]
[--scenario-type {fixed-seq-len,agentic-coding} [{fixed-seq-len,agentic-coding} ...]]
[--model-prefix MODEL_PREFIX [MODEL_PREFIX ...]]
[--precision PRECISION [PRECISION ...]]
[--framework FRAMEWORK [FRAMEWORK ...]]
[--runner-type RUNNER_TYPE [RUNNER_TYPE ...]]
[--seq-lens {1k1k,8k1k} [{1k1k,8k1k} ...]]
[--step-size STEP_SIZE]
[--min-conc MIN_CONC]
[--max-conc MAX_CONC]
[--max-tp MAX_TP]
[--max-ep MAX_EP]
[--single-node] [--multi-node]
If neither --single-node nor --multi-node is specified, both types are generated.
By default, throughput runs for every generated config and eval-only jobs run for the selected 8k1k subset and the AgentX GSM8K subset. --no-evals disables eval jobs, --evals-only emits only that selected subset, and adding --all-evals expands it to every eligible 8k1k fixed-sequence and agentic config. --all-evals always emits only those eval-only jobs, with or without --evals-only, but it cannot be combined with --no-evals.
--step-size must be greater than 1 and applies to concurrency ranges. --min-conc / --max-conc drop concurrencies outside the bounds, including explicit conc-list values. A single-node fixed-sequence conc-start/conc-end range that crosses a bound is clamped to it, and a fixed-sequence config with no concurrency left under --max-conc runs at the cap. When both bounds are set, --min-conc must not exceed --max-conc.
--trim-conc (the trim-conc input of e2e-tests.yml) keeps only the minimum concurrency of every generated single- and multi-node deployment shape, after eval selection, for a lowest-concurrency smoke run; in changelog-ref mode only throughput rows are trimmed, and evals keep their selected concurrency. No PR label enables trimming.
Generate all single-node and multi-node configurations (default):
full-sweep --config-files configs/nvidia-master.yaml
Test all single-node dsr1 configurations on B200 with 8k1k sequence lengths:
full-sweep --single-node --model-prefix dsr1 --runner-type cluster:b200-nscale --seq-lens 8k1k --config-files configs/nvidia-master.yaml
Test all single-node fp8 precision configs for 8k1k workloads:
full-sweep --single-node --precision fp8 --seq-lens 8k1k --config-files configs/nvidia-master.yaml configs/amd-master.yaml
Test all single-node TRT configs on H200 runners:
full-sweep --single-node --framework trt --runner-type h200 cluster:h200-dgxc --config-files configs/nvidia-master.yaml
Test specific single-node model on specific hardware with specific sequence lengths:
full-sweep --single-node --model-prefix dsr1 --runner-type cluster:b200-nscale --precision fp4 --framework sglang --seq-lens 8k1k --config-files configs/nvidia-master.yaml
Limit concurrency and parallelism for faster testing:
full-sweep --single-node --max-conc 64 --max-tp 4 --config-files configs/nvidia-master.yaml
Test all multi-node configurations:
full-sweep --multi-node --config-files configs/nvidia-master.yaml
Test agentic configurations:
full-sweep --scenario-type agentic-coding --config-files configs/nvidia-master.yaml configs/amd-master.yaml
The test-config command generates the full sweep for one or more specific config keys. This is useful for testing individual configurations without filtering by model prefix, framework, etc.
usage: python -m infx.matrix.generate test-config
--config-files CONFIG_FILES [CONFIG_FILES ...]
[--runner-config RUNNER_CONFIG]
[--no-evals | --evals-only] [--all-evals]
[--smoke] [--trim-conc]
[--runner-node-filter RUNNER_NODE_FILTER]
[--scenario-type {fixed-seq-len,agentic-coding} [{fixed-seq-len,agentic-coding} ...]]
--config-keys CONFIG_KEYS [CONFIG_KEYS ...]
[--conc CONC [CONC ...]]
[--exp-names EXP_NAMES [EXP_NAMES ...]]
[--seq-lens {1k1k,8k1k} [{1k1k,8k1k} ...]]
Config keys support wildcard patterns using * (matches any characters) and ? (matches a single character). Patterns that match no keys will raise an error.
Test a single config by exact name:
test-config --config-keys dsr1-fp4-b200-sglang --config-files configs/nvidia-master.yaml
Test multiple exact configs:
test-config --config-keys dsr1-fp4-b200-sglang dsr1-fp8-h200-trt --config-files configs/nvidia-master.yaml
Use wildcard to test all B200 configs:
test-config --config-keys *-b200-* --config-files configs/nvidia-master.yaml
Use wildcard to test all sglang configs:
test-config --config-keys *-sglang --config-files configs/nvidia-master.yaml configs/amd-master.yaml
Use wildcard to test all dsr1 model configs:
test-config --config-keys dsr1* --config-files configs/nvidia-master.yaml
Mix exact keys and patterns:
test-config --config-keys dsr1-fp4-b200-sglang qwen3.5* --config-files configs/nvidia-master.yaml
Override concurrency for targeted testing:
test-config --config-keys *-b200-* --conc 4 8 --config-files configs/nvidia-master.yaml
Run eval-only jobs for every generated fixed-sequence config:
test-config --config-keys dsr1-fp8-h200-sglang --evals-only --all-evals --config-files configs/nvidia-master.yaml
run-sweep.yml sweeps only same-repository PRs that change
inferencex-e2e/perf-changelog.yaml, using the appended entries as the matrix.
Apply exactly one primary label, normally full-sweep-fail-fast.
Fork PRs use the trusted dispatch.
| Primary label | Canary | Per-matrix fail-fast |
|---|---|---|
full-sweep-fail-fast |
Yes | Yes |
full-sweep-enabled |
Yes | No |
non-canary-full-sweep-enabled |
No | No |
All primary labels run the full selected concurrency matrix. Modifiers require
a primary label: all-evals expands eligible evals while retaining throughput;
evals-only suppresses throughput; agentx-fast uses one extra AgentX warmup
request after mandatory primers and a 20-minute profile, leaving fixed-sequence
and eval settings canonical. all-evals/evals-only reject changelog additions
with append-only: true or no-evals: true. Do not reuse an evals-only or
agentx-fast run. For lowest-concurrency smoke, dispatch e2e-tests.yml with
trim-conc: true; no PR label trims concurrency.
Labels authorize same-repository sweeps on draft or ready PRs. Marking ready
does not dispatch a sweep. Changing a recognized primary or modifier label
cancels the active sweep; another starts only if a primary label remains.
To retrigger an already-labeled PR, remove and reapply its primary label.
Merge conflicts block sweeps. Queue priority comes from the PR diff and the
PR description's checklist, not priority labels. A PR gets a small bonus when
every item under its Checklist heading is checked, except conditional items
("If ...", "Before merging ...") that do not apply yet. The checklist is read
when the sweep starts, so later edits count from the next sweep. Trusted
external sweeps classify the approved PR diff the same way. Manual
e2e-tests.yml and profile.yml dispatches of a revision not yet on main
classify its diff from the merge
base only for patchwork, so engine-patching branches still run last. Klaud runs
and revisions already on main keep unclassified scoring.
The canary is the lowest-concurrency non-eval candidate among single-node
fixed-sequence 1k/1k, 8k/1k, or AgentX entries, falling back to multi-node AgentX.
It is removed from the remaining matrix. If none qualify, fan-out proceeds
without a canary; otherwise all matrices require canary success. Fail-fast
cancels siblings within each matrix family, not every independent family.
Find the first actual failure before treating a cancelled run as a flake.
Manual e2e-tests.yml has no canary and defaults fail-fast to false.
Run from inferencex-e2e/. After fetching and merging origin/main, if the
changelog conflicts, use the helper while index stages 1/2/3 still exist:
uv run --extra workflows python -m infx.workflows.prepare_perf_changelog_merge resolve-conflict \
--changelog-file perf-changelog.yaml --pr-number "$PR" --repo SemiAnalysisAI/InferenceX
git add perf-changelog.yaml
git commit --no-edit
uv run --extra workflows python -m infx.workflows.validate_perf_changelog \
--changelog-file perf-changelog.yaml --base-ref origin/main --head-ref HEADThe helper preserves main's bytes and appends only unique PR contributions.
Stop on any refusal or unexpected historical edit. Never accept only one side,
hand-merge, or reformat history. Resolve non-changelog conflicts separately.
For authorized reuse, prefer infx.workflows.merge_with_reuse, which performs
the synchronization and validation together.
Public-fork pull_request workflows receive no repository secrets, and every
run-sweep.yml job requires a same-repository head. For an external PR,
run-sweep.yml therefore runs no jobs: it neither validates the changelog nor
fans out onto GPU runners. A maintainer with write, maintain, or admin
permission can add any modifier labels first, then apply one primary sweep
label to approve the PR's exact current head SHA. The PR must be open and
non-draft. Dispatch waits briefly for GitHub to settle mergeability, then is
refused unless the PR is mergeable and GitHub's test merge commit has the
approved head as its second parent; resolve conflicts or re-add the label if
GitHub is still recomputing it. trusted-external-sweep.yml then dispatches
e2e-tests.yml from main and pins both the approved head and that verified
merge SHA. e2e-tests.yml plans the changelog matrix itself and runs it with the
trusted workflow's secrets.
The approval is revision-specific. A later push is not trusted automatically. Remove and re-add the primary sweep label to approve the new SHA. The trusted dispatcher never checks out or executes PR code itself.
This proof of concept produces benchmark and evaluation artifacts through the
End-to-End Tests workflow. The dispatch also uploads a source-identity
artifact (PR number, full approved head SHA, merge SHA, and the evals-only,
agentx-fast, all-evals, and fail-fast modifiers) and changelog-metadata.
A pinned /use <run_id> accepts these runs; reuse and staging report the
recorded PR head and judge modifiers from the recorded dispatch rather than the
PR's current labels. Older runs without the artifact fall back to the run title
and the PR's current labels. On the fork PR, /stage-results <run_id> stages
such a run when its recorded head is one of the PR's commits. The PoC
also fans out the selected matrix immediately. It does not reproduce
run-sweep.yml's canary-first sequencing: no label runs a canary here, and
only full-sweep-fail-fast sets fail-fast, so the other two primary labels
behave identically.
[skip-sweep] skips PR benchmark setup only. Changelog and reuse checks still
run. The push-to-main merge-ingest.yml run ignores it.
An authorized maintainer can reuse an eligible completed sweep without keeping a primary sweep label on the PR:
/use <run_id>
Keep the command and required run ID on one line. This pins an eligible completed
run-sweep.yml PR run, including failed or cancelled runs with usable results. The
run may come from any PR; its commit need not be part of this one.
The legacy /reuse-sweep-run <run_id> remains equivalent. Bare /reuse-sweep-run
selects the latest successful eligible run automatically; bare /use is rejected.
Both names share authorization, validation, and reactions.
Source validation checks identity and artifacts, not full-matrix coverage. Acceptance does not certify a green full sweep. Verify coverage and pin the run ID when a full sweep is required by the review process.
The latest matching comment across both names by an OWNER, MEMBER, or COLLABORATOR wins.
The bot reacts with 👍 after validating the request, or 👎 on rejection. When the
pinned run's commit is not part of the PR, it also posts one warning comment for
that request and run; reuse still proceeds. Details are in the Actions run summary.
Edits replace the bot's old reaction. /use <run_id> also triggers stage-results.yml.
Staging requires a primary sweep label on the PR and a source run created while
one was applied. A PR without a primary label can instead stage only the run
pinned by its latest authorized /use <run_id>, after the same validation that
acknowledges the request. It posts a staging comment, or a rejection comment
when neither applies. Comments do not trigger or cancel GPU sweeps. Later commits
skip a new sweep after changelog/matrix and source-run validation. Merge-time
validation remains authoritative; an acknowledgment cannot override expired or
invalid artifacts. Reuse is rejected while the PR currently carries
evals-only or agentx-fast, checked when /use is acknowledged and at merge
(and by merge_with_reuse). On a push these labels skip the reuse gate, so a
primary label starts a fresh sweep. Source-run label history is not inspected,
so pin only runs produced without them. To force a fresh sweep after a reuse
command, remove and re-add the primary sweep label.
uv run --extra workflows python -m infx.workflows.merge_with_reuse <pr-number> is the supported merge path for reuse.
It merges main, preserves changelog bytes, fixes an appended XXX PR link,
pushes a synchronization commit, waits for checks, then merges.
At merge, merge-ingest.yml ("Merge Ingest") publishes the reused sweep. It
runs on pushes to main that change inferencex-e2e/perf-changelog.yaml. Its
single ingest job first computes the changelog delta with infx.matrix.plan.
For entries with results, it resolves the merge commit's PR, reuse command, and
source run with infx.workflows.reuse, and fails before uploading or dispatching
anything unless reuse is validly authorized. It then uploads merge-time changelog-metadata
and sends one repository_dispatch to InferenceX-app: ingest-agentic-results
(with database-target: production) when the delta has agentic entries,
otherwise ingest-results. The payload's source-run-id is the reused PR
run-sweep.yml run and its merge-run-id is the Merge Ingest run.
For a nonempty delta consisting entirely of retired: true entries, the planner
verifies that the selected configs existed in the base and are absent from the
head. There are no result artifacts to reuse: merge these PRs directly after
review and required checks, without /use or merge_with_reuse. Merge Ingest
uploads the validated changelog metadata but skips reuse lookup and database
dispatch. Empty or mixed deltas do not receive this exception. Ingest recovery
excludes retired entries from mixed changes and rejects retirement-only changes.
The app downloads source artifacts, keeps the newest upload for each exact artifact name, and ingests them with changelog metadata from the merge run. The normal ingestion code skips failed benchmark rows. Benchmark rows and public links retain source-run provenance. Source coverage is authoritative, so later matrix/eval policy changes do not invalidate reuse.
When the app's ingest finishes, on success or failure, it sends
ingest-results-completed back with per-run counts (benchmark, eval, trace and
power rows: new, duplicate, skipped, unmapped, failed). ingest-results-callback.yml
checks that merge-run-id is a Merge Ingest push to main, resolves the PR merged
by that commit, and posts one comment per merge run, updated in place on reruns
(marker <!-- ingest-results-report merge-run=<id> -->).
Reuse fails closed when authorized but ineligible or invalid. Pushes to main
never run a sweep: run-sweep.yml is PR-only, and without reuse authorization
the Merge Ingest run fails and nothing is benchmarked or ingested.
The benchmarking system uses a strict validation methodology to ensure correctness at every stage. This is implemented in inferencex-e2e/infx/matrix/validation.py using Pydantic models.
The system validates both ends of the configuration pipeline:
- Input Validation (Master Configs): Validates the structure of
inferencex-e2e/configs/*.yamlfiles before any processing occurs - Output Validation (Matrix Entries): Validates the generated matrix entries that are passed to workflow templates
This dual-validation approach ensures:
- No malformed configurations enter the pipeline
- No invalid parameters reach the benchmark workflows
- Workflow templates (
benchmark-tmpl.yml,benchmark-multinode-tmpl.yml) can assume all inputs are valid, with no runtime validation needed
Master config files (e.g., nvidia-master.yaml, amd-master.yaml) are validated against strict Pydantic schemas:
SingleNodeMasterConfigEntry: Validates single-node configurationsMultiNodeMasterConfigEntry: Validates multi-node configurations
Each config must specify:
- Required fields:
image,model,model-prefix,precision,framework,runner,multinode - Sequence length configs with search spaces defining TP, EP, concurrency ranges, etc.
- Optional fields like
disagg,spec-decoding,dp-attn
Invalid or missing fields raise immediate validation errors before any matrix generation.
Generated matrix entries (the actual workflow inputs) are validated against:
SingleNodeMatrixEntry: Matches the inputs expected bybenchmark-tmpl.ymlMultiNodeMatrixEntry: Matches the inputs expected bybenchmark-multinode-tmpl.yml
These Pydantic models mirror the workflow template input definitions exactly. For example, benchmark-tmpl.yml expects:
inputs:
runner: required
image: required
model: required
model-prefix: required
precision: required
framework: required
...The corresponding SingleNodeMatrixEntry enforces these same fields with appropriate types.
-
No defaults in output validation: Matrix entry models don't set defaults. Missing values must fail validation rather than silently using fallbacks.
-
extra='forbid': Unknown fields are rejected, preventing typos or deprecated fields from slipping through. -
Strict typing: Fields like
spec-decodinguseLiteral["mtp", "draft_model", "none"]to restrict values to known options. -
Concurrency validation: The system ensures either
conc-listORconc-start/conc-endis provided, but not both.
inferencex-e2e/configs/*.yaml
│
▼
┌─────────────────────────┐
│ validate_master_config │ ← Input validation (Pydantic)
└─────────────────────────┘
│
▼
┌─────────────────────────┐
│ infx.matrix.generate │ ← Matrix generation
└─────────────────────────┘
│
▼
┌─────────────────────────┐
│ validate_matrix_entry │ ← Output validation (Pydantic)
└─────────────────────────┘
│
▼
benchmark-tmpl.yml or
benchmark-multinode-tmpl.yml