[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:
co-authored by
Claude Fable 5
parent
c3d751b231
commit
df6491d80c
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user