使用不支持工具调用的模型
在本指南中,我们将构建一个不依赖任何特殊模型 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_intprint(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_toolrendered_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}