[model-gateway] Organize CLI arguments into logical groups for better --help output (#16035)

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
Simo Lin
2025-12-28 20:25:53 -08:00
committed by GitHub
co-authored by gemini-code-assist[bot]
parent 9884c9fd4c
commit 41a1d16b02
@@ -152,22 +152,79 @@ class RouterArgs:
""" """
prefix = "router-" if use_router_prefix else "" prefix = "router-" if use_router_prefix else ""
# Create argument groups for organized --help output
worker_group = parser.add_argument_group(
"Worker Configuration", "Settings for worker connections and URLs"
)
routing_group = parser.add_argument_group(
"Routing Policy", "Load balancing and routing configuration"
)
pd_group = parser.add_argument_group(
"PD Disaggregation", "Prefill-Decode disaggregated mode settings"
)
k8s_group = parser.add_argument_group(
"Service Discovery (Kubernetes)", "Kubernetes-based worker discovery"
)
logging_group = parser.add_argument_group("Logging", "Log output configuration")
prometheus_group = parser.add_argument_group(
"Prometheus Metrics", "Metrics export configuration"
)
request_group = parser.add_argument_group(
"Request Handling", "Request timeout and ID configuration"
)
rate_limit_group = parser.add_argument_group(
"Rate Limiting", "Concurrent request and queue limits"
)
retry_group = parser.add_argument_group(
"Retry Configuration", "Automatic retry behavior for failed requests"
)
cb_group = parser.add_argument_group(
"Circuit Breaker", "Circuit breaker pattern configuration"
)
health_group = parser.add_argument_group(
"Health Checks", "Worker health monitoring settings"
)
tokenizer_group = parser.add_argument_group(
"Tokenizer", "Tokenizer and chat template configuration"
)
parser_group = parser.add_argument_group(
"Parsers", "Reasoning and tool-call parser settings"
)
backend_group = parser.add_argument_group(
"Backend", "Backend runtime and history storage selection"
)
oracle_group = parser.add_argument_group(
"Oracle Database", "Oracle database backend configuration"
)
postgres_group = parser.add_argument_group(
"PostgreSQL Database", "PostgreSQL database backend configuration"
)
tls_group = parser.add_argument_group(
"TLS/mTLS Security", "TLS certificates for server and worker communication"
)
trace_group = parser.add_argument_group(
"Tracing (OpenTelemetry)", "Distributed tracing configuration"
)
auth_group = parser.add_argument_group(
"Control Plane Authentication", "API key and JWT/OIDC authentication"
)
# Worker configuration # Worker configuration
if not exclude_host_port: if not exclude_host_port:
parser.add_argument( worker_group.add_argument(
"--host", "--host",
type=str, type=str,
default=RouterArgs.host, default=RouterArgs.host,
help="Host address to bind the router server. Supports IPv4, IPv6 (e.g., ::, ::1), or 0.0.0.0 for all interfaces", help="Host address to bind the router server. Supports IPv4, IPv6 (e.g., ::, ::1), or 0.0.0.0 for all interfaces",
) )
parser.add_argument( worker_group.add_argument(
"--port", "--port",
type=int, type=int,
default=RouterArgs.port, default=RouterArgs.port,
help="Port number to bind the router server", help="Port number to bind the router server",
) )
parser.add_argument( worker_group.add_argument(
"--worker-urls", "--worker-urls",
type=str, type=str,
nargs="*", nargs="*",
@@ -176,14 +233,14 @@ class RouterArgs:
) )
# Routing policy configuration # Routing policy configuration
parser.add_argument( routing_group.add_argument(
f"--{prefix}policy", f"--{prefix}policy",
type=str, type=str,
default=RouterArgs.policy, default=RouterArgs.policy,
choices=["random", "round_robin", "cache_aware", "power_of_two", "manual"], choices=["random", "round_robin", "cache_aware", "power_of_two", "manual"],
help="Load balancing policy to use. In PD mode, this is used for both prefill and decode unless overridden", help="Load balancing policy to use. In PD mode, this is used for both prefill and decode unless overridden",
) )
parser.add_argument( routing_group.add_argument(
f"--{prefix}prefill-policy", f"--{prefix}prefill-policy",
type=str, type=str,
default=None, default=None,
@@ -197,26 +254,78 @@ class RouterArgs:
], ],
help="Specific policy for prefill nodes in PD mode. If not specified, uses the main policy", help="Specific policy for prefill nodes in PD mode. If not specified, uses the main policy",
) )
parser.add_argument( routing_group.add_argument(
f"--{prefix}decode-policy", f"--{prefix}decode-policy",
type=str, type=str,
default=None, default=None,
choices=["random", "round_robin", "cache_aware", "power_of_two", "manual"], choices=["random", "round_robin", "cache_aware", "power_of_two", "manual"],
help="Specific policy for decode nodes in PD mode. If not specified, uses the main policy", help="Specific policy for decode nodes in PD mode. If not specified, uses the main policy",
) )
routing_group.add_argument(
f"--{prefix}cache-threshold",
type=float,
default=RouterArgs.cache_threshold,
help="Cache threshold (0.0-1.0) for cache-aware routing",
)
routing_group.add_argument(
f"--{prefix}balance-abs-threshold",
type=int,
default=RouterArgs.balance_abs_threshold,
help="Absolute threshold for load difference. Balancing is triggered if `(max_load - min_load) > abs_threshold` and the relative threshold is also met.",
)
routing_group.add_argument(
f"--{prefix}balance-rel-threshold",
type=float,
default=RouterArgs.balance_rel_threshold,
help="Relative threshold for load difference. Balancing is triggered if `max_load > min_load * rel_threshold` and the absolute threshold is also met.",
)
routing_group.add_argument(
f"--{prefix}bucket-adjust-interval-secs",
type=int,
default=RouterArgs.bucket_adjust_interval_secs,
help="Interval in seconds between bucket boundary adjustment operations",
)
routing_group.add_argument(
f"--{prefix}eviction-interval-secs",
type=int,
default=RouterArgs.eviction_interval_secs,
help="Interval in seconds between cache eviction operations",
)
routing_group.add_argument(
f"--{prefix}max-tree-size",
type=int,
default=RouterArgs.max_tree_size,
help="Maximum size of the approximation tree for cache-aware routing",
)
routing_group.add_argument(
f"--{prefix}max-payload-size",
type=int,
default=RouterArgs.max_payload_size,
help="Maximum payload size in bytes",
)
routing_group.add_argument(
f"--{prefix}dp-aware",
action="store_true",
help="Enable data parallelism aware schedule",
)
routing_group.add_argument(
f"--{prefix}enable-igw",
action="store_true",
help="Enable IGW (Inference-Gateway) mode for multi-model support",
)
# PD-specific arguments # PD-specific arguments
parser.add_argument( pd_group.add_argument(
f"--{prefix}mini-lb", f"--{prefix}mini-lb",
action="store_true", action="store_true",
help="Enable MiniLB", help="Enable MiniLB",
) )
parser.add_argument( pd_group.add_argument(
f"--{prefix}pd-disaggregation", f"--{prefix}pd-disaggregation",
action="store_true", action="store_true",
help="Enable PD (Prefill-Decode) disaggregated mode", help="Enable PD (Prefill-Decode) disaggregated mode",
) )
parser.add_argument( pd_group.add_argument(
f"--{prefix}prefill", f"--{prefix}prefill",
nargs="+", nargs="+",
action="append", action="append",
@@ -224,127 +333,73 @@ class RouterArgs:
"Format: --prefill URL [BOOTSTRAP_PORT]. " "Format: --prefill URL [BOOTSTRAP_PORT]. "
"BOOTSTRAP_PORT can be a port number, 'none', or omitted (defaults to none).", "BOOTSTRAP_PORT can be a port number, 'none', or omitted (defaults to none).",
) )
parser.add_argument( pd_group.add_argument(
f"--{prefix}decode", f"--{prefix}decode",
nargs=1, nargs=1,
action="append", action="append",
metavar=("URL",), metavar=("URL",),
help="Decode server URL. Can be specified multiple times.", help="Decode server URL. Can be specified multiple times.",
) )
parser.add_argument( pd_group.add_argument(
f"--{prefix}worker-startup-timeout-secs", f"--{prefix}worker-startup-timeout-secs",
type=int, type=int,
default=RouterArgs.worker_startup_timeout_secs, default=RouterArgs.worker_startup_timeout_secs,
help="Timeout in seconds for worker startup and registration (default: 1800 / 30 minutes). Large models can take significant time to load into GPU memory.", help="Timeout in seconds for worker startup and registration (default: 1800 / 30 minutes). Large models can take significant time to load into GPU memory.",
) )
parser.add_argument( pd_group.add_argument(
f"--{prefix}worker-startup-check-interval", f"--{prefix}worker-startup-check-interval",
type=int, type=int,
default=RouterArgs.worker_startup_check_interval, default=RouterArgs.worker_startup_check_interval,
help="Interval in seconds between checks for worker startup", help="Interval in seconds between checks for worker startup",
) )
parser.add_argument(
f"--{prefix}cache-threshold", # Logging configuration
type=float, logging_group.add_argument(
default=RouterArgs.cache_threshold,
help="Cache threshold (0.0-1.0) for cache-aware routing",
)
parser.add_argument(
f"--{prefix}balance-abs-threshold",
type=int,
default=RouterArgs.balance_abs_threshold,
help="Load balancing is triggered when (max_load - min_load) > abs_threshold AND max_load > min_load * rel_threshold. Otherwise, use cache aware",
)
parser.add_argument(
f"--{prefix}balance-rel-threshold",
type=float,
default=RouterArgs.balance_rel_threshold,
help="Load balancing is triggered when (max_load - min_load) > abs_threshold AND max_load > min_load * rel_threshold. Otherwise, use cache aware",
)
parser.add_argument(
f"--{prefix}bucket-adjust-interval-secs",
type=int,
default=RouterArgs.bucket_adjust_interval_secs,
help="Interval in seconds between bucket boundary adjustment operations",
)
parser.add_argument(
f"--{prefix}eviction-interval-secs",
type=int,
default=RouterArgs.eviction_interval_secs,
help="Interval in seconds between cache eviction operations",
)
parser.add_argument(
f"--{prefix}max-tree-size",
type=int,
default=RouterArgs.max_tree_size,
help="Maximum size of the approximation tree for cache-aware routing",
)
parser.add_argument(
f"--{prefix}max-payload-size",
type=int,
default=RouterArgs.max_payload_size,
help="Maximum payload size in bytes",
)
parser.add_argument(
f"--{prefix}dp-aware",
action="store_true",
help="Enable data parallelism aware schedule",
)
parser.add_argument(
f"--{prefix}enable-igw",
action="store_true",
help="Enable IGW (Inference-Gateway) mode for multi-model support",
)
parser.add_argument(
f"--{prefix}api-key",
type=str,
default=None,
help="The api key used for the authorization with the worker. Useful when the dp aware scheduling strategy is enaled.",
)
parser.add_argument(
f"--{prefix}log-dir", f"--{prefix}log-dir",
type=str, type=str,
default=None, default=None,
help="Directory to store log files. If not specified, logs are only output to console.", help="Directory to store log files. If not specified, logs are only output to console.",
) )
parser.add_argument( logging_group.add_argument(
f"--{prefix}log-level", f"--{prefix}log-level",
type=str, type=str,
default="info", default="info",
choices=["debug", "info", "warn", "error"], choices=["debug", "info", "warn", "error"],
help="Set the logging level. If not specified, defaults to INFO.", help="Set the logging level. If not specified, defaults to INFO.",
) )
parser.add_argument(
# Service discovery configuration
k8s_group.add_argument(
f"--{prefix}service-discovery", f"--{prefix}service-discovery",
action="store_true", action="store_true",
help="Enable Kubernetes service discovery", help="Enable Kubernetes service discovery",
) )
parser.add_argument( k8s_group.add_argument(
f"--{prefix}selector", f"--{prefix}selector",
type=str, type=str,
nargs="+", nargs="+",
default={}, default={},
help="Label selector for Kubernetes service discovery (format: key1=value1 key2=value2)", help="Label selector for Kubernetes service discovery (format: key1=value1 key2=value2)",
) )
parser.add_argument( k8s_group.add_argument(
f"--{prefix}service-discovery-port", f"--{prefix}service-discovery-port",
type=int, type=int,
default=RouterArgs.service_discovery_port, default=RouterArgs.service_discovery_port,
help="Port to use for discovered worker pods", help="Port to use for discovered worker pods",
) )
parser.add_argument( k8s_group.add_argument(
f"--{prefix}service-discovery-namespace", f"--{prefix}service-discovery-namespace",
type=str, type=str,
help="Kubernetes namespace to watch for pods. If not provided, watches all namespaces (requires cluster-wide permissions)", help="Kubernetes namespace to watch for pods. If not provided, watches all namespaces (requires cluster-wide permissions)",
) )
parser.add_argument( k8s_group.add_argument(
f"--{prefix}prefill-selector", f"--{prefix}prefill-selector",
type=str, type=str,
nargs="+", nargs="+",
default={}, default={},
help="Label selector for prefill server pods in PD mode (format: key1=value1 key2=value2)", help="Label selector for prefill server pods in PD mode (format: key1=value1 key2=value2)",
) )
parser.add_argument( k8s_group.add_argument(
f"--{prefix}decode-selector", f"--{prefix}decode-selector",
type=str, type=str,
nargs="+", nargs="+",
@@ -352,285 +407,303 @@ class RouterArgs:
help="Label selector for decode server pods in PD mode (format: key1=value1 key2=value2)", help="Label selector for decode server pods in PD mode (format: key1=value1 key2=value2)",
) )
# Prometheus configuration # Prometheus configuration
parser.add_argument( prometheus_group.add_argument(
f"--{prefix}prometheus-port", f"--{prefix}prometheus-port",
type=int, type=int,
default=29000, default=29000,
help="Port to expose Prometheus metrics. If not specified, Prometheus metrics are disabled", help="Port to expose Prometheus metrics (default: 29000).",
) )
parser.add_argument( prometheus_group.add_argument(
f"--{prefix}prometheus-host", f"--{prefix}prometheus-host",
type=str, type=str,
default="0.0.0.0", default="0.0.0.0",
help="Host address to bind the Prometheus metrics server. Supports IPv4, IPv6 (e.g., ::, ::1), or 0.0.0.0 for all interfaces", help="Host address to bind the Prometheus metrics server. Supports IPv4, IPv6 (e.g., ::, ::1), or 0.0.0.0 for all interfaces",
) )
parser.add_argument( prometheus_group.add_argument(
f"--{prefix}prometheus-duration-buckets", f"--{prefix}prometheus-duration-buckets",
type=float, type=float,
nargs="+", nargs="+",
help="Buckets for Prometheus duration metrics", help="Buckets for Prometheus duration metrics",
) )
parser.add_argument(
# Request handling configuration
request_group.add_argument(
f"--{prefix}request-id-headers", f"--{prefix}request-id-headers",
type=str, type=str,
nargs="*", nargs="*",
help="Custom HTTP headers to check for request IDs (e.g., x-request-id x-trace-id). If not specified, uses common defaults.", help="Custom HTTP headers to check for request IDs (e.g., x-request-id x-trace-id). If not specified, uses common defaults.",
) )
parser.add_argument( request_group.add_argument(
f"--{prefix}request-timeout-secs", f"--{prefix}request-timeout-secs",
type=int, type=int,
default=RouterArgs.request_timeout_secs, default=RouterArgs.request_timeout_secs,
help="Request timeout in seconds", help="Request timeout in seconds",
) )
parser.add_argument( request_group.add_argument(
f"--{prefix}shutdown-grace-period-secs", f"--{prefix}shutdown-grace-period-secs",
type=int, type=int,
default=RouterArgs.shutdown_grace_period_secs, default=RouterArgs.shutdown_grace_period_secs,
help="Grace period in seconds to wait for in-flight requests during shutdown", help="Grace period in seconds to wait for in-flight requests during shutdown",
) )
# Retry configuration request_group.add_argument(
parser.add_argument(
f"--{prefix}retry-max-retries",
type=int,
default=RouterArgs.retry_max_retries,
)
parser.add_argument(
f"--{prefix}retry-initial-backoff-ms",
type=int,
default=RouterArgs.retry_initial_backoff_ms,
)
parser.add_argument(
f"--{prefix}retry-max-backoff-ms",
type=int,
default=RouterArgs.retry_max_backoff_ms,
)
parser.add_argument(
f"--{prefix}retry-backoff-multiplier",
type=float,
default=RouterArgs.retry_backoff_multiplier,
)
parser.add_argument(
f"--{prefix}retry-jitter-factor",
type=float,
default=RouterArgs.retry_jitter_factor,
)
parser.add_argument(
f"--{prefix}disable-retries",
action="store_true",
help="Disable retries (equivalent to setting retry_max_retries=1)",
)
# Circuit breaker configuration
parser.add_argument(
f"--{prefix}cb-failure-threshold",
type=int,
default=RouterArgs.cb_failure_threshold,
)
parser.add_argument(
f"--{prefix}cb-success-threshold",
type=int,
default=RouterArgs.cb_success_threshold,
)
parser.add_argument(
f"--{prefix}cb-timeout-duration-secs",
type=int,
default=RouterArgs.cb_timeout_duration_secs,
)
parser.add_argument(
f"--{prefix}cb-window-duration-secs",
type=int,
default=RouterArgs.cb_window_duration_secs,
)
parser.add_argument(
f"--{prefix}disable-circuit-breaker",
action="store_true",
help="Disable circuit breaker (equivalent to setting cb_failure_threshold to u32::MAX)",
)
# Health check configuration
parser.add_argument(
f"--{prefix}health-failure-threshold",
type=int,
default=RouterArgs.health_failure_threshold,
help="Number of consecutive health check failures before marking worker unhealthy",
)
parser.add_argument(
f"--{prefix}health-success-threshold",
type=int,
default=RouterArgs.health_success_threshold,
help="Number of consecutive health check successes before marking worker healthy",
)
parser.add_argument(
f"--{prefix}health-check-timeout-secs",
type=int,
default=RouterArgs.health_check_timeout_secs,
help="Timeout in seconds for health check requests",
)
parser.add_argument(
f"--{prefix}health-check-interval-secs",
type=int,
default=RouterArgs.health_check_interval_secs,
help="Interval in seconds between runtime health checks",
)
parser.add_argument(
f"--{prefix}health-check-endpoint",
type=str,
default=RouterArgs.health_check_endpoint,
help="Health check endpoint path",
)
parser.add_argument(
f"--{prefix}max-concurrent-requests",
type=int,
default=RouterArgs.max_concurrent_requests,
help="Maximum number of concurrent requests allowed (for rate limiting). Set to -1 to disable rate limiting.",
)
parser.add_argument(
f"--{prefix}queue-size",
type=int,
default=RouterArgs.queue_size,
help="Queue size for pending requests when max concurrent limit reached (0 = no queue, return 429 immediately)",
)
parser.add_argument(
f"--{prefix}queue-timeout-secs",
type=int,
default=RouterArgs.queue_timeout_secs,
help="Maximum time (in seconds) a request can wait in queue before timing out",
)
parser.add_argument(
f"--{prefix}rate-limit-tokens-per-second",
type=int,
default=RouterArgs.rate_limit_tokens_per_second,
help="Token bucket refill rate (tokens per second). If not set, defaults to max_concurrent_requests",
)
parser.add_argument(
f"--{prefix}cors-allowed-origins", f"--{prefix}cors-allowed-origins",
type=str, type=str,
nargs="*", nargs="*",
default=[], default=[],
help="CORS allowed origins (e.g., http://localhost:3000 https://example.com)", help="CORS allowed origins (e.g., http://localhost:3000 https://example.com)",
) )
# Rate limiting configuration
rate_limit_group.add_argument(
f"--{prefix}max-concurrent-requests",
type=int,
default=RouterArgs.max_concurrent_requests,
help="Maximum number of concurrent requests allowed (for rate limiting). Set to -1 to disable rate limiting.",
)
rate_limit_group.add_argument(
f"--{prefix}queue-size",
type=int,
default=RouterArgs.queue_size,
help="Queue size for pending requests when max concurrent limit reached (0 = no queue, return 429 immediately)",
)
rate_limit_group.add_argument(
f"--{prefix}queue-timeout-secs",
type=int,
default=RouterArgs.queue_timeout_secs,
help="Maximum time (in seconds) a request can wait in queue before timing out",
)
rate_limit_group.add_argument(
f"--{prefix}rate-limit-tokens-per-second",
type=int,
default=RouterArgs.rate_limit_tokens_per_second,
help="Token bucket refill rate (tokens per second). If not set, defaults to max_concurrent_requests",
)
# Retry configuration
retry_group.add_argument(
f"--{prefix}retry-max-retries",
type=int,
default=RouterArgs.retry_max_retries,
help="Maximum number of retry attempts for failed requests",
)
retry_group.add_argument(
f"--{prefix}retry-initial-backoff-ms",
type=int,
default=RouterArgs.retry_initial_backoff_ms,
help="Initial backoff delay in milliseconds before first retry",
)
retry_group.add_argument(
f"--{prefix}retry-max-backoff-ms",
type=int,
default=RouterArgs.retry_max_backoff_ms,
help="Maximum backoff delay in milliseconds between retries",
)
retry_group.add_argument(
f"--{prefix}retry-backoff-multiplier",
type=float,
default=RouterArgs.retry_backoff_multiplier,
help="Multiplier for exponential backoff between retries",
)
retry_group.add_argument(
f"--{prefix}retry-jitter-factor",
type=float,
default=RouterArgs.retry_jitter_factor,
help="Jitter factor (0.0-1.0) to add randomness to retry delays",
)
retry_group.add_argument(
f"--{prefix}disable-retries",
action="store_true",
help="Disable retries (equivalent to setting retry_max_retries=1)",
)
# Circuit breaker configuration
cb_group.add_argument(
f"--{prefix}cb-failure-threshold",
type=int,
default=RouterArgs.cb_failure_threshold,
help="Number of failures before circuit breaker opens",
)
cb_group.add_argument(
f"--{prefix}cb-success-threshold",
type=int,
default=RouterArgs.cb_success_threshold,
help="Number of successes in half-open state before closing circuit",
)
cb_group.add_argument(
f"--{prefix}cb-timeout-duration-secs",
type=int,
default=RouterArgs.cb_timeout_duration_secs,
help="Time in seconds before attempting to close an open circuit",
)
cb_group.add_argument(
f"--{prefix}cb-window-duration-secs",
type=int,
default=RouterArgs.cb_window_duration_secs,
help="Sliding window duration in seconds for tracking failures",
)
cb_group.add_argument(
f"--{prefix}disable-circuit-breaker",
action="store_true",
help="Disable circuit breaker (equivalent to setting cb_failure_threshold to u32::MAX)",
)
# Health check configuration
health_group.add_argument(
f"--{prefix}health-failure-threshold",
type=int,
default=RouterArgs.health_failure_threshold,
help="Number of consecutive health check failures before marking worker unhealthy",
)
health_group.add_argument(
f"--{prefix}health-success-threshold",
type=int,
default=RouterArgs.health_success_threshold,
help="Number of consecutive health check successes before marking worker healthy",
)
health_group.add_argument(
f"--{prefix}health-check-timeout-secs",
type=int,
default=RouterArgs.health_check_timeout_secs,
help="Timeout in seconds for health check requests",
)
health_group.add_argument(
f"--{prefix}health-check-interval-secs",
type=int,
default=RouterArgs.health_check_interval_secs,
help="Interval in seconds between runtime health checks",
)
health_group.add_argument(
f"--{prefix}health-check-endpoint",
type=str,
default=RouterArgs.health_check_endpoint,
help="Health check endpoint path",
)
# Tokenizer configuration # Tokenizer configuration
parser.add_argument( tokenizer_group.add_argument(
f"--{prefix}model-path", f"--{prefix}model-path",
type=str, type=str,
default=None, default=None,
help="Model path for loading tokenizer (HuggingFace model ID or local path)", help="Model path for loading tokenizer (HuggingFace model ID or local path)",
) )
parser.add_argument( tokenizer_group.add_argument(
f"--{prefix}tokenizer-path", f"--{prefix}tokenizer-path",
type=str, type=str,
default=None, default=None,
help="Explicit tokenizer path (overrides model_path tokenizer if provided)", help="Explicit tokenizer path (overrides model_path tokenizer if provided)",
) )
parser.add_argument( tokenizer_group.add_argument(
f"--{prefix}chat-template", f"--{prefix}chat-template",
type=str, type=str,
default=None, default=None,
help="Chat template path (optional)", help="Chat template path (optional)",
) )
parser.add_argument( tokenizer_group.add_argument(
f"--{prefix}tokenizer-cache-enable-l0", f"--{prefix}tokenizer-cache-enable-l0",
action="store_true", action="store_true",
default=RouterArgs.tokenizer_cache_enable_l0, default=RouterArgs.tokenizer_cache_enable_l0,
help="Enable L0 (whole-string exact match) tokenizer cache (default: False)", help="Enable L0 (whole-string exact match) tokenizer cache (default: False)",
) )
parser.add_argument( tokenizer_group.add_argument(
f"--{prefix}tokenizer-cache-l0-max-entries", f"--{prefix}tokenizer-cache-l0-max-entries",
type=int, type=int,
default=RouterArgs.tokenizer_cache_l0_max_entries, default=RouterArgs.tokenizer_cache_l0_max_entries,
help="Maximum number of entries in L0 tokenizer cache (default: 10000)", help="Maximum number of entries in L0 tokenizer cache (default: 10000)",
) )
parser.add_argument( tokenizer_group.add_argument(
f"--{prefix}tokenizer-cache-enable-l1", f"--{prefix}tokenizer-cache-enable-l1",
action="store_true", action="store_true",
default=RouterArgs.tokenizer_cache_enable_l1, default=RouterArgs.tokenizer_cache_enable_l1,
help="Enable L1 (prefix matching) tokenizer cache (default: False)", help="Enable L1 (prefix matching) tokenizer cache (default: False)",
) )
parser.add_argument( tokenizer_group.add_argument(
f"--{prefix}tokenizer-cache-l1-max-memory", f"--{prefix}tokenizer-cache-l1-max-memory",
type=int, type=int,
default=RouterArgs.tokenizer_cache_l1_max_memory, default=RouterArgs.tokenizer_cache_l1_max_memory,
help="Maximum memory for L1 tokenizer cache in bytes (default: 50MB)", help="Maximum memory for L1 tokenizer cache in bytes (default: 50MB)",
) )
parser.add_argument(
# Parser configuration
parser_group.add_argument(
f"--{prefix}reasoning-parser", f"--{prefix}reasoning-parser",
type=str, type=str,
default=None, default=None,
help="Specify the parser for reasoning models (e.g., deepseek-r1, qwen3)", help="Specify the parser for reasoning models (e.g., deepseek-r1, qwen3)",
) )
tool_call_parser_choices = get_available_tool_call_parsers() tool_call_parser_choices = get_available_tool_call_parsers()
parser.add_argument( parser_group.add_argument(
f"--{prefix}tool-call-parser", f"--{prefix}tool-call-parser",
type=str, type=str,
default=None, default=None,
choices=tool_call_parser_choices, choices=tool_call_parser_choices,
help=f"Specify the parser for tool-call interactions (e.g., json, qwen)", help=f"Specify the parser for tool-call interactions (e.g., json, qwen)",
) )
# MCP server configuration parser_group.add_argument(
parser.add_argument(
f"--{prefix}mcp-config-path", f"--{prefix}mcp-config-path",
type=str, type=str,
default=None, default=None,
help="Path to MCP (Model Context Protocol) server configuration file", help="Path to MCP (Model Context Protocol) server configuration file",
) )
# Backend selection # Backend selection
parser.add_argument( backend_group.add_argument(
f"--{prefix}backend", f"--{prefix}backend",
type=str, type=str,
default=RouterArgs.backend, default=RouterArgs.backend,
choices=["sglang", "openai"], choices=["sglang", "openai"],
help="Backend runtime to use (default: sglang)", help="Backend runtime to use (default: sglang)",
) )
# History backend configuration backend_group.add_argument(
parser.add_argument(
f"--{prefix}history-backend", f"--{prefix}history-backend",
type=str, type=str,
default=RouterArgs.history_backend, default=RouterArgs.history_backend,
choices=["memory", "none", "oracle", "postgres"], choices=["memory", "none", "oracle", "postgres"],
help="History storage backend for conversations and responses (default: memory)", help="History storage backend for conversations and responses (default: memory)",
) )
# Oracle configuration # Oracle configuration
parser.add_argument( oracle_group.add_argument(
f"--{prefix}oracle-wallet-path", f"--{prefix}oracle-wallet-path",
type=str, type=str,
default=os.getenv("ATP_WALLET_PATH"), default=os.getenv("ATP_WALLET_PATH"),
help="Path to Oracle ATP wallet directory (env: ATP_WALLET_PATH)", help="Path to Oracle ATP wallet directory (env: ATP_WALLET_PATH)",
) )
parser.add_argument( oracle_group.add_argument(
f"--{prefix}oracle-tns-alias", f"--{prefix}oracle-tns-alias",
type=str, type=str,
default=os.getenv("ATP_TNS_ALIAS"), default=os.getenv("ATP_TNS_ALIAS"),
help="Oracle TNS alias from tnsnames.ora (env: ATP_TNS_ALIAS).", help="Oracle TNS alias from tnsnames.ora (env: ATP_TNS_ALIAS).",
) )
parser.add_argument( oracle_group.add_argument(
f"--{prefix}oracle-connect-descriptor", f"--{prefix}oracle-connect-descriptor",
type=str, type=str,
default=os.getenv("ATP_DSN"), default=os.getenv("ATP_DSN"),
help="Oracle connection descriptor/DSN (full connection string) (env: ATP_DSN)", help="Oracle connection descriptor/DSN (full connection string) (env: ATP_DSN)",
) )
parser.add_argument( oracle_group.add_argument(
f"--{prefix}oracle-username", f"--{prefix}oracle-username",
type=str, type=str,
default=os.getenv("ATP_USER"), default=os.getenv("ATP_USER"),
help="Oracle database username (env: ATP_USER)", help="Oracle database username (env: ATP_USER)",
) )
parser.add_argument( oracle_group.add_argument(
f"--{prefix}oracle-password", f"--{prefix}oracle-password",
type=str, type=str,
default=os.getenv("ATP_PASSWORD"), default=os.getenv("ATP_PASSWORD"),
help="Oracle database password (env: ATP_PASSWORD)", help="Oracle database password (env: ATP_PASSWORD)",
) )
parser.add_argument( oracle_group.add_argument(
f"--{prefix}oracle-pool-min", f"--{prefix}oracle-pool-min",
type=int, type=int,
default=int(os.getenv("ATP_POOL_MIN", RouterArgs.oracle_pool_min)), default=int(os.getenv("ATP_POOL_MIN", RouterArgs.oracle_pool_min)),
help="Minimum Oracle connection pool size (default: 1, env: ATP_POOL_MIN)", help="Minimum Oracle connection pool size (default: 1, env: ATP_POOL_MIN)",
) )
parser.add_argument( oracle_group.add_argument(
f"--{prefix}oracle-pool-max", f"--{prefix}oracle-pool-max",
type=int, type=int,
default=int(os.getenv("ATP_POOL_MAX", RouterArgs.oracle_pool_max)), default=int(os.getenv("ATP_POOL_MAX", RouterArgs.oracle_pool_max)),
help="Maximum Oracle connection pool size (default: 16, env: ATP_POOL_MAX)", help="Maximum Oracle connection pool size (default: 16, env: ATP_POOL_MAX)",
) )
parser.add_argument( oracle_group.add_argument(
f"--{prefix}oracle-pool-timeout-secs", f"--{prefix}oracle-pool-timeout-secs",
type=int, type=int,
default=int( default=int(
@@ -638,65 +711,75 @@ class RouterArgs:
), ),
help="Oracle connection pool timeout in seconds (default: 30, env: ATP_POOL_TIMEOUT_SECS)", help="Oracle connection pool timeout in seconds (default: 30, env: ATP_POOL_TIMEOUT_SECS)",
) )
# Postgres configuration # Postgres configuration
parser.add_argument( postgres_group.add_argument(
f"--{prefix}postgres-db-url", f"--{prefix}postgres-db-url",
type=str, type=str,
default=os.getenv("POSTGRES_DB_URL"), default=os.getenv("POSTGRES_DB_URL"),
help="PostgreSQL database connection URL (env: POSTGRES_DB_URL)", help="PostgreSQL database connection URL (env: POSTGRES_DB_URL)",
) )
parser.add_argument( postgres_group.add_argument(
f"--{prefix}postgres-pool-max", f"--{prefix}postgres-pool-max",
type=int, type=int,
default=int(os.getenv("POSTGRES_POOL_MAX", RouterArgs.postgres_pool_max)), default=int(os.getenv("POSTGRES_POOL_MAX", RouterArgs.postgres_pool_max)),
help="Maximum PostgreSQL connection pool size (default: 16, env: POSTGRES_POOL_MAX)", help="Maximum PostgreSQL connection pool size (default: 16, env: POSTGRES_POOL_MAX)",
) )
# mTLS configuration
parser.add_argument( # TLS/mTLS configuration
tls_group.add_argument(
f"--{prefix}client-cert-path", f"--{prefix}client-cert-path",
type=str, type=str,
default=None, default=None,
help="Path to client certificate for mTLS authentication with workers", help="Path to client certificate for mTLS authentication with workers",
) )
parser.add_argument( tls_group.add_argument(
f"--{prefix}client-key-path", f"--{prefix}client-key-path",
type=str, type=str,
default=None, default=None,
help="Path to client private key for mTLS authentication with workers", help="Path to client private key for mTLS authentication with workers",
) )
parser.add_argument( tls_group.add_argument(
f"--{prefix}ca-cert-paths", f"--{prefix}ca-cert-paths",
type=str, type=str,
nargs="*", nargs="*",
default=[], default=[],
help="Path(s) to CA certificate(s) for verifying worker TLS certificates. Can specify multiple CAs.", help="Path(s) to CA certificate(s) for verifying worker TLS certificates. Can specify multiple CAs.",
) )
# Server TLS configuration tls_group.add_argument(
parser.add_argument(
f"--{prefix}tls-cert-path", f"--{prefix}tls-cert-path",
type=str, type=str,
default=None, default=None,
help="Path to server TLS certificate (PEM format)", help="Path to server TLS certificate (PEM format)",
) )
parser.add_argument( tls_group.add_argument(
f"--{prefix}tls-key-path", f"--{prefix}tls-key-path",
type=str, type=str,
default=None, default=None,
help="Path to server TLS private key (PEM format)", help="Path to server TLS private key (PEM format)",
) )
parser.add_argument(
# Tracing configuration
trace_group.add_argument(
f"--{prefix}enable-trace", f"--{prefix}enable-trace",
action="store_true", action="store_true",
help="Enable opentelemetry trace", help="Enable opentelemetry trace",
) )
parser.add_argument( trace_group.add_argument(
f"--{prefix}otlp-traces-endpoint", f"--{prefix}otlp-traces-endpoint",
type=str, type=str,
default="localhost:4317", default="localhost:4317",
help="Config opentelemetry collector endpoint if --enable-trace is set. format: <ip>:<port>", help="Config opentelemetry collector endpoint if --enable-trace is set. format: <ip>:<port>",
) )
# Control plane authentication # Control plane authentication
parser.add_argument( auth_group.add_argument(
f"--{prefix}api-key",
type=str,
default=None,
help="The api key used for the authorization with the worker. Useful when the dp aware scheduling strategy is enabled.",
)
auth_group.add_argument(
f"--{prefix}control-plane-api-keys", f"--{prefix}control-plane-api-keys",
type=str, type=str,
nargs="*", nargs="*",
@@ -704,31 +787,31 @@ class RouterArgs:
help="API keys for control plane authentication. Format: 'id:name:role:key' where role is 'admin' or 'user'. " help="API keys for control plane authentication. Format: 'id:name:role:key' where role is 'admin' or 'user'. "
"Example: --control-plane-api-keys 'key1:Service Account:admin:secret123' 'key2:Read Only:user:secret456'", "Example: --control-plane-api-keys 'key1:Service Account:admin:secret123' 'key2:Read Only:user:secret456'",
) )
parser.add_argument( auth_group.add_argument(
f"--{prefix}control-plane-audit-enabled", f"--{prefix}control-plane-audit-enabled",
action="store_true", action="store_true",
default=False, default=False,
help="Enable audit logging for control plane operations", help="Enable audit logging for control plane operations",
) )
parser.add_argument( auth_group.add_argument(
f"--{prefix}jwt-issuer", f"--{prefix}jwt-issuer",
type=str, type=str,
default=None, default=None,
help="OIDC issuer URL for JWT authentication (e.g., https://login.microsoftonline.com/{tenant}/v2.0)", help="OIDC issuer URL for JWT authentication (e.g., https://login.microsoftonline.com/{tenant}/v2.0)",
) )
parser.add_argument( auth_group.add_argument(
f"--{prefix}jwt-audience", f"--{prefix}jwt-audience",
type=str, type=str,
default=None, default=None,
help="Expected audience claim for JWT tokens (usually the client ID or API identifier)", help="Expected audience claim for JWT tokens (usually the client ID or API identifier)",
) )
parser.add_argument( auth_group.add_argument(
f"--{prefix}jwt-jwks-uri", f"--{prefix}jwt-jwks-uri",
type=str, type=str,
default=None, default=None,
help="Explicit JWKS URI. If not provided, discovered from issuer via .well-known/openid-configuration", help="Explicit JWKS URI. If not provided, discovered from issuer via .well-known/openid-configuration",
) )
parser.add_argument( auth_group.add_argument(
f"--{prefix}jwt-role-mapping", f"--{prefix}jwt-role-mapping",
type=str, type=str,
nargs="*", nargs="*",