# 速率限制

许多聊天大模型提供程序给定时间段内可以进行的调用次数施加限制。如果达到速率限制,通常会收到来自提供商的速率限制错误相应,并且需要等待才能发出更多请求。

可以通过rate_limiter参数来设置

langchain内置InMemoryRateLimiter, 是线程安全的,可以由同一进程中的多个线程共享。

from langchain_core.rate_limiters import InMemoryRateLimiter
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
import os
load_dotenv()
rate_limiter = InMemoryRateLimiter(
    requests_per_second=2,
    check_every_n_seconds=0.1,
    max_bucket_size=10
)

model = init_chat_model(
    base_url=os.getenv('OPENAI_BASE_URL'),
    api_key=os.getenv('OPENAI_API_KEY'),
    model=os.getenv('OPENAI_MODEL'),
    temperature=0.5,
    rate_limiter=rate_limiter
)

print(model.invoke('你好'))

InMemoryRateLimiter参数解释:

requests_per_second=2

  • 含义:平均每秒允许通过的请求数是 2 个。

check_every_n_seconds=1

  • 含义:限流器每隔多少秒更新一次内部状态(比如补充令牌、检查是否超限等)。这里是 每 1 秒检查/刷新一次
  • 影响的是:限流的时间粒度
    • 为 1 时:一秒一秒地更新,比较粗略但实现简单。
    • 如果设为更小的值(比如 0.1),则会更细粒度、更平滑,但开销也略大。

max_bucket_size=10

  • 含义:令牌桶的最大容量是 10。

  • 就是说:即使系统空闲很久,桶里最多也只会存 10 个令牌,不会无限累积。

  • 用更直观的话解释

    平时系统按 requests_per_second 的速度生成令牌,比如:

    • 每秒生成 2 个令牌

    但如果一段时间没有请求,那么令牌会积累起来,最多积到:

    • max_bucket_size = 10

    ⚡ 当突然来了很多请求时,只要桶里有令牌,这些请求就可以瞬间(在几毫秒甚至微秒内)全部通过

    这一瞬间允许通过的最大数量,就是:

    最大瞬时突发量 = max_bucket_size

# 🧠 为什么需要「瞬时突发量」?

因为真实场景中,流量不会完全均匀到每秒固定 2 个,一般会“抖动”:

  • 用户点击按钮一瞬间会产生好几个请求
  • 网络传输会把多个请求凑在一起发送
  • 某些任务可能有短暂高峰

桶容量允许短暂的小高峰通过,而不影响整体限流策略。