Skip to content

Commit 34275ab

Browse files
committed
Revert "Merge pull request #14005 from moshemorad/bedrock_fix_structure_output"
This reverts commit 75c327c, reversing changes made to afa6871.
1 parent 48d3aad commit 34275ab

File tree

3 files changed

+9
-299
lines changed

3 files changed

+9
-299
lines changed

dist/litellm-1.57.6.tar.gz

64 Bytes
Binary file not shown.

litellm/llms/bedrock/chat/converse_transformation.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import httpx
1111

1212
import litellm
13-
from litellm.constants import RESPONSE_FORMAT_TOOL_NAME
1413
from litellm.litellm_core_utils.core_helpers import map_finish_reason
1514
from litellm.litellm_core_utils.litellm_logging import Logging
1615
from litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response import (
@@ -323,6 +322,7 @@ def _separate_computer_use_tools(
323322
def _create_json_tool_call_for_response_format(
324323
self,
325324
json_schema: Optional[dict] = None,
325+
schema_name: str = "json_tool_call",
326326
description: Optional[str] = None,
327327
) -> ChatCompletionToolParam:
328328
"""
@@ -347,7 +347,7 @@ def _create_json_tool_call_for_response_format(
347347
_input_schema = json_schema
348348

349349
tool_param_function_chunk = ChatCompletionToolParamFunctionChunk(
350-
name=RESPONSE_FORMAT_TOOL_NAME, parameters=_input_schema
350+
name=schema_name, parameters=_input_schema
351351
)
352352
if description:
353353
tool_param_function_chunk["description"] = description
@@ -391,11 +391,14 @@ def map_openai_params(
391391
continue
392392

393393
json_schema: Optional[dict] = None
394+
schema_name: str = ""
394395
description: Optional[str] = None
395396
if "response_schema" in value:
396397
json_schema = value["response_schema"]
398+
schema_name = "json_tool_call"
397399
elif "json_schema" in value:
398400
json_schema = value["json_schema"]["schema"]
401+
schema_name = value["json_schema"]["name"]
399402
description = value["json_schema"].get("description")
400403

401404
if "type" in value and value["type"] == "text":
@@ -411,6 +414,7 @@ def map_openai_params(
411414
"""
412415
_tool = self._create_json_tool_call_for_response_format(
413416
json_schema=json_schema,
417+
schema_name=schema_name if schema_name != "" else "json_tool_call",
414418
description=description,
415419
)
416420
optional_params = self._add_tools_to_optional_params(
@@ -426,7 +430,7 @@ def map_openai_params(
426430

427431
optional_params["tool_choice"] = ToolChoiceValuesBlock(
428432
tool=SpecificToolChoiceBlock(
429-
name=RESPONSE_FORMAT_TOOL_NAME
433+
name=schema_name if schema_name != "" else "json_tool_call"
430434
)
431435
)
432436
optional_params["json_mode"] = True
@@ -1115,7 +1119,8 @@ def _transform_response(
11151119
self._transform_thinking_blocks(reasoningContentBlocks)
11161120
)
11171121
chat_completion_message["content"] = content_str
1118-
if json_mode is True and tools is not None and len(tools) == 1 and tools[0]["function"]["name"] == RESPONSE_FORMAT_TOOL_NAME:
1122+
if json_mode is True and tools is not None and len(tools) == 1:
1123+
# to support 'json_schema' logic on bedrock models
11191124
json_mode_content_str: Optional[str] = tools[0]["function"].get("arguments")
11201125
if json_mode_content_str is not None:
11211126
chat_completion_message["content"] = json_mode_content_str

tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py

Lines changed: 0 additions & 295 deletions
Original file line numberDiff line numberDiff line change
@@ -475,239 +475,6 @@ def text(self):
475475
assert args["command"] == "ls -la *.py"
476476

477477

478-
def test_transform_response_with_structured_response_being_called():
479-
"""Test response transformation with structured response."""
480-
from litellm.llms.bedrock.chat.converse_transformation import AmazonConverseConfig
481-
from litellm.types.utils import ModelResponse
482-
483-
# Simulate a Bedrock Converse response with a bash tool call
484-
response_json = {
485-
"additionalModelResponseFields": {},
486-
"metrics": {"latencyMs": 100.0},
487-
"output": {
488-
"message": {
489-
"role": "assistant",
490-
"content": [
491-
{
492-
"toolUse": {
493-
"toolUseId": "tooluse_456",
494-
"name": "json_tool_call",
495-
"input": {
496-
"Current_Temperature": 62,
497-
"Weather_Explanation": "San Francisco typically has mild, cool weather year-round due to its coastal location and marine influence. The city is known for its fog, moderate temperatures, and relatively stable climate with little seasonal variation."},
498-
}
499-
}
500-
]
501-
}
502-
},
503-
"stopReason": "tool_use",
504-
"usage": {
505-
"inputTokens": 8,
506-
"outputTokens": 3,
507-
"totalTokens": 11,
508-
"cacheReadInputTokenCount": 0,
509-
"cacheReadInputTokens": 0,
510-
"cacheWriteInputTokenCount": 0,
511-
"cacheWriteInputTokens": 0,
512-
},
513-
}
514-
# Mock httpx.Response
515-
class MockResponse:
516-
def json(self):
517-
return response_json
518-
@property
519-
def text(self):
520-
return json.dumps(response_json)
521-
522-
config = AmazonConverseConfig()
523-
model_response = ModelResponse()
524-
optional_params = {
525-
"json_mode": True,
526-
"tools": [
527-
{
528-
'type': 'function',
529-
'function': {
530-
'name': 'get_weather',
531-
'description': 'Get the current weather in a given location',
532-
'parameters': {
533-
'type': 'object',
534-
'properties': {
535-
'location': {
536-
'type': 'string',
537-
'description': 'The city and state, e.g. San Francisco, CA'
538-
},
539-
'unit': {
540-
'type': 'string',
541-
'enum': ['celsius', 'fahrenheit']
542-
}
543-
},
544-
'required': ['location']
545-
}
546-
}
547-
},
548-
{
549-
'type': 'function',
550-
'function': {
551-
'name': 'json_tool_call',
552-
'parameters': {
553-
'$schema': 'http://json-schema.org/draft-07/schema#',
554-
'type': 'object',
555-
'required': ['Weather_Explanation', 'Current_Temperature'],
556-
'properties': {
557-
'Weather_Explanation': {
558-
'type': ['string', 'null'],
559-
'description': '1-2 sentences explaining the weather in the location'
560-
},
561-
'Current_Temperature': {
562-
'type': ['number', 'null'],
563-
'description': 'Current temperature in the location'
564-
}
565-
},
566-
'additionalProperties': False
567-
}
568-
}
569-
}
570-
]
571-
}
572-
# Call the transformation logic
573-
result = config._transform_response(
574-
model="bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0",
575-
response=MockResponse(),
576-
model_response=model_response,
577-
stream=False,
578-
logging_obj=None,
579-
optional_params=optional_params,
580-
api_key=None,
581-
data=None,
582-
messages=[],
583-
encoding=None,
584-
)
585-
# Check that the tool call is present in the returned message
586-
assert result.choices[0].message.tool_calls is None
587-
588-
assert result.choices[0].message.content is not None
589-
assert result.choices[0].message.content == '{"Current_Temperature": 62, "Weather_Explanation": "San Francisco typically has mild, cool weather year-round due to its coastal location and marine influence. The city is known for its fog, moderate temperatures, and relatively stable climate with little seasonal variation."}'
590-
591-
def test_transform_response_with_structured_response_calling_tool():
592-
"""Test response transformation with structured response."""
593-
from litellm.llms.bedrock.chat.converse_transformation import AmazonConverseConfig
594-
from litellm.types.utils import ModelResponse
595-
596-
# Simulate a Bedrock Converse response with a bash tool call
597-
response_json = {
598-
"metrics": {
599-
"latencyMs": 1148
600-
},
601-
"output": {
602-
"message":
603-
{
604-
"content": [
605-
{
606-
"text": "I\'ll check the current weather in San Francisco for you."
607-
},
608-
{
609-
"toolUse": {
610-
"input": {
611-
"location": "San Francisco, CA",
612-
"unit": "celsius"
613-
},
614-
"name": "get_weather",
615-
"toolUseId": "tooluse_oKk__QrqSUmufMw3Q7vGaQ"
616-
}
617-
}
618-
],
619-
"role": "assistant"
620-
}
621-
},
622-
"stopReason": "tool_use",
623-
"usage": {
624-
"cacheReadInputTokenCount": 0,
625-
"cacheReadInputTokens": 0,
626-
"cacheWriteInputTokenCount": 0,
627-
"cacheWriteInputTokens": 0,
628-
"inputTokens": 534,
629-
"outputTokens": 69,
630-
"totalTokens": 603
631-
}
632-
}
633-
# Mock httpx.Response
634-
class MockResponse:
635-
def json(self):
636-
return response_json
637-
@property
638-
def text(self):
639-
return json.dumps(response_json)
640-
641-
config = AmazonConverseConfig()
642-
model_response = ModelResponse()
643-
optional_params = {
644-
"json_mode": True,
645-
"tools": [
646-
{
647-
'type': 'function',
648-
'function': {
649-
'name': 'get_weather',
650-
'description': 'Get the current weather in a given location',
651-
'parameters': {
652-
'type': 'object',
653-
'properties': {
654-
'location': {
655-
'type': 'string',
656-
'description': 'The city and state, e.g. San Francisco, CA'
657-
},
658-
'unit': {
659-
'type': 'string',
660-
'enum': ['celsius', 'fahrenheit']
661-
}
662-
},
663-
'required': ['location']
664-
}
665-
}
666-
},
667-
{
668-
'type': 'function',
669-
'function': {
670-
'name': 'json_tool_call',
671-
'parameters': {
672-
'$schema': 'http://json-schema.org/draft-07/schema#',
673-
'type': 'object',
674-
'required': ['Weather_Explanation', 'Current_Temperature'],
675-
'properties': {
676-
'Weather_Explanation': {
677-
'type': ['string', 'null'],
678-
'description': '1-2 sentences explaining the weather in the location'
679-
},
680-
'Current_Temperature': {
681-
'type': ['number', 'null'],
682-
'description': 'Current temperature in the location'
683-
}
684-
},
685-
'additionalProperties': False
686-
}
687-
}
688-
}
689-
]
690-
}
691-
# Call the transformation logic
692-
result = config._transform_response(
693-
model="bedrock/eu.anthropic.claude-sonnet-4-20250514-v1:0",
694-
response=MockResponse(),
695-
model_response=model_response,
696-
stream=False,
697-
logging_obj=None,
698-
optional_params=optional_params,
699-
api_key=None,
700-
data=None,
701-
messages=[],
702-
encoding=None,
703-
)
704-
# Check that the tool call is present in the returned message
705-
assert result.choices[0].message.tool_calls is not None
706-
assert len(result.choices[0].message.tool_calls) == 1
707-
assert result.choices[0].message.tool_calls[0].function.name == "get_weather"
708-
assert result.choices[0].message.tool_calls[0].function.arguments == '{"location": "San Francisco, CA", "unit": "celsius"}'
709-
710-
711478
@pytest.mark.asyncio
712479
async def test_bedrock_bash_tool_acompletion():
713480
"""Test Bedrock with bash tool for ls command using acompletion."""
@@ -1171,68 +938,6 @@ def test_transform_request_with_function_tool():
1171938
assert request_data["toolConfig"]["tools"][0]["toolSpec"]["name"] == "get_weather"
1172939

1173940

1174-
def test_map_openai_params_with_response_format():
1175-
"""Test map_openai_params with response_format."""
1176-
config = AmazonConverseConfig()
1177-
1178-
tools = [
1179-
{
1180-
"type": "function",
1181-
"function": {
1182-
"name": "get_weather",
1183-
"description": "Get the current weather in a given location",
1184-
"parameters": {
1185-
"type": "object",
1186-
"properties": {
1187-
"location": {
1188-
"type": "string",
1189-
"description": "The city and state, e.g. San Francisco, CA",
1190-
},
1191-
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
1192-
},
1193-
"required": ["location"],
1194-
},
1195-
}
1196-
}
1197-
]
1198-
1199-
json_schema = {
1200-
"type": "json_schema",
1201-
"json_schema": {
1202-
"name": "WeatherResult",
1203-
"schema": {
1204-
"$schema": "http://json-schema.org/draft-07/schema#",
1205-
"type": "object",
1206-
"required": ["Weather_Explanation", "Current_Temperature"],
1207-
"properties": {
1208-
"Weather_Explanation": {
1209-
"type": ["string", "null"],
1210-
"description": "1-2 sentences explaining the weather in the location",
1211-
},
1212-
"Current_Temperature": {
1213-
"type": ["number", "null"],
1214-
"description": "Current temperature in the location",
1215-
},
1216-
},
1217-
"additionalProperties": False,
1218-
},
1219-
"strict": False,
1220-
},
1221-
}
1222-
1223-
optional_params = config.map_openai_params(
1224-
non_default_params={"response_format": json_schema},
1225-
optional_params={"tools": tools},
1226-
model="eu.anthropic.claude-sonnet-4-20250514-v1:0",
1227-
drop_params=False
1228-
)
1229-
1230-
assert "tools" in optional_params
1231-
assert len(optional_params["tools"]) == 2
1232-
assert optional_params["tools"][1]["type"] == "function"
1233-
assert optional_params["tools"][1]["function"]["name"] == "json_tool_call"
1234-
1235-
1236941
@pytest.mark.asyncio
1237942
async def test_assistant_message_cache_control():
1238943
"""Test that assistant messages with cache_control generate cachePoint blocks."""

0 commit comments

Comments
 (0)