Skip to content

Commit 5439e9f

Browse files
authored
fix(models): give QwenVLModel a timeout, wired to DashScope's request_timeout (#193)
1 parent 41bcc46 commit 5439e9f

2 files changed

Lines changed: 71 additions & 8 deletions

File tree

openjudge/models/qwen_vl_model.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def __init__(
4949
temperature: float = 0.1,
5050
top_p: float = 0.9,
5151
max_tokens: int = 2000,
52+
timeout: Optional[float] = None,
5253
):
5354
"""
5455
Initialize Qwen VL API client
@@ -59,6 +60,8 @@ def __init__(
5960
temperature: Sampling temperature
6061
top_p: Nucleus sampling
6162
max_tokens: Maximum tokens to generate
63+
timeout: Request timeout in seconds (defaults to the DashScope
64+
SDK's own default of 300s when not set)
6265
"""
6366
super().__init__(model=model, stream=False)
6467

@@ -72,6 +75,7 @@ def __init__(
7275
self.temperature = temperature
7376
self.top_p = top_p
7477
self.max_tokens = max_tokens
78+
self.timeout = timeout
7579

7680
# Cost tracking
7781
self._total_requests = 0
@@ -151,15 +155,22 @@ def generate(
151155
messages = self._format_messages(content, system_prompt)
152156

153157
# Call API
158+
call_kwargs: Dict[str, Any] = {
159+
"api_key": self.api_key,
160+
"model": self.model,
161+
"messages": messages,
162+
"temperature": self.temperature,
163+
"top_p": self.top_p,
164+
"max_length": self.max_tokens,
165+
}
166+
if self.timeout is not None:
167+
# DashScope reads the socket timeout from `request_timeout`;
168+
# a `timeout=` kwarg is accepted but dropped into the request
169+
# body unused, so this is not a naming choice.
170+
call_kwargs["request_timeout"] = self.timeout
171+
154172
try:
155-
response = MultiModalConversation.call(
156-
api_key=self.api_key,
157-
model=self.model,
158-
messages=messages,
159-
temperature=self.temperature,
160-
top_p=self.top_p,
161-
max_length=self.max_tokens,
162-
)
173+
response = MultiModalConversation.call(**call_kwargs)
163174

164175
self._total_requests += 1
165176

tests/models/test_qwen_vl_model.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# -*- coding: utf-8 -*-
2+
"""Unit tests for QwenVLModel."""
3+
4+
from unittest.mock import MagicMock, patch
5+
6+
import pytest
7+
8+
from openjudge.models.qwen_vl_model import QwenVLModel
9+
10+
11+
def _fake_response(text: str = "OK"):
12+
response = MagicMock()
13+
response.status_code = 200
14+
response.message = ""
15+
response.output.choices = [MagicMock()]
16+
response.output.choices[0].message.content = [{"text": text}]
17+
return response
18+
19+
20+
@pytest.mark.unit
21+
class TestQwenVLModelTimeout:
22+
"""Test cases for QwenVLModel's timeout handling."""
23+
24+
@pytest.mark.parametrize(
25+
"init_kwargs, expect_request_timeout",
26+
[
27+
({"timeout": 5.0}, 5.0),
28+
({}, None),
29+
({"timeout": None}, None),
30+
],
31+
ids=["with_timeout", "defaults", "explicit_none"],
32+
)
33+
@patch("openjudge.models.qwen_vl_model.MultiModalConversation")
34+
def test_generate_forwards_request_timeout(
35+
self,
36+
mock_conversation,
37+
init_kwargs,
38+
expect_request_timeout,
39+
):
40+
"""timeout=N must reach DashScope as request_timeout=N, never as timeout=N."""
41+
mock_conversation.call.return_value = _fake_response()
42+
43+
model = QwenVLModel(api_key="test-key", **init_kwargs)
44+
model.generate(text="hi")
45+
46+
call_kwargs = mock_conversation.call.call_args[1]
47+
assert "timeout" not in call_kwargs
48+
49+
if expect_request_timeout is None:
50+
assert "request_timeout" not in call_kwargs
51+
else:
52+
assert call_kwargs["request_timeout"] == expect_request_timeout

0 commit comments

Comments
 (0)