Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
7ce0460
feat(sweeper): pin forward-pass estimator inputs [AIC-1770]
jasonqinzhou Aug 26, 2026
410c7ff
refactor(perfmodel): unify estimator construction [AIC-1770]
jasonqinzhou Aug 26, 2026
633ea00
Merge origin/main into AIC-1770 estimator construction
jasonqinzhou Aug 31, 2026
b88ebcb
fix(sweeper): resolve exact estimator configs
jasonqinzhou Aug 31, 2026
d71c9a2
refactor(perfmodel): unify estimator selection and configuration
tedzhouhk Sep 17, 2026
09111ef
Merge remote-tracking branch 'origin/main' into hzhou-codex/pr13-esti…
tedzhouhk Sep 17, 2026
2e591ec
test(perfmodel): align merged fixtures with canonical API
tedzhouhk Sep 17, 2026
56db663
fix(perfmodel): validate search estimator controls before execution
tedzhouhk Sep 17, 2026
8140fc9
fix(perfmodel): pin native replay identity and reject trailing config…
tedzhouhk Sep 17, 2026
2f72e02
fix(replay): retain rank-level memory controls in canonical timing co…
tedzhouhk Sep 17, 2026
b927ff9
fix(perfmodel): preserve estimator contracts across replay and search
tedzhouhk Sep 17, 2026
3cf3d33
fix(perfmodel): validate availability and preserve resolved estimator…
tedzhouhk Sep 17, 2026
a58055e
fix(perfmodel): close configuration and release contract gaps
tedzhouhk Sep 17, 2026
521f528
chore(ci): merge main and preserve release gating
tedzhouhk Sep 17, 2026
6d6eb3f
Merge origin/main and preserve downstream publication gate
tedzhouhk Sep 18, 2026
1b1aba2
fix(perfmodel): enforce readiness and preserve role configuration
tedzhouhk Sep 18, 2026
41fc547
Merge main resource supervision and retain estimator regression tests
tedzhouhk Sep 18, 2026
1291c77
fix(ci): validate migration gates for the publication target
tedzhouhk Sep 18, 2026
cf0c64f
Merge main and preserve canonical estimator construction for ngram an…
tedzhouhk Sep 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/release-gates.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"pending_migrations": [
{
"pull_request": "https://github.com/ai-dynamo/dynamo/pull/14065",
"requirement": "Refresh and merge Dynamo's Planner and wheel-smoke migration to best_available(config), with required worker_type, nested estimator_config, and the released-wheel compatibility bridge. Validate against the canonical wheel before clearing this gate and releasing the API."
}
Comment thread
tedzhouhk marked this conversation as resolved.
]
}
14 changes: 14 additions & 0 deletions .github/workflows/nightly-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,20 @@ jobs:
}
}
core.setFailed('commit_sha is not on main or any release/* branch');
# Both scheduled and approved manual publication require completed migrations.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: ${{ steps.target.outputs.sha }}
persist-credentials: false
# Keep the checker/current policy trusted while also checking the exact
# publication target's migration declarations. Neither can bypass the other.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: ${{ github.sha }}
Comment thread
tedzhouhk marked this conversation as resolved.
path: release-policy
persist-credentials: false
- name: Require completed downstream API migrations
run: python3 release-policy/scripts/check_release_migrations.py --target-gates .github/release-gates.json
# Computed once here so both arch legs stamp the same date even if the
# run crosses a UTC midnight.
- name: Compute unique nightly version
Expand Down
7 changes: 7 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

This file adds explicit repository-wide development guards.

## Performance Model Changes

Before changing a performance model, its configuration, or a caller in Rust,
Python, CLI, Sweeper, Replay, or Planner, MUST read and follow
[`perfmodel-api.md`](python/aisimulate/.claude/rules/perfmodel-api.md).
This includes new features and configuration migrations.

## Required First Step

Before making any change under:
Expand Down
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -879,4 +879,5 @@ Copyright 2018- The Hugging Face team. All rights reserved.
- License: Apache-2.0; NVIDIA maintainer confirmed permission to migrate and
publish this code under Apache-2.0.
- Modified: development-only two-predictor evaluation, public overview export,
GitHub Pages presentation, and local import paths. No Plotly assets included.
GitHub Pages presentation, local import paths, and canonical estimator API
adaptation with older-wheel compatibility. No Plotly assets included.
1 change: 1 addition & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ rand_chacha = "0.3.1"
rustc-hash = "2"
serde = { workspace = true }
serde_json = { workspace = true }
serde_path_to_error = "0.1"
serde_yaml = "0.9"
sha2 = "0.10"
slotmap = "1"
Expand Down
125 changes: 116 additions & 9 deletions crates/core/parity_tests/perfmodel/test_engine_step_parity.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,10 @@ def __call__(self):

def _quiet_call(func, *args, **kwargs):
"""Keep interpolation loader chatter out of parity test output."""
with contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(io.StringIO()):
with (
contextlib.redirect_stdout(io.StringIO()),
contextlib.redirect_stderr(io.StringIO()),
):
return func(*args, **kwargs)


Expand Down Expand Up @@ -1135,7 +1138,9 @@ def _comparison_metrics(
return {name: (python_metrics[name], rust_metrics[name]) for name in rust_metrics}


def _static_comparison_metrics(case: EngineStepParityCase) -> dict[str, tuple[float, float]]:
def _static_comparison_metrics(
case: EngineStepParityCase,
) -> dict[str, tuple[float, float]]:
return _comparison_metrics(case, "static")


Expand All @@ -1145,11 +1150,15 @@ def _mixed_step_comparison_metrics(
return _comparison_metrics(case, "mixed")


def _agg_comparison_metrics(case: EngineStepParityCase) -> dict[str, tuple[float, float]]:
def _agg_comparison_metrics(
case: EngineStepParityCase,
) -> dict[str, tuple[float, float]]:
return _comparison_metrics(case, "agg")


def _disagg_comparison_metrics(case: EngineStepParityCase) -> dict[str, tuple[float, float]]:
def _disagg_comparison_metrics(
case: EngineStepParityCase,
) -> dict[str, tuple[float, float]]:
return _comparison_metrics(case, "disagg")


Expand Down Expand Up @@ -1432,7 +1441,14 @@ class TestRustEngineHandleDatabasePolicyIdentity:
"""

def _static_ctx_ms(self, model, view) -> float:
rc = config.RuntimeConfig(batch_size=1, beam_width=1, isl=1024, osl=8, prefix=0, engine_step_backend="rust")
rc = config.RuntimeConfig(
batch_size=1,
beam_width=1,
isl=1024,
osl=8,
prefix=0,
engine_step_backend="rust",
)
ctx_latency, _gen, *_ = rust_engine_step.estimate_static_latency_breakdown_with_rust(
model, view, rc, "static_ctx", 1, 1.0
)
Expand Down Expand Up @@ -2332,7 +2348,12 @@ def test_hybrid_ngram_mixed_pin(self, fpm_systems_root):

model, backend, database = self._build_ngram()
rc = config.RuntimeConfig(batch_size=4, beam_width=1, isl=1024, osl=2)
est = backend.run_mixed(model, database, rc, MixedStepInput(context_tokens=1024, num_decode_requests=1))
est = backend.run_mixed(
model,
database,
rc,
MixedStepInput(context_tokens=1024, num_decode_requests=1),
)
value = est.latency_ms
if _FPM_HYBRID_MIXED_FROZEN is None:
print(f"\nPIN mixed: {value!r}")
Expand All @@ -2342,6 +2363,77 @@ def test_hybrid_ngram_mixed_pin(self, fpm_systems_root):


class TestRustEngineStepFpmParity:
@pytest.mark.parametrize("database_mode", ["SILICON", "HYBRID"])
def test_auto_skips_absent_op_tables(self, fpm_systems_root, database_mode):
from aiconfigurator_core.sdk import ForwardPassPerfModelConfig, RustForwardPassPerfModel

cfg = ForwardPassPerfModelConfig(
model=_FPM_MODEL,
system="b200_sxm",
backend="vllm",
backend_version=_FPM_VERSION,
worker_type="decode",
tp=2,
moe_tp_size=1,
moe_ep_size=2,
gemm_quant_mode="fp8_block",
moe_quant_mode="fp8_block",
fmha_quant_mode="bfloat16",
kvcache_quant_mode="fp8",
comm_quant_mode="half",
systems_paths=(str(fpm_systems_root),),
database_mode=database_mode,
)
model = RustForwardPassPerfModel.best_available(cfg)
try:
provenance = model.diagnostics()["provenance"]
assert provenance["selected_estimation_mode"] == "fpm_interpolation"
assert "gemm_perf.parquet" in provenance["selection_failures"][0]
# Exact measured fixture row: four decode requests, 4,100 total KV.
assert model.estimate_forward_pass_time_ms(
{
"version": 1,
"scheduled_requests": {"num_decode_requests": 4, "sum_decode_kv_tokens": 4100},
}
) == pytest.approx(4.5)
finally:
model.close()
from dataclasses import replace

from aiconfigurator_core.sdk.errors import PerfDataNotAvailableError

with pytest.raises(PerfDataNotAvailableError, match="required op-level data unavailable"):
RustForwardPassPerfModel.best_available(replace(cfg, estimation_mode="op_level"))

def test_sol_does_not_require_op_tables(self, fpm_systems_root):
from aiconfigurator_core.sdk import ForwardPassPerfModelConfig, RustForwardPassPerfModel

model = RustForwardPassPerfModel.best_available(
ForwardPassPerfModelConfig(
model="Qwen/Qwen3-32B",
system="b200_sxm",
backend="vllm",
backend_version=_FPM_VERSION,
worker_type="decode",
tp=2,
systems_paths=(str(fpm_systems_root),),
database_mode="SOL",
)
)
try:
assert model.diagnostics()["provenance"]["selected_estimation_mode"] == "op_level"
assert (
model.estimate_forward_pass_time_ms(
{
"version": 1,
"scheduled_requests": {"num_decode_requests": 4, "sum_decode_kv_tokens": 4100},
}
)
> 0
)
finally:
model.close()

"""forward_model='fpm' regression vs the frozen Python reference.

The Python FPM walk is gone (Phase 2 PR-3); the live side below is the
Expand Down Expand Up @@ -2417,7 +2509,11 @@ def test_fpm_arena_selects_the_fpm_engine(self, fpm_systems_root, monkeypatch):
"nextn": None,
"forward_model": "fpm",
}
model = RustForwardPassPerfModel.from_native(config)
from aiconfigurator_core.sdk import ForwardPassPerfModelConfig

model = RustForwardPassPerfModel.best_available(
ForwardPassPerfModelConfig.from_legacy_engine_config(config, "aggregated")
)
decode_only = [
{
"version": 1,
Expand Down Expand Up @@ -2471,7 +2567,13 @@ def test_fpm_spec_tags(self, fpm_systems_root, monkeypatch):
("static_gen", 4, 1024, 2, 0), # exact decode hit at B=4
("static_gen", 2, 1024, 2, 0), # uncollected batch -> transfer (SOL)
("static_gen", 4, 9_000_000, 2, 0), # out of domain -> both error
("static_ctx", 16, 256, 1, 0), # above the batch ceiling -> pure clamp (kv/T = 0)
(
"static_ctx",
16,
256,
1,
0,
), # above the batch ceiling -> pure clamp (kv/T = 0)
("static_ctx", 16, 320, 1, 256), # high KV pressure -> SOL-rescaled clamp
],
)
Expand All @@ -2490,7 +2592,12 @@ def test_fpm_static_parity(self, fpm_systems_root, monkeypatch, mode, batch, isl
(0, 4, 1024, 2), # gen-only keeps full decode
(0, 600, 100, 2), # gen-only across the decode regime boundary (eager side)
(1024, 0, 1024, 2), # prefill-only chunk
(4096, 0, 256, 1), # 16 whole prefills: certified batch clamp to the ceiling
(
4096,
0,
256,
1,
), # 16 whole prefills: certified batch clamp to the ceiling
],
)
def test_fpm_mixed_step_parity(self, fpm_systems_root, monkeypatch, ctx_tokens, gen_tokens, isl, osl):
Expand Down
28 changes: 21 additions & 7 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,32 @@ pub use replay::{ReplayReport, ReplaySpec, Replayer};
// the explicit `ReplayEngineConfig` alias above.
pub use perfmodel::EngineConfig;
pub use perfmodel::{
AicError, BackendKind, DataType, DatabaseMode, ENGINE_CONFIG_SCHEMA_VERSION,
ENGINE_SPEC_SCHEMA_VERSION, EstimateSource, FPM_VERSION, ForwardPassMetrics,
ForwardPassPerfDiagnostics, ForwardPassPerfModel, ForwardPassPerfOptions,
ForwardPassPerfReadiness, ForwardPassPerfSource, ForwardPassRegressionStoreDiagnostics,
ForwardPassRegressionWorkloadKind, ForwardPassWorkerType, KvCacheEstimate,
AicError, BackendKind, CorrectionConfig, DataType, DatabaseMode, ENGINE_CONFIG_SCHEMA_VERSION,
ENGINE_SPEC_SCHEMA_VERSION, EstimateSource, EstimationMode, EstimatorConfig, FPM_VERSION,
ForwardPassFallbackPolicy, ForwardPassMetrics, ForwardPassPerfDiagnostics,
ForwardPassPerfModel, ForwardPassPerfModelConfig, ForwardPassPerfOptions,
ForwardPassPerfProvenance, ForwardPassPerfReadiness, ForwardPassPerfSource,
ForwardPassRegressionStoreDiagnostics, ForwardPassRegressionWorkloadKind,
ForwardPassSpeculationConfig, ForwardPassWorkerType, FpmRegressionConfig, KvCacheEstimate,
KvCacheEstimateAdjusted, KvCacheEstimateError, KvCacheEstimateOptions, KvCacheEstimateRequest,
KvCacheMemoryFraction, MemoryBreakdown, ParallelMapping, QuantizationConfig,
QueuedRequestMetrics, ScheduledRequestMetrics, SpeculativeConfig,
QueuedRequestMetrics, RegressionFeatureWeights, SamplingConfig, ScheduledRequestMetrics,
SpeculativeConfig,
};
pub use perfmodel::{
CorrectionFactorBounds, CorrectionFeatureSpace, FpmInterpolationConfig, OpLevelConfig,
RegressionFitConfig, RegressionFitKind,
};

#[cfg(feature = "python")]
pub use perfmodel::{AicEngine, AicEngineBuilder, estimate_kv_cache};
pub use perfmodel::{
AicEngine,
// Low-level Rust embedder API for compiled step-latency handles. This is
// deliberately not registered on the Python module and is not an
// alternative ForwardPassPerfModel construction boundary.
AicEngineBuilder,
estimate_kv_cache,
};

// The imported perf-model sources historically used additional crate-root
// module paths. Keep these module aliases crate-private so the mirror subtree
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/perfmodel/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//! static-inference composition. PyO3 bindings over `Engine` live in
//! [`crate::py`].

mod readiness;
pub mod runtime;
pub mod spec;

Expand Down
Loading
Loading