LangChain / LangGraph 生产环境错误处理

课本示例只捕获 ValueError、ConnectionError生产远远不够 。大模型接口几乎不会抛出原生 ConnectionError,大部分是 langchain_core.exceptions 自定义异常GitHub。

一、先区分 4 大类错误,对应不同策略

表格

错误类型

例子

处理策略

瞬时可重试错误

网络抖动、超时、429 限流、5xx 服务端报错

自动重试(指数退避 + 抖动),不要无限重试

不可重试业务错误

API Key 鉴权 401、上下文超长 ContextOverflow、内容被安全拦截

直接返回给用户,禁止重试

Agent 业务逻辑错误

工具调用异常、输出 JSON 解析失败、Graph 循环超限

包装错误消息丢回给 LLM,让 Agent 自己修复

程序 BUG

TypeError、变量 None、代码逻辑错误

记录完整日志,上报告警,不要暴露原始堆栈给前端

核心异常类(必须导入)

javascript 复制代码
from langchain_core.exceptions import (
    ModelTimeoutError,
    ModelConnectionError,
    RateLimitError,
    ContextOverflowError,
    AuthError,
    PromptBlockedError,
)
from langgraph.errors import GraphRecursionError, NodeTimeoutError

二、底层 ChatModel 侧配置(model 初始化阶段,优先做)

ChatOpenAI(init_chat_model 底层)自带重试、超时配置,优先在模型实例配置,不要全部靠外层 try‑except稀土掘金。

ini 复制代码
model = init_chat_model(
    model="deepseek-chat",
    timeout=30,          # 单次http请求超时,防止无限阻塞
    max_retries=2,       # 瞬时错误内置重试2次,429/网络抖动自动重试
)
  • max_retries:只对可瞬时错误生效;鉴权、上下文溢出不会重试。
  • timeout:流式也生效,避免长请求卡死。

三、invoke /stream 生产完整 try‑except 模板

stream 流式尤其坑:异常不一定在 for 循环外面抛出,可能迭代过程内部抛异常,try 必须包住整个迭代器循环。

1)普通 invoke(阻塞)

python 复制代码
try:
    resp = model.invoke([("user","你好")])
except RateLimitError as e:
    # 429限流,配额耗尽
    print(f"模型接口限流:{e}")
except AuthError as e:
    # api‑key错误、鉴权失败,配置问题,不要重试
    print(f"鉴权失败,请检查API_KEY:{e}")
except ContextOverflowError as e:
    # 上下文窗口超限,业务错误
    print(f"上下文长度超限:{e}")
except ModelTimeoutError as e:
    print(f"模型调用超时:{e}")
except ModelConnectionError as e:
    print(f"网络无法连接模型服务商:{e}")
except PromptBlockedError as e:
    # 内容安全拦截
    print(f"内容安全拦截:{e}")
except Exception as e:
    # 所有其他异常:记录完整堆栈日志,不要把e直接返回前端
    import traceback
    traceback.print_exc()
    print(f"未知异常:{e}")

2)stream 流式模板(高频踩坑!异常发生在迭代内部)

python 复制代码
try:
    stream = model.stream([("user","你好")])
    for chunk in stream:
        if chunk.content:
            print(chunk.content, end="")
# ⚠️所有异常写在最外层,for循环迭代的时候才可能抛出
except RateLimitError as e:
    print("\n【限流】")
except ModelTimeoutError as e:
    print("\n【请求超时】")
except Exception as e:
    import traceback
    traceback.print_exc()
    print(f"\n【未知错误】{e}")

四、LangGraph Agent 生产错误处理(重点)

Agent 有两层错误:

  1. LLM 调用本身异常;
  2. Graph 执行异常:工具报错、递归死循环、节点超时 GraphRecursionErrorNodeTimeoutErrorLangChain。

① agent.stream () 完整捕获示例(你平时写的聊天流式)

python 复制代码
from langgraph.errors import GraphRecursionError

try:
    stream = agent.stream(
        {"messages":[("user","你是谁")]},
        stream_mode=["updates","messages"]
    )
    for mode, data in stream:
        if mode == "messages":
            chunk, _ = data
            print(chunk.content, end="", flush=True)
except GraphRecursionError:
    # Agent无限循环,工具来回调用,超过最大步骤
    print("\nAgent执行循环超限")
except RateLimitError:
    print("\n模型限流")
except ContextOverflowError:
    print("\n上下文超限")
except Exception as e:
    import traceback
    traceback.print_exc()
    print(f"\nAgent执行异常:{e}")

重要坑:Agent 流式迭代过程中随时可能抛异常,不能只包创建 stream 那一行,try 要包住整个 for 循环。

② Agent 节点级别重试策略(生产高级,不用自己写 try‑except)

RetryPolicy:给 Graph 节点配置,瞬时错误自动重跑节点,不用业务层捕获,langgraph>=1.2 支持LangChain。

ini 复制代码
from langgraph.fault_tolerance import RetryPolicy

# 编译agent的时候配置节点重试
agent = create_agent(
    model=model,
    agent_node_name="model",
    retry_policy=RetryPolicy(
        max_attempts=3,
        initial_interval=1.0,
        backoff_factor=2.0
    )
)

只对瞬时错误生效;鉴权、上下文溢出不会重试。

五、生产工程化几条硬性规范

  1. 日志要完整,禁止只打印str(e) 一定要打印堆栈 traceback.print_exc(),或者日志库记录 exc_info=True;否则线上只看到报错文字,看不到堆栈,无法定位。

对外返回给前端,绝对不要把原始异常堆栈返回给用户,只返回友好提示文本。

  1. 区分:哪些错误可以重试,哪些绝对不能重试 ✅可以重试:RateLimitErrorModelTimeoutErrorModelConnectionError ❌禁止重试:AuthErrorContextOverflowErrorPromptBlockedError、参数错误。

  2. Agent 无限循环防护 捕获 GraphRecursionError,代表 agent 陷入工具死循环,需要告诉用户当前无法完成任务。

  3. batch /abatch_as_completed 批量处理一定要开启 return_exceptions=True,单条失败不打断整个批量任务。

    results = agent.batch(inputs, return_exceptions=True)

    遍历结果判断是否isinstance(res, Exception)

  4. Checkpointer 生产不要用 MemorySaver,进程重启状态丢失,用 RedisSaver/PostgresSaver稀土掘金。

六、FastAPI Web 服务场景示例伪代码

前端打字机 sse 接口;异常捕获,SSE 向前端输出友好错误事件,不抛堆栈。

python 复制代码
@app.get("/chat")
async def chat(q:str):
    async def event_generator():
        try:
            async for mode, data in agent.astream(...):
                ... yield数据
        except RateLimitError:
            yield "event:error\ndata:模型访问限流,请稍后重试\n\n"
        except ContextOverflowError:
            yield "event:error\ndata:对话内容过长\n\n"
        except Exception:
            logger.exception("agent异常")
            yield "event:error\ndata:服务内部异常\n\n"
    return StreamingResponse(event_generator(), media_type="text/event-stream")

七、新手常见踩坑回顾

  1. ❌只捕获原生ConnectionError:LLM 库已经把网络错误封装成ModelConnectionError,原生 ConnectionError 抓不到。
  2. ❌stream 只把 try 写在创建迭代器,for 循环里面抛出异常逃逸。
  3. ❌不管什么错误全部重试:鉴权、上下文超限重试只会浪费额度。
  4. ❌把完整异常堆栈直接返回前端,泄露内部信息。
  5. ❌批量任务不开return_exceptions=True,一条坏数据把整个批量任务搞崩。

如果你需要,我可以给一份完整复制即用的 agent.stream 生产模板,包含日志输出、友好错误提示、完整异常分支。

相关推荐
鹏哥带你干乡墅1 小时前
优选乡墅赋能培训平台如何帮助提升乡村建设?
大数据·人工智能·python
冬奇Lab1 小时前
一天一个开源项目(第209篇):holaOS - Agent 原生的本地工作台
人工智能·开源·agent
江畔柳前堤1 小时前
前台·中台·后台:2026年AI原生时代的架构全景图
开发语言·人工智能·算法·机器学习·架构·scala·ai-native
AI服务老曹1 小时前
模型版本管理完整流程:景区文旅项目从0到1怎么做
大数据·人工智能
冬奇Lab1 小时前
Code Agent 解剖(21):从零扩展——接入新的 LLM Provider
人工智能
那个松鼠很眼熟w1 小时前
4.Spring-Ai入门案例
java·人工智能·spring
巫山老妖1 小时前
讲不清楚,是因为你还没想清楚
人工智能·程序员
职场的momo1 小时前
字节生活服务海量内推,挑战亿级订单与AI交易中台
人工智能·程序人生·面试·职场和发展·跳槽·生活·业界资讯
Dawson Zhu1 小时前
知识图谱与 Palantir Ontology:同一套「实体—关系」表象下,两种截然不同的工程范式
人工智能·语言模型·架构·aigc·agi