fix(reasoning): add deepseek-v4-flash and deepseek-v4-pro to reasoning timeout floor
DeepSeek V4 models (deepseek-v4-flash, deepseek-v4-pro) emit reasoning_content in a separate delta field before final content, requiring the same 600s stale timeout floor as R1. Without this, streams hang for 30–50s with APITimeoutError on providers like opencode-go while direct calls succeed in ~3s. Fixes #60338.fix/verification-admin-route-recovery
parent
3ed7c8a8da
commit
1e16120603
|
|
@ -66,9 +66,13 @@ _REASONING_STALE_TIMEOUT_FLOORS: tuple[tuple[str, int], ...] = (
|
|||
("nemotron-3-ultra", 600),
|
||||
("nemotron-3-super", 600),
|
||||
("nemotron-3-nano", 300),
|
||||
# DeepSeek — R1 reasoning model on hosted NIM / DeepSeek direct.
|
||||
# DeepSeek — R1 and V4 reasoning models on hosted NIM / DeepSeek direct.
|
||||
# V4 series emits reasoning_content in a separate delta field before
|
||||
# final content, requiring the same extended stale timeout floor.
|
||||
("deepseek-r1", 600),
|
||||
("deepseek-reasoner", 600),
|
||||
("deepseek-v4-flash", 600),
|
||||
("deepseek-v4-pro", 600),
|
||||
# Qwen — QwQ reasoning + Qwen3 thinking variants. QwQ-32B
|
||||
# preview is the stable slug; ``qwen3`` covers the family of
|
||||
# thinking-mode Qwen3 models (qwen3-235b-a22b, qwen3-32b, etc.)
|
||||
|
|
@ -190,6 +194,10 @@ def get_reasoning_stale_timeout_floor(model: object) -> Optional[float]:
|
|||
300.0
|
||||
>>> get_reasoning_stale_timeout_floor("deepseek/deepseek-r1")
|
||||
600.0
|
||||
>>> get_reasoning_stale_timeout_floor("deepseek/deepseek-v4-flash")
|
||||
600.0
|
||||
>>> get_reasoning_stale_timeout_floor("deepseek/deepseek-v4-pro")
|
||||
600.0
|
||||
>>> get_reasoning_stale_timeout_floor("qwen/qwen3-235b-a22b-thinking")
|
||||
180.0
|
||||
>>> get_reasoning_stale_timeout_floor("x-ai/grok-4-fast-reasoning")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
"""Test get_reasoning_stale_timeout_floor for DeepSeek V4 reasoning models."""
|
||||
|
||||
from agent.reasoning_timeouts import get_reasoning_stale_timeout_floor
|
||||
|
||||
|
||||
def test_deepseek_v4_reasoning_models_have_timeout_floor():
|
||||
"""DeepSeek V4 reasoning models should have 600s timeout floor.
|
||||
|
||||
DeepSeek V4 models (deepseek-v4-flash, deepseek-v4-pro) emit
|
||||
reasoning_content in a separate delta field before final content,
|
||||
requiring the same extended stale timeout floor as R1.
|
||||
See #60338.
|
||||
"""
|
||||
# Direct model names (no aggregator prefix)
|
||||
assert get_reasoning_stale_timeout_floor("deepseek-v4-flash") == 600.0
|
||||
assert get_reasoning_stale_timeout_floor("deepseek-v4-pro") == 600.0
|
||||
|
||||
# With aggregator prefixes (common usage)
|
||||
assert get_reasoning_stale_timeout_floor("deepseek/deepseek-v4-flash") == 600.0
|
||||
assert get_reasoning_stale_timeout_floor("deepseek/deepseek-v4-pro") == 600.0
|
||||
|
||||
# With custom provider prefixes
|
||||
assert get_reasoning_stale_timeout_floor("opencode/deepseek-v4-flash") == 600.0
|
||||
assert get_reasoning_stale_timeout_floor("custom/deepseek-v4-pro") == 600.0
|
||||
|
||||
|
||||
def test_deepseek_v4_timeout_floor_matches_r1():
|
||||
"""V4 models should have the same floor as R1 (600s)."""
|
||||
v4_flash_floor = get_reasoning_stale_timeout_floor("deepseek-v4-flash")
|
||||
v4_pro_floor = get_reasoning_stale_timeout_floor("deepseek-v4-pro")
|
||||
r1_floor = get_reasoning_stale_timeout_floor("deepseek-r1")
|
||||
reasoner_floor = get_reasoning_stale_timeout_floor("deepseek-reasoner")
|
||||
|
||||
assert v4_flash_floor == v4_pro_floor == r1_floor == reasoner_floor == 600.0
|
||||
|
||||
|
||||
def test_deepseek_v4_does_not_match_non_reasoning_deepseek():
|
||||
"""Non-reasoning deepseek variants should not match V4 patterns."""
|
||||
# deepseek-chat is not a reasoning model and should not match
|
||||
# the deepseek-v4 patterns (requires start-of-slug anchor).
|
||||
assert get_reasoning_stale_timeout_floor("deepseek-chat") is None
|
||||
assert get_reasoning_stale_timeout_floor("deepseek/deepseek-chat") is None
|
||||
|
||||
# But V4 patterns should still match V4 models even with non-V4 prefixes
|
||||
assert get_reasoning_stale_timeout_floor("some-deepseek-v4-flash") is None # wrong prefix
|
||||
assert get_reasoning_stale_timeout_floor("deepseek-v4-flash-model") == 600.0 # suffix OK
|
||||
Loading…
Reference in New Issue