前言

本篇笔记主要内容来自小破站楼兰老师的教学视频,再加上自己的一些理解,看一遍相当于看了一遍视频教程,可以节省很多时间,属于入门教程,此外基础的环境搭建,大模型对接,相关基础概念,交互方式,存储记忆等内容可以按顺序看我之前的笔记快速入门。
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工具真的非常强大,在企业里面如果我们需要访问内部的数据来完成一些业务,可以自己封装一个服务,给大模型调用,然后将结果给大模型,但是内部做了什么,访问了什么样的隐私数据是不会暴露在外的。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐