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_ratelimit 和 token_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'>