Skip to main content
Open In Colab在 GitHub 上打开

如何向 LLM 和聊天模型添加临时工具调用功能

谨慎

某些模型已针对工具调用进行了微调,并为工具调用提供了专用 API。通常,此类模型比非微调模型更擅长工具调用,建议用于需要工具调用的用例。请参阅 如何使用聊天模型调用工具 指南以了解更多信息。

先决条件

本指南假定您熟悉以下概念:

在本指南中,我们将了解如何向聊天模型添加临时工具调用支持。如果您使用的是本身不支持工具调用的模型,则这是调用工具的替代方法。

我们将通过简单地编写一个提示来做到这一点,该提示将使模型调用适当的工具。下面是一个逻辑图:

链

设置

我们需要安装以下包:

%pip install --upgrade --quiet langchain langchain-community

如果您想使用 LangSmith,请取消以下注释:

import getpass
import os
# os.environ["LANGSMITH_TRACING"] = "true"
# os.environ["LANGSMITH_API_KEY"] = getpass.getpass()

您可以为本操作指南选择任何给定的模型。请记住,这些模型中的大多数已经支持本机工具调用,因此使用此处显示的提示策略对这些模型没有意义,相反,您应该遵循如何使用聊天模型调用工具指南。

pip install -qU "langchain[openai]"
import getpass
import os

if not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter API key for OpenAI: ")

from langchain.chat_models import init_chat_model

model = init_chat_model("gpt-4", model_provider="openai")

为了说明这个想法,我们将使用phi3通过 Ollama,它没有对工具调用的本机支持。如果您想使用Ollama以及按照这些说明进行作。

from langchain_community.llms import Ollama

model = Ollama(model="phi3")
API 参考:Ollama

创建工具

首先,让我们创建一个addmultiply工具。有关创建自定义工具的更多信息,请参阅本指南

from langchain_core.tools import tool


@tool
def multiply(x: float, y: float) -> float:
"""Multiply two numbers together."""
return x * y


@tool
def add(x: int, y: int) -> int:
"Add two numbers."
return x + y


tools = [multiply, add]

# Let's inspect the tools
for t in tools:
print("--")
print(t.name)
print(t.description)
print(t.args)
API 参考:工具
--
multiply
Multiply two numbers together.
{'x': {'title': 'X', 'type': 'number'}, 'y': {'title': 'Y', 'type': 'number'}}
--
add
Add two numbers.
{'x': {'title': 'X', 'type': 'integer'}, 'y': {'title': 'Y', 'type': 'integer'}}
multiply.invoke({"x": 4, "y": 5})
20.0

创建我们的提示

我们需要编写一个提示,指定模型可以访问的工具、这些工具的参数以及模型所需的输出格式。在本例中,我们将指示它输出以下格式的 JSON blob{"name": "...", "arguments": {...}}.

from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import render_text_description

rendered_tools = render_text_description(tools)
print(rendered_tools)
multiply(x: float, y: float) -> float - Multiply two numbers together.
add(x: int, y: int) -> int - Add two numbers.
system_prompt = f"""\
You are an assistant that has access to the following set of tools.
Here are the names and descriptions for each tool:

{rendered_tools}

Given the user input, return the name and input of the tool to use.
Return your response as a JSON blob with 'name' and 'arguments' keys.

The `arguments` should be a dictionary, with keys corresponding
to the argument names and the values corresponding to the requested values.
"""

prompt = ChatPromptTemplate.from_messages(
[("system", system_prompt), ("user", "{input}")]
)
chain = prompt | model
message = chain.invoke({"input": "what's 3 plus 1132"})

# Let's take a look at the output from the model
# if the model is an LLM (not a chat model), the output will be a string.
if isinstance(message, str):
print(message)
else: # Otherwise it's a chat model
print(message.content)
{
"name": "add",
"arguments": {
"x": 3,
"y": 1132
}
}

添加输出解析器

我们将使用JsonOutputParser用于将我们的模型输出解析为 JSON。

from langchain_core.output_parsers import JsonOutputParser

chain = prompt | model | JsonOutputParser()
chain.invoke({"input": "what's thirteen times 4"})
API 参考:JsonOutputParser
{'name': 'multiply', 'arguments': {'x': 13.0, 'y': 4.0}}
重要

🎉 了不起!🎉 现在,我们指示我们的模型如何请求调用工具。

现在,让我们创建一些逻辑来实际运行该工具!

调用工具 🏃

现在模型可以请求调用工具,我们需要编写一个可以实际调用 工具。

该函数将按名称选择适当的工具,并将模型选择的参数传递给它。

from typing import Any, Dict, Optional, TypedDict

from langchain_core.runnables import RunnableConfig


class ToolCallRequest(TypedDict):
"""A typed dict that shows the inputs into the invoke_tool function."""

name: str
arguments: Dict[str, Any]


def invoke_tool(
tool_call_request: ToolCallRequest, config: Optional[RunnableConfig] = None
):
"""A function that we can use the perform a tool invocation.

Args:
tool_call_request: a dict that contains the keys name and arguments.
The name must match the name of a tool that exists.
The arguments are the arguments to that tool.
config: This is configuration information that LangChain uses that contains
things like callbacks, metadata, etc.See LCEL documentation about RunnableConfig.

Returns:
output from the requested tool
"""
tool_name_to_tool = {tool.name: tool for tool in tools}
name = tool_call_request["name"]
requested_tool = tool_name_to_tool[name]
return requested_tool.invoke(tool_call_request["arguments"], config=config)
API 参考:RunnableConfig

让我们来测试一下🧪!

invoke_tool({"name": "multiply", "arguments": {"x": 3, "y": 5}})
15.0

让我们把它放在一起

让我们把它放在一个链中,创建一个具有加法和乘法功能的计算器。

chain = prompt | model | JsonOutputParser() | invoke_tool
chain.invoke({"input": "what's thirteen times 4.14137281"})
53.83784653

返回工具输入

不仅返回工具输出,还返回工具输入,这会很有帮助。我们可以通过 LCEL 轻松做到这一点RunnablePassthrough.assign- 工具输出。这将获取 RunnablePassrthrough 组件(假设为字典)的任何输入,并向其添加一个键,同时仍然传递当前输入中的所有内容:

from langchain_core.runnables import RunnablePassthrough

chain = (
prompt | model | JsonOutputParser() | RunnablePassthrough.assign(output=invoke_tool)
)
chain.invoke({"input": "what's thirteen times 4.14137281"})
API 参考:RunnablePassthrough
{'name': 'multiply',
'arguments': {'x': 13, 'y': 4.14137281},
'output': 53.83784653}

下一步是什么?

本操作指南显示了模型正确输出所有必需工具信息时的“快乐路径”。

实际上,如果您使用的是更复杂的工具,您将开始遇到来自模型的错误,尤其是对于尚未针对工具调用进行微调的模型和功能较差的模型。

您需要准备好添加策略以提高模型的输出;例如,

  1. 提供一些拍摄示例。
  2. 添加错误处理(例如,捕获异常并将其反馈给 LLM,要求它更正之前的输出)。