Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
8690b0f
feat(engine): thread image placeholders through SGLang requests
wenpengw-nv Sep 20, 2026
a1bf765
feat(engine): SGLang host loop with deferred result observation
wenpengw-nv Sep 20, 2026
6b9e78e
feat(engine): vision embedding cache and encoder timing per prefill b…
wenpengw-nv Sep 20, 2026
9d678e4
feat(engine): frontend resource pools in the SGLang core
wenpengw-nv Sep 20, 2026
b66eac7
feat(cli): native VL prediction with host, frontend and vision config…
wenpengw-nv Sep 20, 2026
1c66bfc
feat(vl): host cost profile schema, identity matching and lowering
wenpengw-nv Sep 20, 2026
fec5e5e
feat(vl): calibrate frontend and scheduler host costs on a serving host
wenpengw-nv Sep 20, 2026
1e863e8
feat(sweeper): VL recommend candidates replay to predict
wenpengw-nv Sep 20, 2026
1114ad3
docs: SGLang VL host loop and frontend modeling
wenpengw-nv Sep 20, 2026
93a2d77
refactor(replay): name TTFT milestones and stage means for what they …
wenpengw-nv Sep 20, 2026
484a838
fix(engine): settle frontend completions before arrivals and deliver …
wenpengw-nv Sep 20, 2026
7ee70b7
fix(engine): defer SGLang forward effects to result observation
wenpengw-nv Sep 20, 2026
ef581af
feat(perfmodel): price the vision tower through the canonical estimator
wenpengw-nv Sep 20, 2026
791ea8e
fix(vl): measure real host boundaries and pin profiles to their workload
wenpengw-nv Sep 20, 2026
3f60ff3
docs: SGLang VL modeling boundaries after the review
wenpengw-nv Sep 20, 2026
2104b31
refactor(vl): black-box frontend collection replaces scheduler cost t…
wenpengw-nv Sep 21, 2026
60be229
docs(vl): collect flow, host_loop, and the CPU costs left out
wenpengw-nv Sep 21, 2026
f47c878
Merge origin/main into feat/vl-e2e-predict-recommend
wenpengw-nv Sep 22, 2026
047b934
refactor(engine): request-level frontend pools, retract discards unob…
wenpengw-nv Sep 22, 2026
259e3a5
refactor(vl): measured frontend stages keyed by transport, derived ho…
wenpengw-nv Sep 22, 2026
1a94908
fix(vl): execution-semantics replay check, measured model, transport …
wenpengw-nv Sep 22, 2026
733b892
fix(vl): a missing host cost table fails closed with the collect command
wenpengw-nv Sep 22, 2026
0fa3e0b
feat(vl): native VL replay on the prefill rank and a native encoder pool
wenpengw-nv Sep 22, 2026
113862f
fix(epd): price native encoder pools canonically and account their GPUs
wenpengw-nv Sep 22, 2026
d4c7169
docs(vl): name the measured serving host neutrally
wenpengw-nv Sep 22, 2026
4be74ce
docs(epd): state the preprocessing origin in the pool docstrings
wenpengw-nv Sep 22, 2026
3106fc8
fix(vl): decode-rank vision, rate-load stops, milestone rebase
wenpengw-nv Oct 8, 2026
35949d0
Merge origin/main into feat/vl-e2e-predict-recommend
wenpengw-nv Oct 12, 2026
c90f7cc
fix(vl): validate the image and encoder-pool boundaries
wenpengw-nv Oct 8, 2026
c32dff2
fix(vl): validate vision inputs and bound the image placeholder hashes
wenpengw-nv Oct 9, 2026
54577a2
refactor(vl): price image preprocessing only and drop the feature-tra…
wenpengw-nv Oct 12, 2026
1da0de1
fix(vl): close the native encoder pool's configuration and accounting…
wenpengw-nv Oct 12, 2026
116c7d9
fix(vl): save the native encoder pool's resolved frontend with the re…
wenpengw-nv Oct 12, 2026
4d68e67
fix(vl): make collect's messages runnable and its table errors readable
wenpengw-nv Oct 12, 2026
7ba8ae8
docs(vl): state the host-table preconditions and the encoder pool's l…
wenpengw-nv Oct 12, 2026
07f2494
fix(vl): omit an inactive host_loop from worker dumps
wenpengw-nv Oct 12, 2026
4fbdd51
fix(vl): size the native memory gate per encoder server and keep the …
wenpengw-nv Oct 12, 2026
8709e99
feat(vl): price the tokenizer-manager send and the scheduler receive …
wenpengw-nv Oct 16, 2026
89a2562
Merge origin/main into feat/vl-e2e-predict-recommend
wenpengw-nv Oct 16, 2026
c893d6a
fix(vl): honor the review's three P2 findings on the public paths
wenpengw-nv Oct 16, 2026
8729ffc
fix(vl): fail closed on the host, encoder and estimator contracts the…
wenpengw-nv Oct 21, 2026
494e1e9
Merge origin/main into feat/vl-e2e-predict-recommend
wenpengw-nv Oct 21, 2026
b2517f9
docs(vl): place the host table, name the encoder pool's GPU and drop …
wenpengw-nv Oct 21, 2026
2c200a5
Merge main into feat/vl-e2e-predict-recommend
Arsene12358 Oct 21, 2026
25497c8
fix: preserve omitted encoder identity in saved configs
Arsene12358 Oct 21, 2026
d30026a
fix: adapt pinned Dynamo requests to the vision API
Arsene12358 Oct 21, 2026
cf04c9a
fix: reject unsupported native image requests before admission
Arsene12358 Oct 21, 2026
9be98f3
fix: address native VL and Dynamo compatibility review findings
Arsene12358 Oct 21, 2026
f78b642
fix: complete VL detail and Dynamo binding contracts
Arsene12358 Oct 21, 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
5 changes: 5 additions & 0 deletions .github/codeowners/areas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ areas:
- python/aisimulate/src/aisimulate/traffic.py
- tests/test_cli_config.py
- tests/test_epd_cli.py
- tests/test_vl_cli.py
- examples/cli/
- tests/test_stack_discovery.py
- tests/test_output_adapter_discovery.py
Expand Down Expand Up @@ -222,6 +223,10 @@ shared:
owners: [replay, sweeper, forward-pass-engine, maintainers]
- glob: tests/test_epd_cli.py
owners: [replay, sweeper, forward-pass-engine, maintainers]
- glob: tests/test_vl_cli.py
owners: [replay, sweeper, forward-pass-engine, maintainers]
- glob: python/aisimulate/src/aisimulate/vl/
owners: [replay, sweeper, forward-pass-engine, maintainers]
- glob: examples/cli/
owners: [replay, sweeper, forward-pass-engine, maintainers]
- glob: tests/test_stack_discovery.py
Expand Down
3 changes: 3 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
/tests/golden/afd-* @ai-dynamo/aisimulate-replay-codeowners
/tests/test_afd_*.py @ai-dynamo/aisimulate-replay-codeowners
/tests/test_runner.py @ai-dynamo/aisimulate-replay-codeowners
/tests/test_vl_cli.py @ai-dynamo/aisimulate-replay-codeowners
/crates/core/examples/ @ai-dynamo/aisimulate-replay-codeowners
/tests/test_epd_cli.py @ai-dynamo/aisimulate-replay-codeowners
/tests/test_traffic.py @ai-dynamo/aisimulate-replay-codeowners
Expand Down Expand Up @@ -161,6 +162,7 @@
/tests/test_afd_*.py @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-sweeper-codeowners @ai-dynamo/aisimulate-forward-pass-engine-codeowners @ai-dynamo/access-aisimulate-maintain
/benchmarks/evidence/ @ai-dynamo/aisimulate-forward-pass-engine-codeowners @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-infra-codeowners @ai-dynamo/access-aisimulate-maintain
/tests/test_runner.py @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/access-aisimulate-maintain
/tests/test_vl_cli.py @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-sweeper-codeowners @ai-dynamo/aisimulate-forward-pass-engine-codeowners @ai-dynamo/access-aisimulate-maintain
/crates/core/README.md @ai-dynamo/aisimulate-mocker-codeowners @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-forward-pass-engine-codeowners @ai-dynamo/access-aisimulate-maintain
/crates/core/deny.toml @ai-dynamo/aisimulate-mocker-codeowners @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-forward-pass-engine-codeowners @ai-dynamo/aisimulate-infra-codeowners @ai-dynamo/access-aisimulate-maintain
/crates/core/examples/ @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/access-aisimulate-maintain
Expand Down Expand Up @@ -220,6 +222,7 @@
/crates/core/parity_tests/perfmodel/ @ai-dynamo/aisimulate-forward-pass-engine-codeowners @ai-dynamo/access-aisimulate-maintain
/tests/test_ci_workflow_contracts.py @ai-dynamo/aisimulate-infra-codeowners @ai-dynamo/access-aisimulate-maintain
/tests/test_e2e_accuracy_overview.py @ai-dynamo/aisimulate-forward-pass-engine-codeowners @ai-dynamo/aisimulate-infra-codeowners @ai-dynamo/access-aisimulate-maintain
/python/aisimulate/src/aisimulate/vl/ @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-sweeper-codeowners @ai-dynamo/aisimulate-forward-pass-engine-codeowners @ai-dynamo/access-aisimulate-maintain
/tests/test_agentx_snapshot_export.py @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/access-aisimulate-maintain
/tests/test_e2e_accuracy_workflow.mjs @ai-dynamo/aisimulate-forward-pass-engine-codeowners @ai-dynamo/aisimulate-replay-codeowners @ai-dynamo/aisimulate-infra-codeowners @ai-dynamo/access-aisimulate-maintain
/tests/test_fpm_accuracy_workflow.mjs @ai-dynamo/aisimulate-infra-codeowners @ai-dynamo/access-aisimulate-maintain
Expand Down
63 changes: 57 additions & 6 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,33 @@ also appear in `python/aisimulate/tests/unit/sdk/models/test_deepseek_v41.py`,
Rust operator/spec unit tests, `docs/perf-model/models/deepseek-v41.md`. They distinguish candidate masking from scoring
and physical FlashMLA cache payload from logical FP4 values.

## SGLang 0.5.19 multimodal frontend and scheduler behavior

The native VL replay path models sgl-project/sglang v0.5.19 at immutable commit
`0bcd822377da7b5718e674eaf9c870d349424dd1`. Repository-root paths:

- `crates/core/src/engine/scheduler/sglang/{host_loop,vision,frontend}.rs` and
their tests re-implement the observed behavior of `Scheduler.event_loop_overlap`,
`run_batch`, `recv_requests`, `process_batch_result_prefill`,
`_batch_encode_per_image_misses`, `MultiModalStaticCache`, `TokenizerManager`,
`BaseMultimodalProcessor`, the scheduler's receive preparation
(`managers/scheduler_components/request_receiver.py`) and the Rust multimodal workers'
feature transport (`RustMmProcessor._use_feature_shm`) as performance models.
They do not execute or copy the upstream implementation.
- `crates/core/src/engine/scheduler/sglang/core.rs` (disaggregated prefill) and
`crates/core/src/replay/components/encoder.rs` likewise re-implement the
observed behavior of `disaggregation/prefill.py` (`SchedulerDisaggregationPrefillMixin`)
and of `disaggregation/encoder/{runtime,server,receiver,preprocessor}.py`
(`EncoderScheduler`, `_assign_items_by_modality`, `zmq_to_scheduler`) as
performance models, without copying the upstream implementation.
- `python/aisimulate/src/aisimulate/vl/collect/` instantiates the pinned
upstream frontend objects unmodified on the serving host and times them from
the outside; it does not copy or modify their implementations.

Source: https://github.com/sgl-project/sglang/tree/0bcd822377da7b5718e674eaf9c870d349424dd1
Copyright 2023-2024 SGLang Team and SGLang contributors. Licensed under Apache-2.0; its terms are
at https://github.com/sgl-project/sglang/blob/0bcd822377da7b5718e674eaf9c870d349424dd1/LICENSE.

## DeepSeek model configuration files

The following model configuration files are copied from, or formatting-only
Expand Down Expand Up @@ -910,6 +937,16 @@ This material is licensed under the Apache License 2.0.
The upstream license at that revision is available at:
https://github.com/huggingface/transformers/blob/cbc1651a032b923da7f4b44b3d0e6f68e6ba6b55/LICENSE

The Qwen VL `smart_resize` pixel-budget rule in
`python/aisimulate/src/aisimulate_core/sdk/backends/base_backend.py`
(`_qwen_smart_resize`) is a modified adaptation of the Qwen2-VL image processor
in Hugging Face Transformers at tag `v4.57.0`:

- https://github.com/huggingface/transformers/blob/v4.57.0/src/transformers/models/qwen2_vl/image_processing_qwen2_vl.py

Copyright 2024 the HuggingFace Inc. team. All rights reserved.
This material is licensed under the Apache License 2.0.

The fixed-tile canvas and global-tile logic in
`src/aiconfigurator_core/sdk/backends/base_backend.py`, and the processor metadata
normalization in `src/aiconfigurator_core/sdk/utils.py`, are modified adaptations
Expand Down Expand Up @@ -1304,29 +1341,43 @@ the upstream copyright header and marks the modified conversion in the output.
## NVIDIA Dynamo CI struct-literal compatibility

The exact-source rewrites in `scripts/performance/build_simulation_dynamo.py`
and their regression fixtures in `tests/test_ci_workflow_contracts.py`
are adapted and modified from NVIDIA Dynamo's
`lib/mocker/src/grouped_scheduler/compatibility.rs` and
`lib/mocker/src/replay/offline/extensions/kv_router/mod.rs` at commit
`lib/mocker/src/replay/offline/extensions/kv_router/mod.rs`,
`lib/mocker/src/replay/offline/entrypoints.rs`,
`lib/mocker/src/replay/offline/extensions/kv_events/mod.rs`, and
`lib/bindings/python/rust/llm/replay.rs` at commit
`def3b79b15c266805540a678dd400aeb6ccada1d`:
https://github.com/ai-dynamo/dynamo/blob/def3b79b15c266805540a678dd400aeb6ccada1d/lib/mocker/src/grouped_scheduler/compatibility.rs
https://github.com/ai-dynamo/dynamo/blob/def3b79b15c266805540a678dd400aeb6ccada1d/lib/mocker/src/replay/offline/extensions/kv_router/mod.rs
https://github.com/ai-dynamo/dynamo/blob/def3b79b15c266805540a678dd400aeb6ccada1d/lib/mocker/src/replay/offline/entrypoints.rs
https://github.com/ai-dynamo/dynamo/blob/def3b79b15c266805540a678dd400aeb6ccada1d/lib/mocker/src/replay/offline/extensions/kv_events/mod.rs
https://github.com/ai-dynamo/dynamo/blob/def3b79b15c266805540a678dd400aeb6ccada1d/lib/bindings/python/rust/llm/replay.rs

Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
Licensed under Apache-2.0; the full license is reproduced in `LICENSE`.
Upstream license: https://github.com/ai-dynamo/dynamo/blob/def3b79b15c266805540a678dd400aeb6ccada1d/LICENSE
The adaptation adds `None` for new optional AISimulate fields to the native
request and offline KV-router placement struct literals for CI builds against
newer AISimulate APIs. It preserves the upstream copyright headers and marks
each modified literal in the output.
newer AISimulate APIs. It also sets an empty image list for the pinned text-only
request when AISimulate requires `images: Vec<ImageSpec>`, rejecting image inputs
instead of adding multimodal support to Dynamo's adapter. Both offline replay
specifications disable the encoder pool; the Python binding's synthetic trace
explicitly retains text-only traffic with `images: None`. The lifecycle conversion explicitly
rejects host-loop TTFT milestones, which its legacy DTO cannot represent.
It preserves the upstream copyright headers and marks each modification in the output.

The replay compatibility rewrite in the same script adapts
`lib/mocker/src/engine_adapter.rs` at that same immutable revision:
https://github.com/ai-dynamo/dynamo/blob/def3b79b15c266805540a678dd400aeb6ccada1d/lib/mocker/src/engine_adapter.rs
Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
Licensed under Apache-2.0 as above. The modified adapter explicitly sets prefill
context parallelism to 1 in four replay descriptors, preserving the pinned
adapter's topology. Its upstream copyright header is retained and each modified
literal is marked in the generated output.
adapter's topology. It also disables the SGLang host loop and takes the vision
cache capacity from the canonical SGLang default, preserving text-only behavior.
Its upstream copyright header is retained and each modified literal is marked
in the generated output.

## NVIDIA Dynamo CI speculation compatibility

Expand Down
33 changes: 33 additions & 0 deletions crates/core/src/engine/common/perf_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,39 @@ impl PerfModel {
Ok(())
}

/// Predict the vision-encoder time in milliseconds for one batch of
/// distinct cache-miss images, grouped by shape for the provider.
pub fn predict_vision_time(&self, images: &[crate::engine::ImageSpec]) -> Result<f64> {
if images.is_empty() {
return Ok(0.0);
}
let PerfModel::External { timing } = self else {
anyhow::bail!("polynomial timing does not support vision batches");
};
let mut shapes: Vec<crate::engine::VisionShape> = Vec::new();
for image in images {
match shapes
.iter_mut()
.find(|shape| shape.encoder == image.encoder)
{
Some(shape) => shape.count += 1,
None => shapes.push(crate::engine::VisionShape {
encoder: image.encoder,
count: 1,
}),
}
}
let time = timing
.predict_vision_ms(&shapes)
.context("external vision prediction failed")?
.context("timing provider does not support vision batches")?;
ensure!(
time.is_finite() && time >= 0.0,
"vision timing provider returned invalid duration {time}ms"
);
Ok(time)
}

/// Predict prefill time in milliseconds.
///
/// Callers always pass all parameters; each variant uses what it needs:
Expand Down
8 changes: 7 additions & 1 deletion crates/core/src/engine/common/protocols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ use derive_builder::Builder;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use crate::engine::KvEvent;
use crate::engine::common::hashing::Token;
use crate::engine::common::perf_model::PerfModel;
use crate::engine::config::{NativeHostOffloadConfig, StateCacheConfig};
use crate::engine::{FrontendConfig, ImageSpec, KvEvent};

/// Sink for neutral KV-cache events emitted by a rank.
pub(crate) trait KvCacheEventSink: Send + Sync {
Expand Down Expand Up @@ -80,6 +80,9 @@ pub(crate) struct DirectRequest {
pub arrival_timestamp_ms: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub session_id: Option<String>,
/// Image placeholders inside `tokens`; empty for text-only requests.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub images: Vec<ImageSpec>,
}

impl DirectRequest {
Expand Down Expand Up @@ -163,6 +166,9 @@ pub(crate) struct SglangArgs {
pub chunked_prefill_size: Option<usize>,
pub clip_max_new_tokens: Option<usize>,
pub schedule_conservativeness: Option<f64>,
pub vlm_cache_bytes: Option<u64>,
pub host_loop: bool,
pub frontend: Option<FrontendConfig>,
}

/// Rank-local view of `EngineConfig`.
Expand Down
Loading
Loading