Repository navigation
refactor: [vLLM] Abstract embedding loading to a class. Encapsulate frontend decoding receiver detail into ImageLoader - #7482
Conversation
WalkthroughThis PR refactors multimodal embedding handling by introducing a new Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Tip CodeRabbit can generate a title for your PR based on the changes with custom instructions.Set the |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
components/src/dynamo/common/utils/runtime.py (1)
76-97: Hardcoded 10-second timeout may cause silent failures.The
timeout=10is hardcoded and not configurable. For operations like NIXL connector initialization that may take variable time depending on network conditions, this could cause unexpectedTimeoutErrorexceptions.Consider making the timeout configurable:
♻️ Proposed refactor to add configurable timeout
-def run_async(func, *args, **kwargs): +def run_async(func, *args, timeout: float = 10.0, **kwargs): """Run an async function as if it is synchronous, handling both sync and async contexts. Args: func: An async function to execute. *args: Positional arguments to pass to the function. + timeout: Timeout in seconds for async context execution (default: 10.0). **kwargs: Keyword arguments to pass to the function. Returns: The result of the async function. + + Raises: + TimeoutError: If the function does not complete within the timeout period + when running from an async context. """ # Handle both sync and async contexts try: asyncio.get_running_loop() # Check if we're in async context # If we're in an async context, we need to run the connection creation in a separate thread to avoid blocking the event loop import concurrent.futures with concurrent.futures.ThreadPoolExecutor() as pool: - return pool.submit(asyncio.run, func(*args, **kwargs)).result(timeout=10) + return pool.submit(asyncio.run, func(*args, **kwargs)).result(timeout=timeout) except RuntimeError: # No running loop - safe to use asyncio.run() return asyncio.run(func(*args, **kwargs))🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/src/dynamo/common/utils/runtime.py` around lines 76 - 97, The run_async helper hardcodes a 10s timeout which can cause silent TimeoutError; update the run_async function signature to accept an optional timeout parameter (e.g., timeout: Optional[float] = None), use that value instead of the hardcoded 10 when calling pool.submit(...).result(timeout=...), and ensure callers are updated (or default remains safe) so longer connector initialization can complete; keep the existing ThreadPoolExecutor/asyncio.run flow and propagate any TimeoutError rather than swallowing it.components/src/dynamo/vllm/multimodal_handlers/multimodal_pd_worker_handler.py (1)
111-115: Consider updatingMultiModalEmbeddingLoadertype signature to acceptClient | None.The
# type: ignoreon line 112 suppresses the type mismatch whereencode_worker_clientmay beNonebut the loader expectsClient. While this is safe at runtime (the loader'sload_multimodal_embeddingshas an early-return guard), aligning the type signature inMultiModalEmbeddingLoader.__init__would be cleaner:def __init__( self, encode_worker_client: Client | None, # Accept None explicitly ... )This would eliminate the need for
# type: ignoreand make the contract explicit.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/src/dynamo/vllm/multimodal_handlers/multimodal_pd_worker_handler.py` around lines 111 - 115, The MultiModalEmbeddingLoader is being passed encode_worker_client which can be None but the constructor currently types it as Client, causing a suppressed type error; update MultiModalEmbeddingLoader.__init__ to accept encode_worker_client: Client | None (or Optional[Client]) in its signature and adjust any internal type hints accordingly (noting load_multimodal_embeddings already guards for None), remove the need for the call-site # type: ignore, and run type checks to ensure no other callers require changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@components/src/dynamo/common/multimodal/image_loader.py`:
- Around line 192-195: The code incorrectly references non-existent attributes
self.enable_frontend_decoding and self.nixl_connector; change those references
to the actual instance attributes self._enable_frontend_decoding and
self._nixl_connector in the block that builds image_futures (the conditional
using DECODED_VARIANT_KEY and the call to read_decoded_media_via_nixl) so the
runtime AttributeError is resolved.
---
Nitpick comments:
In `@components/src/dynamo/common/utils/runtime.py`:
- Around line 76-97: The run_async helper hardcodes a 10s timeout which can
cause silent TimeoutError; update the run_async function signature to accept an
optional timeout parameter (e.g., timeout: Optional[float] = None), use that
value instead of the hardcoded 10 when calling
pool.submit(...).result(timeout=...), and ensure callers are updated (or default
remains safe) so longer connector initialization can complete; keep the existing
ThreadPoolExecutor/asyncio.run flow and propagate any TimeoutError rather than
swallowing it.
In
`@components/src/dynamo/vllm/multimodal_handlers/multimodal_pd_worker_handler.py`:
- Around line 111-115: The MultiModalEmbeddingLoader is being passed
encode_worker_client which can be None but the constructor currently types it as
Client, causing a suppressed type error; update
MultiModalEmbeddingLoader.__init__ to accept encode_worker_client: Client | None
(or Optional[Client]) in its signature and adjust any internal type hints
accordingly (noting load_multimodal_embeddings already guards for None), remove
the need for the call-site # type: ignore, and run type checks to ensure no
other callers require changes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9b46a920-f94a-4e4c-934a-9ad534336844
📒 Files selected for processing (9)
components/src/dynamo/common/multimodal/embedding_transfer.pycomponents/src/dynamo/common/multimodal/image_loader.pycomponents/src/dynamo/common/utils/runtime.pycomponents/src/dynamo/vllm/handlers.pycomponents/src/dynamo/vllm/multimodal_handlers/multimodal_pd_worker_handler.pycomponents/src/dynamo/vllm/multimodal_utils/__init__.pycomponents/src/dynamo/vllm/multimodal_utils/prefill_worker_utils.pycomponents/src/dynamo/vllm/tests/multimodal_handlers/test_vllm_multimodal_pd_worker_handler.pycomponents/src/dynamo/vllm/tests/multimodal_utils/test_vllm_prefill_worker_utils.py
… decoding receiver detail into ImageLoader Signed-off-by: Guan Luo <41310872+GuanLuo@users.noreply.github.com>
b84dfef to
36f8333
Compare
Signed-off-by: Guan Luo <41310872+GuanLuo@users.noreply.github.com>
Signed-off-by: Guan Luo <41310872+GuanLuo@users.noreply.github.com>
…rontend decoding receiver detail into ImageLoader (ai-dynamo#7482) Signed-off-by: Guan Luo <41310872+GuanLuo@users.noreply.github.com>
…rontend decoding receiver detail into ImageLoader (ai-dynamo#7482) Signed-off-by: Guan Luo <41310872+GuanLuo@users.noreply.github.com>
Signed-off-by: Guan Luo 41310872+GuanLuo@users.noreply.github.com
Overview:
Details:
Where should the reviewer start?
Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)
Summary by CodeRabbit
New Features
Refactor