目录
前言
在AI系列:大语言模型的function calling(上) 中我们实现了OpenAI原生的function calling。这篇文章将继续探讨如何使用
LangChain
实现大语言模型(LLM)的function calling。
LangChain Tool/Function calling
LangChain提供了对LLM function calling的支持。前提是底层大模型必须支持function calling。
1. Tool/function加强功能
LangChain的tool装饰器
LangChain在
langchain_core
模块中的
tools
子模块中提供了名为
tool
的装饰器,将根据函数定义和注释自动生成不同LLM function calling功能需要的
schema
,然后传递给LLM。后续对于LLM的调用将包括这些function/tool schema。
在Python中可以通过下面这种方式为自己定义的函数导入tool装饰器:
from langchain_core.tools import tool
@tooldefmultiply(first_int:int, second_int:int)->int:"""两个整数相乘"""return first_int * second_int
@tooldefadd(first_add:int, second_add:int)->int:"""两个整数相加"""return first_add + second_add
tools=[multiply, add]
其他方式: Pydantic
除了tool解释器,LangChain还支持用
Pydantic
来定义schema的方式。比如:
from langchain_core.pydantic_v1 import BaseModel, Field
# 注释很重要,会被用来生成schema。classAdd(BaseModel):"""Add two integers together."""
a:int= Field(..., description="First integer")
b:int= Field(..., description="Second integer")
tools=[Add]
2. 绑定tools/functions
绑定tool组成的列表后,LangChain将根据函数定义和注释自动生成底层LLM的function calling功能需要的
schema
,并传递给LLM。以OpenAI为例,
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo")
llm_with_tools = llm.bind_tools(tools)
3. 调用大模型(LLM)
LangChain调用LLM的接口输入参数为Message的列表。它抽象了几个不同的Message类型。以OpenAI为例,它们分别对应OpenAI的不同role属性的对话项。比如
HumanMessage
,
AIMessage
,
ToolMessage
分别对应OpenAI的user, assistant和tool的角色。
from langchain_core.messages import HumanMessage, ToolMessage
prompt ="一共有3个人,每个人有15个苹果,10个鸭梨,一共有多少苹果?"
messagesLC =[
HumanMessage(prompt)]
调用的方法也比较直接,直接调用
invoke
方法即可。注意我们已经将tools绑定在LLM中,调用时,LangChain将自动将tools的schema传递给LLM。
#通过LangChain调用LLM接口,将LLM回复加入对话上下文
response = llm_with_tools.invoke(messagesLC)
messagesLC.append(response)
返回类型为AIMessage。
4. function calling处理流程
function calling整个处理的逻辑与上篇中的介绍完全一致,这里就不累述了。具体可以参考AI系列:大语言模型的function calling(上)
整个对话上下文如下,抽象成这样,是不是感觉比OpenAI原生的更清楚一点:
[
HumanMessage(content='一共有3个人,每个人有15个苹果,10个鸭梨,一共有多少苹果?'),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_LsvajoCqf1G6ZNNS8M1gildQ', 'function': {'arguments': '{"first_int":3,"second_int":15}', 'name': 'multiply'}, 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'logprobs': None}),
ToolMessage(content='45', tool_call_id='call_LsvajoCqf1G6ZNNS8M1gildQ'),
AIMessage(content='一共有45个苹果。', response_metadata={'finish_reason': 'stop', 'logprobs': None})
]
LangChain版代码
以下是LangChain版function calling的实现代码,可以对比大语言模型的function calling(上) OpenAI原生版的实现代码。
__author__ ='liyane'import json
# 初始化环境from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())#定义function/tool 1: multiply,应用tool装饰器from langchain_core.tools import tool
@tooldefmultiply(first_int:int, second_int:int)->int:"""两个整数相乘"""return first_int * second_int
#定义function/tool 2: add,应用tool装饰器@tooldefadd(first_add:int, second_add:int)->int:"""两个整数相加"""return first_add + second_add
tools=[multiply, add]#定义大模型并绑定toolsfrom langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo")
llm_with_tools = llm.bind_tools(tools)#构建对话from langchain_core.messages import HumanMessage, ToolMessage
prompt ="一共有3个人,每个人有15个苹果,10个鸭梨,一共有多少苹果?"
messagesLC =[
HumanMessage(prompt)]#通过LangChain调用LLM接口,将LLM回复加入对话上下文
response = llm_with_tools.invoke(messagesLC)
messagesLC.append(response)#如果LLM需要function calling,调用相应的函数,并将函数结果数据加入对话上下文,继续调用LLM。while(response.additional_kwargs.get("tool_calls")isnotNone):for tool_call in response.additional_kwargs["tool_calls"]:
selected_tool ={"add": add,"multiply": multiply}[tool_call["function"]["name"]]
args = json.loads(tool_call["function"]["arguments"])
tool_output = selected_tool(args)
messagesLC.append(ToolMessage(tool_output, tool_call_id=tool_call["id"]))
response = llm_with_tools.invoke(messagesLC)
messagesLC.append(response)print("=====最终结果=====")print(response.content)
与原生LLM调用的比较
对于Function calling这部分功能,使用LangChain可以节省大段的手工定义tool schema的代码,也避免了未来有变动时会产生的维护问题。
同时,LangChain屏蔽了底层LLM。当LLM改变时,无需重写代码,只需要替换LangChain对应LLM的库文件即可。
目前LangChain快速迭代过程中,代码大功能上可以用,在细节上可能存在问题,遇到具体问题时可能需要看它的代码。
参考
OpenAI / function calling
LangChain / Tool/function calling
LangChain Message Types
版权归原作者 liyane 所有, 如有侵权,请联系我们删除。