mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-08 03:08:45 +00:00
Merge pull request #35738 from BerriAI/litellm_bedrock_tool_choice_parallel_conflict
fix(bedrock): drop conflicting tool_choice.type when toolConfig.toolChoice is set
This commit is contained in:
commit
27885076e7
2 changed files with 87 additions and 0 deletions
|
|
@ -1213,6 +1213,20 @@ class AmazonConverseConfig(BaseConfig):
|
|||
}
|
||||
return {**additional_request_params, **merged_entries}
|
||||
|
||||
@staticmethod
|
||||
def _drop_tool_choice_type_conflicting_with_tool_config(additional_request_params: dict) -> None:
|
||||
"""Drop ``tool_choice.type`` from the Anthropic passthrough fields.
|
||||
|
||||
Converse rejects a request carrying both ``toolConfig.toolChoice`` and an
|
||||
``additionalModelRequestFields.tool_choice.type``, so once the caller asked for a
|
||||
tool choice the type has to come from ``toolChoice`` alone. Sibling keys such as
|
||||
``disable_parallel_tool_use`` have no ``toolConfig`` equivalent and are accepted
|
||||
alongside ``toolChoice``, so they stay.
|
||||
"""
|
||||
tool_choice = additional_request_params.get("tool_choice")
|
||||
if isinstance(tool_choice, dict):
|
||||
tool_choice.pop("type", None)
|
||||
|
||||
def _prepare_request_params(
|
||||
self, optional_params: dict, model: str, drop_params: bool = False
|
||||
) -> tuple[dict, dict, dict, OutputConfigBlock | None]:
|
||||
|
|
@ -1569,6 +1583,7 @@ class AmazonConverseConfig(BaseConfig):
|
|||
)
|
||||
if tool_choice_values is not None:
|
||||
bedrock_tool_config["toolChoice"] = tool_choice_values
|
||||
self._drop_tool_choice_type_conflicting_with_tool_config(additional_request_params)
|
||||
|
||||
data: Final[CommonRequestObject] = {
|
||||
"inferenceConfig": self._transform_inference_params(inference_params=inference_params),
|
||||
|
|
|
|||
|
|
@ -4263,6 +4263,78 @@ def test_parallel_tool_calls_emits_typed_auto_tool_choice(parallel_tool_calls, e
|
|||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tool_choice, expected_tool_config_choice",
|
||||
[
|
||||
("auto", {"auto": {}}),
|
||||
("required", {"any": {}}),
|
||||
({"type": "function", "function": {"name": "get_current_weather"}}, {"tool": {"name": "get_current_weather"}}),
|
||||
],
|
||||
)
|
||||
def test_parallel_tool_calls_with_explicit_tool_choice_omits_conflicting_type(tool_choice, expected_tool_config_choice):
|
||||
config = AmazonConverseConfig()
|
||||
model = "us.anthropic.claude-opus-4-8"
|
||||
messages = [{"role": "user", "content": "What's the weather in SF and NYC?"}]
|
||||
|
||||
optional_params = config.map_openai_params(
|
||||
non_default_params={"parallel_tool_calls": False, "tool_choice": tool_choice, "tools": _TOOL_PARAM},
|
||||
optional_params={},
|
||||
model=model,
|
||||
drop_params=False,
|
||||
)
|
||||
|
||||
request_data = config.transform_request(
|
||||
model=model,
|
||||
messages=messages,
|
||||
optional_params=optional_params,
|
||||
litellm_params={},
|
||||
headers={},
|
||||
)
|
||||
|
||||
assert request_data["toolConfig"]["toolChoice"] == expected_tool_config_choice
|
||||
assert request_data["additionalModelRequestFields"]["tool_choice"] == {"disable_parallel_tool_use": True}
|
||||
|
||||
|
||||
def test_tool_choice_type_kept_when_no_tool_config_choice_conflicts():
|
||||
config = AmazonConverseConfig()
|
||||
model = "us.anthropic.claude-opus-4-8"
|
||||
|
||||
optional_params = config.map_openai_params(
|
||||
non_default_params={"parallel_tool_calls": False, "tools": _TOOL_PARAM},
|
||||
optional_params={},
|
||||
model=model,
|
||||
drop_params=False,
|
||||
)
|
||||
|
||||
request_data = config.transform_request(
|
||||
model=model,
|
||||
messages=[{"role": "user", "content": "What's the weather in SF and NYC?"}],
|
||||
optional_params=optional_params,
|
||||
litellm_params={},
|
||||
headers={},
|
||||
)
|
||||
|
||||
assert "toolChoice" not in request_data["toolConfig"]
|
||||
assert request_data["additionalModelRequestFields"]["tool_choice"] == {
|
||||
"type": "auto",
|
||||
"disable_parallel_tool_use": True,
|
||||
}
|
||||
|
||||
|
||||
def test_drop_tool_choice_type_leaves_other_passthrough_fields_untouched():
|
||||
additional_request_params = {
|
||||
"tool_choice": {"type": "tool", "name": "get_weather", "disable_parallel_tool_use": True},
|
||||
"anthropic_beta": ["some-beta"],
|
||||
}
|
||||
|
||||
AmazonConverseConfig._drop_tool_choice_type_conflicting_with_tool_config(additional_request_params)
|
||||
|
||||
assert additional_request_params == {
|
||||
"tool_choice": {"name": "get_weather", "disable_parallel_tool_use": True},
|
||||
"anthropic_beta": ["some-beta"],
|
||||
}
|
||||
|
||||
|
||||
def test_parallel_tool_use_merge_preserves_user_tool_choice_type():
|
||||
merged = AmazonConverseConfig._merge_parallel_tool_use_config(
|
||||
{"tool_choice": {"type": "tool", "name": "get_weather", "disable_parallel_tool_use": False}},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue