❝本文经翻译并二次整理自Tool Calling with LangChain一文。为了简化和统一与各种大型语言模型(LLM)提供商的工具调用API的交互,LangChain正在针对
AIMessage引入一个名为tool_calls的新属性。本系列合集,点击链接查看
大型语言模型(LLM)通过工具调用能够与外部数据源进行交互。这项技术让开发者能够利用LLM来获取、交互和操作外部资源(比如数据库、文件和API等)。
随着越来越多的LLM提供商开始提供工具调用功能,我们注意到市场上出现了多种多样的接口。为了解决这个问题,LangChain推出了一个标准化的接口,这样用户就可以轻松地在不同的LLM提供商之间进行切换。
这个标准化接口包括以下几个方面:
ChatModel.bind_tools:这个方法允许您将工具的定义附加到模型的调用过程中。AIMessage.tool_calls:这是一个新增的属性,它使得从模型返回的 AIMessage 中获取工具调用变得更加简单。create_tool_calling_agent:这是一个构建代理的函数,适用于任何实现了 bind_tools 并且能够返回 tool_calls 的模型。下面,我们将详细解释这些组件。
ChatModel.bind_tools为了让模型能够使用工具,我们需要告诉它哪些工具是可以使用的。这可以通过向模型提供一个包含工具定义的列表来实现,这些工具定义包括了工具参数的模式。不同的模型提供商可能需要不同的格式,但是 ChatModel.bind_tools 提供了一个统一的接口,让您可以指定哪些工具对模型来说是可用的。
这意味着,无论您使用的是哪种工具调用模型,代码的结构都将非常相似。
fromlangchain_anthropicimportChatAnthropic
fromlangchain_core.pydantic_v1importBaseModel,Field
fromlangchain_core.toolsimporttool
#✅Pydantic类
classmultiply(BaseModel):
"""返回'x'和'y'的乘积。"""
x:float=Field(...,description="第一个因子")
y:float=Field(...,description="第二个因子")
#✅LangChain工具
@tool
defexponentiate(x:float,y:float)->float:
"""将'x'乘以'y'。"""
returnx**y
#✅函数
defsubtract(x:float,y:float)->float:
"""从'y'中减去'x'。"""
returny-x
#✅OpenAI格式字典
#还可以传入一个带有"title"和"description"的JSON模式
add={
"name":"add",
"description":"将'x'和'y'相加。",
"parameters":{
"type":"object",
"properties":{
"x":{"type":"number","description":"要相加的第一个数字"},
"y":{"type":"number","description":"要相加的第二个数字"}
},
"required":["x","y"]
}
}
llm=ChatAnthropic(model="claude-3-sonnet-20240229",temperature=0)
#每当我们调用`llm_with_tool`时,这三个工具定义
#都会被传递给模型。
llm_with_tools=llm.bind_tools([multiply,exponentiate,add,subtract])
如果我们想使用不同的工具调用模型,我们的代码看起来会非常相似:
fromlangchain_openaiimportChatOpenAI
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 提供了一个标准化的接口来获取模型的工具调用。这样,在调用了绑定了工具的模型之后,您将得到一个包含 tool_calls 属性的输出,其中列出了所有的工具调用。
在调用了绑定工具的模型之后,您将得到以下形式的输出:
llm_with_tools.invoke([
("system","你是一个有用的助手"),
("human","5的2.743次方是多少"),
])
#?注意tool_calls属性?
#->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] 属性,如果有工具调用,它将被填充,并将遵循工具调用的标准接口:
classToolCall(TypedDict):
name:str
args
ict[str,Any]
id:Optional[str]
也就是说,无论您是在调用 Anthropic、OpenAI、Gemini 等,只要有工具调用,它将以 AIMessage.tool_calls 形式作为 ToolCall 出现。
我们还添加了一些其他属性,用于处理流式工具调用块和无效工具调用。有关这些的更多信息,请阅读工具调用文档 这里。
create_tool_calling_agent利用LLM的工具调用能力来构建代理是一个非常强大的应用场景。我们已经有了一个 create_openai_tools_agent() 构造函数,它可以方便地构建一个符合OpenAI工具调用API的代理。但是,这个构造函数并不适用于Anthropic和Gemini等模型。现在,有了 bind_tools() 和 tool_calls 这两个新接口,我们推出了 create_tool_calling_agent(),它能够与任何支持工具调用的模型一起工作。
fromlangchain_core.promptsimportChatPromptTemplate
fromlangchain_core.runnablesimportConfigurableField
fromlangchain_core.toolsimporttool
fromlangchain.agentsimportcreate_tool_calling_agent,AgentExecutor
@tool
defmultiply(x:float,y:float)->float:
"""将'x'乘以'y'。"""
returnx*y
@tool
defexponentiate(x:float,y:float)->float:
"""将'x'乘以'y'的指数。"""
returnx**y
@tool
defadd(x:float,y:float)->float:
"""将'x'和'y'相加。"""
returnx+y
prompt=ChatPromptTemplate.from_messages([
("system","你是一个有用的助手"),
("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":"3 加上 5 的 2.743 次方是多少。还有 17.24 减去 918.1241 是多少。"})
我们可以使用 VertexAI 替代:
fromlangchain_google_vertexaiimportChatVertexAI
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":"3 加上 5 的 2.743 次方是多少。还有 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":"3 加上 5 的 2.743 次方是多少。还有 17.24 减去 918.1241 是多少。"})
等等。
有关新代理的完整文档,请查看 https://python.langchain.com/docs/modules/agents/agent_types/tool_calling。
我们预计,将原生工具调用功能引入LLM的趋势将继续下去。我们希望这个标准化的工具调用接口能够帮助LangChain用户节省时间和精力,并使他们能够更容易地在不同的LLM提供商之间进行切换。
| 欢迎光临 链载Ai (https://www.lianzai.com/) | Powered by Discuz! X3.5 |