category
TLDR:我们在AIMessage上引入了一个新的tool_calls属性。越来越多的LLM提供程序正在公开API用于可靠的工具调用。新属性的目标是提供一个用于与工具调用交互的标准接口。这是完全向后兼容的,并且在所有支持本机工具调用的模型上都受支持。为了访问这些最新功能,您需要升级langchain_core和合作伙伴包的版本。
Python:
- List of chat models that shows status of tool calling capability
- Tool calling explains the new tool calling interface
- Tool calling agent shows how to create an agent that uses the standardized tool calling interface
- LangGraph notebook shows how to create a LangGraph agent that uses the standardized tool calling interface
JS:
- List of chat models that shows status of tool calling capability
- Tool calling explains the new tool calling interface
- Tool calling agent shows how to create an agent that uses the standardized tool calling interface
简介
大型语言模型(LLM)可以通过工具调用功能与外部数据源进行交互。工具调用是一种强大的技术,它允许开发人员构建复杂的应用程序,这些应用程序可以利用LLM访问、交互和操作数据库、文件和API等外部资源。
提供商一直在将本机工具调用功能引入到他们的模型中。在实践中,当LLM为提示提供自动完成时,除了纯文本之外,它还可以返回工具调用列表。大约一年前,OpenAI率先发布了“函数调用”,并于11月迅速演变为“工具调用”。从那时起,其他模型提供商也纷纷效仿:Gemini(12月)、Mistral(2月)、Fireworks(3月)、Together(3月。
所有这些提供商都暴露了略有不同的接口(特别是:OpenAI、Anthropic和Gemini,这三种性能最高的模型是不兼容的)。我们听到社区希望为工具调用提供一个标准化的接口,以便在这些提供者之间轻松切换,我们很高兴今天发布。
标准接口包括:
- ChatModel.bind_tools():一种将工具定义附加到模型调用的方法。
- AIMessage.tool_calls:从模型返回的AIMessage上的一个属性,用于轻松访问模型决定进行的工具调用。
- create_tool_calling_agent():一个代理构造函数,用于实现bind_tools并返回tool_calls的ANY模型。
让我们来看看这些组件中的每一个。
ChatModel.bind_tools(...)
为了允许模型使用工具,我们需要告诉它哪些工具是可用的。我们通过指定将工具定义列表传递给模型来实现这一点,其中包括工具参数的模式。工具定义的确切格式取决于模型提供者——OpenAI需要一个带有“name”、“description”和“parameters”键的字典,而Anthropic需要“name”和“description和”input_schema“。
ChatModel.bind_tools提供了一个由所有工具调用模型实现的标准接口,允许您指定哪些工具可用于模型。您不仅可以传入原始工具定义(dict),还可以传入可以派生工具定义的对象:即Pydantic类、LangChain工具和任意函数。这使得创建可用于任何工具调用模型的通用工具定义变得容易:
from langchain_anthropic import ChatAnthropic
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_core.tools import tool
# ✅ Pydantic class
class multiply(BaseModel):
"""Return product of 'x' and 'y'."""
x: float = Field(..., description="First factor")
y: float = Field(..., description="Second factor")
# ✅ LangChain tool
@tool
def exponentiate(x: float, y: float) -> float:
"""Raise 'x' to the 'y'."""
return x**y
# ✅ Function
def subtract(x: float, y: float) -> float:
"""Subtract 'x' from 'y'."""
return y-x
# ✅ OpenAI-format dict
# Could also pass in a JSON schema with "title" and "description"
add = {
"name": "add",
"description": "Add 'x' and 'y'.",
"parameters": {
"type": "object",
"properties": {
"x": {"type": "number", "description": "First number to add"},
"y": {"type": "number", "description": "Second number to add"}
},
"required": ["x", "y"]
}
}
llm = ChatAnthropic(model="claude-3-sonnet-20240229", temperature=0)
# Whenever we invoke `llm_with_tool`, all three of these tool definitions
# are passed to the model.
llm_with_tools = llm.bind_tools([multiply, exponentiate, add, subtract])
如果我们想使用不同的工具调用模型,我们的代码看起来会非常相似:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4-turbo", temperature=0)
llm_with_tools = llm.bind_tools([multiply, exponentiate, add, subtract])
那么,调用llm_with_tools会是什么样子呢?这就是AIMessage.tool_calls的用武之地。
AIMessage.tool_calls
在使用工具调用模型之前,模型返回的任何工具调用都可以在AIMessage.additional_kwargs或AIMessage.content中找到,具体取决于模型提供程序的API,并遵循特定于提供程序的格式。也就是说,您需要自定义逻辑来从不同模型的输出中提取工具调用。现在,AIMessage.tool_calls为获取模型工具调用提供了一个标准化接口。因此,在使用绑定工具调用模型后,您将获得以下表单的输出:
llm_with_tools.invoke([
("system", "You're a helpful assistant"),
("human", "what's 5 raised to the 2.743"),
])
# 👀 Notice the tool_calls attribute 👀
# -> AIMessage(
# content=...,
# additional_kwargs={...},
# tool_calls=[{'name': 'exponentiate', 'args':
{'y': 2.743, 'x': 5.0}, 'id':
'54c166b2-f81a-481a-9289-eea68fc84e4f'}]
# response_metadata={...},
# id='...'
# )
其中AIMessage有一个tool_calls:List[ToolCall]属性,如果有任何工具调用,该属性将被填充,并遵循工具调用的标准接口:
class ToolCall(TypedDict):
name: str
args: Dict[str, Any]
id: Optional[str]
也就是说,无论你是调用Anthropic、OpenAI、Gemini等,只要有工具调用,它都会作为工具调用出现在AIMessage.tool_calls中。
我们还添加了一些其他属性,用于处理流式工具调用块和无效工具调用。点击此处阅读更多关于工具中调用文档的内容。
create_tool_calling_agent()
LLM工具调用功能最强大和最明显的用途之一是构建代理。LangChain已经有了create_openai_tool_agent()构造函数,可以轻松地使用遵循openai工具调用API的工具调用模型构建代理,但这对Anthropic和Gemini等模型不起作用。由于有了新的bind_tools()和tool_calls接口,我们添加了一个create_tool_calling_agent(),它可以与任何工具调用模型一起使用。
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import ConfigurableField
from langchain_core.tools import tool
from langchain.agents import create_tool_calling_agent, AgentExecutor
@tool
def multiply(x: float, y: float) -> float:
"""Multiply 'x' times 'y'."""
return x * y
@tool
def exponentiate(x: float, y: float) -> float:
"""Raise 'x' to the 'y'."""
return x**y
@tool
def add(x: float, y: float) -> float:
"""Add 'x' and 'y'."""
return x + y
prompt = ChatPromptTemplate.from_messages([
("system", "you're a helpful assistant"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
tools = [multiply, exponentiate, add]
llm = ChatAnthropic(model="claude-3-sonnet-20240229",
temperature=0)
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools,
verbose=True)
agent_executor.invoke({"input":
"what's 3 plus 5 raised to the 2.743.
also what's 17.24 - 918.1241", })
我们可以使用VertexAI
from langchain_google_vertexai import ChatVertexAI
llm = ChatVertexAI(
model="gemini-pro",
temperature=0,
convert_system_message_to_human=True
)
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent,
tools=tools, verbose=True)
agent_executor.invoke({"input": "what's 3 plus 5 raised
to the 2.743. also what's 17.24 - 918.1241", })
或OpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools,
verbose=True)
agent_executor.invoke({"input": "what's 3 plus 5 raised
to the 2.743. also what's 17.24 - 918.1241", })
等
有关新代理的完整文档,请参阅此处。
LangGraph
如果您还没有签出LangGraph,那么绝对应该签出。它是LangChain的一个扩展,使构建任意agent和多agent流变得容易。可以想象,在构建LangGraph代理或流时,使用新的tool_calls接口也会使生活变得更简单。查看此处的笔记本,了解如何在LangGraph代理中使用tool_calls的详细演练。
带_结构化_输出
我们最近发布了ChatModel.with_structured_output()接口,用于从模型中获取结构化输出,这是非常相关的。虽然具体的实现因模型提供程序而异,但with_structured_output是在大多数支持它的模型的工具调用之上构建的。在后台,with_structure d_output使用bind_tools将给定的结构化输出模式传递给模型。
那么,什么时候应该使用with_structured_output,而不是直接使用绑定工具和读取工具调用呢?
with_structured_output始终返回指定模式中的结构化输出。当您希望强制LLM输出与特定模式匹配的信息时,这非常有用。这对于信息提取任务非常有用。
bind_tools更通用,可以选择特定的工具——或者不选择工具,或者选择多个工具!当您希望允许LLM在如何响应方面具有更大的灵活性时,这一点非常有用——例如,在代理应用程序中,您需要选择调用哪些工具,同时还要响应用户。
结论
我们预计,在LLM中引入本机工具调用功能的趋势将在未来继续下去。我们希望标准化的工具调用界面能够帮助LangChain用户节省时间和精力,并使他们能够更容易地在不同的LLM提供商之间切换。
请记住更新您的langchain_core和合作伙伴包版本以利用新接口!
- 登录 发表评论
- 125 次浏览
Tags
最新内容
- 1 week 1 day ago
- 1 week 1 day ago
- 1 week 5 days ago
- 1 week 6 days ago
- 2 weeks ago
- 2 weeks ago
- 2 weeks ago
- 2 weeks ago
- 2 weeks 1 day ago
- 3 weeks ago