错误降级三原则与性能建议


文档摘要

错误降级三原则与性能建议 本节摘要:SDK 四步的最后一步「错误降级」,以及贯穿四步的性能建议。记忆系统是「增强」而非「必需」——它挂了,Agent 仍应正常工作。本节讲清降级三原则(gather 用 returnexceptions、关键路径 try-catch、工具返回错误串而非抛异常),以及性能建议(召回<200ms、注入大小控制、session 粒度)。读完本节你能让自己的 Agent 在记忆系统故障时优雅降级,在日常运行时性能达标。 一、核心理念:记忆是增强,不是必需 降级设计的核心理念只有一句:记忆系统是 Agent 的增强,不是 Agent 的必需。 这个理念决定了所有降级策略的取向:宁可记忆不工作,也要让 Agent 继续响应用户。

错误降级三原则与性能建议

本节摘要:SDK 四步的最后一步「错误降级」,以及贯穿四步的性能建议。记忆系统是「增强」而非「必需」——它挂了,Agent 仍应正常工作。本节讲清降级三原则(gather 用 return_exceptions、关键路径 try-catch、工具返回错误串而非抛异常),以及性能建议(召回<200ms、注入大小控制、session 粒度)。读完本节你能让自己的 Agent 在记忆系统故障时优雅降级,在日常运行时性能达标。

一、核心理念:记忆是增强,不是必需

降级设计的核心理念只有一句:记忆系统是 Agent 的增强,不是 Agent 的必需

理念的含义 记忆系统正常 → Agent 更聪明(有记忆) 记忆系统故障 → Agent 仍能工作(无记忆,但不崩) → 不能让「记忆挂了」导致「Agent 挂了」 → 记忆是"nice to have",不是"must have"

这个理念决定了所有降级策略的取向:宁可记忆不工作,也要让 Agent 继续响应用户。用户可以容忍「这次 Agent 没记住」,但不能容忍「Agent 完全没响应」。

关键概念:这与第 8 章代理层的降级哲学一致——「记忆可丢,响应不可丢」。SDK 接入要把这个哲学落实到代码里:每一步涉及记忆的操作,都要有「失败了怎么办」的处理,且「失败的处理」是「继续无记忆地工作」,而非「报错中断」。

二、降级三原则

具体怎么降级?三个原则覆盖绝大多数场景:

原则一:并发操作用 gather + return_exceptions

当多个记忆操作并发(如同时召回 Chat Memory 和查 Wiki),用 gather 并发,且设置 return_exceptions=True,让单个失败不拖累其他:

# 概念性:并发降级 import asyncio async def recall_all(query, ctx): # 并发执行多个召回,任一失败不拖累其他 results = await asyncio.gather( client.recall_memory(query, **ctx), client.search_wiki(query, **ctx), client.search_code(query, **ctx), return_exceptions=True # 关键:失败返回异常对象,而非抛出 ) # 过滤掉失败的(异常对象),只保留成功的 return [r for r in results if not isinstance(r, Exception)]
做法 后果
串行 + 抛异常 一个失败全停
gather + return_exceptions 单个失败不影响其他

原则二:关键路径 try-catch,降级为无记忆

关键路径(如召回)要 try-catch,失败时降级为「无记忆」继续:

# 概念性:关键路径降级 async def chat(user_message, ctx): try: memories = await client.recall(query=user_message, **ctx) prompt = inject(user_message, memories) except Exception: prompt = user_message # 降级:无记忆,用原始消息 reply = await llm.complete(prompt) # 推理照常 return reply

原则三:工具调用返回错误串,而非抛异常

工具暴露给模型后,模型调用工具若失败,应返回「错误描述字符串」而非抛异常——让模型能理解错误并继续:

# 概念性:工具错误降级 async def handle_tool_call(tool_name, params): try: return await client.call_tool(tool_name, params) except Exception as e: # 不抛异常,返回错误串让模型理解 return f"[工具 {tool_name} 调用失败: {str(e)}]" # 模型看到这个,可以决定:重试/换工具/无工具继续

💡 技巧:原则三尤其重要——工具失败返回错误串,模型能「知道工具坏了」并自行调整(如改用其他工具或直接答)。若抛异常,模型直接崩。这种「把错误作为信息传递给模型」是 Agent 工程的常见模式。

三、性能建议

降级之外,日常运行要满足几个性能指标:

指标 建议 原因
召回延迟 < 200ms 用户在等,慢了影响体验
注入大小 受控(有阈值) 防挤掉用户问题
粒度 session 级 避免每次重新初始化
召回 < 200ms 怎么保证 ├─ 召回预算(条数/字符)控制,不全量检索 ├─ 装配过滤先缩小候选集(第3章),减少检索量 ├─ 索引优化(BM25+向量索引建好) └─ 超时上限兜底(第6章召回预算),超时立即返回

⚠️ 注意:召回 < 200ms 是个重要指标——它直接决定「带记忆的 Agent」是否比「无记忆的 Agent」明显慢。如果召回要 2 秒,用户会觉得「这 Agent 怎么这么慢」,记忆的好处被延迟抵消。所以第 6 章召回预算里的「超时上限」就是为这个服务的:宁可少召回点,也要在 200ms 内返回。

四、session 粒度的优化

「session 粒度」是个常被忽略的性能点——记忆操作尽量在 session 级复用,而非每次请求重来:

session 级复用 一个 session 内: ├─ 装配范围(team/agent/task)不变 → 只算一次 ├─ 稳定记忆(persona/scene)不变 → inject 部分复用 └─ 会话上下文累积 → 增量更新 → 避免每次请求都「从头算装配、从头召回稳定记忆」
操作 每次请求做 session 级复用
装配范围计算 复用(三元组不变)
稳定记忆召回 慢且重复 复用(append 区不变)
动态 L1 召回 必须每次(随问题变) 每次做

session 级复用的核心是「区分稳定与动态」——稳定的(session 内不变)复用,动态的(随问题变)每次算。这与第 8 章 inject/toolize、第 9 章第 2 节 prepend/append 的思路一脉相承:都是按「稳定性」优化。

五、降级与性能的统一:稳健的接入

把降级与性能合起来,一个稳健的 SDK 接入具备两个特征:

稳健接入的两特征 ① 故障能扛(降级):记忆系统任何环节挂,Agent 仍响应 ② 日常够快(性能):正常时召回<200ms,注入受控 → 两者统一于「记忆是增强」的理念: 增强要快(不拖慢)+ 增强可丢(不拖垮)

这就是 SDK 四步法的完整图景——召回(快且准)、捕获(持续生长)、工具(按需用知)、降级(故障能扛),再加性能优化(日常够快)。四步+性能,构成一个「既能增强 Agent、又不会拖累 Agent」的接入方案。第 10 章会把这些落到五类真实框架的接入实战。

本节要点回顾

  1. 核心理念:记忆是增强非必需——挂了 Agent 仍工作,「记忆可丢、响应不可丢」。
  2. 原则一:并发用 gather + return_exceptions,单失败不拖累其他。
  3. 原则二:关键路径 try-catch,降级为无记忆继续——召回失败用原始消息推理。
  4. 原则三:工具失败返回错误串非抛异常,让模型理解并自行调整。
  5. 性能三建议:召回<200ms(超时兜底)、注入受控、session 级复用稳定部分。

第 9 章到此完成——四步法(召回/捕获/工具/降级)加性能建议,SDK 接入的全套技能都覆盖了。下一章把这些落到五类真实 Agent 框架的接入实战。


发布者: 作者: 灏天文库 转发
评论区 (0)
U