diff --git a/litellm/llms/anthropic/chat/transformation.py b/litellm/llms/anthropic/chat/transformation.py index 0e3df4b4514..5e5b0d0ac05 100644 --- a/litellm/llms/anthropic/chat/transformation.py +++ b/litellm/llms/anthropic/chat/transformation.py @@ -240,10 +240,41 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): "minLength", "maxLength", # string constraints } + # Build description additions from removed constraints + constraint_descriptions: list = [] + constraint_labels = { + "minItems": "minimum number of items: {}", + "maxItems": "maximum number of items: {}", + "minimum": "minimum value: {}", + "maximum": "maximum value: {}", + "exclusiveMinimum": "exclusive minimum value: {}", + "exclusiveMaximum": "exclusive maximum value: {}", + "minLength": "minimum length: {}", + "maxLength": "maximum length: {}", + } + for field in unsupported_fields: + if field in schema: + constraint_descriptions.append( + constraint_labels[field].format(schema[field]) + ) + result: Dict[str, Any] = {} + + # Update description with removed constraint info + if constraint_descriptions: + existing_desc = schema.get("description", "") + constraint_note = "Note: " + ", ".join(constraint_descriptions) + "." + if existing_desc: + result["description"] = existing_desc + " " + constraint_note + else: + result["description"] = constraint_note + for key, value in schema.items(): if key in unsupported_fields: continue + if key == "description" and "description" in result: + # Already handled above + continue if key == "properties" and isinstance(value, dict): result[key] = { diff --git a/tests/litellm/llms/anthropic/test_anthropic_schema_filter.py b/tests/litellm/llms/anthropic/test_anthropic_schema_filter.py index bec4aaaf533..1bc2213b948 100644 --- a/tests/litellm/llms/anthropic/test_anthropic_schema_filter.py +++ b/tests/litellm/llms/anthropic/test_anthropic_schema_filter.py @@ -40,7 +40,13 @@ class TestFilterAnthropicOutputSchema: # Other fields preserved assert result["properties"]["age"]["type"] == "integer" - assert result["properties"]["age"]["description"] == "Person's age" + # Description should be updated with removed constraint info + assert "Person's age" in result["properties"]["age"]["description"] + assert "minimum value: 0" in result["properties"]["age"]["description"] + assert "maximum value: 150" in result["properties"]["age"]["description"] + # Score had no description, should get one from constraints + assert "exclusive minimum value: 0" in result["properties"]["score"]["description"] + assert "exclusive maximum value: 100" in result["properties"]["score"]["description"] def test_removes_string_constraints(self): """Test that minLength/maxLength are removed from string schemas.""" @@ -60,6 +66,9 @@ class TestFilterAnthropicOutputSchema: assert "minLength" not in result["properties"]["name"] assert "maxLength" not in result["properties"]["name"] assert result["properties"]["name"]["type"] == "string" + # Description should contain constraint info + assert "minimum length: 1" in result["properties"]["name"]["description"] + assert "maximum length: 100" in result["properties"]["name"]["description"] def test_removes_array_constraints(self): """Test that minItems/maxItems are removed from array schemas.""" @@ -76,6 +85,9 @@ class TestFilterAnthropicOutputSchema: assert "maxItems" not in result assert result["type"] == "array" assert result["items"] == {"type": "string"} + # Description should contain constraint info + assert "minimum number of items: 1" in result["description"] + assert "maximum number of items: 10" in result["description"] def test_handles_nested_schemas(self): """Test that nested schemas are also filtered."""