📖 目录
什么是 Agent?
想象一下,你有一个聪明的助手,它不仅能回答问题,还能主动使用各种工具来完成任务。这就是 Agent(智能代理)!
🎯 Agent vs 普通 LLM
| 特性 | 普通 LLM | Agent |
|---|---|---|
| 回答问题 | ✅ | ✅ |
| 使用工具 | ❌ | ✅ |
| 多步推理 | 有限 | ✅ |
| 自主决策 | ❌ | ✅ |
📊 Agent 的工作流程
用户输入 → LLM 推理 → 选择工具 → 执行工具 → 观察结果 → 再次推理 → 最终答案
↑______________________________________________|
(循环直到得出答案)
Agent 的核心组件
一个完整的 Agent 系统由三个核心部分组成:
1. 🧠 模型(Model)
模型是 Agent 的"大脑",负责推理和决策。
静态模型配置:
在创建agent的时候配置一次,后续在整个执行过程中保持不变。
from langchain.agents import create_agent
from langchain_deepseek import ChatDeepSeek
# 方式1:使用模型标识符字符串(简单快捷)
agent = create_agent("deepseek:deepseek-chat", tools=tools)
# 方式2:使用模型实例(更多控制)
model = ChatDeepSeek(
model="deepseek-chat",
temperature=0.7, # 控制创造性
max_tokens=2000, # 限制输出长度
timeout=60 # 超时设置
)
agent = create_agent(model, tools=tools)
动态模型选择:
有时候,我们需要根据不同场景选择不同的模型。比如简单问题用便宜的模型,复杂问题用强大的模型:
我们通过 @wrap_model_call 装饰器来创建中间件的方式来使用动态模型,概中间件会修改请求中的模型。
from langchain.agents.middleware import wrap_model_call
basic_model = ChatDeepSeek(model="deepseek-chat")
advanced_model = ChatDeepSeek(model="deepseek-reasoner")
@wrap_model_call
def smart_model_selection(request, handler):
"""根据对话复杂度智能选择模型"""
message_count = len(request.state["messages"])
if message_count > 10:
# 长对话使用推理模型
model = advanced_model
print("📈 使用推理模型处理复杂对话")
else:
# 短对话使用对话模型节省成本
model = basic_model
print("💡 使用对话模型处理简单对话")
return handler(request.override(model=model))
agent = create_agent(
model=basic_model,
tools=tools,
middleware=[smart_model_selection]
)
2. 🔧 工具(Tools)
工具赋予 Agent 行动能力,让它能够与外部世界交互。
定义工具示例:
from langchain.tools import tool
@tool
def search_web(query: str) -> str:
"""在互联网上搜索信息"""
# 实际项目中这里会调用真实的搜索 API
return f"搜索结果:{query} 的相关信息..."
@tool
def get_weather(city: str) -> str:
"""获取指定城市的天气信息"""
# 实际项目中这里会调用天气 API
weather_data = {
"北京": "晴天,15°C",
"上海": "多云,18°C",
"深圳": "阴天,22°C"
}
return weather_data.get(city, "未知城市")
@tool
def calculate(expression: str) -> str:
"""计算数学表达式"""
try:
result = eval(expression)
return f"计算结果:{result}"
except Exception as e:
return f"计算错误:{str(e)}"
# 创建 Agent 时传入工具列表
tools = [search_web, get_weather, calculate]
如果提供了一个空的工具列表,智能体将由一个不具备工具调用功能的单个 LLM 节点组成。
工具错误处理:
通过 @wrap_tool_call 中间件自定义工具错误的处理方式。
from langchain.agents.middleware import wrap_tool_call
from langchain.messages import ToolMessage
@wrap_tool_call
def handle_tool_errors(request, handler):
"""优雅地处理工具执行错误"""
try:
return handler(request)
except Exception as e:
print(f"❌ 工具执行失败:{str(e)}")
return ToolMessage(
content=f"工具执行出错,请检查输入后重试。错误信息:{str(e)}",
tool_call_id=request.tool_call["id"]
)
agent = create_agent(
model="deepseek-chat",
tools=[search_web, get_weather, calculate],
middleware=[handle_tool_errors]
)
上述示例,会在工具失败时,返回一个自定义的错误消息 ToolMessage 。
3. 💬 系统提示词(System Prompt)
系统提示词定义了 Agent 的"性格"和行为准则。
# 基础系统提示词
agent = create_agent(
model="deepseek-chat",
tools=tools,
system_prompt="你是一个专业的数据分析助手,擅长用图表和数据说话。"
)
# 动态系统提示词(根据用户角色调整)
from langchain.agents.middleware import dynamic_prompt
@dynamic_prompt
def role_based_prompt(request):
"""根据用户角色生成个性化提示词"""
user_role = request.runtime.context.get("user_role", "普通用户")
prompts = {
"专家": "你是技术专家助手,提供深入的技术分析和详细解释。",
"初学者": "你是新手友好的助手,用简单易懂的语言解释概念,避免术语。",
"学生": "你是教学助手,通过例子和类比帮助学生理解知识。"
}
return prompts.get(user_role, "你是一个友好的通用助手。")
agent = create_agent(
model="deepseek-chat",
tools=tools,
middleware=[role_based_prompt]
)
当未提供 system_prompt 时,agent会直接从消息中推断其任务。 @dynamic_prompt 装饰器创建了一个中间件,可以根据模型请求动态生成系统提示
快速上手:创建你的第一个 Agent
🎬 完整示例:天气查询助手
from langchain.agents import create_agent
from langchain_deepseek import ChatDeepSeek
from langchain.tools import tool
# 步骤1:定义工具
@tool
def get_weather(city: str) -> str:
"""获取城市天气信息
Args:
city: 城市名称,如"北京"、"上海"
Returns:
该城市的天气信息
"""
weather_db = {
"北京": "☀️ 晴天,温度 15°C,空气质量良好",
"上海": "⛅ 多云,温度 18°C,有轻微雾霾",
"深圳": "🌧️ 小雨,温度 22°C,湿度较大",
"广州": "☀️ 晴天,温度 25°C,适合外出"
}
return weather_db.get(city, f"抱歉,暂无 {city} 的天气信息")
@tool
def get_weather_forecast(city: str, days: int = 3) -> str:
"""获取城市未来几天的天气预报
Args:
city: 城市名称
days: 预报天数(默认3天)
Returns:
未来几天的天气预报
"""
return f"{city} 未来 {days} 天天气:\n第1天:晴 20°C\n第2天:多云 18°C\n第3天:小雨 16°C"
# 步骤2:创建 Agent
weather_agent = create_agent(
model=ChatDeepSeek(model="deepseek-chat", temperature=0),
tools=[get_weather, get_weather_forecast],
system_prompt="""你是一个专业的天气助手。
你的职责:
1. 准确提供用户查询的城市天气信息
2. 如果用户询问未来天气,主动使用天气预报工具
3. 给出贴心的出行建议
回答风格:友好、简洁、实用
"""
)
# 步骤3:使用 Agent
print("🤖 天气助手已启动!\n")
# 示例对话1:查询当前天气
result1 = weather_agent.invoke({
"messages": [{"role": "user", "content": "北京现在天气怎么样?"}]
})
print("用户:北京现在天气怎么样?")
print(f"助手:{result1['messages'][-1].content}\n")
# 示例对话2:查询未来天气
result2 = weather_agent.invoke({
"messages": [{"role": "user", "content": "上海这周末天气如何?我想去外滩"}]
})
print("用户:上海这周末天气如何?我想去外滩")
print(f"助手:{result2['messages'][-1].content}")
运行结果:
🤖 天气助手已启动!
用户:北京现在天气怎么样?
助手:北京现在天气很好!☀️ 晴天,温度 15°C,空气质量良好。适合外出活动,建议穿薄外套。
用户:上海这周末天气如何?我想去外滩
助手:上海这周末天气预报:
第1天:晴 20°C
第2天:多云 18°C
第3天:小雨 16°C
建议周六去外滩,天气最好!周日可能有小雨,记得带伞哦。☔
深入理解:Agent 的工作原理
🔄 ReAct 循环:推理 + 行动
Agent 使用 ReAct(Reasoning + Acting)模式工作:
┌─────────────────────────────────────────────────────────────┐
│ ReAct 工作流程 │
└─────────────────────────────────────────────────────────────┘
1️⃣ 用户输入:
"帮我查询北京和上海的天气,然后告诉我哪个城市更适合旅游"
2️⃣ Agent 推理:
💭 "我需要先获取两个城市的天气信息,然后进行比较"
3️⃣ Agent 行动:
🔧 调用工具 get_weather("北京")
4️⃣ 观察结果:
📊 "北京:晴天,15°C,空气质量良好"
5️⃣ Agent 再次推理:
💭 "好的,已经有北京的天气了,现在获取上海的"
6️⃣ Agent 再次行动:
🔧 调用工具 get_weather("上海")
7️⃣ 观察结果:
📊 "上海:多云,18°C,有轻微雾霾"
8️⃣ Agent 最终推理:
💭 "现在我有两个城市的天气数据,可以进行比较了"
9️⃣ 输出答案:
✅ "根据天气情况,北京更适合旅游。北京是晴天且空气质量良好,
而上海多云且有轻微雾霾。建议选择北京。"
📈 实际执行追踪
# 启用详细追踪模式
agent = create_agent(
model="deepseek-chat",
tools=[get_weather, get_weather_forecast],
system_prompt="你是天气助手"
)
# 流式输出,查看中间步骤
print("=" * 60)
print("🔍 Agent 执行追踪")
print("=" * 60)
for chunk in agent.stream(
{"messages": [{"role": "user", "content": "比较北京和上海的天气"}]},
stream_mode="values"
):
latest_message = chunk["messages"][-1]
if latest_message.content:
print(f"\n💬 Agent 回复:{latest_message.content}")
elif hasattr(latest_message, 'tool_calls') and latest_message.tool_calls:
tool_names = [tc['name'] for tc in latest_message.tool_calls]
print(f"\n🔧 正在调用工具:{', '.join(tool_names)}")
高级特性
1. 🎯 结构化输出
让 Agent 返回格式化的数据结构,而不是纯文本。LangChain 通过 response_format 参数提供结构化输出策略。
ToolStrategy
ToolStrategy 使用人工工具调用来生成结构化输出。这适用于任何支持工具调用的模型。
from pydantic import BaseModel, Field
from langchain.agents.structured_output import ToolStrategy
class WeatherReport(BaseModel):
"""天气报告数据模型"""
city: str = Field(description="城市名称")
temperature: int = Field(description="温度(摄氏度)")
weather: str = Field(description="天气状况")
suggestion: str = Field(description="出行建议")
# 创建返回结构化输出的 Agent
structured_agent = create_agent(
model="deepseek-chat",
tools=[get_weather],
response_format=ToolStrategy(WeatherReport)
)
result = structured_agent.invoke({
"messages": [{"role": "user", "content": "查询北京天气"}]
})
# 获取结构化数据
weather_data = result["structured_response"]
print(f"城市:{weather_data.city}")
print(f"温度:{weather_data.temperature}°C")
print(f"天气:{weather_data.weather}")
print(f"建议:{weather_data.suggestion}")
输出示例:
城市:北京
温度:15°C
天气:晴天
建议:天气晴朗,适合户外活动,建议穿薄外套
ProviderStrategy
使用模型提供者原生的结构化输出生成。这更可靠,但仅适用于支持原生结构化输出的提供者(例如 OpenAI)。
from langchain.agents.structured_output import ProviderStrategy
agent = create_agent(
model="gpt-4o",
response_format=ProviderStrategy(ContactInfo)
)
2. 🧠 记忆与状态管理
让 Agent 记住对话上下文和用户偏好。
from langchain.agents import AgentState
from langchain.agents.middleware import AgentMiddleware
from typing import TypedDict
# 定义自定义状态
class WeatherAgentState(AgentState):
user_preferences: dict # 用户偏好
search_history: list # 搜索历史
class MemoryMiddleware(AgentMiddleware):
"""带记忆的中间件"""
state_schema = WeatherAgentState
def before_model(self, state, runtime):
# 在调用模型前,添加历史记录到上下文
history = state.get("search_history", [])
if history:
print(f"📚 用户历史查询:{', '.join(history[-3:])}")
return None
# 创建带记忆的 Agent
memory_agent = create_agent(
model="deepseek-chat",
tools=[get_weather],
middleware=[MemoryMiddleware()]
)
# 使用带状态的调用
result = memory_agent.invoke({
"messages": [{"role": "user", "content": "北京天气"}],
"user_preferences": {"temperature_unit": "celsius"},
"search_history": ["上海", "广州", "深圳"]
})
3. 🔀 动态工具选择
根据不同场景动态提供不同的工具集。
from langchain.agents.middleware import wrap_model_call
@wrap_model_call
def permission_based_tools(request, handler):
"""根据用户权限动态选择工具"""
user_role = request.runtime.context.get("user_role", "guest")
if user_role == "admin":
# 管理员拥有所有工具
tools = [get_weather, get_weather_forecast, update_weather_data]
print("🔐 管理员权限:所有工具可用")
elif user_role == "vip":
# VIP 用户可以使用高级功能
tools = [get_weather, get_weather_forecast]
print("⭐ VIP 权限:基础 + 预报工具")
else:
# 普通用户只能查询基础天气
tools = [get_weather]
print("👤 普通权限:仅基础工具")
return handler(request.override(tools=tools))
dynamic_tool_agent = create_agent(
model="deepseek-chat",
tools=[get_weather, get_weather_forecast],
middleware=[permission_based_tools]
)
# 以不同角色调用
result = dynamic_tool_agent.invoke(
{"messages": [{"role": "user", "content": "查询天气"}]},
context={"user_role": "vip"}
)
实战案例
🌟 案例1:智能旅游助手
结合多个工具的综合应用。
from langchain.tools import tool
from langchain.agents import create_agent
from langchain_deepseek import ChatDeepSeek
# 定义多个旅游相关工具
@tool
def get_weather(city: str) -> str:
"""获取城市天气"""
return f"{city}:晴天,适合旅游"
@tool
def search_attractions(city: str) -> str:
"""搜索城市景点"""
attractions = {
"北京": "故宫、长城、颐和园、天坛",
"上海": "外滩、东方明珠、豫园、迪士尼",
"杭州": "西湖、灵隐寺、千岛湖、宋城"
}
return f"{city}热门景点:{attractions.get(city, '暂无数据')}"
@tool
def estimate_budget(city: str, days: int) -> str:
"""估算旅游预算"""
daily_cost = {"北京": 800, "上海": 900, "杭州": 700}
cost = daily_cost.get(city, 800) * days
return f"{city} {days}天旅游预算约:{cost}元(含住宿、餐饮、门票)"
@tool
def get_transportation(from_city: str, to_city: str) -> str:
"""查询交通方式"""
return f"{from_city} → {to_city}:高铁3小时,飞机1.5小时"
# 创建旅游助手
travel_agent = create_agent(
model=ChatDeepSeek(model="deepseek-chat", temperature=0.7),
tools=[get_weather, search_attractions, estimate_budget, get_transportation],
system_prompt="""你是一个专业的旅游规划助手。
你的能力:
1. 查询天气信息,判断是否适合旅游
2. 推荐热门景点,制定游玩路线
3. 估算旅游预算,帮助用户做好财务规划
4. 查询交通方式,提供出行建议
你的风格:
- 热情友好,充满旅游热情
- 提供详细实用的建议
- 考虑用户预算和时间限制
"""
)
# 示例对话
print("🏖️ 智能旅游助手")
print("=" * 60)
query = """我想从北京去杭州玩3天,帮我规划一下:
1. 现在天气怎么样?
2. 有什么好玩的地方?
3. 大概需要多少预算?
4. 怎么去比较方便?
"""
result = travel_agent.invoke({
"messages": [{"role": "user", "content": query}]
})
print(f"用户提问:\n{query}\n")
print(f"助手回答:\n{result['messages'][-1].content}")
预期输出:
🏖️ 智能旅游助手
============================================================
用户提问:
我想从北京去杭州玩3天,帮我规划一下:
1. 现在天气怎么样?
2. 有什么好玩的地方?
3. 大概需要多少预算?
4. 怎么去比较方便?
助手回答:
太好了!让我为您规划这次杭州之旅 🎉
📍 **目的地天气**
杭州:晴天,非常适合旅游!
🎯 **推荐景点**
杭州的热门景点有:西湖、灵隐寺、千岛湖、宋城
建议第一天游西湖,第二天去灵隐寺,第三天可以去宋城体验文化演出。
💰 **预算估算**
3天旅游预算约:2100元(含住宿、餐饮、门票)
建议多准备500元作为购物和应急资金。
🚄 **交通建议**
北京 → 杭州:高铁3小时,飞机1.5小时
推荐乘坐高铁,舒适便捷,沿途风景也不错!
祝您旅途愉快!✈️
🌟 案例2:客服助手(流式响应)
展示如何实现流式输出,提升用户体验。
@tool
def search_order(order_id: str) -> str:
"""查询订单信息"""
return f"订单 {order_id}:已发货,预计明天到达"
@tool
def check_inventory(product_id: str) -> str:
"""检查库存"""
return f"商品 {product_id}:库存充足,可立即发货"
@tool
def process_refund(order_id: str) -> str:
"""处理退款"""
return f"订单 {order_id} 退款申请已提交,3-5个工作日到账"
customer_service_agent = create_agent(
model="deepseek-chat",
tools=[search_order, check_inventory, process_refund],
system_prompt="你是一个耐心专业的客服助手。"
)
# 流式输出
print("💬 客服对话(流式输出)")
print("=" * 60)
for chunk in customer_service_agent.stream(
{"messages": [{"role": "user", "content": "我的订单 12345 什么时候到?"}]},
stream_mode="values"
):
latest = chunk["messages"][-1]
if latest.content:
print(f"客服:{latest.content}", end="\n\n")
elif hasattr(latest, 'tool_calls') and latest.tool_calls:
print(f"[正在查询订单信息...]", end="\n")