langchain学习笔记——tools工具使用,扩展大模型能力边界
langchain的tools工具使用,这是大模型能力得到扩展的核心
前言
本篇笔记主要内容来自小破站楼兰老师的教学视频,再加上自己的一些理解,看一遍相当于看了一遍视频教程,可以节省很多时间,属于入门教程,此外基础的环境搭建,大模型对接,相关基础概念,交互方式,存储记忆等内容可以按顺序看我之前的笔记快速入门。
tips:有些我觉得值得记下来的内容我懒得打字,太消耗时间,就直接截图了,希望不要介意~
入门篇一基础概念及快速搭建
入门篇二LCEL链式表达式
入门篇三Redis实现记忆
入门篇四记忆整合LCEL链
理解Tools工作机制
举个简单的例子,大模型能知道今天是几月几号吗?并不可以,这就像人类需要看手表一样,需要借助外部工具才能解决类似的问题。
又如一些我们存到本地数据库的一些业务上的数据,没有开放到互联网上,自然大模型是没办法访问的
我问大模型今天几月几号得到的结果:
当然不同的大模型给出的结果不一样,有的会直接告诉你无法给出。这个有点像幻觉问题?
如何解决?
我们很容易用一些工具类得到日期,那我们可以写一个工具,让大模型调用本地api来获取今天是几月几号。
langchain的官网可以看到大模型是否支持工具机制:
楼兰老师说deepseek-v3支持工具机制,而deepseek-r1推理模型不支持,现在支不支持不知道。
定制本地tool工具
一般步骤:
1先通过@tool注解把函数声明成一个工具,并通过注释等方式表示这个工具的作用
2再把大模型和工具进行绑定
3调用带有工具的大模型实例来处理问题
代码示例:
import datetime
import os
from langchain.tools import tool
from langchain_deepseek import ChatDeepSeek
from demo1.config.load_key import load_key
if not os.environ.get("DEEPSEEK_API_KEY"):
os.environ["DEEPSEEK_API_KEY"]=load_key("DEEPSEEK_API_KEY")
#声明工具
@tool
def get_current_time():
"""获取今天的日期"""
return datetime.datetime.today().strftime("%Y-%m-%d")
llm = ChatDeepSeek(model="deepseek-chat", )
# 绑定大模型
llmWithTools = llm.bind_tools([get_current_time])
aimessage = llmWithTools.invoke("今天几月几号")
print(aimessage)
我们看一下返回的结果:
但是为啥没有结果呢?因为大模型这里接收到我们的message之后,判断需要调用本地提供的方法,但是还需要我们调用一下它才能拿到结果呢。它会根据我们提的问题(今天是几月几号)分析出需要调用哪个工具(我们提供的tool,所以我们提供的注释非常重要,要描述好功能大模型才能分析出来)。
总之到目前为止,大模型会返回一个工具调用请求,我们来打印一下看看
所以接下来我们要拿到大模型需要调用哪个工具,帮他调用一下拿到结果,然后再把结果和之前的问题一起传给大模型,大模型会进行一个综合的考虑后给出答案。
代码:
import datetime
import os
from langchain.tools import tool
from langchain_deepseek import ChatDeepSeek
from demo1.config.load_key import load_key
if not os.environ.get("DEEPSEEK_API_KEY"):
os.environ["DEEPSEEK_API_KEY"] = load_key("DEEPSEEK_API_KEY")
# 声明工具
@tool
def get_current_time():
"""获取今天的日期"""
return datetime.datetime.today().strftime("%Y-%m-%d")
llm = ChatDeepSeek(model="deepseek-chat", )
# 工具容器,未来我们要根据大模型的工具调用结果拿到对应的工具
all_tools = {"get_current_time": get_current_time}
# 绑定大模型
llmWithTools = llm.bind_tools([get_current_time])
# 把消息放到一起
query="今天几月几号"
messages=[query]
aimessage = llmWithTools.invoke(messages)
messages.append(aimessage)
# print(aimessage)
print(aimessage.tool_calls)
if aimessage.tool_calls:
for toolcall in aimessage.tool_calls:
selected_tool = all_tools[toolcall["name"].lower()]
tool_message = selected_tool.invoke(toolcall)
print(tool_message)
messages.append(tool_message)
response = llmWithTools.invoke(messages).content
print(response)
结果:
关键代码分析:
大家跟着图中的顺序捋一遍就清楚了
最终我们发给大模型的消息是:
深入理解@tool注解
自定义工具名字
可以同一个方法申明成不同的工具
自定义工具描述
我们把刚刚的代码稍微改造一下,函数名我就不换了:
看看结果:
深度定制工具
这个方式即不通过注解的方式来定义工具,例子:
这种方式对方法没有侵入,灵活性要更高
结合大模型定制工具
我们还可以把一个chain转换成一个工具
当然这个是0.3版本新增的功能,目前还在实验阶段,后续也许会变动
代码:
import os
from langchain.tools import tool
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_deepseek import ChatDeepSeek
from demo1.config.load_key import load_key
if not os.environ.get("DEEPSEEK_API_KEY"):
os.environ["DEEPSEEK_API_KEY"] = load_key("DEEPSEEK_API_KEY")
#大模型
llm = ChatDeepSeek(model="deepseek-chat", )
# 申明工具
# 提示词模板
prompt = ChatPromptTemplate.from_messages([("human","你好,请用{language}翻译一下:{text}.")])
parser = StrOutputParser()
chain=prompt | llm |parser
chainTool = chain.as_tool(name="translatetool", description="翻译任务")
print("chainTool.args=",chainTool.args)
# 工具容器,未来我们要根据大模型的工具调用结果拿到对应的工具
all_tools = {"translatetool": chainTool}
# 绑定大模型
llmWithTools = llm.bind_tools([chainTool])
# 把消息放到一起
query="今天天气真冷,这句话用英语怎么说?"
messages=[query]
aimessage = llmWithTools.invoke(messages)
messages.append(aimessage)
# print("messages=",messages)
# print(aimessage)
print("tool_calls=",aimessage.tool_calls)
if aimessage.tool_calls:
for toolcall in aimessage.tool_calls:
print(toolcall)
selected_tool = all_tools[toolcall["name"].lower()]
tool_message = selected_tool.invoke(toolcall)
print(tool_message)
messages.append(tool_message)
print("messages:")
for message in messages:
print(message)
print(messages)
response = llmWithTools.invoke(messages).content
print(response)
也可以使用langchain提供的一些工具
工具包
这些工具你玩熟悉了会发现其实这些东西就是现在网上很火的MCP
server端部署好这些服务
大语言模型来判断要不要调用这些server工具
只不过这个mcp协议是claude定制了一种标准的协议,定义了服务端应该怎么样去卡法,客户端应该怎样去开发,更加宽泛的一种协议,而不是我们这里使用的http协议这种标准的协议
mcp协议又实现了很多例如读论文,网上搜索信息等各种功能。所以mcp协议是根据tool工具来的
使用Agent执行工具
agent智能体相当于做了一个封装
langchain.agents提供了一些方法来构建智能体
代码也很简单:
import os
from langchain.agents import initialize_agent, AgentType
from langchain.tools import tool
from langchain_deepseek import ChatDeepSeek
from demo1.config.load_key import load_key
if not os.environ.get("DEEPSEEK_API_KEY"):
os.environ["DEEPSEEK_API_KEY"] = load_key("DEEPSEEK_API_KEY")
#大模型
llm = ChatDeepSeek(model="deepseek-chat", )
# 声明工具
@tool
def get_current_time(city:str):
"""获取某个城市的天气
Args:
city: 具体城市
"""
return city+"今天天气不错"
query="北京今天天气怎么样?"
agent = initialize_agent(
tools=[get_current_time],
llm=llm,
agent_type=AgentType.OPENAI_FUNCTIONS,
verbose=True)
response = agent.invoke(query)
print("response=",response)
看看结果:
爆红色的解释是:
这个警告信息是 LangChain 团队发出的正式通知,表明他们正在逐步淘汰传统的代理系统(如 initialize_agent),并推荐用户迁移到新的 LangGraph 框架。
总结
tools工具真的非常强大,在企业里面如果我们需要访问内部的数据来完成一些业务,可以自己封装一个服务,给大模型调用,然后将结果给大模型,但是内部做了什么,访问了什么样的隐私数据是不会暴露在外的。
更多推荐
所有评论(0)