[refactor] Wire the config resolution pipeline (dispatch, stash, dual-apply, publish) (stack 6/15) (#30068)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cheng Wan
2026-07-04 02:21:21 -07:00
committed by GitHub
co-authored by Claude Fable 5
parent c3d751b231
commit df6491d80c
5 changed files with 138 additions and 2 deletions
+6 -1
View File
@@ -85,7 +85,12 @@ class Arg:
@functools.lru_cache(maxsize=None)
def model_overridable_fields(cls) -> frozenset:
"""Names of ``cls`` dataclass fields whose ``Arg`` metadata declares
``model_overridable=True`` — the whitelist for model-override resolution."""
``model_overridable=True`` — the whitelist for model-override resolution.
Non-dataclass types (e.g. mock config objects in tests) have no Arg
metadata and yield an empty whitelist."""
if not dataclasses.is_dataclass(cls):
return frozenset()
hints = get_type_hints(cls, include_extras=True)
names = set()
for field in dataclasses.fields(cls):
+16
View File
@@ -172,7 +172,23 @@ def apply_declarations_to_server_args(
Retired per field once that field's readers have all flipped to the flags
tier (at which point the server_args field returns to pristine).
Validates against the same whitelist as the publish gate BEFORE any write:
a registry typo or a not-yet-resolvable field must fail fast here, not
mutate ``server_args`` and only be rejected at publish time.
"""
# Non-dataclass fixtures carry no Arg metadata (mirrors the
# model_overridable_fields escape); only real ServerArgs is validated.
if dataclasses.is_dataclass(type(server_args)):
whitelist = model_overridable_fields(type(server_args))
for source, decl in list(declarations) + list(terminal):
unknown = set(decl) - whitelist
if unknown:
raise ValueError(
f"{source}: {sorted(unknown)} not model-overridable; the "
"transition dual-apply refuses fields the publish gate "
"would reject."
)
for _source, decl in list(declarations) + list(terminal):
for field, value in decl.items():
setattr(server_args, field, value)
+31
View File
@@ -359,9 +359,40 @@ class RuntimeContext:
Overwrite-allowed: a re-publish replaces the slot (test kits re-publish
per test; production ordering discipline lives at the call-sites, e.g.
the draft-worker guard in ``ModelRunner.__init__``).
Publishing also resolves the stashed model-override declarations
into the flags tier (skipped for objects without the stash — dummy /
"none" fixture ServerArgs and test-kit mocks never compute it).
Resolution runs first: if it fails, the previous publish stays intact.
"""
self._resolve_flags(server_args)
self._server_args = server_args
def _resolve_flags(self, server_args: ServerArgs) -> None:
declarations = getattr(server_args, "_resolved_overrides", None)
if declarations is None:
return
from sglang.srt.arg_groups.overrides import (
apply_model_overrides,
assert_flag_parity,
)
# Resolve into a fresh container and only install it once everything
# passed: a failed resolution (gate validation or the parity assert)
# must not leave the process-global flags half-written for callers
# that catch the error or republish (same install-fresh semantics as
# reset_context()).
flags = Flags()
apply_model_overrides(flags, server_args, declarations)
# Transition-period drift guard: dual-apply keeps the declared fields
# on server_args byte-identical to the resolved flag leaves.
assert_flag_parity(
flags,
server_args,
{field for _source, decl in declarations for field in decl},
)
self.flags = flags
_PARALLEL = ParallelContext()
_CONTEXT = RuntimeContext(parallel=_PARALLEL)
+23
View File
@@ -2569,6 +2569,12 @@ class ServerArgs:
Orchestrates the handling of various server arguments, ensuring proper configuration and validation.
"""
# Declaration stash for the override/post-process passes. Set before any
# short-circuit (none/dummy model paths) so run_post_process_pass and
# direct handler invocations can rely on it even when
# _handle_model_specific_adjustments never runs.
self._resolved_overrides = []
self._maybe_download_model_for_runai()
# Normalize load balancing defaults early (before dummy-model short-circuit).
@@ -3709,6 +3715,7 @@ class ServerArgs:
self.uses_mamba_radix_cache = False
if parse_connector_type(self.model_path) == ConnectorType.INSTANCE:
self._resolved_overrides = []
return
hf_config = self.get_model_config().hf_config
@@ -3718,6 +3725,22 @@ class ServerArgs:
if _hybrid_spec is not None and _hybrid_spec.uses_mamba_radix_cache:
self._handle_mamba_radix_cache(model_arch=model_arch)
# Collect the declarative model overrides (registry) on the
# pristine config and stash them for publish-time flags resolution.
# Transition dual-apply: the same declarations are applied to
# server_args right here, byte-identical to the imperative arch
# branches this dispatch gradually replaces (dual-apply is retired
# per field once that field's readers migrate to the flags tier).
from sglang.srt.arg_groups.overrides import (
apply_declarations_to_server_args,
collect_model_override_declarations,
)
self._resolved_overrides = collect_model_override_declarations(
model_arch, self, hf_config
)
apply_declarations_to_server_args(self, self._resolved_overrides)
if model_arch in [
"MistralLarge3ForCausalLM",
"PixtralForConditionalGeneration",