Skip to content

Commit fa2c405

Browse files
authored
[STT] Refactor request boundary and enforce fail-fast runner behavior (#157)
This PR is: - To move STT request parsing and validation out of the runtime path. - To make the v1 STT runner use one normalized internal request shape. - To fail fast on bad STT requests instead of silently returning fallback output. ### Refactor (why this is needed) The STT runtime path was doing two jobs: - parsing raw vLLM request shapes - running STT encode/decode That made the code harder to maintain and could hide invalid input. This refactor keeps responsibilities clear: - serve boundary: parse + validate - runtime path: execute only ### Note - Added STT request adapter and normalized DTO in `vllm_metal/stt/serve.py`. - Added fail-fast validation for missing/invalid `req_id`, `prompt_token_ids`, `mm_features`, and `input_features`. - Updated `_execute_stt` to normalize request first, then run extract/decode. - Removed silent malformed-input fallback behavior. --------- Signed-off-by: Yuan Lik Xun <lxyuan0420@gmail.com>
1 parent a00cba6 commit fa2c405

4 files changed

Lines changed: 246 additions & 255 deletions

File tree

tests/test_stt_serve.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
"""Tests for STT serve-boundary request normalization."""
3+
4+
from __future__ import annotations
5+
6+
from collections import UserDict
7+
from types import SimpleNamespace
8+
9+
import numpy as np
10+
import pytest
11+
12+
from vllm_metal.stt.serve import STTRequestInput, VLLMSTTRequestAdapter
13+
14+
15+
class TestSTTServeRequestAdapter:
16+
"""Tests for STT serve-boundary normalization."""
17+
18+
@staticmethod
19+
def _make_request(
20+
*,
21+
req_id: str = "req-1",
22+
prompt_token_ids: list[int] | None = None,
23+
mm_features=None,
24+
) -> SimpleNamespace:
25+
return SimpleNamespace(
26+
req_id=req_id,
27+
prompt_token_ids=prompt_token_ids,
28+
mm_features=mm_features or [],
29+
)
30+
31+
def test_normalizes_multimodal_feature_spec_payload(self) -> None:
32+
mel = np.zeros((80, 3000), dtype=np.float32)
33+
field_elem = SimpleNamespace(data=mel)
34+
feature_spec = SimpleNamespace(data=UserDict({"input_features": field_elem}))
35+
36+
normalized = VLLMSTTRequestAdapter.from_vllm_request(
37+
self._make_request(prompt_token_ids=[1, 2], mm_features=[feature_spec])
38+
)
39+
40+
assert isinstance(normalized, STTRequestInput)
41+
assert normalized.req_id == "req-1"
42+
assert normalized.prompt_token_ids == (1, 2)
43+
assert normalized.input_features is mel
44+
45+
def test_rejects_empty_mm_features(self) -> None:
46+
request = self._make_request(req_id="broken-req", mm_features=[])
47+
48+
with pytest.raises(ValueError, match="broken-req"):
49+
VLLMSTTRequestAdapter.from_vllm_request(request)
50+
51+
def test_rejects_missing_input_features(self) -> None:
52+
feature_spec = SimpleNamespace(data=UserDict({"other": "value"}))
53+
request = self._make_request(req_id="broken-req", mm_features=[feature_spec])
54+
55+
with pytest.raises(ValueError, match="input_features"):
56+
VLLMSTTRequestAdapter.from_vllm_request(request)
57+
58+
def test_rejects_missing_feature_payload(self) -> None:
59+
feature_spec = SimpleNamespace(data=None)
60+
request = self._make_request(req_id="broken-req", mm_features=[feature_spec])
61+
62+
with pytest.raises(ValueError, match="input_features"):
63+
VLLMSTTRequestAdapter.from_vllm_request(request)
64+
65+
def test_rejects_wrapped_none_input_features(self) -> None:
66+
field_elem = SimpleNamespace(data=None)
67+
feature_spec = SimpleNamespace(data=UserDict({"input_features": field_elem}))
68+
69+
with pytest.raises(ValueError, match="input_features"):
70+
VLLMSTTRequestAdapter.from_vllm_request(
71+
self._make_request(req_id="broken-req", mm_features=[feature_spec])
72+
)

0 commit comments

Comments
 (0)