用例(User Case)
工具使用(ToolUse)
提示(Prompting)

使用不支持工具调用的模型

在本指南中,我们将构建一个不依赖任何特殊模型 API(如我们在 快速开始 中展示的工具调用)的链,而是直接提示模型来调用工具。

设置

我们需要安装以下包:

%pip install --upgrade --quiet langchain langchain-openai

并设置这些环境变量:

import getpass
import os
 
os.environ["OPENAI_API_KEY"] = getpass.getpass()
 
# If you'd like to use LangSmith, uncomment the below:
# os.environ ["LANGCHAIN_TRACING_V2"] = "true"
# os.environ ["LANGCHAIN_API_KEY"] = getpass.getpass()

创建工具

首先,我们需要创建一个要调用的工具。在本例中,我们将从函数创建一个自定义工具。有关创建自定义工具的所有细节的更多信息,请参阅 本指南。

from langchain_core.tools import tool
 
 
@tool
def multiply(first_int: int, second_int: int) -> int:
    """Multiply two integers together."""
    return first_int * second_int
print(multiply.name)
print(multiply.description)
print(multiply.args)
multiply
multiply(first_int: int, second_int: int) -> int - Multiply two integers together.
{'first_int': {'title': 'First Int', 'type': 'integer'}, 'second_int': {'title': 'Second Int', 'type': 'integer'}}
multiply.invoke({"first_int": 4, "second_int": 5})
20

创建我们的提示

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

from langchain.tools.render import render_text_description
 
rendered_tools = render_text_description([multiply])
rendered_tools
'multiply: multiply(first_int: int, second_int: int) -> int - Multiply two integers together.'
from langchain_core.prompts import ChatPromptTemplate
 
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."""
 
prompt = ChatPromptTemplate.from_messages(
    [("system", system_prompt), ("user", "{input}")]
)

添加输出解析器

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

from langchain_core.output_parsers import JsonOutputParser
from langchain_openai import ChatOpenAI
 
model = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
chain = prompt | model | JsonOutputParser()
chain.invoke({"input": "what's thirteen times 4"})
{'name': 'multiply', 'arguments': {'first_int': 13, 'second_int': 4}}

调用工具

我们可以通过将模型生成的 "arguments" 传递给它,从而在链中调用该工具:

from operator import itemgetter
 
chain = prompt | model | JsonOutputParser() | itemgetter("arguments") | multiply
chain.invoke({"input": "what's thirteen times 4"})
52

从多个工具中选择

假设我们有多个工具,希望链能够从中选择:

@tool
def add(first_int: int, second_int: int) -> int:
    "Add two integers."
    return first_int + second_int
 
 
@tool
def exponentiate(base: int, exponent: int) -> int:
    "Exponentiate the base to the exponent power."
    return base**exponent

使用函数调用,我们可以像这样做到:

如果我们想运行模型选择的工具,我们可以使用一个根据模型输出返回工具的函数来做到。具体来说,我们的函数将返回它自己的子链,该子链获取模型输出的 "arguments" 部分并将其传递给所选择的工具:

tools = [add, exponentiate, multiply]
 
 
def tool_chain(model_output):
    tool_map = {tool.name: tool for tool in tools}
    chosen_tool = tool_map[model_output["name"]]
    return itemgetter("arguments") | chosen_tool
rendered_tools = render_text_description(tools)
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."""
 
prompt = ChatPromptTemplate.from_messages(
    [("system", system_prompt), ("user", "{input}")]
)
 
chain = prompt | model | JsonOutputParser() | tool_chain
chain.invoke({"input": "what's 3 plus 1132"})
1135

返回工具输入

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

from langchain_core.runnables import RunnablePassthrough
 
chain = (
    prompt | model | JsonOutputParser() | RunnablePassthrough.assign(output=tool_chain)
)
chain.invoke({"input": "what's 3 plus 1132"})
{'name': 'add',
 'arguments': {'first_int': 3, 'second_int': 1132},
 'output': 1135}