Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e42826b
implement hierarchical level models
tmonty12 Feb 6, 2026
74fbb4c
add plan doc
tmonty12 Feb 6, 2026
e5caee7
add prefix mode to frontend
tmonty12 Feb 6, 2026
907273d
fix compilation errors
tmonty12 Feb 6, 2026
4b20406
update comments
tmonty12 Feb 6, 2026
ad07335
helper for model namespace key
tmonty12 Feb 6, 2026
9b28293
use client instance count instead
tmonty12 Feb 6, 2026
47a10a2
filter out 0 worker sets
tmonty12 Feb 6, 2026
13b9bbe
add back comments and address bug for in-process vs dynamic mode
tmonty12 Feb 6, 2026
8910601
fix edge cases and race conditions
tmonty12 Feb 6, 2026
493822f
add unit tests
tmonty12 Feb 6, 2026
53aed43
use DYN_NAMESPACE_WORKER_SUFFIX for backwards compatibility
tmonty12 Feb 6, 2026
f2ec432
revert global namespace to dynamo
tmonty12 Feb 9, 2026
18852f0
prefill router worker monitor selection is ns scoped
tmonty12 Feb 9, 2026
a6b21e1
use ns filter for common
tmonty12 Feb 9, 2026
d1c3dd7
get_worker_namespace method name is more accurate
tmonty12 Feb 10, 2026
f132e67
separate out prefill and decode registration
tmonty12 Feb 11, 2026
f893b61
fix test
tmonty12 Feb 11, 2026
7d3cea8
add comment
tmonty12 Feb 11, 2026
ad4c6c5
remove dupl condition
tmonty12 Feb 11, 2026
24b1fd7
fix pre-merge checks
tmonty12 Feb 11, 2026
32671da
remove unused import
tmonty12 Feb 11, 2026
b2d5a35
fix cargo check
tmonty12 Feb 11, 2026
2672c37
fix compilation error
tmonty12 Feb 12, 2026
aca6f0d
fix error
tmonty12 Feb 17, 2026
a85b8bd
consolidate dynamo namespace calculation for worker
tmonty12 Feb 17, 2026
54edc9d
fix clippy error
tmonty12 Feb 18, 2026
0e6103b
only emit Removed event only when model type list is empty
tmonty12 Feb 18, 2026
de60a75
updates to get_worker_namespace
tmonty12 Feb 19, 2026
2aba4ab
fix anthropic api issue
tmonty12 Feb 19, 2026
492e565
enforce mdc checksum across WorkerSets
tmonty12 Feb 20, 2026
ddaff5d
fix cargo checks
tmonty12 Feb 20, 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
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from dynamo.common.configuration.arg_group import ArgGroup
from dynamo.common.configuration.config_base import ConfigBase
from dynamo.common.configuration.utils import add_argument, add_negatable_bool_argument
from dynamo.common.utils.namespace import get_worker_namespace
from dynamo.common.utils.output_modalities import OutputModality


Expand All @@ -35,6 +36,8 @@ class DynamoRuntimeConfig(ConfigBase):
media_output_http_url: Optional[str] = None

def validate(self) -> None:
self.namespace = get_worker_namespace(self.namespace)

# TODO get a better way for spot fixes like this.
self.enable_local_indexer = not self.durable_kv_events
self._validate_output_modalities()
Expand Down Expand Up @@ -69,7 +72,8 @@ def add_arguments(self, parser) -> None:
flag_name="--namespace",
env_var="DYN_NAMESPACE",
default="dynamo",
help="Dynamo namespace",
help="Dynamo namespace. If DYN_NAMESPACE_WORKER_SUFFIX is set, "
"'-{suffix}' is appended to support multiple worker pools",
)
add_argument(
g,
Expand Down
2 changes: 2 additions & 0 deletions components/src/dynamo/common/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from dynamo.common.utils import (
endpoint_types,
engine_response,
namespace,
otel_tracing,
paths,
prometheus,
Expand All @@ -26,6 +27,7 @@
__all__ = [
"endpoint_types",
"engine_response",
"namespace",
"otel_tracing",
"paths",
"prometheus",
Expand Down
22 changes: 22 additions & 0 deletions components/src/dynamo/common/utils/namespace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

import os
from typing import Optional


def get_worker_namespace(namespace: Optional[str] = None) -> str:
"""Get the Dynamo namespace for a worker.

Uses the provided namespace, or falls back to the DYN_NAMESPACE environment
variable (defaulting to "dynamo"). If DYN_NAMESPACE_WORKER_SUFFIX is set,
it is appended as "{namespace}-{suffix}" to support multiple sets of workers
for the same model.
"""
if not namespace:
namespace = os.environ.get("DYN_NAMESPACE", "dynamo")

suffix = os.environ.get("DYN_NAMESPACE_WORKER_SUFFIX")
if suffix:
namespace = f"{namespace}-{suffix}"
Comment thread
tmonty12 marked this conversation as resolved.
Resolved
return namespace
18 changes: 15 additions & 3 deletions components/src/dynamo/frontend/frontend_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class FrontendConfig(ConfigBase):
router_max_tree_size: int
router_prune_target_ratio: float
namespace: Optional[str] = None
namespace_prefix: Optional[str] = None
router_replica_sync: bool
router_snapshot_threshold: int
router_reset_states: bool
Expand Down Expand Up @@ -128,9 +129,8 @@ def add_arguments(self, parser) -> None:
env_var="DYN_NAMESPACE",
default=None,
help=(
"Dynamo namespace for model discovery scoping. If specified, models will "
"only be discovered from this namespace. If not specified, discovers models "
"from all namespaces (global discovery)."
"Dynamo namespace for model discovery scoping. Use for exact namespace matching. "
"If --namespace-prefix is also specified, prefix takes precedence."
),
)

Expand Down Expand Up @@ -256,6 +256,18 @@ def add_arguments(self, parser) -> None:
arg_type=float,
)

add_argument(
g,
flag_name="--namespace-prefix",
env_var="DYN_NAMESPACE_PREFIX",
default=None,
help=(
"Dynamo namespace prefix for model discovery scoping. Discovers models from "
"namespaces starting with this prefix (e.g., 'ns' matches 'ns', 'ns-abc123', "
"'ns-def456'). Takes precedence over --namespace if both are specified."
),
)

add_negatable_bool_argument(
g,
flag_name="--router-replica-sync",
Expand Down
2 changes: 2 additions & 0 deletions components/src/dynamo/frontend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ def signal_handler():
kwargs["tls_key_path"] = config.tls_key_path
if config.namespace:
kwargs["namespace"] = config.namespace
if config.namespace_prefix:
kwargs["namespace_prefix"] = config.namespace_prefix
if config.kserve_grpc_server and config.grpc_metrics_port:
kwargs["http_metrics_port"] = config.grpc_metrics_port

Expand Down
4 changes: 3 additions & 1 deletion components/src/dynamo/mocker/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
import tempfile
from pathlib import Path

from dynamo.common.utils.namespace import get_worker_namespace

from . import __version__
from .utils.planner_profiler_perf_data_converter import (
convert_profile_results_to_npz,
is_mocker_format_npz,
is_profile_results_dir,
)

DYN_NAMESPACE = os.environ.get("DYN_NAMESPACE", "dynamo")
DYN_NAMESPACE = get_worker_namespace()
DEFAULT_ENDPOINT = f"dyn://{DYN_NAMESPACE}.backend.generate"
DEFAULT_PREFILL_ENDPOINT = f"dyn://{DYN_NAMESPACE}.prefill.generate"

Expand Down
5 changes: 3 additions & 2 deletions components/src/dynamo/trtllm/configs/diffusion_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
video and image diffusion workers.
"""

import os
from dataclasses import dataclass
from typing import Optional

DYN_NAMESPACE = os.environ.get("DYN_NAMESPACE", "dynamo")
from dynamo.common.utils.namespace import get_worker_namespace

DYN_NAMESPACE = get_worker_namespace()

# Default model paths
DEFAULT_VIDEO_MODEL_PATH = "Wan-AI/Wan2.1-T2V-1.3B-Diffusers"
Expand Down
1 change: 1 addition & 0 deletions lib/bindings/c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ pub unsafe extern "C" fn create_routers(
Some(prefill_config),
enforce_disagg,
model_name.clone(),
namespace_str.clone(),
)
}
None if enforce_disagg => {
Expand Down
8 changes: 6 additions & 2 deletions lib/bindings/python/rust/llm/entrypoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ pub(crate) struct EntrypointArgs {
tls_key_path: Option<PathBuf>,
extra_engine_args: Option<PathBuf>,
namespace: Option<String>,
namespace_prefix: Option<String>,
is_prefill: bool,
migration_limit: u32,
chat_engine_factory: Option<PyEngineFactory>,
Expand All @@ -191,7 +192,7 @@ pub(crate) struct EntrypointArgs {
impl EntrypointArgs {
#[allow(clippy::too_many_arguments)]
#[new]
#[pyo3(signature = (engine_type, model_path=None, model_name=None, endpoint_id=None, context_length=None, template_file=None, router_config=None, kv_cache_block_size=None, http_host=None, http_port=None, http_metrics_port=None, tls_cert_path=None, tls_key_path=None, extra_engine_args=None, namespace=None, is_prefill=false, migration_limit=0, chat_engine_factory=None))]
#[pyo3(signature = (engine_type, model_path=None, model_name=None, endpoint_id=None, context_length=None, template_file=None, router_config=None, kv_cache_block_size=None, http_host=None, http_port=None, http_metrics_port=None, tls_cert_path=None, tls_key_path=None, extra_engine_args=None, namespace=None, namespace_prefix=None, is_prefill=false, migration_limit=0, chat_engine_factory=None))]
pub fn new(
py: Python<'_>,
engine_type: EngineType,
Expand All @@ -209,6 +210,7 @@ impl EntrypointArgs {
tls_key_path: Option<PathBuf>,
extra_engine_args: Option<PathBuf>,
namespace: Option<String>,
namespace_prefix: Option<String>,
is_prefill: bool,
migration_limit: u32,
chat_engine_factory: Option<PyObject>,
Expand Down Expand Up @@ -254,6 +256,7 @@ impl EntrypointArgs {
tls_key_path,
extra_engine_args,
namespace,
namespace_prefix,
is_prefill,
migration_limit,
chat_engine_factory,
Expand Down Expand Up @@ -296,7 +299,8 @@ pub fn make_engine<'p>(
.tls_key_path(args.tls_key_path.clone())
.is_mocker(matches!(args.engine_type, EngineType::Mocker))
.extra_engine_args(args.extra_engine_args.clone())
.namespace(args.namespace.clone());
.namespace(args.namespace.clone())
.namespace_prefix(args.namespace_prefix.clone());
pyo3_async_runtimes::tokio::future_into_py(py, async move {
if let Some(model_path) = args.model_path.clone() {
let local_path = if model_path.exists() {
Expand Down
6 changes: 6 additions & 0 deletions lib/llm/src/discovery.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

mod model;
pub use model::Model;

mod model_manager;
pub use model_manager::{ModelManager, ModelManagerError};

mod worker_set;
pub use worker_set::WorkerSet;

pub(crate) mod runtime_configs;
pub use runtime_configs::{RuntimeConfigWatch, runtime_config_watch};

Expand Down
Loading
Loading