mirror of
https://github.com/usestrix/strix.git
synced 2026-08-16 09:26:39 +02:00
feat(config): accept STRIX_REASONING_EFFORT=max for providers that support it (#956)
Co-authored-by: Ahmed Allam <allam@usestrix.com>
This commit is contained in:
co-authored by
Ahmed Allam
parent
22d668d538
commit
2e7040240d
@@ -36,7 +36,7 @@ Configure Strix using environment variables or a config file.
|
|||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField path="STRIX_REASONING_EFFORT" default="high" type="string">
|
<ParamField path="STRIX_REASONING_EFFORT" default="high" type="string">
|
||||||
Control thinking effort for reasoning models. Valid values: `none`, `minimal`, `low`, `medium`, `high`, `xhigh`. Defaults to `medium` for quick scan mode.
|
Control thinking effort for reasoning models. Valid values: `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`. Defaults to `medium` for quick scan mode.
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
<ParamField path="STRIX_MEMORY_COMPRESSOR_TIMEOUT" default="30" type="integer">
|
<ParamField path="STRIX_MEMORY_COMPRESSOR_TIMEOUT" default="30" type="integer">
|
||||||
|
|||||||
@@ -83,10 +83,13 @@ class _CodexResponsesModel(OpenAIResponsesModel):
|
|||||||
effort = self._reasoning_effort
|
effort = self._reasoning_effort
|
||||||
if effort and effort != "none":
|
if effort and effort != "none":
|
||||||
# Clamp to efforts the backend accepts.
|
# Clamp to efforts the backend accepts.
|
||||||
if effort == "minimal":
|
match effort:
|
||||||
effort = "low"
|
case "minimal":
|
||||||
elif effort == "xhigh":
|
effort = "low"
|
||||||
effort = "high"
|
case "xhigh" | "max":
|
||||||
|
effort = "high"
|
||||||
|
case _:
|
||||||
|
pass
|
||||||
overrides = overrides.resolve(ModelSettings(reasoning=Reasoning(effort=effort)))
|
overrides = overrides.resolve(ModelSettings(reasoning=Reasoning(effort=effort)))
|
||||||
return model_settings.resolve(overrides)
|
return model_settings.resolve(overrides)
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from pydantic import AliasChoices, Field
|
|||||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
|
|
||||||
|
|
||||||
ReasoningEffort = Literal["none", "minimal", "low", "medium", "high", "xhigh"]
|
ReasoningEffort = Literal["none", "minimal", "low", "medium", "high", "xhigh", "max"]
|
||||||
|
|
||||||
_BASE_CONFIG = SettingsConfigDict(
|
_BASE_CONFIG = SettingsConfigDict(
|
||||||
case_sensitive=False,
|
case_sensitive=False,
|
||||||
|
|||||||
+17
-1
@@ -147,7 +147,7 @@ def make_model_settings(
|
|||||||
and model_supports_reasoning(model_name)
|
and model_supports_reasoning(model_name)
|
||||||
):
|
):
|
||||||
model_settings = model_settings.resolve(
|
model_settings = model_settings.resolve(
|
||||||
ModelSettings(reasoning=Reasoning(effort=reasoning_effort)),
|
_reasoning_settings(reasoning_effort, model_settings.extra_args),
|
||||||
)
|
)
|
||||||
if force_required_tool_choice and _accepts_required_tool_choice(model_name):
|
if force_required_tool_choice and _accepts_required_tool_choice(model_name):
|
||||||
model_settings = model_settings.resolve(ModelSettings(tool_choice="required"))
|
model_settings = model_settings.resolve(ModelSettings(tool_choice="required"))
|
||||||
@@ -162,6 +162,22 @@ def make_model_settings(
|
|||||||
return model_settings
|
return model_settings
|
||||||
|
|
||||||
|
|
||||||
|
def _reasoning_settings(
|
||||||
|
effort: ReasoningEffort,
|
||||||
|
extra_args: dict[str, Any] | None,
|
||||||
|
) -> ModelSettings:
|
||||||
|
"""``max`` is not in the OpenAI SDK's ``Reasoning.effort`` enum, so send it as
|
||||||
|
a raw body field instead — also keeping it clear of LiteLLM's DeepSeek mapping,
|
||||||
|
which collapses every ``reasoning_effort`` level to plain thinking-enabled.
|
||||||
|
Providers that don't support ``max`` reject the request.
|
||||||
|
"""
|
||||||
|
if effort != "max":
|
||||||
|
return ModelSettings(reasoning=Reasoning(effort=effort))
|
||||||
|
return ModelSettings(
|
||||||
|
extra_args={**(extra_args or {}), "extra_body": {"reasoning_effort": "max"}},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _prompt_cache_extra_args(model_name: str) -> dict[str, Any] | None:
|
def _prompt_cache_extra_args(model_name: str) -> dict[str, Any] | None:
|
||||||
"""LiteLLM ``cache_control_injection_points`` for Claude prompt caching.
|
"""LiteLLM ``cache_control_injection_points`` for Claude prompt caching.
|
||||||
|
|
||||||
|
|||||||
@@ -171,8 +171,8 @@ def validate_environment() -> None:
|
|||||||
error_text.append("• ", style="white")
|
error_text.append("• ", style="white")
|
||||||
error_text.append("STRIX_REASONING_EFFORT", style="bold cyan")
|
error_text.append("STRIX_REASONING_EFFORT", style="bold cyan")
|
||||||
error_text.append(
|
error_text.append(
|
||||||
" - Reasoning effort level: none, minimal, low, medium, high, xhigh "
|
" - Reasoning effort level: none, minimal, low, medium, high, xhigh, "
|
||||||
"(default: high)\n",
|
"max (default: high)\n",
|
||||||
style="white",
|
style="white",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -129,6 +129,17 @@ def test_prompt_cache_kept_for_non_bedrock_claude_even_if_unmapped(monkeypatch:
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_max_reasoning_effort_sent_as_raw_body_field() -> None:
|
||||||
|
# "max" is absent from the OpenAI SDK's Reasoning enum, and LiteLLM's DeepSeek
|
||||||
|
# mapping collapses every effort to thinking-enabled, so it has to ride along
|
||||||
|
# as a raw body field to reach the provider.
|
||||||
|
settings = make_model_settings(
|
||||||
|
"max", model_name="deepseek/deepseek-v4-flash", request_timeout=30
|
||||||
|
)
|
||||||
|
assert settings.reasoning is None
|
||||||
|
assert settings.extra_args == {"timeout": 30, "extra_body": {"reasoning_effort": "max"}}
|
||||||
|
|
||||||
|
|
||||||
def test_conversation_tail_breakpoint_moves_with_appended_transcript() -> None:
|
def test_conversation_tail_breakpoint_moves_with_appended_transcript() -> None:
|
||||||
# LiteLLM must place the index=-1 cache_control on the last message however
|
# LiteLLM must place the index=-1 cache_control on the last message however
|
||||||
# long the transcript grows.
|
# long the transcript grows.
|
||||||
|
|||||||
Reference in New Issue
Block a user