mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-12 08:42:18 +00:00
fix(anthropic): drop the clear_thinking edit when the reasoning budget cannot fit
When reasoning_effort maps to a budget that max_tokens cannot hold, thinking is dropped. The clear_thinking edit now goes with it on native /v1/messages and in the Rust path, unless the caller sent thinking themselves.
This commit is contained in:
parent
de22512809
commit
7bb8650140
3 changed files with 35 additions and 1 deletions
|
|
@ -250,7 +250,13 @@ fn translate_reasoning_effort(
|
|||
});
|
||||
}
|
||||
let Some(budget) = fit_budget_to_max_tokens(budget, request.params.max_tokens) else {
|
||||
return Ok(request);
|
||||
if request.params.thinking.is_some() {
|
||||
return Ok(request);
|
||||
}
|
||||
return Ok(MessagesRequest {
|
||||
params: without_thinking(request.params, context),
|
||||
..request
|
||||
});
|
||||
};
|
||||
let enabled = ThinkingConfig::enabled(budget);
|
||||
Ok(MessagesRequest {
|
||||
|
|
@ -687,6 +693,20 @@ mod tests {
|
|||
serde_json::json!({"max_tokens": 8192, "reasoning_effort": "high"}),
|
||||
true
|
||||
)]
|
||||
#[case::reasoning_effort_budget_cannot_fit(
|
||||
haiku_4_5(),
|
||||
serde_json::json!({"max_tokens": 1024, "reasoning_effort": "high"}),
|
||||
false
|
||||
)]
|
||||
#[case::caller_thinking_kept_when_budget_cannot_fit(
|
||||
haiku_4_5(),
|
||||
serde_json::json!({
|
||||
"max_tokens": 1024,
|
||||
"reasoning_effort": "high",
|
||||
"thinking": {"type": "enabled", "budget_tokens": 1000}
|
||||
}),
|
||||
true
|
||||
)]
|
||||
#[case::effort_model_drops_adaptive(opus_4_5(), claude_code_payload("high", 8192), false)]
|
||||
#[case::adaptive_model_keeps_adaptive(sonnet_4_6(), claude_code_payload("high", 8192), true)]
|
||||
#[case::non_reasoning_model(haiku_3_5(), claude_code_payload("high", 8192), false)]
|
||||
|
|
|
|||
|
|
@ -459,6 +459,8 @@ class AnthropicMessagesConfig(BaseAnthropicMessagesConfig):
|
|||
fitted_thinking: Final = AnthropicConfig.cap_thinking_budget_to_max_tokens(mapped_thinking, max_tokens)
|
||||
if fitted_thinking is None:
|
||||
verbose_logger.warning(DROP_UNFITTING_REASONING_EFFORT_WARNING, reasoning_effort, model, max_tokens)
|
||||
if "thinking" not in optional_params:
|
||||
self._drop_thinking(optional_params, model, custom_llm_provider)
|
||||
return
|
||||
|
||||
optional_params.setdefault("thinking", fitted_thinking)
|
||||
|
|
|
|||
|
|
@ -347,6 +347,18 @@ CLEAR_TOOL_USES_EDIT: Final = {"type": "clear_tool_uses_20250919"}
|
|||
[
|
||||
pytest.param("claude-sonnet-4-5", {"reasoning_effort": "none"}, False, id="reasoning-effort-none"),
|
||||
pytest.param("claude-haiku-4-5", {"reasoning_effort": "high"}, True, id="reasoning-effort-high"),
|
||||
pytest.param(
|
||||
"claude-haiku-4-5",
|
||||
{"max_tokens": 1024, "reasoning_effort": "high"},
|
||||
False,
|
||||
id="reasoning-effort-budget-cannot-fit",
|
||||
),
|
||||
pytest.param(
|
||||
"claude-haiku-4-5",
|
||||
{"max_tokens": 1024, "reasoning_effort": "high", "thinking": {"type": "enabled", "budget_tokens": 1000}},
|
||||
True,
|
||||
id="caller-thinking-kept-when-budget-cannot-fit",
|
||||
),
|
||||
pytest.param("claude-opus-4-5", _claude_code_payload(effort="high"), False, id="effort-model-drops-adaptive"),
|
||||
pytest.param("claude-sonnet-4-6", _claude_code_payload(effort="high"), True, id="adaptive-model"),
|
||||
pytest.param("claude-3-5-haiku-latest", _claude_code_payload(), False, id="non-reasoning-model"),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue