Skip to content
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
74bc13f
use BTreeSet, and allow for push_front (preemption)
PeaBrane May 27, 2025
f2343d5
preemption is push_front
PeaBrane May 27, 2025
6fe3154
use Hongkuan's quadratic formulas for decode and prefill
PeaBrane May 27, 2025
cccebad
cleaner scheduling + generation separation, and waterline bug fix
PeaBrane May 28, 2025
793d1d1
Merge branch 'main' into rupei/mocker-v0
PeaBrane May 28, 2025
394c2bf
restore printing out fwd pass metrics in test
PeaBrane May 30, 2025
f5ab2e1
Merge remote-tracking branch 'origin/main' into rupei/mocker-v0
PeaBrane Jun 11, 2025
dad183f
multi-dp mocker engine
PeaBrane Jun 11, 2025
009ec78
fixed prefill cost, and more conservative watermarking
PeaBrane Jun 12, 2025
ee11427
fwd pass metrics
PeaBrane Jun 12, 2025
8e8d0b4
can emit kv event, not tested
PeaBrane Jun 13, 2025
e96f810
move block resp test in kv manager
PeaBrane Jun 13, 2025
c09f007
basic test passes for both load metrics and kv events
PeaBrane Jun 14, 2025
4502e5e
better tracing
PeaBrane Jun 14, 2025
fe20aa3
async engine core
PeaBrane Jun 16, 2025
2fbf998
hook up with dynamo run
PeaBrane Jun 17, 2025
b548050
docs
PeaBrane Jun 17, 2025
c7c4be5
fmt
PeaBrane Jun 17, 2025
1845a8d
Merge branch 'main' into rupei/mocker-v0
PeaBrane Jun 17, 2025
3ad7780
refactor
PeaBrane Jun 17, 2025
c78bef2
works with kv router
PeaBrane Jun 17, 2025
a206569
actually load extra mocker args in guide
PeaBrane Jun 17, 2025
d3730ff
free blocks if failed to send (receiver dropped)
PeaBrane Jun 23, 2025
68d822a
do not regenereate tokens after pre-emption
PeaBrane Jun 23, 2025
d69edcf
evictor cleanup
PeaBrane Jun 30, 2025
c08f9ea
only need runtime in dynamic arms
PeaBrane Jun 30, 2025
dee1413
no separate extra-mocker-args
PeaBrane Jun 30, 2025
082bcec
Merge branch 'main' into rupei/mocker-v0
PeaBrane Jun 30, 2025
99fd3f2
update to match batched tokens
PeaBrane Jun 30, 2025
85c7ccf
max-num-seqs
PeaBrane Jun 30, 2025
ec1f360
enable_prefix_caching arg
PeaBrane Jun 30, 2025
94abc0d
only publish kv events if enable_prefix_caching set true
PeaBrane Jun 30, 2025
35da284
small note on chunked prefill being false for now
PeaBrane Jun 30, 2025
c7c072d
revert flags
PeaBrane Jul 1, 2025
de54247
revert dynamo-run changes
PeaBrane Jul 1, 2025
81c12aa
tiny reversion
PeaBrane Jul 1, 2025
b959df4
another reversion
PeaBrane Jul 1, 2025
f07e28d
Merge remote-tracking branch 'origin/main' into rupei/mocker-v0
PeaBrane Jul 1, 2025
b15070a
usize reversion
PeaBrane Jul 1, 2025
3a20b9d
clippy
PeaBrane Jul 1, 2025
c747606
more clippy
PeaBrane Jul 1, 2025
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
29 changes: 28 additions & 1 deletion docs/guides/dynamo_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ It supports these engines: mistralrs, llamacpp, sglang, vllm, and tensorrt-llm.

Usage:
```
dynamo-run in=[http|text|dyn://<path>|batch:<folder>] out=echo_core|echo_full|mistralrs|llamacpp|sglang|vllm|dyn [--http-port 8080] [--model-path <path>] [--model-name <served-model-name>] [--model-config <hf-repo>] [--tensor-parallel-size=1] [--context-length=N] [--num-nodes=1] [--node-rank=0] [--leader-addr=127.0.0.1:9876] [--base-gpu-id=0] [--extra-engine-args=args.json] [--router-mode random|round-robin|kv] [--kv-overlap-score-weight=2.0] [--kv-gpu-cache-usage-weight=1.0] [--kv-waiting-requests-weight=1.0] [--verbosity (-v|-vv)]
dynamo-run in=[http|text|dyn://<path>|batch:<folder>] out=echo_core|echo_full|mocker|mistralrs|llamacpp|sglang|vllm|dyn [--http-port 8080] [--model-path <path>] [--model-name <served-model-name>] [--model-config <hf-repo>] [--tensor-parallel-size=1] [--context-length=N] [--num-nodes=1] [--node-rank=0] [--leader-addr=127.0.0.1:9876] [--base-gpu-id=0] [--extra-engine-args=args.json] [--router-mode random|round-robin|kv] [--kv-overlap-score-weight=2.0] [--kv-gpu-cache-usage-weight=1.0] [--kv-waiting-requests-weight=1.0] [--verbosity (-v|-vv)]
```

Example: `dynamo run Qwen/Qwen3-0.6B`
Expand Down Expand Up @@ -514,6 +514,33 @@ The output looks like this:
{"text":"What is the capital of Spain?","response":".The capital of Spain is Madrid.","tokens_in":7,"tokens_out":7,"elapsed_ms":855}
```

#### Mocker engine

The mocker engine is a mock vLLM implementation designed for testing and development purposes. It simulates realistic token generation timing without requiring actual model inference, making it useful for:

- Testing distributed system components without GPU resources
- Benchmarking infrastructure and networking overhead
- Developing and debugging Dynamo components
- Load testing and performance analysis

**Basic usage:**

The `--model-path` is required but can point to any valid model path - the mocker doesn't actually load the model weights. The arguments `block-size`, `num-gpu-blocks`, `max-num-seqs`, `max-num-batched-tokens`, and `enable-prefix-caching` are common arguments shared with the real VLLM engine.

And below are arguments that are mocker-specific:
- `speedup_ratio`: Speed multiplier for token generation (default: 1.0). Higher values make the simulation engines run faster.
- `dp_size`: Number of data parallel workers to simulate (default: 1)
- `watermark`: KV cache watermark threshold as a fraction (default: 0.01). This argument also exists for the real VLLM engine but cannot be passed as an engine arg.

>[!NOTE]
>Currently, `enable_chunked_prefill` is always assumed to be false, which mirrors the vllm v0 behavior. This is also the current behavior in `examples/llm`. This will be updated in the near future as we move to support vllm v1 (and deprecate support for vllm v0).

```bash
echo '{"speedup_ratio": 10.0}' > mocker_args.json
dynamo-run in=dyn://dynamo.mocker.generate out=mocker --model-path TinyLlama/TinyLlama-1.1B-Chat-v1.0 --extra-engine-args mocker_args.json
dynamo-run in=http out=dyn --router-mode kv
```

### Extra engine arguments
The vllm and sglang backends support passing any argument the engine accepts.
Put the arguments in a JSON file:
Expand Down
16 changes: 12 additions & 4 deletions launch/dynamo-run/src/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,19 +216,27 @@ impl Flags {
out
}

/// Load extra engine arguments from a JSON file
/// Load extra arguments from a JSON file
/// Returns a HashMap of parameter names to values
pub fn load_extra_engine_args(
&self,
fn load_json_args(
path: &Option<PathBuf>,
) -> anyhow::Result<Option<HashMap<String, serde_json::Value>>> {
if let Some(path) = &self.extra_engine_args {
if let Some(path) = path {
let file_content = std::fs::read_to_string(path)?;
let args: HashMap<String, serde_json::Value> = serde_json::from_str(&file_content)?;
Ok(Some(args))
} else {
Ok(None)
}
}

/// Load extra engine arguments from a JSON file
/// Returns a HashMap of parameter names to values
pub fn load_extra_engine_args(
&self,
) -> anyhow::Result<Option<HashMap<String, serde_json::Value>>> {
Self::load_json_args(&self.extra_engine_args)
}
}

#[derive(Default, PartialEq, Eq, ValueEnum, Clone, Debug, Copy)]
Expand Down
88 changes: 86 additions & 2 deletions launch/dynamo-run/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use dynamo_llm::{backend::ExecutionContext, engines::StreamingEngine, local_mode
use dynamo_runtime::protocols::Endpoint as EndpointId;
use dynamo_runtime::slug::Slug;
use dynamo_runtime::{CancellationToken, DistributedRuntime};
use tokio::sync::OnceCell;

mod flags;
pub use flags::Flags;
Expand Down Expand Up @@ -64,6 +65,21 @@ pub async fn run(
.clone()
.or(flags.model_path_flag.clone());

// Create a OnceCell for lazy initialization of distributed runtime
let distributed_runtime_cell: OnceCell<DistributedRuntime> = OnceCell::new();
let runtime_clone = runtime.clone();

// Helper closure to get or initialize the distributed runtime
let get_distributed_runtime = || async {
distributed_runtime_cell
.get_or_init(|| async {
DistributedRuntime::from_settings(runtime_clone.clone())
.await
.expect("Failed to create distributed runtime")
})
.await
};

let mut local_model: LocalModel = if is_out_dynamic(&out_opt) {
// If output is dynamic we are ingress and don't have a local model, but making an
// empty one cleans up the code.
Expand Down Expand Up @@ -285,6 +301,73 @@ pub async fn run(
model: Box::new(local_model),
}
}

Output::Mocker => {
let endpoint = match &in_opt {
Input::Endpoint(path) => path.parse()?,
_ => internal_endpoint("mocker"),
};

// Load mocker args from JSON file if provided
let engine_args = flags.load_extra_engine_args()?;

let mut builder = dynamo_llm::mocker::protocols::MockEngineArgs::builder();

// Use kv_cache_block_size flag as block_size if provided
if let Some(block_size) = flags.kv_cache_block_size {
builder = builder.block_size(block_size);
}

// Apply args from JSON file if provided
if let Some(args) = engine_args {
// This overwrites the kv_cache_block_size passed in
if let Some(v) = args.get("block_size").and_then(|v| v.as_u64()) {
builder = builder.block_size(v as usize);
}
if let Some(v) = args.get("num_gpu_blocks").and_then(|v| v.as_u64()) {
builder = builder.num_gpu_blocks(v as usize);
}
if let Some(v) = args.get("max_num_seqs").and_then(|v| v.as_u64()) {
builder = builder.max_num_seqs(Some(v as usize));
}
if let Some(v) = args.get("max_num_batched_tokens").and_then(|v| v.as_u64()) {
builder = builder.max_num_batched_tokens(Some(v as usize));
}
if let Some(v) = args.get("enable_prefix_caching").and_then(|v| v.as_bool()) {
builder = builder.enable_prefix_caching(v);
}

// These are mocker-specific args
if let Some(v) = args.get("speedup_ratio").and_then(|v| v.as_f64()) {
builder = builder.speedup_ratio(v);
}
if let Some(v) = args.get("watermark").and_then(|v| v.as_f64()) {
builder = builder.watermark(v);
}
if let Some(v) = args.get("dp_size").and_then(|v| v.as_u64()) {
builder = builder.dp_size(v as u32);
}
}

let args = builder
.build()
.map_err(|e| anyhow::anyhow!("Failed to build MockEngineArgs: {e}"))?;

// Get or initialize the distributed runtime
let distributed_runtime = get_distributed_runtime().await;
let engine = dynamo_llm::mocker::engine::make_mocker_engine(
distributed_runtime.clone(),
endpoint,
args,
)
.await
.map_err(|e| anyhow::anyhow!("Failed to create mocker engine: {e}"))?;

EngineConfig::StaticCore {
engine,
model: Box::new(local_model),
}
}
};

match in_opt {
Expand All @@ -311,8 +394,9 @@ pub async fn run(
.await?;
}
Input::Endpoint(path) => {
let distributed_runtime = DistributedRuntime::from_settings(runtime.clone()).await?;
crate::input::endpoint::run(distributed_runtime, path, engine_config).await?;
// Get or initialize the distributed runtime
let distributed_runtime = get_distributed_runtime().await;
crate::input::endpoint::run(distributed_runtime.clone(), path, engine_config).await?;
}
}

Expand Down
12 changes: 11 additions & 1 deletion launch/dynamo-run/src/opt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ pub enum Output {
/// Listen for models on nats/etcd, add/remove dynamically
Dynamic,

/// Mock vLLM engine for testing and development
Mocker,

#[cfg(feature = "mistralrs")]
/// Run inference on a model in a GGUF file using mistralrs w/ candle
MistralRs,
Expand Down Expand Up @@ -126,6 +129,7 @@ impl TryFrom<&str> for Output {

"echo_full" => Ok(Output::EchoFull),
"echo_core" => Ok(Output::EchoCore),
"mocker" => Ok(Output::Mocker),

"dyn" => Ok(Output::Dynamic),

Expand Down Expand Up @@ -160,6 +164,8 @@ impl fmt::Display for Output {
Output::EchoCore => "echo_core",

Output::Dynamic => "dyn",

Output::Mocker => "mocker",
};
write!(f, "{s}")
}
Expand All @@ -168,7 +174,11 @@ impl fmt::Display for Output {
impl Output {
#[allow(unused_mut)]
pub fn available_engines() -> Vec<String> {
let mut out = vec!["echo_core".to_string(), "echo_full".to_string()];
let mut out = vec![
"echo_core".to_string(),
"echo_full".to_string(),
"mocker".to_string(),
];
#[cfg(feature = "mistralrs")]
{
out.push(Output::MistralRs.to_string());
Expand Down
1 change: 1 addition & 0 deletions lib/llm/src/mocker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod engine;
pub mod evictor;
pub mod kv_manager;
pub mod protocols;
Expand Down
Loading
Loading