1. 十分钟带你搞定LLM工具调用

在上一篇文章中,详细介绍了工具调用的基本流程,以及创建工具的几种方式,工具创建完成后,下一步就是让大语言模型(LLM)进行工具调用。

可能第一次听到工具调用的同学,会认为是LLM直接调用了工具本身,实际上并非如此,LLM只会根据用户提问,给出要调用的工具并生成调用工具的参数,实际是否调用工具,由应用本身决定。

整个工具调用基本流程如下,本文将会对如何让LLM完成工具调用进行详细的介绍。

img

1.1 工具创建

首先,创建一个根据IP获取用户地理位置信息的工具,这个工具调用高德地图的IP定位API,该API文档地址如下:

高德地图IP定位:https://lbs.amap.com/api/webservice/guide/api/ipconfig

在.env文件中配置高德开放平台API KEY

1
2
# 高德开放平台API KEY
GAODE_API_KEY=***************************

之后,通过继承BaseTool类的方式创建工具,在_run方法中实现工具逻辑,实际上就是调用指定API,传递IP地址和API KEY即可,具体大家结合文档理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class GaoDeIPLocationInput(BaseModel):
"""IP定位入参"""
ip: str = Field(description="ip地址")


class GaoDeIPLocationTool(BaseTool):
"""根据IP定位位置工具"""
name = "ip_location_tool"
description = "当你需要根据IP,获取定位信息时,可以调用这个工具"
args_schema = GaoDeIPLocationInput

def _run(self, ip: str) -> str:
api_key = os.getenv("GAODE_API_KEY")
if api_key isNone:
return"请配置GAODE_API_KEY"
url = "https://restapi.amap.com/v3/ip?ip={ip}&key={key}".format(ip=ip, key=api_key)

session = requests.session()
response = session.request(
method="GET",
url=url,
headers={"Content-Type": "application/json; charset=UTF-8"},
)
result = response.json()
return result.get("province") + result.get("city")

另一个工具是此前已经创建过的工具:加法计算器,具体实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class AddNumberInput(BaseModel):
"""加法工具入参"""
num1: int = Field(description="第一个数")
num2: int = Field(description="第二个数")


class AddNumberTool(BaseTool):
"""加法工具"""
name = "add_number_tool"
description = "两数相加工具"
args_schema = AddNumberInput

def _run(self, num1: int, num2: int) -> int:
return num1 + num2

创建这两个工具的对象,并把它们放到一个字典当中,key是工具的名称,value是工具对象,这样做的原因是方便后面LLM返回工具调用信息,可以根据工具名称获取工具对象,从而进行工具调用,后面会详细解释。

1
2
3
4
5
6
7
8
# 创建工具对象
add_number_tool = AddNumberTool()
gaode_ip_location_tool = GaoDeIPLocationTool()

tools_dict = {
add_number_tool.name: add_number_tool,
gaode_ip_location_tool.name: gaode_ip_location_tool,
}

1.2 工具绑定

在进行工具调用之前,需要先使用.bind_tools()方法将工具列表绑定到LLM对象上,只有绑定了工具列表的LLM,LLM在执行过程中才知道可以调用哪些工具、参数有哪些。

这里一定要注意使用新的变量llm_with_tool接收,并且后续调用中使用llm_with_tool,如果继续使用llm进行调用,是无法触发大模型返回工具调用参数的。

1
2
3
4
5
6
7
8
9
10
11
# 1.创建Prompt
prompt = ChatPromptTemplate.from_messages([
("system",
"你是一个智能助手,可以帮助用户解决问题。当问题需要使用工具时,必须调用提供的工具,并一次性调用所有必要工具,避免分步调用。"),
("human", "{query}"),
])

# 2.创建LLM并绑定工具
llm = ChatOpenAI(model="gpt-4o")
llm_with_tool = llm.bind_tools(tools=[tool for tool in tools_dict.values()])

1.3 调用工具

完成工具绑定之后,构建并调用chain,传递query查询,LLM会返回一个AIMessage,在消息内部如果需要调用工具会返回tool_calls列表,里面包含要tool_call_id(工具调用的唯一id标识)、调用工具的名字、生成的调用参数等信息。

1
2
3
4
5
6
7
8
9
# 3.创建链
chain = prompt | llm_with_tool

# 4.调用链
query = "帮我查询一下IP为122.234.134.158用户的位置"
resp = chain.invoke({"query": query})
print("LLM生成内容:", resp.content)
print("LLM生成调用信息:", resp.tool_calls)

接下来,构建一个消息列表messages,把之前渲染模板的消息列表保存messages,这个列表的作用是将这些历史消息以及调用工具生成的工具消息,一起发送给LLM生成回答。

保存好消息记录后,通过判断AIMessage中的tool_calls是否为None判断是否存在工具调用,如果存在工具调用,则遍历tools_calls,取出每一个tool_call,根据tool_call里面的name属性,获取对应的工具对象。

接下来,调用工具并传入tool_call中的args属性中生成的参数,接收工具调用结果,构建一个ToolMessage,即工具消息,ToolMessage包含tool_call_id、工具调用结果,最后,将工具消息添加到messages消息列表中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 5.构建消息列表,插入AI返回的AIMessage
messages = prompt.invoke({"query": query}).to_messages()
messages.append(resp)

# 6.判断是否需要工具调用
if resp.tool_calls isNone:
print(resp.content)
else:
# 7.遍历工具调用信息
for tool_call in resp.tool_calls:
# 8.根据调用的工具名称获取工具对象
print("工具{tool_name}调用信息:{tool_call}".format(tool_name=tool_call.get("name"), tool_call=tool_call))
target_tool = tools_dict.get(tool_call.get("name"))
# 9.执行工具调用
result = target_tool.invoke(tool_call.get("args"))
print("工具{tool_name}调用结果:{result}".format(tool_name=target_tool.name, result=result))
tool_call_id = tool_call.get("id")
# 10.创建工具消息
tool_message = ToolMessage(
tool_call_id=tool_call_id,
content=result,
)
# 11.将工具消息添加到消息列表中
messages.append(tool_message)

1.4 返回调用结果给大模型

最后,将包含工具消息的messages消息列表传递给LLM,大模型输出最终结果。

1
print("最终结果:" + llm.invoke(messages).content)

执行结果如下,执行结果符合我们的预期

1
2
3
4
5
LLM生成内容: 
LLM生成调用信息: [{'name': 'ip_location_tool', 'args': {'ip': '122.234.134.158'}, 'id': 'call_R36kxZo9S78PlOakiXk6Ib0M', 'type': 'tool_call'}]
工具ip_location_tool调用信息:{'name': 'ip_location_tool', 'args': {'ip': '122.234.134.158'}, 'id': 'call_R36kxZo9S78PlOakiXk6Ib0M', 'type': 'tool_call'}
工具ip_location_tool调用结果:浙江省杭州市
最终结果:IP地址为122.234.134.158的用户位于中国浙江省杭州市。

完整案例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import os

import dotenv
import requests
from langchain_core.messages import ToolMessage
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import BaseTool
from langchain_openai import ChatOpenAI
from pydantic.v1 import BaseModel, Field

# 读取env配置
dotenv.load_dotenv()


class GaoDeIPLocationInput(BaseModel):
"""IP定位入参"""
ip: str = Field(description="ip地址")


class GaoDeIPLocationTool(BaseTool):
"""根据IP定位位置工具"""
name = "ip_location_tool"
description = "当你需要根据IP,获取定位信息时,可以调用这个工具"
args_schema = GaoDeIPLocationInput

def _run(self, ip: str) -> str:
api_key = os.getenv("GAODE_API_KEY")
if api_key isNone:
return"请配置GAODE_API_KEY"
url = "https://restapi.amap.com/v3/ip?ip={ip}&key={key}".format(ip=ip, key=api_key)

session = requests.session()
response = session.request(
method="GET",
url=url,
headers={"Content-Type": "application/json; charset=UTF-8"},
)
result = response.json()
return result.get("province") + result.get("city")


class AddNumberInput(BaseModel):
"""加法工具入参"""
num1: int = Field(description="第一个数")
num2: int = Field(description="第二个数")


class AddNumberTool(BaseTool):
"""加法工具"""
name = "add_number_tool"
description = "两数相加工具"
args_schema = AddNumberInput

def _run(self, num1: int, num2: int) -> int:
return num1 + num2


# 创建工具对象
add_number_tool = AddNumberTool()
gaode_ip_location_tool = GaoDeIPLocationTool()

tools_dict = {
add_number_tool.name: add_number_tool,
gaode_ip_location_tool.name: gaode_ip_location_tool,
}

# 1.创建Prompt
prompt = ChatPromptTemplate.from_messages([
("system",
"你是一个智能助手,可以帮助用户解决问题。当问题需要使用工具时,必须调用提供的工具,并一次性调用所有必要工具,避免分步调用。"),
("human", "{query}"),
])

# 2.创建LLM并绑定工具
llm = ChatOpenAI(model="gpt-4o")
llm_with_tool = llm.bind_tools(tools=[tool for tool in tools_dict.values()])

# 3.创建链
chain = prompt | llm_with_tool

# 4.调用链
query = "帮我查询一下IP为122.234.134.158用户的位置"
resp = chain.invoke({"query": query})
print("LLM生成内容:", resp.content)
print("LLM生成调用信息:", resp.tool_calls)

# 5.构建消息列表,插入AI返回的AIMessage
messages = prompt.invoke({"query": query}).to_messages()
messages.append(resp)

# 6.判断是否需要工具调用
if resp.tool_calls isNone:
print(resp.content)
else:
# 7.遍历工具调用信息
for tool_call in resp.tool_calls:
# 8.根据调用的工具名称获取工具对象
print("工具{tool_name}调用信息:{tool_call}".format(tool_name=tool_call.get("name"), tool_call=tool_call))
target_tool = tools_dict.get(tool_call.get("name"))
# 9.执行工具调用
result = target_tool.invoke(tool_call.get("args"))
print("工具{tool_name}调用结果:{result}".format(tool_name=target_tool.name, result=result))
tool_call_id = tool_call.get("id")
# 10.创建工具消息
tool_message = ToolMessage(
tool_call_id=tool_call_id,
content=result,
)
# 11.将工具消息添加到消息列表中
messages.append(tool_message)
print("最终结果:" + llm.invoke(messages).content)

1.5 总结

本文从 工具创建、LLM工具绑定、调用工具 、 返回调用结果给LLM、LLM生成最终结果,完整展示了LLM工具调用的全过程。

其中,需要特别注意以下几点:

LLM 本身并不会直接执行工具,它的作用是决定是否调用工具、调用哪个工具和生成调用参数,实际的工具调用逻辑由应用本身控制。
即使绑定了工具,大模型也不一定会调用工具,是否调用工具、如何调用工具是由LLM本身决定的,
在调用工具完成之后,传递工具消息时,必须传递原始工具调用传入的 tool_call_id ,这样LLM才能将工具调用结果与工具调用请求相匹配。
通过本文,相信你已经掌握了如何通过LLM进行工具调用,其实本文的案例代码就是一个Agent智能体的雏形,在下一篇文章中,将会对LangChain中的Agent智能体进行详细介绍,欢迎持续关注。

2. 构建你的第一个 AI 智能体

在上一篇文章中,介绍了工具调用的完整流程,包括工具创建、工具绑定、调用工具、将调用结果返回给大语言模型(LLM),以及由LLM输出最终结果,相当于实现了一个智能体(Agent)的雏形。

本文将会介绍什么是 Agent,并通过 LangChain 中的 AgentExecutor 来构建智能体。

需要注意的一点是:AgentExecutor 虽然仍然保留在 LangChain 中,但官方已经不再推荐使用,而是更倾向于使用 LangGraph Agents。关于 LangGraph 的内容会在后续文章中详细展开。

虽然,AgentExecutor 已经不推荐使用,但AgentExecutor 作为一个经典且易于理解的Agent实现方式,依旧是学习 Agent 的良好切入点,因此,本文将会对AgentExecutor 进行详细讲解。

img

2.1 什么Agent智能体

AI Agent(AI 智能体)是一种能够自主调用工具完成特定任务的系统。它不仅具备自然语言处理能力,还能进行智能决策、问题解决、与外部环境交互以及执行操作。

这些 AI Agent 可以应用于各种场景,帮助企业解决实际问题,例如自动化运维、代码生成、智能客服等场景。

AI Agent 的核心是大语言模型(LLM)。因此,AI Agent 也常被称为 LLM 智能体。由于 LLM 的知识受训练数据限制,推理能力也存在一定局限,AI Agent 技术则通过工具调用来弥补这些不足,从而获取最新信息、优化工作流、拆解任务,最终实现更复杂的功能。

与传统 LLM 相比,AI Agent 多了几个关键能力:

(1)目标初始化与规划:在用户给定目标和工具的前提下,Agent 能够将任务拆解并制定执行计划。简单任务可以边执行边调整,复杂任务则会先做整体规划。

(2)借助工具进行推理:当遇到无法直接解决的问题时,Agent 会调用外部工具补充知识,例如联网搜索或调用 API。

(3)学习与反思:Agent 能够记住与用户的交互,并不断调整优化自己的行为。

2.2 构建ReAct智能体

ReAct 全称是 Reasoning + Acting(推理 + 行动),是2022 年 Google 在一篇论文中提出的思路。

它的核心思想是:

让LLM在回答问题时,不直接生成答案,而是像人类一样先思考,再决定是否要调用工具,然后基于观察继续推理,最后得出答案。
这种模式很适合工具调用场景(搜索、数据库查询、API调用等),因为模型可以“边推理边用工具补充信息”,最终给出完整的答案。

2.2.1 定义Google Serper工具

在创建智能体之前,首先创建工具,第一个工具是LangChain内置的Google Serper工具,通过Google Serper可以进行谷歌搜索,通过搜索结果,LLM可以获取到实时信息。

在使用Google Serper之前需要去申请对应的API KEY,初次注册会送3000次免费调用额度。

Google Serper:https://serper.dev/

在.env下配置Google Serper API Key

1
2
# Google SerperAPI KEY
SERPER_API_KEY=**************************************

定义工具信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1.定义google_serper工具
class GoogleSerperInput(BaseModel):
query: str = Field(description="执行谷歌搜索的查询语句")


google_serper_tool = GoogleSerperRun(
name="google_serper_tool",
description=(
"谷歌搜索工具"
"如果要获取实时内容可以调用这个工具"
"调用该工具传入搜索关键词相当于完成了一次谷歌搜索"
),
args_schema=GoogleSerperInput,
api_wrapper=GoogleSerperAPIWrapper()
)

2.2.2 定义根据IP获取定位信息工具

第二个工具是此前已经创建过的,通过高德地图API获取IP对应定位。

该API文档地址如下:

高德地图IP定位:https://lbs.amap.com/api/webservice/guide/api/ipconfig

在.env文件中配置高德开放平台API KEY

1
2
3
# 高德开放平台API KEY
GAODE_API_KEY=***************************

定义工具信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class GaoDeIPLocationInput(BaseModel):
"""IP定位入参"""
ip: str = Field(description="ip地址")


class GaoDeIPLocationTool(BaseTool):
"""根据IP定位位置工具"""
name = "ip_location_tool"
description = "当你需要根据IP,获取定位信息时,可以调用这个工具"
args_schema = GaoDeIPLocationInput

def _run(self, ip: str) -> str:
api_key = os.getenv("GAODE_API_KEY")
if api_key isNone:
return"请配置GAODE_API_KEY"
url = "https://restapi.amap.com/v3/ip?ip={ip}&key={key}".format(ip=ip, key=api_key)

session = requests.session()
response = session.request(
method="GET",
url=url,
headers={"Content-Type": "application/json; charset=UTF-8"},
)
result = response.json()
return result.get("province") + result.get("city")

之后,创建工具对象,并将工具对象添加到tools列表中。

1
2
3
4
ip_location_tool = GaoDeIPLocationTool()

tools = [google_serper_tool, ip_location_tool]

2.2.3 创建ReAct智能体

接下来,为ReAct智能体创建一个提示词模板,要注意的是:这段提示词模板不能进行汉化,因为LangChain内部是根据英文关键词去解析提示词模板的,如果进行汉化执行时会发生错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 3.创建提示词模板
prompt = ChatPromptTemplate.from_template(
"Answer the following questions as best you can. You have access to the following tools:\n\n"
"{tools}\n\n"
"Use the following format:\n\n"
"Question: the input question you must answer\n"
"Thought: you should always think about what to do\n"
"Action: the action to take, should be one of [{tool_names}]\n"
"Action Input: the input to the action\n"
"Observation: the result of the action\n"
"... (this Thought/Action/Action Input/Observation can repeat N times)\n"
"Thought: I now know the final answer\n"
"Final Answer: the final answer to the original input question\n\n"
"Begin!\n\n"
"Question: {input}\n"
"Thought:{agent_scratchpad}"
)

这段提示词来自于

https://smith.langchain.com/hub/hwchase17/react

这段提示词的含义是:让LLM基于“推理+行动”去回答问题,过程中可以调用一些外部工具,而不是直接给出答案,并且给出了工具清单,在执行过程中,要严格遵守以下思考流程:

  • Question:用户问了什么问题。
  • Thought:思考下一步要做什么
  • Action:要调用哪个工具(必须是给定的 {tool_names} 之一)。
  • Action Input:工具需要输入什么参数
  • Observation:工具返回了什么结果

上面这几步可以多次循环直到找到答案:

  • Thought: 我现在知道答案了。
  • Final Answer: 最终答案是xxx。

下一步,创建一个基于gpt-4o的LLM对象,然后使用create_react_agent()方法创建ReAct智能体,需要传入llm、prompt、tools、tools_renderer,其中tools_renderer参数传递一个函数,该函数的作用是:将工具信息格式化成字符串,并放到提示词模板中的{tools}中。

之后,创建智能体执行者AgentExecutor,传入agent、tools、verbose,其中verbose为True表示智能体执行过程中推理过程会打印出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 4.创建LLM
llm = ChatOpenAI(model="gpt-4o", temperature=0)

# 5.创建智能体
agent = create_react_agent(
llm=llm,
prompt=prompt,
tools=tools,
tools_renderer=render_text_description_and_args,
)

# 6.创建智能体执行者
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 7.调用智能体执行者,进行提问
print(agent_executor.invoke({"input": "北京今天天气预报"}))

最后,调用智能体执行者并传入问题,执行结果如下,可以控制台打印了Agent的推理过程,最终成功返回了正确答案。

1
2
3
4
5
6
7
8
9
我需要使用谷歌搜索工具来获取北京今天的天气预报。
Action: google_serper_tool
Action Input: "北京今天天气预报"星期一 08/18. 雷阵雨 · 31℃ ; 星期二 08/19. 中雨 · 29℃ ; 星期三 08/20. 雷阵雨 · 31℃ ; 星期四 08/21. 中雨 · 32℃ ; 星期五 08/22. 多云 · 32℃. 22日(今天). 雷阵雨. 23℃. <3级 · 23日(明天). 阴转小雨. 29℃/22℃. <3级 · 24日(后天). 小雨转多云. 28℃/21℃. <3级 · 25日(周一). 多云. 31℃/21℃. <3级 · 26日(周二). 阴转小雨. 11:00 · 24.6℃. 3.3m/s. 北风. 1012.5hPa ; 14:00 · 26.3℃. 3.2m/s. 东北风. 1011.6hPa ; 17:00 · 27.8℃. 3.3m/s. 东风. 1010.9hPa. 星期五 08/22 · 西北风 · 33℃ · 雷阵雨. 南风 ; 星期六 08/23 · 北风 · 30℃ · 小雨. 北风 ; 星期日 08/24 · 东北风 · 28℃ · 多云. 西北风. 今天白天 最高气温33℃ 晴转多云,山区有雷阵雨 2、3级 北转南风 · 今天夜间 最低气温23℃ 多云间阴,有分散性雷阵雨 2级左右,局地阵风7级左右 偏南风 · 明天白天 最高气温31℃ ... 今天. 8/23. 84° 70°. 有幾場陣雨,主要在晚間. 幾場陣雨 ; 周日. 8/24. 82° 68°. 多雲轉晴. 晴朗 ; 周一. 8/25. 89° 69°. 變暖. 局部多雲轉多雲. 今天. 22 ~ 29°C 阴. 北风1级. 优 · 24. 21 ~ 28°C 小雨. 东北风1级. 优. 周五(29日) 多云转晴 30℃/21℃ 西南风转北风 <3级 · 周六(30日) 晴转阴 30℃/21℃ 西南风转北风 <3级 · 周日(31日) 阴转晴 30℃/19℃ 西南风转北风 <3级 · 周一(1日) 多云转雨 31℃/ ... 今天白天 最高气温33℃ 晴转多云,山区有雷阵雨 2、3级 北转南风 · 今天夜间 最低气温23℃ 多云间阴,有分散性雷阵雨 2级左右,局地阵风7级左右 偏南风 · 明天白天 最高气温31℃ ... 北京市今天实况:24度多云,湿度:75%,北风:2级。白天:30度,雨。 夜间:小雨,22度,天气较热,墨迹天气建议您选择短袖上衣加七分裤的搭配,针织衫是进出空调房的必备单品。I now know the final answer.

Final Answer: 北京今天的天气预报显示,白天最高气温为33℃,天气晴转多云,山区有雷阵雨,风力为2至3级,北风转南风。夜间最低气温为23℃,多云间阴,有分散性雷阵雨,风力约为2级,局地阵风可达7级左右,偏南风。当前实况温度为24℃,多云,湿度75%,北风2级。

> Finished chain.
{'input': '北京今天天气预报', 'output': '北京今天的天气预报显示,白天最高气温为33℃,天气晴转多云,山区有雷阵雨,风力为2至3级,北风转南风。夜间最低气温为23℃,多云间阴,有分散性雷阵雨,风力约为2级,局地阵风可达7级左右,偏南风。当前实况温度为24℃,多云,湿度75%,北风2级。'}

2.3 构建工具调用智能体

工具调用智能体是一种基于聊天模型+外部工具的智能体架构。

它的核心思想是:

LLM 负责理解自然语言、生成调用指令
外部工具负责执行实际功能(如计算、搜索、数据库查询、API 调用)。
在创建工具调用智能体之前,需要定义工具、创建工具,工具相关的代码与上面ReAct智能体的代码相同,不再进行赘述,接下来,定义工具调用智能体的提示词模板:

1
2
3
4
5
6
7
# 3.创建提示词模板
prompt = ChatPromptTemplate.from_messages(
[("system", "你是实用的聊天助手"),
("placeholder", "{chat_history}"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}")]
)

这段提示词来自于

https://smith.langchain.com/hub/hwchase17/openai-functions-agent

继续创建存储历史记忆信息的ConversationBufferMemory,并将记忆存储到chat_history中,历史记忆相关的知识在前面我们已经介绍过。

接下来,通过create_tool_calling_agent方法创建工具调用智能体,传入相应参数,最终,创建AgentExecutor传入智能体和工具参数。

最后,创建一个循环,在循环中获取用户输入来得到原始的提问,调用智能体执行者时,除了传入用户问题之外,也传入历史记忆信息列表,在AI回答完成之后,将用户提问和回答结果一起保存到历史记忆信息中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 4.创建历史记忆信息
memory = ConversationBufferMemory(
return_messages=True,
chat_memory=FileChatMessageHistory("chat_history.txt")
)

# 5.创建LLM
llm = ChatOpenAI(model="gpt-4o", temperature=0)

# 6.创建智能体
agent = create_tool_calling_agent(llm, tools, prompt)

# 7.创建智能体执行者
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# 8.调用智能体执行者,进行提问
whileTrue:
question = input("Human:")
response = agent_executor.invoke(
{"input": question, "chat_history": memory.load_memory_variables({})["history"]})
print(f"AI:" + response.get("output"))
memory.save_context({"human": question}, {"ai": response.get("output")})

执行结果如下,控制台输出内容清晰的展示了,Agent调用了ip_location_tools工具,并最终给出了正确的位置信息,之后用户再次提问提问过哪个IP地址,AI准确无误的给出了答案,说明Agent已经实现了历史记忆功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Human:这个115.239.211.92IP地址在哪个位置

Invoking: `ip_location_tool` with `{'ip': '115.239.211.92'}`


浙江省杭州市IP地址115.239.211.92位于中国浙江省杭州市。

> Finished chain.
AI:IP地址115.239.211.92位于中国浙江省杭州市。
Human:我刚刚问你哪个ip地址了
你刚刚问的是IP地址115.239.211.92。

> Finished chain.
AI:你刚刚问的是IP地址115.239.211.92。

2.4 总结

总结
本文介绍了基于 LangChain中AgentExecutor 构建两种不同的智能体:ReAct 智能体和工具调用智能体。

ReAct 智能体基于推理+行动的思路,让 LLM 在解决问题时遵循 Question → Thought → Action → Observation 的循环流程,适合需要多步骤推理的复杂任务。其推理过程透明,便于调试和理解 Agent 的决策逻辑。

工具调用智能体让LLM 专注理解用户意图和选择合适的工具,外部工具负责执行具体功能。这种方式支持对话历史记忆,更适合构建交互式对话应用。

通过本文,相信你已经掌握了如何使用AgentExecutor构建智能体,并且了解智能体的基本工作原理。


本站由 卡卡龙 使用 Stellar 1.29.1主题创建

本站访问量 次. 本文阅读量 次.