智能体在真实环境中需应对突发错误(如工具调用失败、服务不可用),异常处理与恢复模式的核心是:通过错误检测、分层处理、恢复机制,确保智能体在故障时不崩溃,保持功能连续性或优雅降级,提升系统可靠性。
核心逻辑
1. 核心组成
- 错误检测:识别工具调用失败、API 错误(404/500)、数据格式异常等问题。
- 错误处理:日志记录、重试、备用方案、优雅降级、通知告警。
- 恢复机制:状态回滚、自我修正、人工升级,将系统恢复至稳定状态。
2. 典型应用场景
- 客服机器人:数据库不可用时,告知用户并转人工。
- 交易机器人:处理“资金不足”“市场关闭”等错误,避免重复无效操作。
- 数据处理智能体:跳过损坏文件,继续批量任务并记录异常。
- 爬虫智能体:应对验证码、服务器错误,优雅暂停或报告失败。
实战代码示例(LangChain)
以下基于 LangChain 实现健壮的位置查询系统,核心能力:主工具调用失败时自动触发备用方案,最终统一输出结果,全程记录错误日志。
依赖安装
pip install langchain langchain-google-genai python-dotenv requests
创建 .env 文件配置密钥:
GOOGLE_API_KEY=你的 Gemini API 密钥(从 Google AI Studio 获取)
核心代码
"""
LangChain 异常处理与恢复示例:健壮位置查询系统
核心特性:
1. 主工具(精确位置查询)优先执行,失败自动触发备用工具(城市级查询)
2. 全程错误日志记录,支持问题追溯
3. 统一结果输出,失败时给出友好提示
4. 状态管理确保流程衔接顺畅
"""
import logging
from typing import Dict, Any
from dotenv import load_dotenv
from langchain.agents import AgentType, initialize_agent, Tool
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain.callbacks.base import BaseCallbackHandler
# --------------------------
# 1. 日志配置:记录错误与流程(便于调试和追溯)
# --------------------------
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
logging.FileHandler("agent_error.log"), # 错误日志写入文件
logging.StreamHandler() # 同时输出到控制台
]
)
logger = logging.getLogger("location_agent")
# 加载环境变量
load_dotenv()
# --------------------------
# 2. 自定义异常类:统一管理位置查询相关错误
# --------------------------
class LocationToolError(Exception):
"""位置查询工具专用异常类,区分不同故障场景"""
pass
# --------------------------
# 3. 位置查询工具实现(模拟真实场景中的工具/API)
# --------------------------
def get_precise_location_info(address: str) -> str:
"""
主工具:获取精确位置信息(需完整地址)
功能:返回包含经纬度、详细地址的精确结果
失败条件:地址缺少街道、门牌号等关键信息
"""
try:
# 模拟业务校验:仅接受包含街道关键词的完整地址
street_keywords = ["街", "路", "巷", "弄", "号"]
if not any(keyword in address for keyword in street_keywords):
raise LocationToolError(f"地址 '{address}' 不完整,缺少街道或门牌号信息")
# 模拟成功响应(实际场景中对接地图API)
return (
f"精确位置结果:\n"
f"- 地址:{address}\n"
f"- 经度:120.123456\n"
f"- 纬度:30.654321\n"
f"- 行政区域:XX省XX市XX区"
)
except LocationToolError as e:
# 记录业务错误日志
logger.error(f"精确位置查询失败:{str(e)}")
raise # 抛出异常,让智能体检测
except Exception as e:
# 捕获未知错误,统一包装为自定义异常
logger.error(f"精确位置查询意外错误:{str(e)}")
raise LocationToolError(f"系统异常:{str(e)}") from e
def get_general_area_info(city: str) -> str:
"""
备用工具:获取城市级模糊位置信息(容错性更高)
功能:仅需城市名称,返回大致区域信息
适用场景:主工具失败时的降级方案
"""
try:
# 模拟基础校验:城市名称不为空
if not city.strip():
raise LocationToolError("城市名称不能为空")
# 模拟成功响应(实际场景中对接简化版地图API)
return (
f"城市级位置结果:\n"
f"- 城市:{city}\n"
f"- 经度:120.123\n"
f"- 纬度:30.654\n"
f"- 行政区域:XX省{city}市"
)
except Exception as e:
logger.error(f"城市位置查询错误:{str(e)}")
raise LocationToolError(f"获取城市信息失败:{str(e)}") from e
# --------------------------
# 4. 回调处理器:检测工具错误并管理状态
# --------------------------
class ErrorDetectionCallback(BaseCallbackHandler):
"""
自定义回调处理器,核心作用:
1. 监听工具调用失败事件
2. 维护流程状态(主工具是否失败、查询结果等)
3. 为后续智能体提供状态数据
"""
def __init__(self):
# 初始化状态字典,存储流程关键信息
self.state: Dict[str, Any] = {
"primary_failed": False, # 主工具是否失败
"location_result": None, # 最终位置结果
"original_query": "", # 用户原始查询
"extracted_city": "" # 提取的城市名称
}
def on_tool_error(self, error: Exception, **kwargs):
"""工具调用失败时触发的回调方法"""
if isinstance(error, LocationToolError):
self.state["primary_failed"] = True
logger.info("主工具调用失败,将触发备用方案")
def reset(self):
"""重置状态(每次处理新查询前调用)"""
self.state = {
"primary_failed": False,
"location_result": None,
"original_query": "",
"extracted_city": ""
}
# --------------------------
# 5. 构建核心智能体(分层设计,各司其职)
# --------------------------
# 初始化 LLM 模型
llm = ChatGoogleGenerativeAI(
model="gemini-2.0-flash",
temperature=0.3 # 低温度保证结果稳定性
)
# 初始化状态管理回调
state_callback = ErrorDetectionCallback()
# 5.1 主智能体:尝试精确位置查询
primary_agent = initialize_agent(
tools=[
Tool(
name="get_precise_location_info",
func=get_precise_location_info,
description="获取精确位置信息,必须传入包含街道、门牌号的完整地址(示例:上海市浦东新区博云路2号)"
)
],
llm=llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
callbacks=[state_callback], # 绑定状态回调
agent_kwargs={
"system_message": """
你的任务:
1. 从用户查询中提取完整地址(含街道、门牌号)
2. 调用 get_precise_location_info 工具查询
3. 若工具调用成功,将结果存入 state["location_result"]
4. 若工具调用失败,无需额外操作,直接结束
"""
}
)
# 5.2 备用智能体:主工具失败时触发
fallback_agent = initialize_agent(
tools=[
Tool(
name="get_general_area_info",
func=get_general_area_info,
description="获取城市级模糊位置信息,仅需传入城市名称(示例:杭州市、上海市)"
)
],
llm=llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
callbacks=[state_callback],
agent_kwargs={
"system_message": """
你的任务:
1. 先检查 state["primary_failed"] 是否为 True(主工具是否失败)
2. 若是:从用户原始查询中提取城市名称,调用 get_general_area_info 工具
3. 将查询结果存入 state["location_result"]
4. 若主工具未失败,直接返回空结果,不调用工具
"""
}
)
# 5.3 结果输出智能体:统一响应格式
response_agent = initialize_agent(
tools=[], # 仅处理状态,无需调用工具
llm=llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
agent_kwargs={
"system_message": """
你的任务:
1. 检查 state["location_result"] 是否存在且有效
2. 若有效:用清晰的语言展示位置信息
3. 若无效:向用户致歉,说明无法获取位置,并建议提供完整地址(含街道、门牌号)
"""
}
)
# --------------------------
# 6. 主控制流程:串联各智能体,实现异常处理与恢复
# --------------------------
def robust_location_agent(user_query: str) -> str:
"""
健壮位置查询主函数:
流程:主工具查询 → 检测失败 → 备用工具查询 → 统一结果输出
"""
# 重置状态(处理新查询前清空历史数据)
state_callback.reset()
state_callback.state["original_query"] = user_query
logger.info(f"接收用户查询:{user_query}")
# 第一步:执行主智能体(精确位置查询)
logger.info("开始执行精确位置查询...")
try:
primary_result = primary_agent.run(f"用户查询:{user_query},当前状态:{state_callback.state}")
if "精确位置结果" in primary_result:
state_callback.state["location_result"] = primary_result
except Exception as e:
# 捕获主智能体执行失败(工具调用失败或其他异常)
logger.info(f"精确查询执行失败:{str(e)}")
state_callback.state["primary_failed"] = True
# 第二步:主工具失败时,执行备用智能体
if state_callback.state["primary_failed"] and not state_callback.state["location_result"]:
logger.info("开始执行城市级备用查询...")
try:
fallback_result = fallback_agent.run(f"用户查询:{user_query},当前状态:{state_callback.state}")
if "城市级位置结果" in fallback_result:
state_callback.state["location_result"] = fallback_result
except Exception as e:
logger.error(f"备用查询执行失败:{str(e)}")
state_callback.state["location_result"] = None
# 第三步:执行结果输出智能体,返回最终响应
logger.info("生成最终用户响应...")
final_response = response_agent.run(f"当前状态:{state_callback.state}")
return final_response
# --------------------------
# 测试运行:验证不同场景下的异常处理能力
# --------------------------
if __name__ == "__main__":
print("=== 健壮位置查询智能体测试 ===\n")
# 测试用例 1:完整地址(主工具成功)
print("【测试用例 1】输入完整地址")
query1 = "查询上海市浦东新区张江高科技园区博云路2号的位置"
print(f"用户输入:{query1}")
print(f"智能体响应:{robust_location_agent(query1)}\n")
# 测试用例 2:仅城市名称(主工具失败,触发备用工具)
print("【测试用例 2】输入仅城市名称")
query2 = "查询杭州市的位置"
print(f"用户输入:{query2}")
print(f"智能体响应:{robust_location_agent(query2)}\n")
# 测试用例 3:无效地址(主备工具均失败)
print("【测试用例 3】输入无效地址")
query3 = "查询火星XXX区域的位置"
print(f"用户输入:{query3}")
print(f"智能体响应:{robust_location_agent(query3)}")
核心亮点
- 分层容错:主工具优先,失败自动降级至备用工具,避免单点故障。
- 状态可控:通过回调处理器统一管理流程状态,确保各智能体衔接顺畅。
- 错误可追溯:完整日志记录错误详情,便于后续问题排查。
- 用户友好:无论成功失败,均输出统一格式的友好响应,提升体验。

被折叠的 条评论
为什么被折叠?



