From a03e45aadfbadceeb8c1568593afb6626a25bcab Mon Sep 17 00:00:00 2001 From: Cheng Wan Date: Sat, 29 Aug 2026 07:11:43 +0000 Subject: [PATCH] config: the lazy imports that buy nothing become eager `arg_groups.overrides` is imported at module scope by thirty-five files already, `server_args` among them, so importing it is not a cycle and not a cost -- by the time any resolution step runs, the module is loaded. Ninety-three `from ...overrides import` statements were nonetheless written inside the functions that use them. The ones that buy nothing become module-scope imports, including the twenty-three that were **mixed**: a name a test patches, plus names riding along on the same statement that nothing patches. Splitting those frees the riders -- the `_dsa_*` pass callables are the shape of it, only ever handed to `run_post_process_pass` as arguments, never looked up through the module. Three groups were kept lazy for a test seam, which is the wrong way round, and each is fixed at the test rather than in the code the runtime executes: - The four declaration paths. `test_no_entry_changes_after_it_is_recorded` wrapped `declare_resolution`, `declare_late_resolution`, `declare_direct_writes` and `run_post_process_pass` by `setattr` on the module, purely to snapshot the stash after each append. The property it checks belongs to the stash, so the seam is now the stash: a list that snapshots on append, installed by a test-local `ServerArgs` subclass that survives the pipeline's own reset of it. The guard is strictly stronger -- it records at the append rather than after the call -- and still fails on an injected in-place edit. - `use_mla_backend`. Eight cases patched the answer; it is `model_config_of(server_args).attention_arch == AttentionArch.MLA`, so the fixtures now state the model instead. Five of the patches were redundant outright -- their stand-in already answered "not MLA" -- and the rest set `_model_config.attention_arch`, which is the input the value is derived from. - `model_config_of` had no patch site at all and was lazy on a hunch. What is left is load-bearing, for exactly two reasons and nothing else: `attention_backends_of` (3 patch sites) and `supports_mamba_cache_extra_buffer` (2) are still patched through the module, and `runtime_context` is imported by `utils.common`, which `overrides` needs, so it sits *below* `overrides` and cannot import it at module scope -- a cycle, not a preference. A function-local `overrides` import that is neither of those: zero. A dummy resolution is unchanged at ~9 ms and loads the same six `arg_groups` modules; the 62-shape resolution probe is byte-identical to the base commit. Co-Authored-By: Claude Opus 5 --- .../sglang/srt/arg_groups/attention_hook.py | 47 +++++------- .../sglang/srt/arg_groups/cuda_graph_hook.py | 9 +-- .../sglang/srt/arg_groups/deepseek_v4_hook.py | 6 +- python/sglang/srt/arg_groups/dllm_hook.py | 11 ++- .../sglang/srt/arg_groups/expert_pack_hook.py | 7 +- python/sglang/srt/arg_groups/hicache_hook.py | 2 +- python/sglang/srt/arg_groups/hisparse_hook.py | 11 ++- python/sglang/srt/arg_groups/kv_cache_hook.py | 5 +- python/sglang/srt/arg_groups/memory_hook.py | 9 +-- python/sglang/srt/arg_groups/model_hook.py | 57 +++++---------- .../sglang/srt/arg_groups/model_path_hook.py | 6 +- python/sglang/srt/arg_groups/moe_hook.py | 21 ++---- python/sglang/srt/arg_groups/parallel_hook.py | 14 ++-- .../srt/arg_groups/pd_disaggregation_hook.py | 4 +- python/sglang/srt/arg_groups/serving_hook.py | 2 +- .../sglang/srt/arg_groups/speculative_hook.py | 25 ++----- .../sglang/srt/arg_groups/validation_hook.py | 6 +- python/sglang/srt/configs/model_config.py | 2 +- python/sglang/srt/dllm/config.py | 2 +- python/sglang/srt/entrypoints/grpc_server.py | 3 +- .../sglang/srt/hardware_backend/npu/utils.py | 7 +- .../layers/attention/attention_registry.py | 6 +- python/sglang/srt/layers/cp/bcg.py | 7 +- python/sglang/srt/layers/moe/kt_ep_wrapper.py | 3 +- .../srt/lora/marlin_lora_temp/policy.py | 3 +- .../kv_pool_runtime.py | 2 +- .../srt/model_loader/expert_pack_runtime.py | 11 ++- python/sglang/srt/runtime_context.py | 4 +- python/sglang/srt/server_args.py | 2 +- .../srt/speculative/adaptive_spec_params.py | 6 +- .../dspark_components/dspark_config.py | 2 +- python/sglang/srt/speculative/spec_info.py | 2 +- .../sglang/srt/speculative/spec_registry.py | 3 +- .../test_multimodal_piecewise_cuda_graph.py | 11 ++- .../test_page_major_backend_allowlist.py | 27 +++---- .../test_resolution_declarations.py | 71 +++++++++---------- .../unit/server_args/test_server_args.py | 29 ++------ test/registered/unit/test_model_overrides.py | 5 +- 38 files changed, 176 insertions(+), 274 deletions(-) diff --git a/python/sglang/srt/arg_groups/attention_hook.py b/python/sglang/srt/arg_groups/attention_hook.py index df14894fac61..120724a14222 100644 --- a/python/sglang/srt/arg_groups/attention_hook.py +++ b/python/sglang/srt/arg_groups/attention_hook.py @@ -8,9 +8,25 @@ from typing import Any from sglang.srt.arg_groups.overrides import ( + _attention_backend_default, + _attention_backend_dual_chunk, + _attention_backend_fa3_fp8_fallback, + _attention_backend_platform_fallbacks, + _cutedsl_prefill_backend_fill, + _deterministic_allreduce_fusion_disable, + _deterministic_attention_backend, + _deterministic_sampling_backend, + _fa4_page_constraint, + _intel_xpu_page_constraint, + _mla_backend_page_constraints, + _mla_kv_cache_dtype_checks, declare_resolution, + mamba_extra_buffer_of, + model_config_of, resolved_view, resolving_view, + run_post_process_pass, + use_mla_backend, ) from sglang.srt.connector import ConnectorType from sglang.srt.environ import envs @@ -29,11 +45,7 @@ def handle_attention_backend_compatibility(server_args: Any): - from sglang.srt.arg_groups.overrides import ( - attention_backends_of, - model_config_of, - use_mla_backend, - ) + from sglang.srt.arg_groups.overrides import attention_backends_of cfg = resolving_view(server_args) model_config = model_config_of(server_args) @@ -41,16 +53,6 @@ def handle_attention_backend_compatibility(server_args: Any): # The attention_backend write clusters of this handler moved to the # resolution pipeline (arg_groups/overrides.py), each invoked below at # its legacy slot; the interleaved non-attention adjustments stay. - from sglang.srt.arg_groups.overrides import ( - _attention_backend_default, - _attention_backend_dual_chunk, - _attention_backend_fa3_fp8_fallback, - _attention_backend_platform_fallbacks, - _fa4_page_constraint, - _intel_xpu_page_constraint, - _mla_backend_page_constraints, - run_post_process_pass, - ) # Split-backend override + default fill. run_post_process_pass(server_args, _attention_backend_default) @@ -122,14 +124,12 @@ def handle_attention_backend_compatibility(server_args: Any): # The TRT-LLM / tokenspeed MLA kv-dtype validations moved to the # resolution pipeline (arg_groups/overrides.py: # _mla_kv_cache_dtype_checks), invoked here at their legacy slot. - from sglang.srt.arg_groups.overrides import _mla_kv_cache_dtype_checks run_post_process_pass(server_args, _mla_kv_cache_dtype_checks) # The CuteDSL MLA validation + prefill fill moved to the resolution # pipeline (arg_groups/overrides.py: _cutedsl_prefill_backend_fill), # invoked here at its legacy slot. - from sglang.srt.arg_groups.overrides import _cutedsl_prefill_backend_fill run_post_process_pass(server_args, _cutedsl_prefill_backend_fill) @@ -334,9 +334,6 @@ def handle_linear_attn_backend(server_args: Any): "KDA, as the linear-attn decode backend; got " f"--linear-attn-decode-backend={decode!r}." ) - from sglang.srt.arg_groups.overrides import ( - mamba_extra_buffer_of, - ) if mamba_extra_buffer_of(resolved_view(server_args)): raise ValueError( @@ -505,7 +502,6 @@ def handle_multi_item_scoring(server_args: Any): def handle_deterministic_inference(server_args: Any): - from sglang.srt.arg_groups.overrides import model_config_of from sglang.srt.server_args import ( RADIX_SUPPORTED_DETERMINISTIC_ATTENTION_BACKEND, ) @@ -538,21 +534,12 @@ def handle_deterministic_inference(server_args: Any): # Moved to the resolution pipeline (arg_groups/overrides.py: # _deterministic_allreduce_fusion_disable), invoked here at its # legacy slot. - from sglang.srt.arg_groups.overrides import ( - _deterministic_allreduce_fusion_disable, - run_post_process_pass, - ) run_post_process_pass(server_args, _deterministic_allreduce_fusion_disable) # The forced-pytorch sampling write and the attention backend # fill/validation moved to the resolution pipeline # (arg_groups/overrides.py), invoked at their legacy slots. - from sglang.srt.arg_groups.overrides import ( - _deterministic_attention_backend, - _deterministic_sampling_backend, - run_post_process_pass, - ) run_post_process_pass(server_args, _deterministic_sampling_backend) is_deepseek_model = False diff --git a/python/sglang/srt/arg_groups/cuda_graph_hook.py b/python/sglang/srt/arg_groups/cuda_graph_hook.py index 47ba48f76d72..9a958188d04f 100644 --- a/python/sglang/srt/arg_groups/cuda_graph_hook.py +++ b/python/sglang/srt/arg_groups/cuda_graph_hook.py @@ -8,6 +8,7 @@ from sglang.srt.arg_groups.overrides import ( declare_resolution, + model_config_of, resolved_view, resolving_view, ) @@ -110,7 +111,7 @@ def apply_cuda_graph_compatibility(server_args: Any): prefill backend (this folds in the old --enforce-piecewise-cuda-graph contract). """ - from sglang.srt.arg_groups.overrides import attention_backends_of, model_config_of + from sglang.srt.arg_groups.overrides import attention_backends_of cfg = resolving_view(server_args) if (Phase.PREFILL, "backend") in server_args._cuda_graph_config_locked: @@ -153,7 +154,6 @@ def disable_tc_piecewise_cudagraph_if_incompatible(server_args: Any): """TcPiecewise (torch.compile + piecewise) is incompatible with these configurations. Most are torch.compile / dynamo limitations. """ - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) @@ -244,7 +244,6 @@ def disable_breakable_cudagraph_if_incompatible(server_args: Any): memory-saver rejection in its own __init__; config-time rules can be added here as they're discovered. """ - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) from sglang.srt.configs.model_config import is_deepseek_v4 @@ -331,7 +330,7 @@ def disable_prefill_cuda_graph_for_deepseek_trtllm_mla(server_args: Any): breakable) trtllm_mla falls back to FlashAttention for prefill and regresses performance, so disable whichever prefill graph backend is in effect. """ - from sglang.srt.arg_groups.overrides import attention_backends_of, model_config_of + from sglang.srt.arg_groups.overrides import attention_backends_of cfg = resolving_view(server_args) @@ -403,7 +402,6 @@ def apply_inkling_prefill_cuda_graph_default(server_args: Any): auto-disabled for this multimodal arch, and declarative model overrides materialize too late to steer cuda-graph resolution. Honors an explicit --cuda-graph-backend-prefill / --disable-prefill-cuda-graph.""" - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) if ( @@ -425,7 +423,6 @@ def apply_inkling_prefill_cuda_graph_default(server_args: Any): def apply_muse_glimmer_prefill_cuda_graph_max_bs_default(server_args: Any): - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) if ( diff --git a/python/sglang/srt/arg_groups/deepseek_v4_hook.py b/python/sglang/srt/arg_groups/deepseek_v4_hook.py index 8bf9800f8c00..ca96a1f0241e 100644 --- a/python/sglang/srt/arg_groups/deepseek_v4_hook.py +++ b/python/sglang/srt/arg_groups/deepseek_v4_hook.py @@ -4,8 +4,10 @@ from typing import TYPE_CHECKING from sglang.srt.arg_groups.overrides import ( + _deepseek_v4_kv_cache_dtype, declare_resolution, resolving_view, + run_post_process_pass, ) from sglang.srt.environ import envs @@ -129,10 +131,6 @@ def apply_deepseek_v4_defaults(server_args: ServerArgs, model_arch: str) -> None # The kv-cache dtype default moved to the resolution pipeline # (arg_groups/overrides.py: _deepseek_v4_kv_cache_dtype), invoked here at # its legacy slot. - from sglang.srt.arg_groups.overrides import ( - _deepseek_v4_kv_cache_dtype, - run_post_process_pass, - ) run_post_process_pass(server_args, _deepseek_v4_kv_cache_dtype) diff --git a/python/sglang/srt/arg_groups/dllm_hook.py b/python/sglang/srt/arg_groups/dllm_hook.py index c590636026d0..bc3b631d4469 100644 --- a/python/sglang/srt/arg_groups/dllm_hook.py +++ b/python/sglang/srt/arg_groups/dllm_hook.py @@ -7,8 +7,12 @@ from typing import Any from sglang.srt.arg_groups.overrides import ( + _dllm_attention_backend, + _dllm_overlap_disable, + _dllm_page_size, declare_resolution, resolving_view, + run_post_process_pass, ) from sglang.srt.model_executor.cuda_graph_config import Backend, Phase, with_phase from sglang.srt.utils.common import is_hip @@ -46,12 +50,6 @@ def handle_dllm_inference(server_args: Any): ), ) - from sglang.srt.arg_groups.overrides import ( - _dllm_attention_backend, - _dllm_overlap_disable, - run_post_process_pass, - ) - run_post_process_pass(server_args, _dllm_attention_backend) run_post_process_pass(server_args, _dllm_overlap_disable) @@ -60,7 +58,6 @@ def handle_dllm_inference(server_args: Any): # Invoked outside the radix gate: the alignment fill keeps its radix # gate inside the pass, the block-size cap applies regardless (it # replaces the unconditional scheduler-init fallback). - from sglang.srt.arg_groups.overrides import _dllm_page_size run_post_process_pass(server_args, _dllm_page_size) diff --git a/python/sglang/srt/arg_groups/expert_pack_hook.py b/python/sglang/srt/arg_groups/expert_pack_hook.py index 23a903f1fea9..ecb4aa5c90eb 100644 --- a/python/sglang/srt/arg_groups/expert_pack_hook.py +++ b/python/sglang/srt/arg_groups/expert_pack_hook.py @@ -9,7 +9,11 @@ from pathlib import Path from typing import Any -from sglang.srt.arg_groups.overrides import declare_resolution, resolving_view +from sglang.srt.arg_groups.overrides import ( + declare_resolution, + model_config_of, + resolving_view, +) from sglang.srt.environ import envs from sglang.srt.model_executor.cuda_graph_config import ( Backend, @@ -27,7 +31,6 @@ def handle_expert_pack(server_args: Any) -> None: """Normalize expert-pack settings and report all startup errors together.""" - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) if cfg.load_format != "expert_pack": diff --git a/python/sglang/srt/arg_groups/hicache_hook.py b/python/sglang/srt/arg_groups/hicache_hook.py index 28c1ddbb1b52..cd3c02df63b1 100644 --- a/python/sglang/srt/arg_groups/hicache_hook.py +++ b/python/sglang/srt/arg_groups/hicache_hook.py @@ -9,6 +9,7 @@ from sglang.srt.arg_groups.overrides import ( declare_resolution, resolving_view, + use_mla_backend, ) logger = logging.getLogger(__name__) @@ -68,7 +69,6 @@ def handle_hicache_ratio_default(server_args: Any): def resolve_hicache_dcp_compatibility(server_args: Any): - from sglang.srt.arg_groups.overrides import use_mla_backend cfg = resolving_view(server_args) if cfg.dcp_size <= 1 or not cfg.enable_hierarchical_cache: diff --git a/python/sglang/srt/arg_groups/hisparse_hook.py b/python/sglang/srt/arg_groups/hisparse_hook.py index e3754ae4b18e..e94a0510c16e 100644 --- a/python/sglang/srt/arg_groups/hisparse_hook.py +++ b/python/sglang/srt/arg_groups/hisparse_hook.py @@ -3,7 +3,11 @@ import logging from typing import TYPE_CHECKING -from sglang.srt.arg_groups.overrides import resolving_view +from sglang.srt.arg_groups.overrides import ( + model_config_of, + resolved_view, + resolving_view, +) if TYPE_CHECKING: from sglang.srt.server_args import ServerArgs @@ -46,7 +50,6 @@ def _hisparse_allowed_backends(kv_cache_dtype: str) -> set[str]: def validate_hisparse_dsa_backend( server_args: ServerArgs, attr: str, label: str ) -> None: - from sglang.srt.arg_groups.overrides import resolved_view # Invoked after the DSA kv-cache-dtype / split-backend declarations: # read the resolving state through the view. @@ -65,7 +68,6 @@ def validate_hisparse_dsa_backend( def validate_hisparse_kv_cache_dtype(server_args: ServerArgs) -> None: - from sglang.srt.arg_groups.overrides import resolved_view kv_cache_dtype = resolved_view(server_args).kv_cache_dtype if kv_cache_dtype in HISPARSE_KV_CACHE_DTYPES: @@ -82,7 +84,6 @@ def validate_hisparse_kv_cache_dtype(server_args: ServerArgs) -> None: def validate_hisparse(server_args: ServerArgs) -> None: """Validate --enable-hisparse constraints (model class, radix cache, DSA backend).""" - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) if not cfg.enable_hisparse: @@ -126,8 +127,6 @@ def validate_hisparse(server_args: ServerArgs) -> None: ) return - from sglang.srt.arg_groups.overrides import resolved_view - if resolved_view(server_args).kv_cache_dtype not in ( "bfloat16", "auto", diff --git a/python/sglang/srt/arg_groups/kv_cache_hook.py b/python/sglang/srt/arg_groups/kv_cache_hook.py index d8a65ad9df29..1a58fbe87004 100644 --- a/python/sglang/srt/arg_groups/kv_cache_hook.py +++ b/python/sglang/srt/arg_groups/kv_cache_hook.py @@ -10,6 +10,7 @@ declare_resolution, resolved_view, resolving_view, + use_mla_backend, ) from sglang.srt.environ import envs from sglang.srt.model_executor.cuda_graph_config import Backend @@ -37,7 +38,7 @@ def handle_mxfp8_kv_cache_compatibility(server_args: Any) -> None: def handle_kv4_compatibility(server_args: Any) -> None: """Check FP4 KV cache compatibility with the attention backend""" - from sglang.srt.arg_groups.overrides import attention_backends_of, use_mla_backend + from sglang.srt.arg_groups.overrides import attention_backends_of cfg = resolving_view(server_args) @@ -279,7 +280,7 @@ def handle_page_major_kv_layout(server_args: Any): # The unified pool stores state in the page-major envelope-strided layout, so # enabling it implies --enable-page-major-kv-layout — routing it through the # single page-major path + stride-aware Triton asserts (set before the guard). - from sglang.srt.arg_groups.overrides import attention_backends_of, use_mla_backend + from sglang.srt.arg_groups.overrides import attention_backends_of cfg = resolving_view(server_args) if cfg.enable_unified_memory: diff --git a/python/sglang/srt/arg_groups/memory_hook.py b/python/sglang/srt/arg_groups/memory_hook.py index d060fca3f9c6..65ec050bfff8 100644 --- a/python/sglang/srt/arg_groups/memory_hook.py +++ b/python/sglang/srt/arg_groups/memory_hook.py @@ -9,8 +9,11 @@ from sglang.srt.arg_groups.overrides import ( declare_resolution, + model_config_of, + post_capture_kv_sizing_planned, resolved_view, resolving_view, + use_mla_backend, ) from sglang.srt.environ import envs from sglang.srt.model_executor.cuda_graph_config import Backend @@ -47,11 +50,6 @@ def handle_gpu_memory_settings(server_args: Any, gpu_mem): generate_decode_cuda_graph_batch_sizes, generate_prefill_cuda_graph_batch_sizes, ) - from sglang.srt.arg_groups.overrides import ( - model_config_of, - post_capture_kv_sizing_planned, - use_mla_backend, - ) cfg = resolving_view(server_args) # A copy, so an earlier declaration keeps the value it recorded. @@ -278,7 +276,6 @@ def handle_gpu_memory_settings(server_args: Any, gpu_mem): def reserve_for_graph_mb(server_args: Any) -> float: - from sglang.srt.arg_groups.overrides import use_mla_backend cfg = resolving_view(server_args) decode_cuda_graph_config = cfg.cuda_graph_config.decode diff --git a/python/sglang/srt/arg_groups/model_hook.py b/python/sglang/srt/arg_groups/model_hook.py index da135d50bd01..4db9df2528d4 100644 --- a/python/sglang/srt/arg_groups/model_hook.py +++ b/python/sglang/srt/arg_groups/model_hook.py @@ -7,10 +7,25 @@ from typing import Any from sglang.srt.arg_groups.overrides import ( + _deepseek_moe_quant_resolution, + _deepseek_spec_moe_resolution, + _dsa_kv_cache_dtype_default, + _dsa_split_backend_resolution, + _enforce_disable_allreduce_fusion, + _flashinfer_allreduce_fusion_auto_enable, + _hrm_text_attention_force, + _mamba_radix_cache_resolution, + _sparse_head_overlap_disable, + collect_model_override_declarations, declare_resolution, mamba_cache_chunk_size, + mamba_extra_buffer_of, + model_config_of, resolved_view, resolving_view, + run_post_process_pass, + use_mla_backend, + validate_declarations, ) from sglang.srt.configs.embedding_model_spec import BCGPrefillPolicy from sglang.srt.configs.linear_attn_model_registry import get_linear_attn_spec_by_arch @@ -35,11 +50,7 @@ def handle_model_specific_adjustments(server_args: Any): - from sglang.srt.arg_groups.overrides import ( - attention_backends_of, - model_config_of, - use_mla_backend, - ) + from sglang.srt.arg_groups.overrides import attention_backends_of cfg = resolving_view(server_args) from sglang.srt.configs.model_config import ( @@ -107,10 +118,6 @@ def handle_model_specific_adjustments(server_args: Any): # server_args is never mutated — mid-resolution readers see the # declared values through resolved_view, runtime readers through the # flags tier. - from sglang.srt.arg_groups.overrides import ( - collect_model_override_declarations, - validate_declarations, - ) model_overrides = collect_model_override_declarations( model_arch, server_args, hf_config @@ -210,11 +217,6 @@ def handle_model_specific_adjustments(server_args: Any): import torch major, _ = torch.cuda.get_device_capability() - from sglang.srt.arg_groups.overrides import ( - _dsa_kv_cache_dtype_default, - _dsa_split_backend_resolution, - run_post_process_pass, - ) run_post_process_pass(server_args, _dsa_kv_cache_dtype_default) run_post_process_pass(server_args, _dsa_split_backend_resolution) @@ -298,10 +300,6 @@ def handle_model_specific_adjustments(server_args: Any): # kv-cache-dtype default above must read the pristine # quantization). The HIP arm (fusion log + spec_moe writes, the # latter awaiting the speculative-hook migration) stays below. - from sglang.srt.arg_groups.overrides import ( - _deepseek_moe_quant_resolution, - run_post_process_pass, - ) run_post_process_pass(server_args, _deepseek_moe_quant_resolution) if is_hip(): @@ -324,9 +322,6 @@ def handle_model_specific_adjustments(server_args: Any): # resolution pipeline (arg_groups/overrides.py: # _deepseek_spec_moe_resolution), invoked here at its legacy # slot. - from sglang.srt.arg_groups.overrides import ( - _deepseek_spec_moe_resolution, - ) run_post_process_pass(server_args, _deepseek_spec_moe_resolution) @@ -576,11 +571,6 @@ def handle_model_specific_adjustments(server_args: Any): # resolved before that tail write of disable_overlap_schedule. handle_mamba_radix_cache(server_args, model_arch) - from sglang.srt.arg_groups.overrides import ( - _sparse_head_overlap_disable, - run_post_process_pass, - ) - run_post_process_pass(server_args, _sparse_head_overlap_disable) # The FlashInfer AllReduce Fusion auto-enable and the enforce-disable @@ -588,10 +578,6 @@ def handle_model_specific_adjustments(server_args: Any): # _flashinfer_allreduce_fusion_auto_enable / # _enforce_disable_allreduce_fusion), invoked here at their legacy # slots. - from sglang.srt.arg_groups.overrides import ( - _enforce_disable_allreduce_fusion, - _flashinfer_allreduce_fusion_auto_enable, - ) run_post_process_pass(server_args, _flashinfer_allreduce_fusion_auto_enable) run_post_process_pass(server_args, _enforce_disable_allreduce_fusion) @@ -604,15 +590,10 @@ def handle_model_capability_adjustments(server_args: Any): from sglang.srt.arg_groups.kv_cache_hook import ( validate_prefill_only_disable_kv_cache_args, ) - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) if parse_connector_type(cfg.model_path) == ConnectorType.INSTANCE: return - from sglang.srt.arg_groups.overrides import ( - _hrm_text_attention_force, - run_post_process_pass, - ) model_config = model_config_of(server_args) hf_config = model_config.hf_config @@ -833,11 +814,6 @@ def handle_mamba_radix_cache(server_args: Any, model_arch: str): validate_mamba_extra_buffer, validate_mamba_no_buffer, ) - from sglang.srt.arg_groups.overrides import ( - _mamba_radix_cache_resolution, - mamba_extra_buffer_of, - run_post_process_pass, - ) run_post_process_pass(server_args, _mamba_radix_cache_resolution) view = resolved_view(server_args) @@ -855,7 +831,6 @@ def handle_mamba_radix_cache(server_args: Any, model_arch: str): def handle_language_model_only(server_args: Any): - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) if not cfg.language_model_only: diff --git a/python/sglang/srt/arg_groups/model_path_hook.py b/python/sglang/srt/arg_groups/model_path_hook.py index 083fe81e0bfb..0093fac31515 100644 --- a/python/sglang/srt/arg_groups/model_path_hook.py +++ b/python/sglang/srt/arg_groups/model_path_hook.py @@ -10,8 +10,10 @@ from typing import Any, Optional from sglang.srt.arg_groups.overrides import ( + _gguf_quantization, declare_resolution, resolving_view, + run_post_process_pass, ) from sglang.srt.utils.common import is_remote_url from sglang.srt.utils.hf_transformers_utils import check_gguf_file @@ -163,10 +165,6 @@ def handle_load_format(server_args: Any): # (arg_groups/overrides.py: _gguf_quantization); load_format itself is # genuine config (runtime user updates write it) and stays imperative. cfg = resolving_view(server_args) - from sglang.srt.arg_groups.overrides import ( - _gguf_quantization, - run_post_process_pass, - ) run_post_process_pass(server_args, _gguf_quantization) if (cfg.load_format == "auto" or cfg.load_format == "gguf") and check_gguf_file( diff --git a/python/sglang/srt/arg_groups/moe_hook.py b/python/sglang/srt/arg_groups/moe_hook.py index 792bee10ada8..15f48159cd60 100644 --- a/python/sglang/srt/arg_groups/moe_hook.py +++ b/python/sglang/srt/arg_groups/moe_hook.py @@ -8,12 +8,19 @@ from typing import Any from sglang.srt.arg_groups.overrides import ( + _a2a_backend_overrides, + _a2a_ep_size, + _a2a_fusion_adjustments, + _moe_runner_backend_quant_constraints, + _moe_runner_fusion_disable, cutedsl_moe_max_num_tokens, declare_resolution, max_prefill_buffer_tokens, max_speculative_num_draft_tokens, + model_config_of, resolved_view, resolving_view, + run_post_process_pass, ) from sglang.srt.connector import ConnectorType from sglang.srt.environ import envs @@ -27,14 +34,8 @@ def handle_moe_kernel_config(server_args: Any): # The quantization-driven runner resolutions moved to the pipeline # (arg_groups/overrides.py: _moe_runner_backend_quant_constraints); # the compatibility asserts and fusion writes stay below. - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) - from sglang.srt.arg_groups.overrides import ( - _moe_runner_backend_quant_constraints, - _moe_runner_fusion_disable, - run_post_process_pass, - ) run_post_process_pass(server_args, _moe_runner_backend_quant_constraints) @@ -121,15 +122,8 @@ def handle_a2a_moe(server_args: Any): # the resolution pipeline (arg_groups/overrides.py: # _a2a_backend_overrides / _a2a_ep_size); the per-backend logs, # asserts, fusion/deepep_mode/env/cuda-graph writes stay below. - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) - from sglang.srt.arg_groups.overrides import ( - _a2a_backend_overrides, - _a2a_ep_size, - _a2a_fusion_adjustments, - run_post_process_pass, - ) run_post_process_pass(server_args, _a2a_backend_overrides) run_post_process_pass(server_args, _a2a_ep_size) @@ -420,7 +414,6 @@ def validate_deepep_v2_dispatch_token_budget(server_args: Any) -> None: def validate_deepep_v2_model_architecture(server_args: Any) -> None: """Allow DeepEP v2 only where its model workflow is validated.""" - from sglang.srt.arg_groups.overrides import model_config_of if ( parse_connector_type(resolved_view(server_args).model_path) diff --git a/python/sglang/srt/arg_groups/parallel_hook.py b/python/sglang/srt/arg_groups/parallel_hook.py index 1def83629be1..31b19ee99574 100644 --- a/python/sglang/srt/arg_groups/parallel_hook.py +++ b/python/sglang/srt/arg_groups/parallel_hook.py @@ -8,9 +8,14 @@ from typing import Any from sglang.srt.arg_groups.overrides import ( + _data_parallelism_defaults, + _dp_lm_head_validation, + _tp_lm_head_all_to_all_default, declare_resolution, + model_config_of, resolved_view, resolving_view, + run_post_process_pass, should_report_expert_balancedness, ) from sglang.srt.connector import ConnectorType @@ -22,7 +27,6 @@ def handle_context_parallelism(server_args: Any): - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) if parse_connector_type(cfg.model_path) != ConnectorType.INSTANCE: @@ -162,10 +166,6 @@ def handle_data_parallelism(server_args: Any): ) cfg = resolving_view(server_args) - from sglang.srt.arg_groups.overrides import ( - _data_parallelism_defaults, - run_post_process_pass, - ) run_post_process_pass(server_args, _data_parallelism_defaults) @@ -233,10 +233,6 @@ def handle_data_parallelism(server_args: Any): # Resolve the phase-aware TP LM-head default before validating the # resulting DP/TP LM-head configuration. - from sglang.srt.arg_groups.overrides import ( - _dp_lm_head_validation, - _tp_lm_head_all_to_all_default, - ) run_post_process_pass(server_args, _tp_lm_head_all_to_all_default) run_post_process_pass(server_args, _dp_lm_head_validation) diff --git a/python/sglang/srt/arg_groups/pd_disaggregation_hook.py b/python/sglang/srt/arg_groups/pd_disaggregation_hook.py index 456827dec28f..78bf2f755174 100644 --- a/python/sglang/srt/arg_groups/pd_disaggregation_hook.py +++ b/python/sglang/srt/arg_groups/pd_disaggregation_hook.py @@ -7,6 +7,8 @@ from sglang.srt.arg_groups.overrides import ( declare_resolution, + model_config_of, + resolved_view, resolving_view, ) from sglang.srt.environ import envs @@ -89,7 +91,6 @@ def handle_pd_disaggregation(server_args: ServerArgs) -> None: "with speculative decoding " f"(--speculative-algorithm {cfg.speculative_algorithm})" ) - from sglang.srt.arg_groups.overrides import resolved_view if resolved_view(server_args).enable_dp_attention: logger.warning( @@ -186,7 +187,6 @@ def _alias_bootstrap_port_to_api_port(server_args: ServerArgs) -> None: def handle_encoder_disaggregation(server_args: Any): from sglang.srt.arg_groups.model_hook import handle_language_model_only - from sglang.srt.arg_groups.overrides import model_config_of from sglang.srt.arg_groups.validation_hook import validate_ib_devices from sglang.srt.server_args import resolve_encoder_transfer_backend diff --git a/python/sglang/srt/arg_groups/serving_hook.py b/python/sglang/srt/arg_groups/serving_hook.py index 416a89285029..8219156cae0b 100644 --- a/python/sglang/srt/arg_groups/serving_hook.py +++ b/python/sglang/srt/arg_groups/serving_hook.py @@ -12,6 +12,7 @@ from sglang.srt.arg_groups.overrides import ( declare_resolution, + model_config_of, resolved_view, resolving_view, ) @@ -751,7 +752,6 @@ def handle_multimodal_feature_transport(server_args: Any): may still auto-select CUDA VMM. The legacy CUDA IPC flag and environment variable remain supported so existing deployments map to this policy. """ - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) requested_transport = cfg.mm_feature_transport diff --git a/python/sglang/srt/arg_groups/speculative_hook.py b/python/sglang/srt/arg_groups/speculative_hook.py index bd20e21f0d1a..8a2650b63119 100644 --- a/python/sglang/srt/arg_groups/speculative_hook.py +++ b/python/sglang/srt/arg_groups/speculative_hook.py @@ -6,9 +6,13 @@ from typing import TYPE_CHECKING, Optional from sglang.srt.arg_groups.overrides import ( + _speculative_moe_runner_default, declare_direct_writes, declare_resolution, + model_config_of, + resolved_view, resolving_view, + run_post_process_pass, ) if TYPE_CHECKING: @@ -86,10 +90,6 @@ def handle_speculative_decoding(server_args: ServerArgs) -> None: # Moved to the resolution pipeline (arg_groups/overrides.py: # _speculative_moe_runner_default), invoked here at its legacy slot. - from sglang.srt.arg_groups.overrides import ( - _speculative_moe_runner_default, - run_post_process_pass, - ) run_post_process_pass(server_args, _speculative_moe_runner_default) @@ -184,7 +184,6 @@ def handle_speculative_decoding(server_args: ServerArgs) -> None: def _handle_dflash(server_args: ServerArgs) -> None: cfg = resolving_view(server_args) - from sglang.srt.arg_groups.overrides import resolved_view if not (cfg.device.startswith("cuda") or cfg.device == "npu"): raise ValueError( @@ -337,7 +336,6 @@ def _handle_dflash(server_args: ServerArgs) -> None: def _target_checkpoint_bundles_dspark_draft(server_args: ServerArgs) -> bool: - from sglang.srt.arg_groups.overrides import model_config_of from sglang.srt.speculative.dspark_components.dspark_config import ( checkpoint_bundles_dspark_draft, ) @@ -580,10 +578,7 @@ def _resolve_dflash_draft_attention_backend(server_args: ServerArgs) -> None: draft_backend = cfg.speculative_draft_attention_backend if draft_backend is None: - from sglang.srt.arg_groups.overrides import ( - attention_backends_of, - resolved_view, - ) + from sglang.srt.arg_groups.overrides import attention_backends_of draft_backend, _ = attention_backends_of(resolved_view(server_args)) if draft_backend is None: @@ -663,13 +658,9 @@ def _handle_frozen_kv_mtp(server_args: ServerArgs) -> None: def _handle_eagle_family(server_args: ServerArgs) -> None: - from sglang.srt.arg_groups.overrides import model_config_of cfg = resolving_view(server_args) - from sglang.srt.arg_groups.overrides import ( - attention_backends_of, - resolved_view, - ) + from sglang.srt.arg_groups.overrides import attention_backends_of if ( cfg.speculative_algorithm == "STANDALONE" @@ -799,8 +790,6 @@ def _handle_eagle_family(server_args: ServerArgs) -> None: "coins from the global RNG and is not batch-invariant." ) - from sglang.srt.arg_groups.overrides import resolved_view - if ( resolved_view(server_args).enable_multi_layer_eagle and cfg.speculative_eagle_topk != 1 @@ -915,8 +904,6 @@ def _handle_ngram(server_args: ServerArgs) -> None: "using ngram speculative decoding." ) - from sglang.srt.arg_groups.overrides import resolved_view - view = resolved_view(server_args) if ( cfg.speculative_eagle_topk > 1 diff --git a/python/sglang/srt/arg_groups/validation_hook.py b/python/sglang/srt/arg_groups/validation_hook.py index c9fcb92427e4..6364f7ec9221 100644 --- a/python/sglang/srt/arg_groups/validation_hook.py +++ b/python/sglang/srt/arg_groups/validation_hook.py @@ -9,8 +9,10 @@ from typing import Any, Dict, List, Optional from sglang.srt.arg_groups.overrides import ( + _hisparse_validation, resolved_view, resolving_view, + run_post_process_pass, ) from sglang.srt.distributed.device_communicators.mooncake_transfer_engine import ( parse_ib_device_config, @@ -154,10 +156,6 @@ def check_server_args(server_args: Any): # Check hisparse # Moved to the resolution pipeline (arg_groups/overrides.py: # _hisparse_validation), invoked here at its legacy slot. - from sglang.srt.arg_groups.overrides import ( - _hisparse_validation, - run_post_process_pass, - ) run_post_process_pass(server_args, _hisparse_validation) diff --git a/python/sglang/srt/configs/model_config.py b/python/sglang/srt/configs/model_config.py index 952dda79b17f..32ea0fd3c96f 100644 --- a/python/sglang/srt/configs/model_config.py +++ b/python/sglang/srt/configs/model_config.py @@ -25,6 +25,7 @@ import torch from transformers import PretrainedConfig +from sglang.srt.arg_groups.overrides import resolving_view from sglang.srt.configs.embedding_model_spec import resolve_embedding_model_spec from sglang.srt.configs.linear_attn_model_registry import get_linear_attn_config from sglang.srt.environ import envs @@ -604,7 +605,6 @@ def from_server_args( context_length: Optional[int] = None, **kwargs, ): - from sglang.srt.arg_groups.overrides import resolving_view cfg = resolving_view(server_args) quantization = ( diff --git a/python/sglang/srt/dllm/config.py b/python/sglang/srt/dllm/config.py index a2206feb92a9..ac942c44b8c4 100644 --- a/python/sglang/srt/dllm/config.py +++ b/python/sglang/srt/dllm/config.py @@ -1,5 +1,6 @@ from typing import Any +from sglang.srt.arg_groups.overrides import resolving_view from sglang.srt.configs.model_config import ModelConfig from sglang.srt.server_args import ServerArgs @@ -25,7 +26,6 @@ def __init__( def from_server_args( server_args: ServerArgs, ): - from sglang.srt.arg_groups.overrides import resolving_view cfg = resolving_view(server_args) if cfg.dllm_algorithm is None: diff --git a/python/sglang/srt/entrypoints/grpc_server.py b/python/sglang/srt/entrypoints/grpc_server.py index 0c2a8c559316..3c7fba8ea98e 100644 --- a/python/sglang/srt/entrypoints/grpc_server.py +++ b/python/sglang/srt/entrypoints/grpc_server.py @@ -17,6 +17,7 @@ from aiohttp import web +from sglang.srt.arg_groups.overrides import resolving_view from sglang.srt.managers.io_struct import ProfileReq, ProfileReqType from sglang.srt.utils.common import get_bool_env_var @@ -165,8 +166,6 @@ async def serve_grpc(server_args, model_info=None): "version mismatch — see the chained exception above for details." ) from e - from sglang.srt.arg_groups.overrides import resolving_view - # The integrated servicer builds an `Engine`, which validates and publishes # on its own. Validating here would run `check_server_args` twice, and the # LoRA normalization is not idempotent -- the second pass sees the `LoRARef` diff --git a/python/sglang/srt/hardware_backend/npu/utils.py b/python/sglang/srt/hardware_backend/npu/utils.py index df4fc2920f90..3fd179443620 100644 --- a/python/sglang/srt/hardware_backend/npu/utils.py +++ b/python/sglang/srt/hardware_backend/npu/utils.py @@ -6,7 +6,11 @@ import torch -from sglang.srt.arg_groups.overrides import declare_resolution +from sglang.srt.arg_groups.overrides import ( + declare_resolution, + resolving_view, + use_mla_backend, +) from sglang.srt.environ import envs from sglang.srt.model_executor.cuda_graph_config import Phase, with_phase from sglang.srt.utils import get_npu_memory_capacity, is_npu @@ -44,7 +48,6 @@ def set_default_server_args(args: "ServerArgs"): """ Set default server arguments for NPU backend. """ - from sglang.srt.arg_groups.overrides import resolving_view, use_mla_backend cfg = resolving_view(args) diff --git a/python/sglang/srt/layers/attention/attention_registry.py b/python/sglang/srt/layers/attention/attention_registry.py index 8f7b178c258b..a0615766dfed 100644 --- a/python/sglang/srt/layers/attention/attention_registry.py +++ b/python/sglang/srt/layers/attention/attention_registry.py @@ -2,6 +2,7 @@ import warnings from typing import TYPE_CHECKING +from sglang.srt.arg_groups.overrides import resolved_view from sglang.srt.configs.hybrid_arch import ( hybrid_gdn_config, hybrid_lightning_config, @@ -74,10 +75,7 @@ def create_trtllm_mla_backend(runner): if not runner.use_mla_backend: raise ValueError("trtllm_mla backend can only be used with MLA models.") if get_parallel().dcp_enabled and get_spec().speculative_algorithm is not None: - from sglang.srt.arg_groups.overrides import ( - attention_backends_of, - resolved_view, - ) + from sglang.srt.arg_groups.overrides import attention_backends_of _, decode_backend = attention_backends_of(resolved_view(runner.server_args)) if decode_backend == "trtllm_mla": diff --git a/python/sglang/srt/layers/cp/bcg.py b/python/sglang/srt/layers/cp/bcg.py index df8f74f607d3..6c26099dd9b9 100644 --- a/python/sglang/srt/layers/cp/bcg.py +++ b/python/sglang/srt/layers/cp/bcg.py @@ -21,7 +21,10 @@ import torch -from sglang.srt.arg_groups.overrides import resolved_view +from sglang.srt.arg_groups.overrides import ( + resolved_view, + resolving_view, +) from sglang.srt.layers.cp.base import get_cp_strategy from sglang.srt.layers.cp.padding import get_cp_padding_align_size from sglang.srt.layers.cp.utils import ( @@ -43,7 +46,7 @@ def supports_prefill_cp_bcg(server_args: ServerArgs) -> bool: """Return whether the selected prefill-CP configuration supports BCG.""" - from sglang.srt.arg_groups.overrides import attention_backends_of, resolving_view + from sglang.srt.arg_groups.overrides import attention_backends_of cfg = resolving_view(server_args) resolved = resolved_view(server_args) diff --git a/python/sglang/srt/layers/moe/kt_ep_wrapper.py b/python/sglang/srt/layers/moe/kt_ep_wrapper.py index 17c55559520a..8eb3d0fc89e3 100644 --- a/python/sglang/srt/layers/moe/kt_ep_wrapper.py +++ b/python/sglang/srt/layers/moe/kt_ep_wrapper.py @@ -12,6 +12,7 @@ import torch +from sglang.srt.arg_groups.overrides import model_config_of from sglang.srt.layers.quantization.base_config import FusedMoEMethodBase from sglang.srt.runtime_context import ( get_exec, @@ -77,8 +78,6 @@ def create_kt_config_from_server_args( if get_exec().moe.kt_weight_path is None: return None - from sglang.srt.arg_groups.overrides import model_config_of - num_layers = getattr( model_config_of(server_args).hf_config, "num_hidden_layers", None ) diff --git a/python/sglang/srt/lora/marlin_lora_temp/policy.py b/python/sglang/srt/lora/marlin_lora_temp/policy.py index c05838fa1365..eac576ee5cdc 100644 --- a/python/sglang/srt/lora/marlin_lora_temp/policy.py +++ b/python/sglang/srt/lora/marlin_lora_temp/policy.py @@ -9,12 +9,13 @@ from typing import Any +from sglang.srt.arg_groups.overrides import resolving_view + def validate_experimental_sgl_marlin_server_args( server_args: Any, resolved_args: Any ) -> None: """Validate startup options before the experimental runner is constructed.""" - from sglang.srt.arg_groups.overrides import resolving_view cfg = resolving_view(server_args) diff --git a/python/sglang/srt/model_executor/model_runner_components/kv_pool_runtime.py b/python/sglang/srt/model_executor/model_runner_components/kv_pool_runtime.py index 4b702e1518df..ac1c61418da0 100644 --- a/python/sglang/srt/model_executor/model_runner_components/kv_pool_runtime.py +++ b/python/sglang/srt/model_executor/model_runner_components/kv_pool_runtime.py @@ -6,6 +6,7 @@ import msgspec import torch +from sglang.srt.arg_groups.overrides import post_capture_kv_sizing_planned from sglang.srt.configs.hybrid_arch import mambaish_config from sglang.srt.distributed import get_world_group from sglang.srt.mem_cache.kv_cache_configurator import mm_runtime_reservation_gb @@ -29,7 +30,6 @@ def is_post_capture_kv_active( *, server_args: ServerArgs, is_draft_worker: bool ) -> bool: - from sglang.srt.arg_groups.overrides import post_capture_kv_sizing_planned return ( post_capture_kv_sizing_planned(server_args) diff --git a/python/sglang/srt/model_loader/expert_pack_runtime.py b/python/sglang/srt/model_loader/expert_pack_runtime.py index 6e5e4c035ee3..5f5ea5b81047 100644 --- a/python/sglang/srt/model_loader/expert_pack_runtime.py +++ b/python/sglang/srt/model_loader/expert_pack_runtime.py @@ -15,7 +15,10 @@ from pathlib import Path from typing import Any -from sglang.srt.arg_groups.overrides import declare_resolution +from sglang.srt.arg_groups.overrides import ( + declare_resolution, + resolving_view, +) METADATA_FORMAT_VERSION = 3 GGUF_SHARD_SUFFIX_RE = re.compile(r"-\d{5}-of-\d{5}\.gguf$") @@ -204,8 +207,6 @@ def prepare_raw_kimi_server_args( ) -> None: """Resolve a raw GGUF model path into the normal loader inputs.""" - from sglang.srt.arg_groups.overrides import resolving_view - cfg = resolving_view(server_args) model_path = Path(cfg.model_path).expanduser() if not model_path.is_file() or model_path.suffix.lower() != ".gguf": @@ -516,8 +517,6 @@ def prepare_raw_deepseek_server_args( ) -> None: """Resolve a raw DeepSeek V4 GGUF into metadata and Expert Pack inputs.""" - from sglang.srt.arg_groups.overrides import resolving_view - cfg = resolving_view(server_args) source = Path(cfg.model_path).expanduser().resolve(strict=True) if not source.is_file(): @@ -564,8 +563,6 @@ def prepare_raw_expert_pack_server_args( ) -> None: """Dispatch a raw GGUF to the model-specific expert-pack preparation path.""" - from sglang.srt.arg_groups.overrides import resolving_view - cfg = resolving_view(server_args) source = Path(cfg.model_path).expanduser() if not source.is_file(): diff --git a/python/sglang/srt/runtime_context.py b/python/sglang/srt/runtime_context.py index 02e331178b43..eaf7efab873b 100644 --- a/python/sglang/srt/runtime_context.py +++ b/python/sglang/srt/runtime_context.py @@ -864,12 +864,12 @@ def get_stream(self, name: str) -> Any: name (the keyed-lazy pattern of the persistent buffers). Creation is a driver call that must stay outside cuda-graph capture — call sites lease their stream at init/warmup time.""" + from sglang.srt.arg_groups.overrides import resolution_result + stream = self.resources.streams.get(name) if stream is None: import torch - from sglang.srt.arg_groups.overrides import resolution_result - device = ( resolution_result(self._server_args, "device") if self._server_args diff --git a/python/sglang/srt/server_args.py b/python/sglang/srt/server_args.py index 009184acbf2d..7e1102e29ea3 100644 --- a/python/sglang/srt/server_args.py +++ b/python/sglang/srt/server_args.py @@ -56,6 +56,7 @@ mamba_extra_buffer_lazy_of, mamba_extra_buffer_of, remote_instance_transfer_engine_of, + resolution_projection, resolving_view, ) from sglang.srt.environ import envs @@ -3697,7 +3698,6 @@ def resolved_dict(self) -> Dict[str, Any]: the way `asdict` expands them; the private resolution bookkeeping and the `model_config` memo are not fields and do not appear. """ - from sglang.srt.arg_groups.overrides import resolution_projection return resolution_projection(self) diff --git a/python/sglang/srt/speculative/adaptive_spec_params.py b/python/sglang/srt/speculative/adaptive_spec_params.py index c3c252f82310..96997c1ffbf1 100644 --- a/python/sglang/srt/speculative/adaptive_spec_params.py +++ b/python/sglang/srt/speculative/adaptive_spec_params.py @@ -12,6 +12,10 @@ from functools import cached_property from typing import TYPE_CHECKING +from sglang.srt.arg_groups.overrides import ( + resolved_view, + resolving_view, +) from sglang.srt.utils import log_info_on_rank0 if TYPE_CHECKING: @@ -49,10 +53,8 @@ def adaptive_unsupported_reason(server_args: ServerArgs) -> str | None: """Return why adaptive spec cannot run under the given server args, or None if supported.""" - from sglang.srt.arg_groups.overrides import resolving_view cfg = resolving_view(server_args) - from sglang.srt.arg_groups.overrides import resolved_view if cfg.speculative_algorithm not in ("EAGLE", "EAGLE3"): return ( diff --git a/python/sglang/srt/speculative/dspark_components/dspark_config.py b/python/sglang/srt/speculative/dspark_components/dspark_config.py index 88bc14405b3b..50909f9f7ae9 100644 --- a/python/sglang/srt/speculative/dspark_components/dspark_config.py +++ b/python/sglang/srt/speculative/dspark_components/dspark_config.py @@ -6,6 +6,7 @@ import msgspec +from sglang.srt.arg_groups.overrides import resolved_view from sglang.srt.runtime_context import ( get_model, get_spec, @@ -142,7 +143,6 @@ def read_draft_checkpoint_config(*, server_args: ServerArgs) -> DSparkDraftConfi silently drops the checkpoint's gamma and the cross-check with `--speculative-num-draft-tokens` along with it. """ - from sglang.srt.arg_groups.overrides import resolved_view from sglang.srt.utils.hf_transformers_utils import get_config resolving = resolved_view(server_args) diff --git a/python/sglang/srt/speculative/spec_info.py b/python/sglang/srt/speculative/spec_info.py index 97ca92d31f0f..c2c494ed82fb 100644 --- a/python/sglang/srt/speculative/spec_info.py +++ b/python/sglang/srt/speculative/spec_info.py @@ -7,6 +7,7 @@ import torch +from sglang.srt.arg_groups.overrides import resolving_view from sglang.srt.runtime_context import get_spec as get_spec_config from sglang.srt.speculative.spec_registry import ( CustomSpecAlgo, @@ -254,7 +255,6 @@ def get_num_tokens_per_bs_for_target_verify( def create_worker( self, server_args: ServerArgs ) -> Optional[Union[Type[BaseSpecWorker], Type[TpModelWorker], Type[NGRAMWorker]]]: - from sglang.srt.arg_groups.overrides import resolving_view cfg = resolving_view(server_args) assert ( diff --git a/python/sglang/srt/speculative/spec_registry.py b/python/sglang/srt/speculative/spec_registry.py index 933d4e05d7b0..20c0902bf88f 100644 --- a/python/sglang/srt/speculative/spec_registry.py +++ b/python/sglang/srt/speculative/spec_registry.py @@ -10,6 +10,8 @@ import torch +from sglang.srt.arg_groups.overrides import resolving_view + if TYPE_CHECKING: from sglang.srt.managers.overlap_utils import FutureMap from sglang.srt.managers.schedule_batch import ScheduleBatch @@ -108,7 +110,6 @@ def handle_server_args(self, server_args: ServerArgs) -> None: pass def create_worker(self, server_args: ServerArgs) -> Type: - from sglang.srt.arg_groups.overrides import resolving_view cfg = resolving_view(server_args) if not cfg.disable_overlap_schedule and not self.supports_overlap: diff --git a/test/registered/unit/configs/test_multimodal_piecewise_cuda_graph.py b/test/registered/unit/configs/test_multimodal_piecewise_cuda_graph.py index 98e9003b92f0..7f016d5fcf5d 100644 --- a/test/registered/unit/configs/test_multimodal_piecewise_cuda_graph.py +++ b/test/registered/unit/configs/test_multimodal_piecewise_cuda_graph.py @@ -9,6 +9,7 @@ from sglang.srt.arg_groups.overrides import resolution_result from sglang.srt.configs.embedding_model_spec import resolve_embedding_model_spec from sglang.srt.configs.model_config import ( + AttentionArch, is_multimodal_piecewise_cuda_graph_supported, ) from sglang.srt.model_executor.cuda_graph_config import ( @@ -109,6 +110,7 @@ def test_trtllm_mla_stays_on_breakable(self): is_multimodal_piecewise_cuda_graph_supported=True, is_multimodal=False, is_multimodal_breakable_cuda_graph_supported=False, + attention_arch=AttentionArch.MLA, hf_config=SimpleNamespace(architectures=["DeepseekV2ForCausalLM"]), ) args.cuda_graph_config = CudaGraphConfig( @@ -116,12 +118,9 @@ def test_trtllm_mla_stays_on_breakable(self): ) args._cuda_graph_config_locked = set() - with ( - patch( - "sglang.srt.arg_groups.overrides.attention_backends_of", - return_value=("trtllm_mla", "trtllm_mla"), - ), - patch("sglang.srt.arg_groups.overrides.use_mla_backend", return_value=True), + with patch( + "sglang.srt.arg_groups.overrides.attention_backends_of", + return_value=("trtllm_mla", "trtllm_mla"), ): apply_cuda_graph_compatibility(args) diff --git a/test/registered/unit/server_args/test_page_major_backend_allowlist.py b/test/registered/unit/server_args/test_page_major_backend_allowlist.py index 3b185722010f..5cf9e3717cb5 100644 --- a/test/registered/unit/server_args/test_page_major_backend_allowlist.py +++ b/test/registered/unit/server_args/test_page_major_backend_allowlist.py @@ -30,9 +30,10 @@ """ import unittest -from unittest import mock +from types import SimpleNamespace from sglang.srt.arg_groups.kv_cache_hook import handle_page_major_kv_layout +from sglang.srt.configs.model_config import AttentionArch from sglang.srt.server_args import ServerArgs from sglang.test.ci.ci_register import register_cpu_ci @@ -67,18 +68,18 @@ def _accepts( "mamba_backend": "triton", }.items(): object.__setattr__(sa, name, value) - # `use_mla_backend` asks the model configuration, which this stand-in has - # no room for; the case under test is what the handler does with the answer. - # The handler imports it inside the function, so the source module is - # where the patch has to go. - with mock.patch( - "sglang.srt.arg_groups.overrides.use_mla_backend", return_value=use_mla - ): - try: - handle_page_major_kv_layout(sa) - return True - except AssertionError: - return False + object.__setattr__( + sa, + "_model_config", + SimpleNamespace( + attention_arch=AttentionArch.MLA if use_mla else AttentionArch.MHA + ), + ) + try: + handle_page_major_kv_layout(sa) + return True + except AssertionError: + return False class TestPageMajorBackendAllowlist(unittest.TestCase): diff --git a/test/registered/unit/server_args/test_resolution_declarations.py b/test/registered/unit/server_args/test_resolution_declarations.py index 269300f2e45b..89ef72d69828 100644 --- a/test/registered/unit/server_args/test_resolution_declarations.py +++ b/test/registered/unit/server_args/test_resolution_declarations.py @@ -934,47 +934,42 @@ def restore(): self.addCleanup(restore) def _resolve_recording_each_entry(self, **supplied): - """Resolve, deep-copying every stash entry the moment it is appended.""" - from sglang.srt.arg_groups import overrides + """Resolve, deep-copying every stash entry the moment it is appended. + The property is about the stash, so the seam is the stash: a list that + snapshots on append. Every declaration path -- `declare_resolution`, + `declare_late_resolution`, `declare_direct_writes` and the passes -- + reaches it through `.append`, whatever it was imported as. + """ recorded = [] - def watch(name): - original = getattr(overrides, name) - - def wrapper(server_args, *args, **kwargs): - result = original(server_args, *args, **kwargs) - stash = getattr(server_args, "_resolved_overrides", None) or [] - while len(recorded) < len(stash): - index = len(recorded) - recorded.append((index, copy.deepcopy(stash[index]))) - return result - - return original, wrapper - - # Every path that appends to the stash. - patched = {} - for name in ( - "declare_resolution", - "declare_late_resolution", - "declare_direct_writes", - "run_post_process_pass", - ): - original, wrapper = watch(name) - patched[name] = original - setattr(overrides, name, wrapper) - try: - path = tempfile.mkdtemp(prefix="declared_values_") - self.addCleanup(shutil.rmtree, path, ignore_errors=True) - with open(os.path.join(path, "config.json"), "w") as handle: - json.dump(_MINI_CONFIG, handle) - server_args = ServerArgs( - model_path=path, device="cuda", random_seed=42, **supplied - ) - server_args.resolve_once() - finally: - for name, original in patched.items(): - setattr(overrides, name, original) + class _SnapshotOnAppend(list): + def append(self, entry): + super().append(entry) + recorded.append((len(self) - 1, copy.deepcopy(entry))) + + class _WatchedArgs(ServerArgs): + """Whatever list the pipeline installs, snapshot what lands in it. + + The pipeline resets the stash at the start of a resolution, so the + seam has to survive that assignment rather than precede it. + """ + + def __setattr__(self, name, value): + if name == "_resolved_overrides" and not isinstance( + value, _SnapshotOnAppend + ): + value = _SnapshotOnAppend(value) + super().__setattr__(name, value) + + path = tempfile.mkdtemp(prefix="declared_values_") + self.addCleanup(shutil.rmtree, path, ignore_errors=True) + with open(os.path.join(path, "config.json"), "w") as handle: + json.dump(_MINI_CONFIG, handle) + server_args = _WatchedArgs( + model_path=path, device="cuda", random_seed=42, **supplied + ) + server_args.resolve_once() return server_args, recorded def test_no_entry_changes_after_it_is_recorded(self): diff --git a/test/registered/unit/server_args/test_server_args.py b/test/registered/unit/server_args/test_server_args.py index 2b0fed392ca7..dd60a4ff96ef 100644 --- a/test/registered/unit/server_args/test_server_args.py +++ b/test/registered/unit/server_args/test_server_args.py @@ -979,10 +979,7 @@ def _make_args(self, attention_backend, prefill=None, decode=None, page_size=1): return args @patch("sglang.srt.arg_groups.overrides.is_sm100_supported", return_value=True) - @patch("sglang.srt.arg_groups.overrides.use_mla_backend", return_value=False) - def test_combined_attention_backend_fa4_forces_page_size_128( - self, _mock_mla, _mock_sm100 - ): + def test_combined_attention_backend_fa4_forces_page_size_128(self, _mock_sm100): # `--attention-backend fa4` (combined): prefill/decode fields stay None. args = self._make_args(attention_backend="fa4") @@ -994,8 +991,7 @@ def test_combined_attention_backend_fa4_forces_page_size_128( self.assertEqual(resolved_view(args).page_size, 128) @patch("sglang.srt.arg_groups.overrides.is_sm100_supported", return_value=True) - @patch("sglang.srt.arg_groups.overrides.use_mla_backend", return_value=False) - def test_explicit_prefill_fa4_forces_page_size_128(self, _mock_mla, _mock_sm100): + def test_explicit_prefill_fa4_forces_page_size_128(self, _mock_sm100): # `--prefill-attention-backend fa4`: the previously-covered path. args = self._make_args(attention_backend=None, prefill="fa4", page_size=1) @@ -1869,12 +1865,7 @@ def _handled_args(self, **overrides): is_multimodal=False, is_multimodal_piecewise_cuda_graph_supported=False, ) - with ( - patch("sglang.srt.utils.is_cuda", return_value=True), - patch( - "sglang.srt.arg_groups.overrides.use_mla_backend", return_value=False - ), - ): + with patch("sglang.srt.utils.is_cuda", return_value=True): handle_cuda_graph_config(args) return args @@ -1944,12 +1935,7 @@ def _handled_args(self, **overrides): is_multimodal=False, is_multimodal_piecewise_cuda_graph_supported=False, ) - with ( - patch("sglang.srt.utils.is_cuda", return_value=True), - patch( - "sglang.srt.arg_groups.overrides.use_mla_backend", return_value=False - ), - ): + with patch("sglang.srt.utils.is_cuda", return_value=True): handle_cuda_graph_config(args) return args @@ -2010,12 +1996,7 @@ def _handled_args(self, *, architectures, is_multimodal, allowlisted): is_multimodal_piecewise_cuda_graph_supported=False, is_multimodal_breakable_cuda_graph_supported=allowlisted, ) - with ( - patch("sglang.srt.utils.is_cuda", return_value=True), - patch( - "sglang.srt.arg_groups.overrides.use_mla_backend", return_value=False - ), - ): + with patch("sglang.srt.utils.is_cuda", return_value=True): handle_cuda_graph_config(args) return args diff --git a/test/registered/unit/test_model_overrides.py b/test/registered/unit/test_model_overrides.py index 73b9e4ce567b..16068f9919b0 100644 --- a/test/registered/unit/test_model_overrides.py +++ b/test/registered/unit/test_model_overrides.py @@ -2231,6 +2231,7 @@ def _args(default_backend, **kw): defaults.update(kw) args = SimpleNamespace(**defaults) args.default_backend_for_test = default_backend + args._model_config = SimpleNamespace(attention_arch=AttentionArch.MHA) return args with patch.object( @@ -2239,10 +2240,6 @@ def _args(default_backend, **kw): overrides_module, "get_default_attn_backend", lambda server_args, **_: server_args.default_backend_for_test, - ), patch.object( - overrides_module, "use_mla_backend", return_value=False - ), patch.object( - overrides_module, "model_config_of", return_value=None ): # radix on + no extra buffer + no spec -> page_size=1 path self.assertEqual(