mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-11 03:38:38 +00:00
fix: Bedrock Converse
This commit is contained in:
parent
84d17d036d
commit
bd9ecca85f
3 changed files with 73 additions and 7 deletions
|
|
@ -45,6 +45,7 @@ class LiteLLMMessagesToCompletionTransformationHandler:
|
|||
tools: Optional[List[Dict]] = None,
|
||||
top_k: Optional[int] = None,
|
||||
top_p: Optional[float] = None,
|
||||
output_format: Optional[Dict] = None,
|
||||
extra_kwargs: Optional[Dict[str, Any]] = None,
|
||||
) -> Dict[str, Any]:
|
||||
"""Prepare kwargs for litellm.completion/acompletion"""
|
||||
|
|
@ -76,6 +77,8 @@ class LiteLLMMessagesToCompletionTransformationHandler:
|
|||
request_data["top_k"] = top_k
|
||||
if top_p is not None:
|
||||
request_data["top_p"] = top_p
|
||||
if output_format:
|
||||
request_data["output_format"] = output_format
|
||||
|
||||
openai_request = ANTHROPIC_ADAPTER.translate_completion_input_params(
|
||||
request_data
|
||||
|
|
@ -130,6 +133,7 @@ class LiteLLMMessagesToCompletionTransformationHandler:
|
|||
tools: Optional[List[Dict]] = None,
|
||||
top_k: Optional[int] = None,
|
||||
top_p: Optional[float] = None,
|
||||
output_format: Optional[Dict] = None,
|
||||
**kwargs,
|
||||
) -> Union[AnthropicMessagesResponse, AsyncIterator]:
|
||||
"""Handle non-Anthropic models asynchronously using the adapter"""
|
||||
|
|
@ -148,6 +152,7 @@ class LiteLLMMessagesToCompletionTransformationHandler:
|
|||
tools=tools,
|
||||
top_k=top_k,
|
||||
top_p=top_p,
|
||||
output_format=output_format,
|
||||
extra_kwargs=kwargs,
|
||||
)
|
||||
)
|
||||
|
|
@ -189,6 +194,7 @@ class LiteLLMMessagesToCompletionTransformationHandler:
|
|||
tools: Optional[List[Dict]] = None,
|
||||
top_k: Optional[int] = None,
|
||||
top_p: Optional[float] = None,
|
||||
output_format: Optional[Dict] = None,
|
||||
_is_async: bool = False,
|
||||
**kwargs,
|
||||
) -> Union[
|
||||
|
|
@ -212,6 +218,7 @@ class LiteLLMMessagesToCompletionTransformationHandler:
|
|||
tools=tools,
|
||||
top_k=top_k,
|
||||
top_p=top_p,
|
||||
output_format=output_format,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
|
|
@ -230,6 +237,7 @@ class LiteLLMMessagesToCompletionTransformationHandler:
|
|||
tools=tools,
|
||||
top_k=top_k,
|
||||
top_p=top_p,
|
||||
output_format=output_format,
|
||||
extra_kwargs=kwargs,
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
"""
|
||||
Which anthropic params, we need to translate to the openai format.
|
||||
"""
|
||||
return ["messages", "metadata", "system", "tool_choice", "tools", "thinking"]
|
||||
return ["messages", "metadata", "system", "tool_choice", "tools", "thinking", "output_format"]
|
||||
|
||||
def translate_anthropic_messages_to_openai( # noqa: PLR0915
|
||||
self,
|
||||
|
|
@ -554,6 +554,42 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
|
||||
return new_tools
|
||||
|
||||
def translate_anthropic_output_format_to_openai(
|
||||
self, output_format: Any
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Translate Anthropic's output_format to OpenAI's response_format.
|
||||
|
||||
Anthropic output_format: {"type": "json_schema", "schema": {...}}
|
||||
OpenAI response_format: {"type": "json_schema", "json_schema": {"name": "...", "schema": {...}}}
|
||||
|
||||
Args:
|
||||
output_format: Anthropic output_format dict with 'type' and 'schema'
|
||||
|
||||
Returns:
|
||||
OpenAI-compatible response_format dict, or None if invalid
|
||||
"""
|
||||
if not isinstance(output_format, dict):
|
||||
return None
|
||||
|
||||
output_type = output_format.get("type")
|
||||
if output_type != "json_schema":
|
||||
return None
|
||||
|
||||
schema = output_format.get("schema")
|
||||
if not schema:
|
||||
return None
|
||||
|
||||
# Convert to OpenAI response_format structure
|
||||
return {
|
||||
"type": "json_schema",
|
||||
"json_schema": {
|
||||
"name": "structured_output",
|
||||
"schema": schema,
|
||||
"strict": True,
|
||||
},
|
||||
}
|
||||
|
||||
def translate_anthropic_to_openai(
|
||||
self, anthropic_message_request: AnthropicMessagesRequest
|
||||
) -> ChatCompletionRequest:
|
||||
|
|
@ -636,6 +672,16 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
if reasoning_effort:
|
||||
new_kwargs["reasoning_effort"] = reasoning_effort
|
||||
|
||||
## CONVERT OUTPUT_FORMAT to RESPONSE_FORMAT
|
||||
if "output_format" in anthropic_message_request:
|
||||
output_format = anthropic_message_request["output_format"]
|
||||
if output_format:
|
||||
response_format = self.translate_anthropic_output_format_to_openai(
|
||||
output_format=output_format
|
||||
)
|
||||
if response_format:
|
||||
new_kwargs["response_format"] = response_format
|
||||
|
||||
translatable_params = self.translatable_anthropic_params()
|
||||
for k, v in anthropic_message_request.items():
|
||||
if k not in translatable_params: # pass remaining params as is
|
||||
|
|
|
|||
|
|
@ -107,14 +107,26 @@ class BaseAnthropicMessagesStructuredOutputTest(ABC):
|
|||
|
||||
print(f"Response: {response}")
|
||||
|
||||
# Validate response structure
|
||||
assert "content" in response
|
||||
assert len(response["content"]) > 0
|
||||
# Validate response structure - handle both dict and object responses
|
||||
if isinstance(response, dict):
|
||||
assert "content" in response
|
||||
content_list = response["content"]
|
||||
else:
|
||||
assert hasattr(response, "content")
|
||||
content_list = response.content
|
||||
|
||||
content = response["content"][0]
|
||||
assert "text" in content
|
||||
assert len(content_list) > 0
|
||||
|
||||
content = content_list[0]
|
||||
|
||||
# Handle both dict and object content blocks
|
||||
if isinstance(content, dict):
|
||||
assert "text" in content
|
||||
response_text = content["text"]
|
||||
else:
|
||||
assert hasattr(content, "text")
|
||||
response_text = content.text
|
||||
|
||||
response_text = content["text"]
|
||||
print(f"Response text: {response_text}")
|
||||
|
||||
# The response should be valid JSON
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue