From 5ff8f76e1c8d5b68abce53d9c1524484e1c78d5e Mon Sep 17 00:00:00 2001 From: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com> Date: Tue, 5 Dec 2023 18:50:44 -0800 Subject: [PATCH] bind_tools --- .../langchain/langchain/chat_models/openai.py | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/libs/langchain/langchain/chat_models/openai.py b/libs/langchain/langchain/chat_models/openai.py index 74c24066cb8d2..cf0bfe3f9389f 100644 --- a/libs/langchain/langchain/chat_models/openai.py +++ b/libs/langchain/langchain/chat_models/openai.py @@ -629,6 +629,7 @@ def bind_functions( self, functions: Sequence[Union[Dict[str, Any], Type[BaseModel], Callable]], function_call: Optional[str] = None, + json_mode: bool = False, **kwargs: Any, ) -> Runnable[LanguageModelInput, BaseMessage]: """Bind functions (and other objects) to this chat model. @@ -642,6 +643,9 @@ def bind_functions( Must be the name of the single provided function or "auto" to automatically determine which function to call (if any). + json_mode: Whether to set JSON mode for the function call. + This guarantees the model will respond in valid JSON + (unless truncated). kwargs: Any additional parameters to pass to the :class:`~langchain.runnable.Runnable` constructor. """ @@ -661,7 +665,59 @@ def bind_functions( ) function_call_ = {"name": function_call} kwargs = {**kwargs, "function_call": function_call_} - return super().bind( + return self.bind( functions=formatted_functions, **kwargs, ) + + def bind_tools( + self, + tools: Sequence[Union[Dict[str, Any], Type[BaseModel], Callable]], + tool_choice: Optional[str] = None, + json_mode: bool = False, + **kwargs: Any, + ) -> Runnable[LanguageModelInput, BaseMessage]: + """Bind tools (and other objects) to this chat model. + + Args: + tools: A list of tool definitions to bind to this chat model. + Can be a dictionary, pydantic model, or callable. Pydantic + models and callables will be automatically converted to + their schema dictionary representation. + tool_choice: Which tool to require the model to call. + Must be the name of the single provided tool or + "auto" to automatically determine which tool to call + (if any). + json_mode: Whether to set JSON mode for the tool call. + This guarantees the model will respond in valid JSON + (unless truncated). + kwargs: Any additional parameters to pass to the + :class:`~langchain.runnable.Runnable` constructor. + + """ + from langchain.chains.openai_functions.base import convert_to_openai_function + + formatted_tools = [ + {"type": "function", "function": convert_to_openai_function(tool)} + for tool in tools + ] + if tool_choice is not None: + if not formatted_tools: + raise ValueError( + "When specifying `tool_choice`, you must provide at least one " + "tool." + ) + tool_names = [tool["function"]["name"] for tool in formatted_tools] + if not any(tool_name == tool_choice for tool_name in tool_names): + raise ValueError( + f"Tool choice {tool_choice} was specified, but the only " + f"provided tools were {tool_names}." + ) + tool_choice_ = {"type": "function", "function": {"name": tool_choice}} + kwargs = {**kwargs, "tool_choice": tool_choice_} + if json_mode: + kwargs = {**kwargs, "response_format": {"type": "json_object"}} + return self.bind( + tools=formatted_tools, + **kwargs, + )