3.1 什么是 Agent
Agent(代理)是 LangChain 中让模型能够自主决策并调用工具的核心组件。与普通的 Chain 不同,Agent 可以根据输入动态决定下一步操作。
🤖 一句话理解:Agent = 模型(大脑)+ 工具(手脚)+ 循环(思考→行动→观察)
🔄 Chain vs Agent
| 特性 | Chain | Agent |
|---|---|---|
| 执行方式 | 固定顺序 | 动态决策 |
| 下一步 | 预先定义 | 模型决定 |
| 工具调用 | 不支持 | 支持 |
| 循环 | 单次执行 | 多轮循环 |
| 适用场景 | 固定流程 | 复杂任务 |
3.1.1 Agent 的工作流程
Agent 通过一个循环来处理任务:
- 接收输入:获取用户的请求
- 思考(Think):模型分析当前情况,决定是否需要调用工具
- 行动(Action):调用选定的工具
- 观察(Observe):获取工具返回的结果
- 判断:如果任务完成,返回结果;否则继续循环
3.2 ReAct 思考模式
ReAct(Reasoning + Acting)是一种让模型同时进行推理和行动的方法。它结合了链式思考(Chain-of-Thought)的推理能力和工具调用的行动能力。
相比纯推理(Chain-of-Thought),ReAct 的优势在于:模型可以与外部世界交互,获取实时信息;相比纯行动(Action-only),ReAct 的优势在于:模型有明确的思考过程,决策更透明、更可解释。
3.3 Agent 类型详解
LangChain 提供了多种预置的 Agent 类型,适用于不同的场景。
| Agent 类型 | 特点 | 适用场景 |
|---|---|---|
| OpenAI Functions | 使用 OpenAI 的 function calling 功能 | OpenAI 模型首选 |
| ReAct | 标准的 ReAct 循环 | 通用场景 |
| Self-Ask | 包含自我追问 | 复杂推理 |
| Conversational | 对话式,带记忆 | 聊天机器人 |
3.3.1 使用 OpenAI Functions Agent
from langchain_openai import ChatOpenAI
from langchain.agents import create_openai_functions_agent
from langchain.tools.render import format_tool_to_openai_function
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
# 初始化模型
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# 定义工具
from langchain_community.tools import WikipediaQueryRun, DuckDuckGoSearchRun
search = DuckDuckGoSearchRun()
wikipedia = WikipediaQueryRun()
tools = [search, wikipedia]
# 创建 Agent
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个有帮助的助手,擅长搜索信息并回答问题。"),
MessagesPlaceholder("chat_history", optional=True),
("human", "{input}"),
MessagesPlaceholder("agent_scratchpad"), # Agent 的中间思考过程
])
agent = create_openai_functions_agent(llm, tools, prompt)
# 运行 Agent
from langchain.agents import AgentExecutor
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = agent_executor.invoke({"input": "特斯拉的 CEO 是谁?"})
print(result["output"])
3.3.2 使用 ReAct Agent
from langchain_openai import ChatOpenAI
from langchain.agents import create_react_agent
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
# 初始化模型
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 创建 ReAct Agent
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个有帮助的助手。"),
("human", "{input}"),
MessagesPlaceholder("agent_scratchpad"),
])
# 工具列表
tools = [search, wikipedia] # 复用上面的工具
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True, # 打印思考过程
max_iterations=5 # 最大迭代次数
)
result = agent_executor.invoke({"input": "LangChain 是什么时候发布的?"})
print(result["output"])
3.4 Tools 工具系统
Tools(工具)是 Agent 与外部世界交互的桥梁。通过工具,Agent 可以搜索网络、执行计算、读写文件、调用 API 等。
3.4.1 内置工具
LangChain 内置了大量常用工具:
| 工具 | 功能 | 安装 |
|---|---|---|
| DuckDuckGoSearch | 网络搜索 | langchain-community |
| Wikipedia | 维基百科查询 | wikipedia |
| WolframAlpha | 计算引擎 | wolframalpha |
| Python REPL | 执行 Python 代码 | 内置 |
| SerpAPI | Google 搜索 | google-search-results |
3.4.2 自定义工具
你可以创建自己的工具:
from langchain_core.tools import tool
from datetime import datetime
# 方式一:使用 @tool 装饰器
@tool
def get_current_time() -> str:
"""获取当前的日期和时间"""
return datetime.now().strftime("%Y年%m月%d日 %H:%M:%S")
@tool
def calculate(expression: str) -> str:
"""执行数学计算
Args:
expression: 数学表达式,如 "2 + 2" 或 "sqrt(16)"
"""
try:
import math
# 安全评估简单表达式
result = eval(expression, {"__builtins__": {}, "sqrt": math.sqrt, "pi": math.pi}, {})
return str(result)
except Exception as e:
return f"计算错误:{str(e)}"
# 使用
print(get_current_time.invoke({}))
# 2026年04月21日 09:20:30
print(calculate.invoke({"expression": "2 + 2 * 3"}))
# 8
3.4.3 工具的完整示例
from langchain_openai import ChatOpenAI
from langchain.agents import create_openai_functions_agent, AgentExecutor
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# 定义自定义工具
@tool
def get_weather(city: str) -> str:
"""获取指定城市的天气信息
Args:
city: 城市名称,如"北京"、"上海"
"""
# 实际应用中这里会调用天气 API
weather_data = {
"北京": "晴,15-25°C",
"上海": "多云,18-28°C",
"广州": "雨,22-30°C",
}
return weather_data.get(city, "未知城市")
@tool
def get_time() -> str:
"""获取当前时间"""
from datetime import datetime
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 创建 Agent
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个天气助手,可以查询城市天气和时间。"),
MessagesPlaceholder("chat_history", optional=True),
("human", "{input}"),
MessagesPlaceholder("agent_scratchpad"),
])
tools = [get_weather, get_time]
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# 测试
result = agent_executor.invoke({
"input": "北京今天天气怎么样?现在几点了?"
})
print(result["output"])
3.5 Memory 记忆系统
Memory(记忆)让 Agent 能够记住之前的对话内容和中间结果。这是构建多轮对话应用的基础。
3.5.1 Memory 的类型
| 类型 | 描述 | 适用场景 |
|---|---|---|
| BufferMemory | 保存所有对话历史 | 简单场景 |
| SummaryMemory | 总结对话内容 | 长对话 |
| EntityMemory | 提取实体信息 | 用户画像 |
| ConversationBufferWindowMemory | 只保留最近 N 轮 | 限制上下文长度 |
3.5.2 使用 BufferMemory
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents import create_openai_functions_agent, AgentExecutor
from langchain_core.chat_history import InMemoryChatMessageHistory
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# 创建带记忆的 Agent
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个乐于助人的助手。"),
MessagesPlaceholder("chat_history", optional=True),
("human", "{input}"),
MessagesPlaceholder("agent_scratchpad"),
])
agent = create_openai_functions_agent(llm, tools=[], prompt=prompt)
# 创建记忆管理
chat_history = InMemoryChatMessageHistory()
agent_executor = AgentExecutor(agent=agent, tools=[], memory=chat_history)
# 多轮对话
response1 = agent_executor.invoke({"input": "我叫张三"})
print(response1["output"]) # 很高兴认识你,张三!
response2 = agent_executor.invoke({"input": "我叫什么名字?"})
print(response2["output"]) # 你叫张三!
# 查看记忆内容
print(chat_history.messages)
# [HumanMessage(content='我叫张三'), AIMessage(content='很高兴认识你,张三!'),
# HumanMessage(content='我叫什么名字?'), AIMessage(content='你叫张三!')]
3.5.3 对话摘要记忆
对于很长的对话,我们可以使用摘要记忆来压缩历史:
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain.memory.summary import GeneratedSummary
# 创建摘要记忆
summary_memory = GeneratedSummary(
chat_memory=InMemoryChatMessageHistory(),
llm=llm, # 用于生成摘要的模型
)
# 或者使用内置的 ConversationSummaryMemory
from langchain.memory import ConversationSummaryMemory
memory = ConversationSummaryMemory(llm=llm, return_messages=True)
# 添加对话
memory.save_context({"input": "我叫李四"}, {"output": "你好李四!"})
memory.save_context({"input": "我喜欢编程"}, {"output": "编程是一项很棒的技能!"})
# 获取记忆
print(memory.load_memory_variables({})["history"])
# "用户叫李四,喜欢编程。助手已友好地回应。"
3.6 对话历史管理
3.6.1 RunnableWithMessageHistory
使用 RunnableWithMessageHistory 可以轻松实现多会话管理:
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.chat_history import InMemoryChatMessageHistory
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个乐于助人的助手。"),
MessagesPlaceholder("history"),
("human", "{message}"),
])
chain = prompt | llm
# 创建带对话历史的链
chat_history_store = {} # 存储不同会话的历史
def get_history(session_id: str):
"""获取或创建指定会话的历史"""
if session_id not in chat_history_store:
chat_history_store[session_id] = InMemoryChatMessageHistory()
return chat_history_store[session_id]
chain_with_history = RunnableWithMessageHistory(
chain,
get_history,
input_messages_key="message",
history_messages_key="history",
)
# 用户 1 的对话
print(chain_with_history.invoke(
{"message": "我叫王五"},
config={"configurable": {"session_id": "user_001"}}
).content)
# 很高兴认识你,王五!
# 用户 2 的对话(独立会话)
print(chain_with_history.invoke(
{"message": "我叫赵六"},
config={"configurable": {"session_id": "user_002"}}
).content)
# 你好赵六!
# 用户 1 继续对话
print(chain_with_history.invoke(
{"message": "我叫什么名字?"},
config={"configurable": {"session_id": "user_001"}}
).content)
# 你叫王五!
3.6.2 滑动窗口记忆
只保留最近 N 轮对话,避免超出模型的上下文限制:
from langchain.memory import ConversationBufferWindowMemory
from langchain.agents import create_openai_functions_agent
# 只保留最近 3 轮对话
window_size = 3
memory = ConversationBufferWindowMemory(
k=window_size,
return_messages=True,
llm=llm,
)
# 每次对话后更新记忆
memory.save_context({"input": "第1轮问题"}, {"output": "第1轮回答"})
memory.save_context({"input": "第2轮问题"}, {"output": "第2轮回答"})
memory.save_context({"input": "第3轮问题"}, {"output": "第3轮回答"})
memory.save_context({"input": "第4轮问题"}, {"output": "第4轮回答"})
# 查看记忆 - 只有最近的3轮
print(memory.load_memory_variables({})["history"])
# 第2轮、第3轮、第4轮的对话(不包含第1轮)
3.7 本章小结
📝 关键概念回顾
| 概念 | 说明 |
|---|---|
| Agent | 让模型自主决策并调用工具 |
| ReAct | 推理 + 行动的思考循环 |
| Tools | Agent 与外部世界交互的桥梁 |
| Memory | 管理对话历史和上下文 |
| RunnableWithMessageHistory | 多会话管理 |
- Agent:相比 Chain,可以动态决定下一步操作,支持工具调用
- ReAct:Think → Action → Observe 的循环,让模型既会思考又会行动
- Tools:使用
@tool装饰器创建自定义工具 - Memory:BufferMemory、SummaryMemory、EntityMemory 等多种类型
- 对话历史:使用
RunnableWithMessageHistory管理多会话
在下一章中,我们将学习 模型 I/O 与 Tools,深入了解如何与不同类型的模型交互,以及如何构建更复杂的工具系统。
关注我们
微信公众号
第一时间获取更新
小红书
更多学习干货分享