multiple: enforce standards on tool_choice (#30372)

- Test if models support forcing tool calls via `tool_choice`. If they
do, they should support
  - `"any"` to specify any tool
  - the tool name as a string to force calling a particular tool
- Add `tool_choice` to signature of `BaseChatModel.bind_tools` in core
- Deprecate `tool_choice_value` in standard tests in favor of a boolean
`has_tool_choice`

Will follow up with PRs in external repos (tested in AWS and Google
already).
This commit is contained in:
ccurme
2025-03-20 13:48:59 -04:00
committed by GitHub
parent b86cd8270c
commit de3960d285
10 changed files with 190 additions and 56 deletions

View File

@@ -685,6 +685,7 @@ class ChatMistralAI(BaseChatModel):
def bind_tools(
self,
tools: Sequence[Union[Dict[str, Any], Type, Callable, BaseTool]],
tool_choice: Optional[Union[dict, str, Literal["auto", "any"]]] = None,
**kwargs: Any,
) -> Runnable[LanguageModelInput, BaseMessage]:
"""Bind tool-like objects to this chat model.
@@ -705,6 +706,22 @@ class ChatMistralAI(BaseChatModel):
"""
formatted_tools = [convert_to_openai_tool(tool) for tool in tools]
if tool_choice:
tool_names = []
for tool in formatted_tools:
if "function" in tool and (name := tool["function"].get("name")):
tool_names.append(name)
elif name := tool.get("name"):
tool_names.append(name)
else:
pass
if tool_choice in tool_names:
kwargs["tool_choice"] = {
"type": "function",
"function": {"name": tool_choice},
}
else:
kwargs["tool_choice"] = tool_choice
return super().bind(tools=formatted_tools, **kwargs)
def with_structured_output(