Skip to content

如何处理 LangChain 应用中的错误和异常? ​

  • 标签:LangChain、异常处理

🏛 业务架构师 ​

LangChain 应用的错误与异常处理,我按"错误分类—处理策略—架构设计"讲:

错误分四类,处理策略不同:

  1. 模型 API 错误(超时、429 限流、5xx、网络抖动):指数退避重试(2~3 次)+ 备用模型降级(主模型挂了路由到备用 Provider)+ 熔断(错误率超阈值暂停流量)。框架层:with_retry()、超时参数显式设置;
  2. 输出解析错误(模型返回不合 schema 的内容):解析失败自动带着错误信息重试一次(模型的自纠错成功率很高)+ 结构化输出约束(从源头减少)+ 最终失败的兜底值/降级路径;
  3. 工具执行错误(下游接口挂、参数不合法):工具内部捕获并返回可行动的错误信息("date 格式应为 YYYY-MM-DD"而非裸 stacktrace)让 Agent 能自我修正;写操作要幂等;连续失败熔断转人工;
  4. 业务逻辑错误(答案偏离、越界内容):输出校验器(格式/内容红线检查)+ 护栏拦截 + badcase 日志回流。

架构设计三原则:

  • 每个环节显式声明超时与重试策略——LLM 应用的默认行为不该是"无限等待";
  • 降级链路预先设计:主模型→备用模型→缓存答案→兜底话术+转人工,四级降级保住可用性;
  • 错误可观测:错误分类计数、告警阈值(解析失败率>5% 说明提示词要改)、全链路 trace 定位是哪层出错。

业务视角:错误处理的成熟度决定 AI 应用能不能上生产——Demo 只考虑 happy path,生产要假设"每一环都会坏"。我的检查单:超时/重试/降级/幂等/观测五项齐了,才算可上线。

🏗 系统架构师 ​

LangChain 应用的错误处理我按调用链分层设防——LLM 应用的错误面比传统应用大(模型是概率组件):

LLM 调用层:

  • 网络/服务错误(429 限流、5xx、超时):指数退避重试(2~3 次)+ 抖动;多供应商降级链(primary 挂 → fallback 模型,注意能力差异下质量声明);每类错误独立超时(TTFT 超时与总时长超时分开);
  • 内容策略拒绝(content filter):识别该错误类型,改写请求或走人工通道,不要盲目重试(同样会被拒)。

输出解析层(最高频故障):

  • 结构化输出解析失败 → auto-fix 循环:原始输出 + 解析错误信息回喂模型重生成(限 2~3 次)→ 仍失败降级(默认值/兜底响应/人工队列);
  • 根治:用模型原生结构化输出(受限解码)从源头消除。

工具执行层:

  • 工具异常结构化返回(错误码 + 原因 + 建议动作)而不是裸抛——模型能读懂并改道;超时与幂等重试(幂等工具才可重试);高危工具失败直接熔断转人工。

检索层:检索失败/空结果 → 降级策略(无引用回答 + 声明)而不是硬编;相关度过低的过滤后为空 → 触发澄清追问。

全局兜底(架构师强调):

  • 分级降级链:完整链路 → 简化链路(去 Rerank)→ 缓存/规则响应 → 友好报错——永远给用户一个可用响应;
  • 错误分类打点(错误率按层归因)+ 告警阈值;所有失败样本进 badcase 库(错误的存量是迭代燃料);
  • 用户侧话术:模糊承诺优于技术细节("服务繁忙"而非 stacktrace)。

纪律:每个 try 都要有业务语义的 catch——except Exception: pass 在 LLM 应用里等于把故障藏进概率噪声。

💻 全栈开发专家 ​

LangChain 应用的错误处理,我按「出错位置」分层处理(都是生产套路):

1. 模型 API 层(网络/限流/超时):

python
from langchain_core.runnables import RunnableLambda
robust_llm = llm.with_retry(
    stop_after_attempt=3,          # 指数退避重试
    retry_if_exception_type=(RateLimitError, APITimeoutError)
).with_fallbacks([cheap_llm, static_answer_llm])   # 降级链
  • 分级降级:主力模型超时→备用模型→固定兜底话术;
  • 限流主动处理:客户端令牌桶,别把 429 重试风暴打给自己。

2. 输出解析层(格式不符):

  • 优先用结构化输出(API 约束解码)根治;
  • 解析器带重试:解析失败把报错+原输出回喂模型修正(RetryWithErrorOutputParser);
  • 兜底:正则抽首个 JSON 块、宽松字段映射,最终失败走默认值+告警。

3. 工具/Retriever 层:

  • 工具执行 try/except,异常转结构化文本回喂(模型能据此换路或道歉),绝不让异常炸掉 Agent 循环;
  • 向量库超时降级为空结果+提示「知识检索暂不可用」而不是 500。

4. 业务层(内容性错误):

  • 输出护栏校验(安全、格式),不合格拦截重生成;
  • 幻觉高风险场景加拒答分支。

5. 全局兜底与观测:

  • 最外层「安全网」:一切失败返回友好兜底话术+转人工入口,绝不给用户看堆栈;
  • 错误分类落监控(模型错误/解析错误/工具错误/超时各占多少)——修复优先级看这张表;
  • 慢日志:P99 恶化时按 trace 下钻定位是重试放大还是某个组件拖垮。

原则:每层都有重试、都有降级、都留痕迹——LLM 应用是「不可靠组件的组合」,可用性靠分层防御堆出来。