Skip to main content
Open In ColabOpen on GitHub

Upstash Ratelimit 回调

在本指南中,我们将介绍如何使用 UpstashRatelimitHandler 基于请求数量或 token 数量添加速率限制。此处理器使用了 Upstash 的 ratelimit 库,该库利用了 Upstash Redis

Upstash Ratelimit 的工作原理是在每次调用 limit 方法时向 Upstash Redis 发送一个 HTTP 请求。检查并更新用户的剩余 token/请求数。根据剩余的 token 数,我们可以停止执行昂贵的操作,例如调用 LLM 或查询向量存储:

response = ratelimit.limit()
if response.allowed:
execute_costly_operation()

UpstashRatelimitHandler 允许您在几分钟内将速率限制逻辑集成到您的链中。

首先,您需要访问 Upstash 控制台 并创建一个 Redis 数据库(请参阅我们的文档)。创建数据库后,您需要设置环境变量:

UPSTASH_REDIS_REST_URL="****"
UPSTASH_REDIS_REST_TOKEN="****"

接下来,您需要通过以下方式安装 Upstash Ratelimit 和 Redis 库:

pip install upstash-ratelimit upstash-redis

现在您可以开始为您的链添加速率限制了!

按请求进行速率限制

假设我们希望允许用户每分钟调用我们的链 10 次。实现这一点很简单:

# set env variables
import os

os.environ["UPSTASH_REDIS_REST_URL"] = "****"
os.environ["UPSTASH_REDIS_REST_TOKEN"] = "****"

from langchain_community.callbacks import UpstashRatelimitError, UpstashRatelimitHandler
from langchain_core.runnables import RunnableLambda
from upstash_ratelimit import FixedWindow, Ratelimit
from upstash_redis import Redis

# create ratelimit
ratelimit = Ratelimit(
redis=Redis.from_env(),
# 10 requests per window, where window size is 60 seconds:
limiter=FixedWindow(max_requests=10, window=60),
)

# create handler
user_id = "user_id" # should be a method which gets the user id
handler = UpstashRatelimitHandler(identifier=user_id, request_ratelimit=ratelimit)

# create mock chain
chain = RunnableLambda(str)

# invoke chain with handler:
try:
result = chain.invoke("Hello world!", config={"callbacks": [handler]})
except UpstashRatelimitError:
print("Handling ratelimit.", UpstashRatelimitError)
Error in UpstashRatelimitHandler.on_chain_start callback: UpstashRatelimitError('Request limit reached!')
``````output
Handling ratelimit. <class 'langchain_community.callbacks.upstash_ratelimit_callback.UpstashRatelimitError'>

请注意,我们将 handler 传递给了 invoke 方法,而不是在定义 chain 时传递。

对于 FixedWindow 以外的限流算法,请参阅 upstash-ratelimit 文档

在执行我们 pipeline 中的任何步骤之前,ratelimit 会检查用户是否已达到请求限制。如果达到,将引发 UpstashRatelimitError

按 Token 限流

另一个选项是基于以下内容对 chain 调用进行限流:

  1. prompt 中的 token 数量
  2. prompt 和 LLM completions 中的 token 数量

这仅在您的 chain 中包含 LLM 时才有效。另一个要求是您使用的 LLM 应在其 LLMOutput 中返回 token 使用情况。

工作原理

在调用 LLM 之前,handler 将获取剩余的 token 数。如果剩余 token 数大于 0,则会调用 LLM。否则将引发 UpstashRatelimitError

调用 LLM 后,token 使用信息将用于从用户的剩余 token 中减去。在此 chain 阶段不会引发错误。

配置

对于第一种配置,只需像这样初始化 handler:

ratelimit = Ratelimit(
redis=Redis.from_env(),
# 1000 tokens per window, where window size is 60 seconds:
limiter=FixedWindow(max_requests=1000, window=60),
)

handler = UpstashRatelimitHandler(identifier=user_id, token_ratelimit=ratelimit)

对于第二个配置,初始化 handler 的方式如下:

ratelimit = Ratelimit(
redis=Redis.from_env(),
# 1000 tokens per window, where window size is 60 seconds:
limiter=FixedWindow(max_requests=1000, window=60),
)

handler = UpstashRatelimitHandler(
identifier=user_id,
token_ratelimit=ratelimit,
include_output_tokens=True, # set to True
)

你也可以通过同时传递 request_ratelimittoken_ratelimit 参数,来基于请求和 token 来实施速率限制。

这是一个使用 LLM 的链的示例:

# set env variables
import os

os.environ["UPSTASH_REDIS_REST_URL"] = "****"
os.environ["UPSTASH_REDIS_REST_TOKEN"] = "****"
os.environ["OPENAI_API_KEY"] = "****"

from langchain_community.callbacks import UpstashRatelimitError, UpstashRatelimitHandler
from langchain_core.runnables import RunnableLambda
from langchain_openai import ChatOpenAI
from upstash_ratelimit import FixedWindow, Ratelimit
from upstash_redis import Redis

# create ratelimit
ratelimit = Ratelimit(
redis=Redis.from_env(),
# 500 tokens per window, where window size is 60 seconds:
limiter=FixedWindow(max_requests=500, window=60),
)

# create handler
user_id = "user_id" # should be a method which gets the user id
handler = UpstashRatelimitHandler(identifier=user_id, token_ratelimit=ratelimit)

# create mock chain
as_str = RunnableLambda(str)
model = ChatOpenAI()

chain = as_str | model

# invoke chain with handler:
try:
result = chain.invoke("Hello world!", config={"callbacks": [handler]})
except UpstashRatelimitError:
print("Handling ratelimit.", UpstashRatelimitError)
Error in UpstashRatelimitHandler.on_llm_start callback: UpstashRatelimitError('Token limit reached!')
``````output
Handling ratelimit. <class 'langchain_community.callbacks.upstash_ratelimit_callback.UpstashRatelimitError'>