config: one control-plane log for the process (#35028)

This commit is contained in:
Cheng Wan
2026-08-17 16:19:00 -07:00
committed by GitHub
parent c70c7d72a8
commit b3c8f0d923
8 changed files with 245 additions and 95 deletions
@@ -75,7 +75,9 @@ class _MockTokenizerManager:
self.model_path = self.server_args.model_path
# The manager tracks the served name itself; a weight update rewrites it.
self.served_model_name = "test-model"
self._config_updates = []
# Stands in for the context's resolved leaves: an override replaces the
# field's one live value, the seed stays on server_args.
self._config_overrides = {}
# Mock hf_config for _resolve_chat_encoding_spec check
mock_hf_config = Mock()
@@ -114,10 +116,9 @@ class _MockTokenizerManager:
self.request_logger = Mock(log_requests=False, log_requests_level=0)
def config_value(self, name: str):
"""The manager's overlay accessor: no control-plane update recorded."""
for _source, fields in reversed(self._config_updates):
if name in fields:
return fields[name]
"""The value in effect for one config field."""
if name in self._config_overrides:
return self._config_overrides[name]
return getattr(self.server_args, name)
@@ -160,15 +161,12 @@ class ServingChatTestCase(unittest.TestCase):
self.fastapi_request.headers = {}
def test_parsers_follow_the_control_plane_overlay(self):
"""Template detection records the parsers on the manager, not on its
ServerArgs — the instance keeps what the launcher passed."""
"""Template detection records the parsers through `override`, so they
answer from the bags; `ServerArgs` keeps the launcher's seed."""
self.tm.server_args.tool_call_parser = "auto"
self.tm.server_args.reasoning_parser = "auto"
self.tm._config_updates.append(
(
"template-detection",
{"tool_call_parser": "qwen25", "reasoning_parser": None},
)
self.tm._config_overrides.update(
{"tool_call_parser": "qwen25", "reasoning_parser": None}
)
chat = OpenAIServingChat(self.tm, self.template_manager)
@@ -180,9 +178,7 @@ class ServingChatTestCase(unittest.TestCase):
def test_the_xgrammar_gate_follows_the_overlay(self):
"""A detected `reasoning_parser` must gate xgrammar, not the seed's "auto"."""
self.tm.server_args.reasoning_parser = "auto"
self.tm._config_updates.append(
("template-detection", {"reasoning_parser": "qwen3"})
)
self.tm._config_overrides["reasoning_parser"] = "qwen3"
chat = OpenAIServingChat(self.tm, self.template_manager)
self.assertEqual(chat.reasoning_parser, "qwen3")
# the gate reads the same value the parser was built from
@@ -54,7 +54,9 @@ class MockTokenizerManager:
tool_call_parser=None,
incremental_streaming_output=False,
)
self._config_updates = []
# Stands in for the context's resolved leaves: an override replaces the
# field's one live value, the seed stays on server_args.
self._config_overrides = {}
self.tokenizer = Mock()
self.tokenizer.encode.return_value = [1, 2, 3]
self.tokenizer.chat_template = None
@@ -64,10 +66,9 @@ class MockTokenizerManager:
self.create_abort_task = Mock()
def config_value(self, name: str):
"""The manager's overlay accessor: no control-plane update recorded."""
for _source, fields in reversed(self._config_updates):
if name in fields:
return fields[name]
"""The value in effect for one config field."""
if name in self._config_overrides:
return self._config_overrides[name]
return getattr(self.server_args, name)
@@ -43,15 +43,13 @@ def _stub_tokenizer_manager(
"""A manager carrying the state `/server_info` and its writers read.
`__new__` skips `__init__`, which would open the ZMQ sockets and start
the handle loop; `_config_updates` is the log `record_config_updates`
appends to.
the handle loop.
"""
tokenizer_manager = TokenizerManager.__new__(TokenizerManager)
tokenizer_manager.server_args = server_args
tokenizer_manager.model_path = server_args.model_path
tokenizer_manager.served_model_name = server_args.served_model_name
tokenizer_manager.startup_time = None
tokenizer_manager._config_updates = []
tokenizer_manager.get_internal_state = get_internal_state
return tokenizer_manager