Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
18 changes: 18 additions & 0 deletions components/src/dynamo/common/configuration/arg_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@ class ArgGroup(ABC):
Base interface for configuration groups.

Each ArgGroup represents a domain of configuration parameters with clear ownership.

Examples:
>>> import argparse
>>> from dynamo.common.configuration.arg_group import ArgGroup
>>> from dynamo.common.configuration.utils import add_argument
>>>
>>> class MyArgGroup(ArgGroup):
... def add_arguments(self, parser) -> None:
... add_argument(
... parser,
... flag_name="--my-option",
... env_var="DYN_MY_OPTION",
... default="value",
... help="A custom option.",
... )
>>>
>>> parser = argparse.ArgumentParser()
>>> MyArgGroup().add_arguments(parser)
"""

@abstractmethod
Expand Down
19 changes: 18 additions & 1 deletion components/src/dynamo/common/configuration/config_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,24 @@


class ConfigBase:
"""Base configuration class that allows properties with and without defaults in arbitrary order."""
"""Base configuration class that allows properties with and without defaults in arbitrary order.

Examples:
>>> import argparse
>>> from dynamo.common.configuration.config_base import ConfigBase
>>>
>>> class MyConfig(ConfigBase):
... model_name: str
... http_port: int = 8000
>>>
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument("--model-name", default="llama")
>>> parser.add_argument("--http-port", type=int, default=8000)
>>> args = parser.parse_args([])
>>> config = MyConfig.from_cli_args(args)
>>> config.http_port
8000
"""

@classmethod
def from_cli_args(cls, args: argparse.Namespace) -> Self:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,22 @@


class KvRouterConfigBase(ConfigBase):
"""Mixin carrying the 16 KvRouterConfig fields."""
"""Mixin carrying the 16 KvRouterConfig fields.

Examples:
>>> from dynamo.common.configuration.groups.kv_router_args import (
... KvRouterArgGroup,
... KvRouterConfigBase,
... )
>>>
>>> class MyRouterConfig(KvRouterConfigBase):
... endpoint: str = "http://localhost:8080"
>>>
>>> config = MyRouterConfig()
>>> kwargs = config.kv_router_kwargs()
>>> "overlap_score_weight" in kwargs
True
"""
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

overlap_score_weight: float
router_temperature: float
Expand All @@ -63,7 +78,21 @@ def kv_router_kwargs(self) -> dict:


class KvRouterArgGroup(ArgGroup):
"""CLI arguments for the 16 KvRouterConfig parameters."""
"""CLI arguments for the 16 KvRouterConfig parameters.

Examples:
>>> import argparse
>>> from dynamo.common.configuration.groups.kv_router_args import KvRouterArgGroup
>>>
>>> parser = argparse.ArgumentParser()
>>> KvRouterArgGroup().add_arguments(parser)
>>> args = parser.parse_args([
... "--router-kv-overlap-score-weight", "0.8",
... "--router-temperature", "0.5",
... ])
>>> args.overlap_score_weight
0.8

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These don't need examples, they are trivial.

"""

def add_arguments(self, parser) -> None:
g = parser.add_argument_group("KV Router Options")
Expand Down
17 changes: 17 additions & 0 deletions components/src/dynamo/common/configuration/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,23 @@ def add_argument(
"""
Add a CLI argument with env var default, optional alias and dest, and help message construction.

Examples:
>>> import argparse
>>> from dynamo.common.configuration.utils import add_argument
>>>
>>> parser = argparse.ArgumentParser()
>>> add_argument(
... parser,
... flag_name="--http-port",
... env_var="DYN_HTTP_PORT",
... default=8000,
... help="HTTP port for the engine.",
... arg_type=int,
... )
>>> args = parser.parse_args([])
>>> args.http_port
8000

Args:
parser: ArgumentParser or argument group
flag_name: Primary flag (must start with '--', e.g., "--foo")
Expand Down
20 changes: 18 additions & 2 deletions components/src/dynamo/common/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,31 @@


class DisaggregationMode(Enum):
"""Disaggregation mode for LLM workers."""
"""Disaggregation mode for LLM workers.

Examples:
>>> from dynamo.common.constants import DisaggregationMode
>>> DisaggregationMode.PREFILL.value
'prefill'
>>> DisaggregationMode("agg") == DisaggregationMode.AGGREGATED
True

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, come on. It's an enum. Everyone looking at this code knows how to use an enum.

"""

AGGREGATED = "agg"
PREFILL = "prefill"
DECODE = "decode"


class EmbeddingTransferMode(Enum):
"""Embedding transfer mode for LLM workers."""
"""Embedding transfer mode for LLM workers.

Examples:
>>> from dynamo.common.constants import EmbeddingTransferMode
>>> EmbeddingTransferMode.NIXL_WRITE.value
'nixl-write'
>>> EmbeddingTransferMode("local") == EmbeddingTransferMode.LOCAL
True
"""

LOCAL = "local"
NIXL_WRITE = "nixl-write"
Expand Down
10 changes: 10 additions & 0 deletions components/src/dynamo/common/lora/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ class LoRAManager:

The manager uses the Rust-based LoRADownloader for S3 and local file sources,
and allows registering custom Python sources for other protocols.

Examples:
>>> import asyncio
>>> from dynamo.common.lora import LoRAManager
>>> manager = LoRAManager()
>>> result = asyncio.run(
... manager.download_lora("s3://bucket/adapters/lora-v1")
... ) # doctest: +SKIP
>>> manager.is_cached("s3://bucket/adapters/lora-v1") # doctest: +SKIP
True
"""

def __init__(self, cache_path: Optional[Path] = None):
Expand Down
30 changes: 30 additions & 0 deletions components/src/dynamo/common/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ def get_fs(fs_url: str) -> DirFileSystem:
Args:
fs_url: The URL of the filesystem to initialize. e.g. s3://bucket, gs://bucket, file:///local/path

Examples:
>>> from dynamo.common.storage import get_fs
>>>
>>> fs = get_fs("file:///data/media")
>>> protocol = fs.fs.protocol
>>> protocol if isinstance(protocol, str) else protocol[0]
'file'
>>> fs = get_fs("s3://my-bucket")
>>> fs.path
'my-bucket'
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

Returns:
The initialized DirFileSystem wrapper for the filesystem.

Expand Down Expand Up @@ -81,6 +92,15 @@ def get_media_url(
``{base_url}/{storage_path}``. When *None*, the URL is constructed
from the filesystem's protocol and root path.

Examples:
>>> from dynamo.common.storage import get_fs, get_media_url
>>>
>>> fs = get_fs("file:///data/media")
>>> get_media_url(fs, "videos/req-123.mp4")
'file:///data/media/videos/req-123.mp4'
>>> get_media_url(fs, "img.png", base_url="https://cdn.example.com/media")
'https://cdn.example.com/media/img.png'

Returns:
Public URL string for the uploaded file.
"""
Expand Down Expand Up @@ -110,6 +130,16 @@ async def upload_to_fs(
data: Raw bytes to upload.
base_url: Optional CDN / proxy base URL for URL rewriting.

Examples:
>>> import asyncio
>>> from dynamo.common.storage import get_fs, upload_to_fs
>>>
>>> fs = get_fs("s3://my-media-bucket")
>>> image_bytes = b"\\x89PNG..."
>>> url = asyncio.run(
... upload_to_fs(fs, "images/req-123/output.png", image_bytes)
... ) # doctest: +SKIP

Returns:
Public URL string for the uploaded file.
"""
Expand Down
66 changes: 56 additions & 10 deletions components/src/dynamo/frontend/frontend_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,24 @@ def validate_model_path(value: str) -> str:


class FrontendConfig(KvRouterConfigBase):
"""Configuration for the Dynamo frontend."""
"""Configuration for the Dynamo frontend.

Examples:
>>> import argparse
>>> from dynamo.frontend.frontend_args import FrontendArgGroup, FrontendConfig
>>>
>>> parser = argparse.ArgumentParser()
>>> FrontendArgGroup().add_arguments(parser)
>>> args = parser.parse_args([
... "--model-name", "Llama-3.2-1B-Instruct",
... "--http-port", "8080",
... ])
>>> config = FrontendConfig.from_cli_args(args)
>>> config.model_name
'Llama-3.2-1B-Instruct'
>>> config.http_port
8080
"""

interactive: bool
kv_cache_block_size: Optional[int]
Expand All @@ -52,7 +69,7 @@ class FrontendConfig(KvRouterConfigBase):
router_mode: str
namespace: Optional[str] = None
namespace_prefix: Optional[str] = None
enforce_disagg: bool
decode_fallback: bool
Comment thread
dagil-nvidia marked this conversation as resolved.
Resolved

migration_limit: int
active_decode_blocks_threshold: Optional[float]
Expand All @@ -71,6 +88,7 @@ class FrontendConfig(KvRouterConfigBase):
event_plane: str
chat_processor: str
enable_anthropic_api: bool
debug_perf: bool
preprocess_workers: int

def validate(self) -> None:
Expand All @@ -93,7 +111,23 @@ def _preprocess_for_encode_config(config: FrontendConfig) -> Dict[str, Any]:


class FrontendArgGroup(ArgGroup):
"""Frontend configuration parameters."""
"""Frontend configuration parameters.

Examples:
>>> import argparse
>>> from dynamo.frontend.frontend_args import FrontendArgGroup
>>>
>>> parser = argparse.ArgumentParser()
>>> group = FrontendArgGroup()
>>> group.add_arguments(parser)
>>> args = parser.parse_args([
... "--model-name", "Llama-3.2-1B-Instruct",
... "--router-mode", "kv",
... "--http-port", "8080",
... ])
>>> args.model_name
'Llama-3.2-1B-Instruct'
"""

def add_arguments(self, parser) -> None:
parser.add_argument(
Expand Down Expand Up @@ -190,15 +224,14 @@ def add_arguments(self, parser) -> None:

add_negatable_bool_argument(
g,
flag_name="--enforce-disagg",
env_var="DYN_ENFORCE_DISAGG",
flag_name="--decode-fallback",
env_var="DYN_DECODE_FALLBACK",
default=False,
dest="enforce_disagg",
dest="decode_fallback",
help=(
"Strictly enforce disaggregated mode. Requests will fail if the prefill router "
"has not activated yet (e.g., prefill workers still registering). This is stricter "
"than the default: without this flag, requests arriving before prefill workers are "
"discovered fall through to aggregated decode-only routing."
"Allow falling back to decode-only (aggregated) mode when prefill workers are "
"unavailable. By default, disaggregated prefill-decode is enforced and requests "
"fail if no prefill workers are found."
),
)
Comment thread
dagil-nvidia marked this conversation as resolved.
Resolved

Expand Down Expand Up @@ -356,6 +389,19 @@ def add_arguments(self, parser) -> None:
choices=["dynamo", "vllm"],
)

add_negatable_bool_argument(
g,
flag_name="--dyn-debug-perf",
env_var="DYN_DEBUG_PERF",
default=False,
dest="debug_perf",
help=(
"[EXPERIMENTAL] Enable performance instrumentation for diagnosing preprocessing bottlenecks. "
"Logs per-function timing, request concurrency, and hot-path section durations. "
"'--dyn-chat-processor vllm' only."
),
)

add_argument(
g,
flag_name="--dyn-preprocess-workers",
Expand Down
Loading
Loading