langchain1.0中的agent
本文介绍了LangChain 1.0中基于LangGraph图构建的Agent系统。主要内容包括:1) Agent的创建过程,通过整合搜索和数学计算工具;2) 工具调用的ReAct模式,展示查询两国人口比率的完整交互流程;3) 错误处理机制,可自定义工具异常提示;4) 动态模型选择功能,根据上下文切换不同AI模型;5) 提示词定制方法,支持静态和动态系统提示;6) 结构化输出能力,可定义JSON或
1.概述
langchain1.0中的agent是基于langgraph中图构建的,所以一个agent的外部形态与图完全相同,比如调用时传入的数据和响应数据,可以使用长短期记忆,agent还能作为图中的节点。于此同时agent简化了老版本中agent的使用。
2.创建agent
以下分步创建一个能访问两个工具的agent,一个搜索工具,一个除法工具。
首先创建两个工具:
import os
from langchain_tavily import TavilySearchfrom langchain.tools import tool
os.environ["TAVILY_API_KEY"] = "tvly-*"
search_tool = TavilySearch(max_results=2)@tool
def divide(a: int, b:int)->int:
'''Divide two integers'''
return 1 / 0
tools = [search_tool, divide]
然后初始化大模型:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model = 'qwen-plus',
api_key = "sk-*",
base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1")
创建agent:
from langchain.agents import create_agent
agent = create_agent(
model=llm,
tools=tools,
)
3.工具调用
agent严格遵循ReAct (推理+行动)模式,在大模型推理和工具调用直接来回切换,并把工具执行结果传递给大模型作为推理的物料,直到最后给出答案。
如下例子直观了显示了推理和行动的过程:
state = {"messages":
[
{
"role": "user",
"content": "find population of north korea and south korea, then calculate ratio
between two countrys?"
}
]
}
for event in agent.invoke(state )['messages']:
event.pretty_print()
看看输出结果:
================================ Human Message =================================
find population of north korea and south korea, then calculate ratio between two countrys?
================================== Ai Message ==================================
Tool Calls:
tavily_search (call_4390975385c04954a90544)
Call ID: call_4390975385c04954a90544
Args:
query: population of North Korea and South Korea 2024
================================= Tool Message =================================
Name: tavily_search{"query": "population of North Korea and South Korea 2024", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://countryeconomy.com/countries/compare/south-korea/north-korea?sc=XE23", "title": "Country comparison South Korea vs North Korea Population 2025", "content": "Country comparison South Korea vs North Korea ; Crude marriage rate [+], 2024, 4.40‰ ; Population [+], 2024, 51,751,000 ; Immigrant stock [+], 2020, 1,728,182", "score": 0.8793233, "raw_content": null}, {"url": "https://www.macrotrends.net/global-metrics/countries/prk/north-korea/population", "title": "North Korea Population (1950-2025) - Macrotrends", "content": "## North Korea Population (1950-2025) ##### Total current population for North Korea in 2025 is **26,319,924**, a **0.29% increase** from 2024. * Total population for North Korea in 2024 was **26,244,582**, a **0.66% decline** from 2023. * Total population for North Korea in 2023 was **26,418,204**, a **0.34% increase** from 2022. * Total population for North Korea in 2022 was **26,328,845**, a **0.37% increase** from 2021. ###### Chart The chart has 2 X axes displaying Time, and navigator-x-axis. The chart has 2 Y axes displaying values, and navigator-y-axis. | North Korea Population Population | | | South Africa | 61,673,081 | | North Korea | 26,319,924 | | Guinea | 14,873,051 | | Papua New Guinea | 10,701,144 |", "score": 0.8742601, "raw_content": null}], "response_time": 1.03, "request_id": "558b6cda-ecb9-4eef-955a-74f320ca3fe2"}
================================== Ai Message ==================================
Tool Calls:
tavily_search (call_31675128eff442c4bd4203)
Call ID: call_31675128eff442c4bd4203
Args:
query: South Korea population 2024
================================= Tool Message =================================
Name: tavily_search{"query": "South Korea population 2024", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://countryeconomy.com/demography/population/south-korea", "title": "South Korea - Population 2024 - countryeconomy.com", "content": "South Korea ended 2024 with a population of 51751000 people, which represents an increasea of 38000 people compared to 2023.", "score": 0.97212255, "raw_content": null}, {"url": "https://tradingeconomics.com/south-korea/population", "title": "South Korea Population - Trading Economics", "content": "The total population in South Korea was estimated at 51.8 million people in 2024, according to the latest census figures and projections from Trading Economics.", "score": 0.96626127, "raw_content": null}], "response_time": 1.65, "request_id": "f4b16b66-1494-45c2-86d1-d46bab653904"}
================================== Ai Message ==================================
Tool Calls:
divide (call_f39084d0fa9643d2aa4dfc)
Call ID: call_f39084d0fa9643d2aa4dfc
Args:
a: 51751000
b: 26244582
================================= Tool Message =================================
Name: divide1.9718736613903776
================================== Ai Message ==================================Based on the latest available data:
- The population of **South Korea** in 2024 is approximately **51,751,000**.
- The population of **North Korea** in 2024 is approximately **26,244,582**.To calculate the ratio of South Korea's population to North Korea's population:
$$
\frac{51,751,000}{26,244,582} \approx 1.97
$$Thus, the ratio of the population of South Korea to North Korea is approximately **1.97:1**. This means South Korea has nearly twice the population of North Korea.
新版本的agent中工具调用功能更加强大,可以:
1)使用提示词实现对多个工具的串行调用
2)根据需要可以实现多个工具并行调用
3)基于运行状态动态选择需要调用的工具
4)支持工具调用出错重试和错误处理
5)基于持久化实现跨工具调用的状态共享
4.处理工具调用错误
可以对工具执行过程中的错误提示信息进行定制,具体方法如下:
1)首先定义一个方法,处理工具执行异常,该方法在工具执行出错时被调用
from langchain.agents.middleware import wrap_tool_call
from langchain_core.messages import ToolMessage
@wrap_tool_call
def handle_tool_errors(request, handler):
"""Handle tool execution errors with custom messages."""
try:
return handler(request)
except Exception as e:
# Return a custom error message to the model
return ToolMessage(
content=f"Tool error: Please check your input and try again. ({str(e)})",
tool_call_id=request.tool_call["id"]
)
2)在创建agent是把错误处理方法作为中间件参数传入
agent = create_agent(
model=llm,
tools=tools,
middleware=[handle_tool_errors]
)
3)模拟错误
修改divide,在内部计算1/0:
@tool
def divide(a: int, b:int)->int:
'''Divide two integers'''
return 1 / 0
再次执行,输出如下:
================================ Human Message =================================
find population of north korea and south korea, then calculate ratio between two countrys?
================================== Ai Message ==================================
Tool Calls:
tavily_search (call_74791527de4d4e42bb0e5e)
Call ID: call_74791527de4d4e42bb0e5e
Args:
query: population of North Korea and South Korea 2024
================================= Tool Message =================================
Name: tavily_search{"query": "population of North Korea and South Korea 2024", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://countryeconomy.com/countries/compare/south-korea/north-korea?sc=XE23", "title": "Country comparison South Korea vs North Korea Population 2025", "content": "Country comparison South Korea vs North Korea ; Crude marriage rate [+], 2024, 4.40‰ ; Population [+], 2024, 51,751,000 ; Immigrant stock [+], 2020, 1,728,182", "score": 0.8793233, "raw_content": null}, {"url": "https://www.macrotrends.net/global-metrics/countries/prk/north-korea/population", "title": "North Korea Population (1950-2025) - Macrotrends", "content": "## North Korea Population (1950-2025) ##### Total current population for North Korea in 2025 is **26,319,924**, a **0.29% increase** from 2024. * Total population for North Korea in 2024 was **26,244,582**, a **0.66% decline** from 2023. * Total population for North Korea in 2023 was **26,418,204**, a **0.34% increase** from 2022. * Total population for North Korea in 2022 was **26,328,845**, a **0.37% increase** from 2021. ###### Chart The chart has 2 X axes displaying Time, and navigator-x-axis. The chart has 2 Y axes displaying values, and navigator-y-axis. | North Korea Population Population | | | South Africa | 61,673,081 | | North Korea | 26,319,924 | | Guinea | 14,873,051 | | Papua New Guinea | 10,701,144 |", "score": 0.8742601, "raw_content": null}], "response_time": 0.0, "request_id": "0d1edfa9-9967-4dc6-a939-d35faeb74813"}
================================== Ai Message ==================================
Tool Calls:
tavily_search (call_43f90b6d8efe48fcaa2e79)
Call ID: call_43f90b6d8efe48fcaa2e79
Args:
query: South Korea population 2024
================================= Tool Message =================================
Name: tavily_search{"query": "South Korea population 2024", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://countryeconomy.com/demography/population/south-korea", "title": "South Korea - Population 2024 - countryeconomy.com", "content": "South Korea ended 2024 with a population of 51751000 people, which represents an increasea of 38000 people compared to 2023.", "score": 0.97212255, "raw_content": null}, {"url": "https://tradingeconomics.com/south-korea/population", "title": "South Korea Population - Trading Economics", "content": "The total population in South Korea was estimated at 51.8 million people in 2024, according to the latest census figures and projections from Trading Economics.", "score": 0.96626127, "raw_content": null}], "response_time": 0.0, "request_id": "90d0ad39-3454-4e81-8b72-37dbe46fd715"}
================================== Ai Message ==================================
Tool Calls:
divide (call_7b0cb5b71b304780ba728b)
Call ID: call_7b0cb5b71b304780ba728b
Args:
a: 51751000
b: 26244582
================================= Tool Message ================================='''这里是定制的错误提示'''
Tool error: Please check your input and try again. (division by zero)
================================== Ai Message ==================================It seems there was an error in the calculation due to a formatting issue. Let me correct it and calculate the ratio of the population of South Korea to North Korea properly.
Using the data:
- **South Korea population (2024):** 51,751,000
- **North Korea population (2024):** 26,244,582Now calculating the ratio:
$$
\text{Ratio} = \frac{51,751,000}{26,244,582} \approx 1.97
$$So, the population of South Korea is approximately **1.97 times** that of North Korea.
5.动态选择模型
与langgraph中的图一样,agent也可以根据上下文选择使用不同的模型,具体实现如下。
首先,声明一个上下文类,类中有一个provider属性,可以在调用时指定。
from dataclasses import dataclass
from typing import Literal@dataclass
class CustomContext:
provider: Literal["qwen", "deepseek"]
第二,定义模型选择器:
from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
@wrap_model_call
def dynamic_model_selection(request: ModelRequest, handler) -> ModelResponse:
provider = request.runtime.context.provider#从上下文获取provider
if provider == "qwen":
model = qwen_model
elif provider == "deepseek":
model = deepseek_model
else:
raise ValueError(f"Unsupported provider: {provider}")
request.model = model
return handler(request)
第三,创建两个大模型:
qwen_model = ChatOpenAI(
model = 'qwen-plus',
api_key = "sk-*",
base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1")
deepseek_model = ChatOpenAI(
model='deepseek-chat',
base_url='https://api.deepseek.com',
api_key='sk-*')
第四,创建agent,并传入模型选择器:
agent = create_agent(
model=qwen_model, # Default model
tools=tools,
middleware=[dynamic_model_selection]
)
第五:调用agent,在上下文中传入provider:
for event in agent.invoke(
{"messages":
[
{
"role": "user",
"content": "find population of north korea and south korea, then calculate ratio between two countrys?"
}
]
}
, context=CustomContext(provider="deepseek"),)['messages']:
event.pretty_print()
6.设置提示词
可以在创建agent时传入系统提示词,限定大模型的行为,比如:
agent = create_agent(
model,
tools,
system_prompt="你是一个精通唐诗的陕西人。." )
跟动态选择大模型一样,也可以根据上下文动态选择系统提示词,具体实现与动态选择模型非常类似,只不过使用了不同的注解。
#上下文,提供了提示词选择器。在这里就是level
class Context(TypedDict):
level: str#使用dynamic_prompt注解下面的方式,作为提示选择器
@dynamic_prompt
def user_level_prompt(request: ModelRequest) -> str:
"""Generate system prompt based on user role."""
level = request.runtime.context.get("level", "beginner")
base_prompt = "你是一个精通机器学习方面的专家."if user_role == "expert":
return f"{base_prompt} 解释问题时,提供更多的细节."
elif user_role == "beginner":
return f"{base_prompt} 解答问题时,尽量通俗易懂."return base_prompt
agent = create_agent(
model=llm,
tools=tools,#中间件中传入提示词选择器,当然可同时传入模型选择器
middleware=[user_level_prompt],
context_schema=Context
)
在调用时上下文中传入用户的level:
result = agent.invoke(
{"messages": [{"role": "user", "content": "解释一下朴素贝叶斯算法"}]},
context={"level": "expert"}
)
7.结构化输出
在langchain老版本中的输出解析器在agent中仍可以使用,当然使用方式有些不同。
首先定义,输出模式,比如下面的Resume,然后在创建agent时以response_format传入,具体代码如下:
from pydantic import BaseModel
from typing_extensions import TypedDict
from langchain.agents import create_agentfrom langchain.agents.structured_output import ToolStrategy
class Resume(TypedDict): #输出格式为JSON
name: str
age: str
phone: stragent = create_agent(
model=llm,
tools=tools,
response_format=ToolStrategy(Resume)
)result = agent.invoke({
"messages": [{"role": "user", "content": "从以下信息中提取Resume信息。我叫宋昌,今年35岁,我的电话号码是13812345678"}]
})result["structured_response"]
输出结果如下:
{'name': '宋昌', 'age': '35', 'phone': '13812345678'}
以上示例的输出是JSON,如果想使用一个标准类输出,则在定义模式时继承BaseModel即可。
8.agent的记忆
agent基于graph构建的,所以内置了状态(包括对话历史)作为短期记忆。agent支持对短期记忆进行扩展,保存用户自定义的数据。
agent在记忆中增加自定义数据有两种方式,一种是通过中间件,一种是通过state_schema参数传入。
1)通过中间件
如果需要在特定的中间件或者工具中访问自定义的数据,则必须通过中间件方式注入到agent中。
from langchain.agents import AgentState
from langchain.agents.middleware import AgentMiddleware#自定义数据
class CustomState(AgentState):
user_info: dict#中间件方法
class CustomMiddleware(AgentMiddleware):
state_schema = CustomState
tools = tools
#在调用模型前访问自定义数据,具体实现视具体情况而定
def before_model(self, state: CustomState, runtime) -> dict[str, Any] | None:
...agent = create_agent(
model,
tools=tools,
middleware=[CustomMiddleware()]
)# agent可以使用对话历史之外的定制数据
result = agent.invoke({
"messages": [{"role": "user", "content": "I prefer technical explanations"}],
"user_info": {"name": "赵无恤", "title": "大将军"},
})
2)通过state_schema传入
from langchain.agents import AgentState
#自定义数据
class CustomState(AgentState):
user_info: dictagent = create_agent(
model=llm,
tools=tools,
state_schema=CustomState#传入自定义数据
)
# agent可以使用对话历史之外的定制数据
result = agent.invoke({
"messages": [{"role": "user", "content": "I prefer technical explanations"}],
"user_info": {"name": "赵无恤", "title": "大将军"},
})
更多推荐
所有评论(0)