[LLM] Fix nested dict to Namespace conversion in vLLM engine initialization#60380
[LLM] Fix nested dict to Namespace conversion in vLLM engine initialization#60380edoakes merged 3 commits intoray-project:masterfrom
Conversation
There was a problem hiding this comment.
Code Review
This pull request correctly addresses a bug where nested dictionaries in vLLM engine arguments were not being converted to argparse.Namespace objects. The introduction of the _dict_to_namespace helper function and its application during engine initialization is a good solution.
My review includes a couple of suggestions to improve code clarity and conciseness:
- Adding type hints to the new helper function and translating its docstring to English for consistency.
- Refactoring the logic that applies the conversion to be more direct and Pythonic.
Additionally, I noticed some comments in Russian. It would be great to translate them to English to maintain consistency across the codebase.
Overall, the changes are solid and address the issue effectively. Once the suggested improvements are considered, this PR should be good to merge.
Signed-off-by: MiXaiLL76 <mike.milos@yandex.ru>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Михаил <mike.milos@yandex.ru> Signed-off-by: MiXaiLL76 <mike.milos@yandex.ru>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Михаил <mike.milos@yandex.ru> Signed-off-by: MiXaiLL76 <mike.milos@yandex.ru>
2834bad to
e5b40e7
Compare
|
@edoakes What do you think about this? |
|
Looks like a reasonable fix to me, but will defer to @kouroshHakha et al. because I'm not familiar with this code |
eicherseiji
left a comment
There was a problem hiding this comment.
Thanks @MiXaiLL76!
Verified the fix as follows:
"""Minimal reproducer for PR #60380"""
import argparse
from vllm.config.structured_outputs import StructuredOutputsConfig
from typing import Any
# PR #60380 fix: recursive dict→Namespace converter
def _dict_to_namespace(obj: Any) -> Any:
"""Recursively converts dictionaries to argparse.Namespace."""
if isinstance(obj, dict):
return argparse.Namespace(**{k: _dict_to_namespace(v) for k, v in obj.items()})
elif isinstance(obj, list):
return [_dict_to_namespace(item) for item in obj]
else:
return obj
engine_args = argparse.Namespace(
model="facebook/opt-125m",
structured_outputs_config={"backend": "xgrammar", "reasoning_parser": "qwen3"}
)
frontend_args = argparse.Namespace(host="0.0.0.0", port=8000)
# Original (broken)
# args = argparse.Namespace(**(frontend_args.__dict__ | engine_args.__dict__))
# PR #60380 fix (uncomment to test)
args = _dict_to_namespace(frontend_args.__dict__ | engine_args.__dict__)
args.structured_outputs_config.backend # AttributeError: 'dict' object has no attribute 'backend'I will follow up with a regression test
Add a GPU test that verifies vLLM engine can start with nested dicts in engine_kwargs (e.g., structured_outputs_config). This test will fail without the fix from PR ray-project#60380 with: AttributeError: 'dict' object has no attribute 'backend' The test ensures that nested dicts are properly converted to argparse.Namespace objects so vLLM's init_app_state() can access nested attributes via dot notation. See: ray-project#60380 Signed-off-by: Seiji Eicher <seiji@anyscale.com>
…zation (ray-project#60380) ## Summary This PR fixes a bug in the vLLM engine initialization where nested dictionaries in engine arguments were not being converted to `argparse.Namespace` objects, causing `AttributeError` when accessing nested configuration attributes. ## Problem When merging `vllm_frontend_args` and `vllm_engine_args`, nested dictionary values remained as `dict` objects instead of being converted to `Namespace` objects. This caused issues when vLLM's initialization code attempted to access nested attributes using dot notation. **Example failing configuration:** When deploying a RayService with nested `structured_outputs_config`, the service would fail to initialize: ```yaml apiVersion: ray.io/v1 kind: RayService metadata: name: qwen-thinking-service spec: serveConfigV2: | applications: - name: llms import_path: ray.serve.llm:build_openai_app route_prefix: "/" args: llm_configs: - model_loading_config: model_id: qwen3-4b-thinking model_source: /models/Qwen3-4B engine_kwargs: tensor_parallel_size: 2 trust_remote_code: true gpu_memory_utilization: 0.9 dtype: auto max_model_len: 4096 structured_outputs_config: # This nested dict caused the issue backend: xgrammar reasoning_parser: qwen3 deployment_config: autoscaling_config: min_replicas: 1 max_replicas: 1 target_ongoing_requests: 32 max_ongoing_requests: 64 ``` The error occurred because structured_outputs_config was passed as a dict, but vLLM expected it as a Namespace object to access attributes like args.structured_outputs_config.backend. Solution - Added _dict_to_namespace() helper function that recursively converts dictionaries and lists of dictionaries to argparse.Namespace objects - Applied this conversion to all nested dictionary values in the merged args Namespace after initialization in VLLMEngine.__init__() Changes - Added _dict_to_namespace() function at python/ray/llm/_internal/serve/engines/vllm/vllm_engine.py:65 - Added recursive conversion logic in VLLMEngine.__init__() at python/ray/llm/_internal/serve/engines/vllm/vllm_engine.py:273-276 Testing - Tested with Kubernetes RayService deployment using nested structured_outputs_config - Verified that the vLLM engine initializes correctly with nested configuration parameters --------- Signed-off-by: MiXaiLL76 <mike.milos@yandex.ru> Signed-off-by: Михаил <mike.milos@yandex.ru> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…zation (ray-project#60380) ## Summary This PR fixes a bug in the vLLM engine initialization where nested dictionaries in engine arguments were not being converted to `argparse.Namespace` objects, causing `AttributeError` when accessing nested configuration attributes. ## Problem When merging `vllm_frontend_args` and `vllm_engine_args`, nested dictionary values remained as `dict` objects instead of being converted to `Namespace` objects. This caused issues when vLLM's initialization code attempted to access nested attributes using dot notation. **Example failing configuration:** When deploying a RayService with nested `structured_outputs_config`, the service would fail to initialize: ```yaml apiVersion: ray.io/v1 kind: RayService metadata: name: qwen-thinking-service spec: serveConfigV2: | applications: - name: llms import_path: ray.serve.llm:build_openai_app route_prefix: "/" args: llm_configs: - model_loading_config: model_id: qwen3-4b-thinking model_source: /models/Qwen3-4B engine_kwargs: tensor_parallel_size: 2 trust_remote_code: true gpu_memory_utilization: 0.9 dtype: auto max_model_len: 4096 structured_outputs_config: # This nested dict caused the issue backend: xgrammar reasoning_parser: qwen3 deployment_config: autoscaling_config: min_replicas: 1 max_replicas: 1 target_ongoing_requests: 32 max_ongoing_requests: 64 ``` The error occurred because structured_outputs_config was passed as a dict, but vLLM expected it as a Namespace object to access attributes like args.structured_outputs_config.backend. Solution - Added _dict_to_namespace() helper function that recursively converts dictionaries and lists of dictionaries to argparse.Namespace objects - Applied this conversion to all nested dictionary values in the merged args Namespace after initialization in VLLMEngine.__init__() Changes - Added _dict_to_namespace() function at python/ray/llm/_internal/serve/engines/vllm/vllm_engine.py:65 - Added recursive conversion logic in VLLMEngine.__init__() at python/ray/llm/_internal/serve/engines/vllm/vllm_engine.py:273-276 Testing - Tested with Kubernetes RayService deployment using nested structured_outputs_config - Verified that the vLLM engine initializes correctly with nested configuration parameters --------- Signed-off-by: MiXaiLL76 <mike.milos@yandex.ru> Signed-off-by: Михаил <mike.milos@yandex.ru> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: jinbum-kim <jinbum9958@gmail.com>
…zation (ray-project#60380) ## Summary This PR fixes a bug in the vLLM engine initialization where nested dictionaries in engine arguments were not being converted to `argparse.Namespace` objects, causing `AttributeError` when accessing nested configuration attributes. ## Problem When merging `vllm_frontend_args` and `vllm_engine_args`, nested dictionary values remained as `dict` objects instead of being converted to `Namespace` objects. This caused issues when vLLM's initialization code attempted to access nested attributes using dot notation. **Example failing configuration:** When deploying a RayService with nested `structured_outputs_config`, the service would fail to initialize: ```yaml apiVersion: ray.io/v1 kind: RayService metadata: name: qwen-thinking-service spec: serveConfigV2: | applications: - name: llms import_path: ray.serve.llm:build_openai_app route_prefix: "/" args: llm_configs: - model_loading_config: model_id: qwen3-4b-thinking model_source: /models/Qwen3-4B engine_kwargs: tensor_parallel_size: 2 trust_remote_code: true gpu_memory_utilization: 0.9 dtype: auto max_model_len: 4096 structured_outputs_config: # This nested dict caused the issue backend: xgrammar reasoning_parser: qwen3 deployment_config: autoscaling_config: min_replicas: 1 max_replicas: 1 target_ongoing_requests: 32 max_ongoing_requests: 64 ``` The error occurred because structured_outputs_config was passed as a dict, but vLLM expected it as a Namespace object to access attributes like args.structured_outputs_config.backend. Solution - Added _dict_to_namespace() helper function that recursively converts dictionaries and lists of dictionaries to argparse.Namespace objects - Applied this conversion to all nested dictionary values in the merged args Namespace after initialization in VLLMEngine.__init__() Changes - Added _dict_to_namespace() function at python/ray/llm/_internal/serve/engines/vllm/vllm_engine.py:65 - Added recursive conversion logic in VLLMEngine.__init__() at python/ray/llm/_internal/serve/engines/vllm/vllm_engine.py:273-276 Testing - Tested with Kubernetes RayService deployment using nested structured_outputs_config - Verified that the vLLM engine initializes correctly with nested configuration parameters --------- Signed-off-by: MiXaiLL76 <mike.milos@yandex.ru> Signed-off-by: Михаил <mike.milos@yandex.ru> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: 400Ping <jiekaichang@apache.org>
…zation (ray-project#60380) ## Summary This PR fixes a bug in the vLLM engine initialization where nested dictionaries in engine arguments were not being converted to `argparse.Namespace` objects, causing `AttributeError` when accessing nested configuration attributes. ## Problem When merging `vllm_frontend_args` and `vllm_engine_args`, nested dictionary values remained as `dict` objects instead of being converted to `Namespace` objects. This caused issues when vLLM's initialization code attempted to access nested attributes using dot notation. **Example failing configuration:** When deploying a RayService with nested `structured_outputs_config`, the service would fail to initialize: ```yaml apiVersion: ray.io/v1 kind: RayService metadata: name: qwen-thinking-service spec: serveConfigV2: | applications: - name: llms import_path: ray.serve.llm:build_openai_app route_prefix: "/" args: llm_configs: - model_loading_config: model_id: qwen3-4b-thinking model_source: /models/Qwen3-4B engine_kwargs: tensor_parallel_size: 2 trust_remote_code: true gpu_memory_utilization: 0.9 dtype: auto max_model_len: 4096 structured_outputs_config: # This nested dict caused the issue backend: xgrammar reasoning_parser: qwen3 deployment_config: autoscaling_config: min_replicas: 1 max_replicas: 1 target_ongoing_requests: 32 max_ongoing_requests: 64 ``` The error occurred because structured_outputs_config was passed as a dict, but vLLM expected it as a Namespace object to access attributes like args.structured_outputs_config.backend. Solution - Added _dict_to_namespace() helper function that recursively converts dictionaries and lists of dictionaries to argparse.Namespace objects - Applied this conversion to all nested dictionary values in the merged args Namespace after initialization in VLLMEngine.__init__() Changes - Added _dict_to_namespace() function at python/ray/llm/_internal/serve/engines/vllm/vllm_engine.py:65 - Added recursive conversion logic in VLLMEngine.__init__() at python/ray/llm/_internal/serve/engines/vllm/vllm_engine.py:273-276 Testing - Tested with Kubernetes RayService deployment using nested structured_outputs_config - Verified that the vLLM engine initializes correctly with nested configuration parameters --------- Signed-off-by: MiXaiLL76 <mike.milos@yandex.ru> Signed-off-by: Михаил <mike.milos@yandex.ru> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: peterxcli <peterxcli@gmail.com>
…zation (ray-project#60380) ## Summary This PR fixes a bug in the vLLM engine initialization where nested dictionaries in engine arguments were not being converted to `argparse.Namespace` objects, causing `AttributeError` when accessing nested configuration attributes. ## Problem When merging `vllm_frontend_args` and `vllm_engine_args`, nested dictionary values remained as `dict` objects instead of being converted to `Namespace` objects. This caused issues when vLLM's initialization code attempted to access nested attributes using dot notation. **Example failing configuration:** When deploying a RayService with nested `structured_outputs_config`, the service would fail to initialize: ```yaml apiVersion: ray.io/v1 kind: RayService metadata: name: qwen-thinking-service spec: serveConfigV2: | applications: - name: llms import_path: ray.serve.llm:build_openai_app route_prefix: "/" args: llm_configs: - model_loading_config: model_id: qwen3-4b-thinking model_source: /models/Qwen3-4B engine_kwargs: tensor_parallel_size: 2 trust_remote_code: true gpu_memory_utilization: 0.9 dtype: auto max_model_len: 4096 structured_outputs_config: # This nested dict caused the issue backend: xgrammar reasoning_parser: qwen3 deployment_config: autoscaling_config: min_replicas: 1 max_replicas: 1 target_ongoing_requests: 32 max_ongoing_requests: 64 ``` The error occurred because structured_outputs_config was passed as a dict, but vLLM expected it as a Namespace object to access attributes like args.structured_outputs_config.backend. Solution - Added _dict_to_namespace() helper function that recursively converts dictionaries and lists of dictionaries to argparse.Namespace objects - Applied this conversion to all nested dictionary values in the merged args Namespace after initialization in VLLMEngine.__init__() Changes - Added _dict_to_namespace() function at python/ray/llm/_internal/serve/engines/vllm/vllm_engine.py:65 - Added recursive conversion logic in VLLMEngine.__init__() at python/ray/llm/_internal/serve/engines/vllm/vllm_engine.py:273-276 Testing - Tested with Kubernetes RayService deployment using nested structured_outputs_config - Verified that the vLLM engine initializes correctly with nested configuration parameters --------- Signed-off-by: MiXaiLL76 <mike.milos@yandex.ru> Signed-off-by: Михаил <mike.milos@yandex.ru> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: peterxcli <peterxcli@gmail.com>
Summary
This PR fixes a bug in the vLLM engine initialization where nested dictionaries in engine arguments were not being converted to
argparse.Namespaceobjects, causingAttributeErrorwhen accessing nested configuration attributes.Problem
When merging
vllm_frontend_argsandvllm_engine_args, nested dictionary values remained asdictobjects instead of being converted toNamespaceobjects. This caused issues when vLLM's initialization code attempted to access nested attributes using dot notation.Example failing configuration:
When deploying a RayService with nested
structured_outputs_config, the service would fail to initialize:The error occurred because structured_outputs_config was passed as a dict, but vLLM expected it as a Namespace object to access attributes like args.structured_outputs_config.backend.
Solution
Changes
Testing