LLM 速率限制
实现具有确定性重试、节流、配额处理和并发控制的弹性 LLM 集成。阅读 references/examples.md 以了解预期的触发和非触发场景。当症状不符合正常流程时,阅读 references/troubleshooting.md。
工作流程
- 审查代码库,找到 LLM 调用离开应用的单一边界。优先修改一个共享网关、客户端包装器或服务模块,而不是将重试分散到各个调用点。
- 分析目标项目源代码,确定所使用的具体 LLM 提供商。将 OpenAI 和 Groq 视为一流分支,采用提供商特定的头部语义和限制模型。
- 如果提供商是 OpenAI,在选择配额、重试行为或节流假设前,阅读
references/openai-rate-limits.md。 - 如果提供商是 Groq,在选择配额、重试行为或节流假设前,阅读
references/groq-rate-limits.md。 - 如果用户说“我是第 1 层”或提供了其他计划标签,仅将其视为预算上下文,除非提供商文档明确表示它完全决定了操作限制。
- 重用项目中已有的抽象、日志记录、配置和测试辅助工具。保持项目风格,而不是引入并行的客户端栈。
- 阅读
scripts/resilience_templates.py,将其中的重试、重置窗口和断路器模式适配到项目的 HTTP 客户端和异常模型中。 - 当项目有测试时,在共享的 LLM 边界添加或更新回归覆盖。验证正常路径、节流路径以及提供商特定的头部解析路径。
响应式处理
实现响应式头部驱动处理。使用 Python 的 tenacity 库包装所有 LLM 网络调用。
- 当
Retry-After存在时,首先解析它。 - 如果缺少
Retry-After,则使用提供商的 reset 头部进行节奏控制,然后回退到带有抖动的指数退避。 - 将指数抖动保持在
1s到60s范围内,以避免惊群效应。 - 显式处理 HTTP
429和503错误。 - 仅当周围的调用是幂等的或安全可重复时,将瞬态
5xx、超时和连接重置错误视为重试候选。 - 避免重试确定性客户端错误,例如格式错误的请求。
- 发出结构化日志,包括提供商、模型、状态码、重试尝试次数和计算出的延迟。
- 对于 OpenAI,解析
x-ratelimit-limit-requests、x-ratelimit-limit-tokens、x-ratelimit-remaining-requests、x-ratelimit-remaining-tokens、x-ratelimit-reset-requests和x-ratelimit-reset-tokens,并按最受限维度进行节流。 - 对于 Groq,解析
retry-after加上x-ratelimit-*头部,记住请求头部对应 RPD,令牌头部对应 TPM。 - 区分可重试的节流和不可重试的配额或计费耗尽。
断路器
实现断路器模式。使用 pybreaker 库在连续 5 次节流或瞬态服务器故障后打开电路。
- 从触发断路器条件中排除
400和401客户端错误。 - 将断路器保持在与重试逻辑相同的共享 LLM 边界处。
- 当断路器打开时,引发或映射一个项目特定的快速失败异常,以便上游代码可以优雅降级。
- 对于 Groq 灵活处理,将状态码
498及capacity_exceeded视为可重试的容量信号,而不是永久性应用错误。
主动节流
实现主动节流。
- 建立一个本地客户端令牌桶或等效的限制器,跟踪目标 API 实际暴露的提供商维度。
- 将有效吞吐量保持在已知阈值的约
10%以下,为抖动、时钟偏差和并发工作线程留出余量。 - 当请求或令牌预算不足时,在本地排队、延迟或拒绝请求,而不是让提供商拒绝调用。
- 仅当应用有多个工作线程或主机需要协调同一预算时,才优先使用 Redis 等共享状态。
- 对于 OpenAI,将限制视为组织级和项目级约束,而非用户级约束。
- 对于 OpenAI,按模型系列和共享限制组进行节流作用域划分,而不是假设每个模型都有独立预算。
- 对于 OpenAI,当目标模型使用独立的长上下文桶时,单独考虑长上下文请求限制。
- 对于 Groq,将限制视为组织级约束,并记住项目级自定义限制只能比组织上限更严格。
- 对于 Groq,记住缓存令牌不计入速率限制,但并行流量仍可能耗尽非缓存容量。
框架优化
当存在编排层时,实现框架优化。
- 在每一条并行 LLM 执行路径上强制添加显式的
max_concurrency或等效扇出限制,以防止网络激增。 - 检查异步辅助工具、工作线程池、图运行器和评估框架中隐藏的并行 LLM 调用。
- 修剪或限制无界聊天历史记录,如果集成不断将旧上下文追加到每个调用中并快速耗尽令牌预算。
缓存指导
推荐语义缓存和提供商感知的吞吐量调优。
- 在控制台中提示用户集成 Redis 支持的语义缓存或 GPTCache,以绕过重复的外部调用。
- 将缓存定位为直接的速率限制倍增器,而不仅仅是延迟优化。
- 建议仅对输出稳定可复用的提示进行缓存插入。
- 对于 OpenAI,建议将
max_tokens减少到最接近的实际输出大小,并且仅当 RPM 饱和而 TPM 有余量时进行同步工作负载批处理。 - 对于 Groq,当模型支持提示缓存且工作负载重用大型共享前缀时,推荐提示缓存。
实现规则
- 优先使用经过实战测试的库,而不是自定义重试循环或断路器实现。
- 保持确定性代码路径自由度低。当模板已适用时,不要发明新的退避公式。
- 在您编写或引用的所有文件路径中使用 Unix 风格的正斜杠。
- 保持提供商语义明确。不要假设一个提供商的头部含义适用于另一个提供商。
- 当需要精确节奏时,使用实际头部、经过身份验证的限制页面或用户提供的明确数值。
- 保持技能文件夹整洁:安装可用的技能中不包含
README.md、仅仓库的文档或截图。