Speed up local vLLM ASR client requests#1481
Conversation
Patch httpcore's async connection-pool assignment hot path by default so high-concurrency OpenAI-compatible clients do not spend the event loop rebuilding connection-state lists. Signed-off-by: Dongji Gao <dongjig@nvidia.com>
Default local vLLM multimodal audio requests to file:// URLs instead of inline base64, while retaining the base64 path for external APIs and as an explicit fallback. Signed-off-by: Dongji Gao <dongjig@nvidia.com>
📝 WalkthroughWalkthroughOptional file-path ( ChangesAudio Path Representation and Async Optimizations
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests/test_vllm_audio.py (1)
55-87: ⚡ Quick winAdd direct constructor tests for
audio_as_pathdefaulting/validation.These fixtures bypass
VLLMMultimodalModel.__init__, so the new init behavior isn’t covered (defaulting from mode + rejection of invalid combinations). A small set of direct init tests would lock this down.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_vllm_audio.py` around lines 55 - 87, The fixtures patch VLLMMultimodalModel.__init__ so constructor logic (defaulting audio_as_path based on audio_format and rejecting invalid combinations) isn’t tested; add direct unit tests that call VLLMMultimodalModel.__init__ (real constructor) to verify defaulting and validation: instantiate with audio_format values ("audio_url", "input_audio") and assert audio_as_path defaults correctly, and assert that invalid combos (e.g., audio_format="audio_url" with audio_as_path=False or other disallowed combinations) raise the expected error; reference VLLMMultimodalModel.__init__, the audio_as_path and audio_format parameters, and any validation behavior around enable_audio_chunking/audio_chunk_task_types/chunk_audio_threshold_sec to ensure constructor enforces invariants.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@nemo_skills/inference/generate.py`:
- Around line 298-309: The cleanup loop is comparing len(self._connections)
(total connections) to self._max_keepalive_connections and thus may close too
many idle connections; change the surplus-idle check to count idle connections
only (e.g. compute idle_count = sum(1 for c in self._connections if c.is_idle())
or an equivalent generator/scalar) and use idle_count >
self._max_keepalive_connections in the condition that evaluates
connection.is_idle(); keep using the same loop over self._connections and
connection.is_idle()/is_closed()/has_expired() methods but base the surplus
decision on the idle-only count.
---
Nitpick comments:
In `@tests/test_vllm_audio.py`:
- Around line 55-87: The fixtures patch VLLMMultimodalModel.__init__ so
constructor logic (defaulting audio_as_path based on audio_format and rejecting
invalid combinations) isn’t tested; add direct unit tests that call
VLLMMultimodalModel.__init__ (real constructor) to verify defaulting and
validation: instantiate with audio_format values ("audio_url", "input_audio")
and assert audio_as_path defaults correctly, and assert that invalid combos
(e.g., audio_format="audio_url" with audio_as_path=False or other disallowed
combinations) raise the expected error; reference VLLMMultimodalModel.__init__,
the audio_as_path and audio_format parameters, and any validation behavior
around enable_audio_chunking/audio_chunk_task_types/chunk_audio_threshold_sec to
ensure constructor enforces invariants.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 9f87cae9-790a-44e7-9b06-42f9498ecafe
📒 Files selected for processing (5)
nemo_skills/inference/generate.pynemo_skills/inference/model/__init__.pynemo_skills/inference/model/audio_utils.pynemo_skills/inference/model/vllm_multimodal.pytests/test_vllm_audio.py
Replace the connection-pool assignment hot path with a single-pass O(N+M) algorithm ported from encode/httpcore#1035 (still unmerged in 1.0.9). Categorize connections once, assign queued requests from the available bucket (popping each so a connection is never handed to two requests in one pass), then enforce keepalive. HTTP/2 pools fall back to the original since they need per-connection stream-capacity tracking. This removes the short-circuit scan-depth dependence of the prior patch (cost varied ~2x with where a free connection sat in the list), trading a slightly slower best case for consistent, lower worst-case cost.
Add direct VLLMMultimodalModel.__init__ tests (stubbing only the heavy VLLMModel base) for audio_as_path defaulting from mode/format and the validation that rejects path mode for external APIs / non-audio_url formats, plus unsupported-format rejection. Addresses PR review feedback that the existing fixtures bypass the constructor. Signed-off-by: Dongji Gao <dongjig@nvidia.com>
|
Addressed in eca6b2b (patch) and 701cbf0 (tests). Rather than only fix the
HTTP/2 pools fall back to the original implementation, since the single-pass path intentionally omits the per-connection stream-capacity tracking #1035 adds for multiplexing. Validated for assignment-decision equivalence + liveness across 20k randomized pool states, and end-to-end on the 8-chunk ASR leaderboard (WER 6.21, no throughput regression). For the test nitpick: added direct |
|
Tip For best results, initiate chat on the files or code changes.
The 🐇✨ |
pzelasko
left a comment
There was a problem hiding this comment.
LGTM, very welcome speedup, great work!
Summary
max_keepalive_connectionsidle-count miscount, and the HTTP/1.1 double-assign that can raiseConnectionNotAvailable.file://audio URLs by default for localaudio_urlrequests, avoiding inline base64 payloads (base64 retained for external APIs and as an explicit fallback).make_audio_url_content_blockhelper and expand vLLM audio tests (file:// vs base64 content, plus directVLLMMultimodalModel.__init__tests foraudio_as_pathdefaulting/validation).Test plan
python3 -m py_compile nemo_skills/inference/generate.py nemo_skills/inference/model/vllm_multimodal.py nemo_skills/inference/model/audio_utils.pypytest tests/test_vllm_audio.py→ 16 passed;ruff check+ruff format --checkclean.max_queued=1,max_conn=512). Residual wall-clock variance traces to server-startup / chunk-start skew, not the request path.Summary by CodeRabbit
New Features
Tests