mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
fix(bedrock): handle definitions keyword and schemaless json_object in native structured outputs
- Add `definitions` handling alongside `$defs` in schema normalization
(older JSON Schema drafts use `definitions` instead of `$defs`)
- Fall back to tool-call approach when `response_format: {type: json_object}`
has no explicit schema, since the native API requires one
- Add tests for both cases
This commit is contained in:
parent
212906118a
commit
da8c1bd111
2 changed files with 61 additions and 7 deletions
|
|
@ -757,11 +757,12 @@ class AmazonConverseConfig(BaseConfig):
|
|||
result["items"] = AmazonConverseConfig._add_additional_properties_to_schema(
|
||||
result["items"]
|
||||
)
|
||||
if "$defs" in result and isinstance(result["$defs"], dict):
|
||||
result["$defs"] = {
|
||||
k: AmazonConverseConfig._add_additional_properties_to_schema(v)
|
||||
for k, v in result["$defs"].items()
|
||||
}
|
||||
for defs_key in ("$defs", "definitions"):
|
||||
if defs_key in result and isinstance(result[defs_key], dict):
|
||||
result[defs_key] = {
|
||||
k: AmazonConverseConfig._add_additional_properties_to_schema(v)
|
||||
for k, v in result[defs_key].items()
|
||||
}
|
||||
for key in ("anyOf", "allOf", "oneOf"):
|
||||
if key in result and isinstance(result[key], list):
|
||||
result[key] = [
|
||||
|
|
@ -955,9 +956,11 @@ class AmazonConverseConfig(BaseConfig):
|
|||
if "type" in value and value["type"] == "text":
|
||||
return optional_params
|
||||
|
||||
if self._supports_native_structured_outputs(model):
|
||||
if self._supports_native_structured_outputs(model) and json_schema is not None:
|
||||
# Use Bedrock's native structured outputs API (outputConfig.textFormat)
|
||||
# No synthetic tool injection, no fake_stream needed
|
||||
# No synthetic tool injection, no fake_stream needed.
|
||||
# Requires an explicit schema — json_object with no schema falls through
|
||||
# to the tool-call path below.
|
||||
output_config = self._create_output_config_for_response_format(
|
||||
json_schema=json_schema,
|
||||
name=name,
|
||||
|
|
|
|||
|
|
@ -3308,6 +3308,57 @@ def test_add_additional_properties_non_object():
|
|||
assert result == {"type": "string"}
|
||||
|
||||
|
||||
def test_add_additional_properties_definitions():
|
||||
"""Recursively processes object types inside 'definitions' (not just '$defs')."""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"item": {"$ref": "#/definitions/Item"},
|
||||
},
|
||||
"definitions": {
|
||||
"Item": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string"},
|
||||
"details": {
|
||||
"type": "object",
|
||||
"properties": {"weight": {"type": "number"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
result = AmazonConverseConfig._add_additional_properties_to_schema(schema)
|
||||
# Top-level
|
||||
assert result["additionalProperties"] is False
|
||||
# definitions object
|
||||
assert result["definitions"]["Item"]["additionalProperties"] is False
|
||||
# Nested object inside definitions
|
||||
assert result["definitions"]["Item"]["properties"]["details"]["additionalProperties"] is False
|
||||
|
||||
|
||||
def test_json_object_no_schema_falls_back_to_tool_call():
|
||||
"""response_format: {type: json_object} with no schema should use tool-call fallback,
|
||||
even for models that support native structured outputs."""
|
||||
config = AmazonConverseConfig()
|
||||
optional_params: dict = {}
|
||||
non_default_params = {"response_format": {"type": "json_object"}}
|
||||
|
||||
result = config._translate_response_format_param(
|
||||
value=non_default_params["response_format"],
|
||||
model="anthropic.claude-sonnet-4-5-20250929-v1:0",
|
||||
optional_params=optional_params,
|
||||
non_default_params=non_default_params,
|
||||
is_thinking_enabled=False,
|
||||
)
|
||||
|
||||
# Should NOT use native outputConfig (no schema provided)
|
||||
assert "outputConfig" not in result
|
||||
# Should use tool-call fallback
|
||||
assert "tools" in result
|
||||
assert result["json_mode"] is True
|
||||
|
||||
|
||||
def test_output_config_applies_additional_properties():
|
||||
"""_create_output_config_for_response_format normalizes the schema."""
|
||||
schema = {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue