mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-11 22:51:28 +00:00
Merge pull request #21598 from jtsaw/fix/anthropic-sonnet-4-6-reasoning-effort
support reasoning and effort parameters on sonnet 4.6
This commit is contained in:
commit
b405f64688
2 changed files with 285 additions and 222 deletions
|
|
@ -171,9 +171,22 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
return tool_call
|
||||
|
||||
@staticmethod
|
||||
def _is_claude_opus_4_6(model: str) -> bool:
|
||||
"""Check if the model is Claude Opus 4.5 or Sonnet 4.6."""
|
||||
return "opus-4-6" in model.lower() or "opus_4_6" in model.lower() or "sonnet-4-6" in model.lower() or "sonnet_4_6" in model.lower() or "sonnet-4.6" in model.lower()
|
||||
def _is_claude_4_6_model(model: str) -> bool:
|
||||
"""Check if the model is a Claude 4.6 model that uses adaptive thinking."""
|
||||
model_lower = model.lower()
|
||||
return any(
|
||||
model_variant in model_lower
|
||||
for model_variant in (
|
||||
"opus-4-6",
|
||||
"opus_4_6",
|
||||
"opus-4.6",
|
||||
"opus_4.6",
|
||||
"sonnet-4-6",
|
||||
"sonnet_4_6",
|
||||
"sonnet-4.6",
|
||||
"sonnet_4.6",
|
||||
)
|
||||
)
|
||||
|
||||
def get_supported_openai_params(self, model: str):
|
||||
params = [
|
||||
|
|
@ -194,9 +207,13 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
"context_management",
|
||||
]
|
||||
|
||||
if "claude-3-7-sonnet" in model or supports_reasoning(
|
||||
model=model,
|
||||
custom_llm_provider=self.custom_llm_provider,
|
||||
if (
|
||||
"claude-3-7-sonnet" in model
|
||||
or AnthropicConfig._is_claude_4_6_model(model)
|
||||
or supports_reasoning(
|
||||
model=model,
|
||||
custom_llm_provider=self.custom_llm_provider,
|
||||
)
|
||||
):
|
||||
params.append("thinking")
|
||||
params.append("reasoning_effort")
|
||||
|
|
@ -207,27 +224,26 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
def filter_anthropic_output_schema(schema: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
Filter out unsupported fields from JSON schema for Anthropic's output_format API.
|
||||
|
||||
|
||||
Anthropic's output_format doesn't support certain JSON schema properties:
|
||||
- maxItems/minItems: Not supported for array types
|
||||
- minimum/maximum: Not supported for numeric types
|
||||
- minLength/maxLength: Not supported for string types
|
||||
|
||||
|
||||
This mirrors the transformation done by the Anthropic Python SDK.
|
||||
See: https://platform.claude.com/docs/en/build-with-claude/structured-outputs#how-sdk-transformation-works
|
||||
|
||||
|
||||
The SDK approach:
|
||||
1. Remove unsupported constraints from schema
|
||||
2. Add constraint info to description (e.g., "Must be at least 100")
|
||||
3. Validate responses against original schema
|
||||
|
||||
Args:
|
||||
schema: The JSON schema dictionary to filter
|
||||
|
||||
|
||||
Returns:
|
||||
A new dictionary with unsupported fields removed and descriptions updated
|
||||
|
||||
Related issues:
|
||||
|
||||
Related issues:
|
||||
- https://github.com/BerriAI/litellm/issues/19444
|
||||
"""
|
||||
if not isinstance(schema, dict):
|
||||
|
|
@ -236,7 +252,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
# All numeric/string/array constraints not supported by Anthropic
|
||||
unsupported_fields = {
|
||||
"maxItems", "minItems", # array constraints
|
||||
"minimum", "maximum", # numeric constraints
|
||||
"minimum", "maximum", # numeric constraints
|
||||
"exclusiveMinimum", "exclusiveMaximum", # numeric constraints
|
||||
"minLength", "maxLength", # string constraints
|
||||
}
|
||||
|
|
@ -706,12 +722,12 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
|
||||
@staticmethod
|
||||
def _map_reasoning_effort(
|
||||
reasoning_effort: Optional[Union[REASONING_EFFORT, str]],
|
||||
reasoning_effort: Optional[Union[REASONING_EFFORT, str]],
|
||||
model: str,
|
||||
) -> Optional[AnthropicThinkingParam]:
|
||||
if reasoning_effort is None or reasoning_effort == "none":
|
||||
return None
|
||||
if AnthropicConfig._is_claude_opus_4_6(model):
|
||||
if AnthropicConfig._is_claude_4_6_model(model):
|
||||
return AnthropicThinkingParam(
|
||||
type="adaptive",
|
||||
)
|
||||
|
|
@ -759,10 +775,10 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
)
|
||||
if json_schema is None:
|
||||
return None
|
||||
|
||||
|
||||
# Filter out unsupported fields for Anthropic's output_format API
|
||||
filtered_schema = self.filter_anthropic_output_schema(json_schema)
|
||||
|
||||
|
||||
return AnthropicOutputSchema(
|
||||
type="json_schema",
|
||||
schema=filtered_schema,
|
||||
|
|
@ -1140,7 +1156,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
"""
|
||||
Ensure a beta header value is present in the anthropic-beta header.
|
||||
Merges with existing values instead of overriding them.
|
||||
|
||||
|
||||
Args:
|
||||
headers: Dictionary of headers to update
|
||||
beta_value: The beta header value to add
|
||||
|
|
@ -1196,7 +1212,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
self, headers: dict, optional_params: dict
|
||||
) -> dict:
|
||||
"""Update headers with optional anthropic beta."""
|
||||
|
||||
|
||||
# Skip adding beta headers for Vertex requests
|
||||
# Vertex AI handles these headers differently
|
||||
is_vertex_request = optional_params.get("is_vertex_request", False)
|
||||
|
|
@ -1357,9 +1373,9 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
raise ValueError(
|
||||
f"Invalid effort value: {effort}. Must be one of: 'high', 'medium', 'low', 'max'"
|
||||
)
|
||||
if effort == "max" and not self._is_claude_opus_4_6(model):
|
||||
if effort == "max" and not self._is_claude_4_6_model(model):
|
||||
raise ValueError(
|
||||
f"effort='max' is only supported by Claude Opus 4.6. Got model: {model}"
|
||||
f"effort='max' is only supported by Claude 4.6 models (Opus 4.6, Sonnet 4.6). Got model: {model}"
|
||||
)
|
||||
data["output_config"] = output_config
|
||||
|
||||
|
|
@ -1435,7 +1451,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
elif content["type"] == "web_fetch_tool_result":
|
||||
if web_search_results is None:
|
||||
web_search_results = []
|
||||
web_search_results.append(content)
|
||||
web_search_results.append(content)
|
||||
else:
|
||||
# All other tool results (bash_code_execution_tool_result, text_editor_code_execution_tool_result, etc.)
|
||||
if tool_results is None:
|
||||
|
|
@ -1452,7 +1468,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
thinking_blocks.append(
|
||||
cast(ChatCompletionRedactedThinkingBlock, content)
|
||||
)
|
||||
|
||||
|
||||
## COMPACTION
|
||||
elif content["type"] == "compaction":
|
||||
if compaction_blocks is None:
|
||||
|
|
@ -1660,7 +1676,7 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
provider_specific_fields["container"] = container
|
||||
if compaction_blocks is not None:
|
||||
provider_specific_fields["compaction_blocks"] = compaction_blocks
|
||||
|
||||
|
||||
_message = litellm.Message(
|
||||
tool_calls=tool_calls,
|
||||
content=text_content or None,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue