Upstash 速率限制回调
在本指南中,我们将介绍如何使用 UpstashRatelimitHandler
基于请求数或令牌数添加速率限制。该处理程序使用 Upstash 的速率限制库,该库利用 Upstash Redis。
Upstash 速率限制通过每次调用 limit
方法时向 Upstash Redis 发送 HTTP 请求来工作。用户的剩余令牌/请求将被检查和更新。根据剩余令牌,我们可以停止执行代价高昂的操作,例如调用 LLM 或查询向量存储。
const response = await ratelimit.limit();
if (response.success) {
execute_costly_operation();
}
UpstashRatelimitHandler
允许您在几分钟内将此速率限制逻辑整合到您的链中。
设置
首先,您需要访问 Upstash 控制台 并创建一个 Redis 数据库(请参见我们的文档)。创建数据库后,您需要设置环境变量
UPSTASH_REDIS_REST_URL="****"
UPSTASH_REDIS_REST_TOKEN="****"
接下来,您需要安装 Upstash Ratelimit 和 @langchain/community
请参见 本节以获取有关安装集成包的一般说明。
- npm
- Yarn
- pnpm
npm install @upstash/ratelimit @langchain/community @langchain/core
yarn add @upstash/ratelimit @langchain/community @langchain/core
pnpm add @upstash/ratelimit @langchain/community @langchain/core
现在您可以为您的链添加速率限制了!
每请求速率限制
假设我们希望允许用户每分钟调用我们的链 10 次。要实现这一点,只需执行以下操作即可:
const UPSTASH_REDIS_REST_URL = "****";
const UPSTASH_REDIS_REST_TOKEN = "****";
import {
UpstashRatelimitHandler,
UpstashRatelimitError,
} from "@langchain/community/callbacks/handlers/upstash_ratelimit";
import { RunnableLambda } from "@langchain/core/runnables";
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
// create ratelimit
const ratelimit = new Ratelimit({
redis: new Redis({
url: UPSTASH_REDIS_REST_URL,
token: UPSTASH_REDIS_REST_TOKEN,
}),
// 10 requests per window, where window size is 60 seconds:
limiter: Ratelimit.fixedWindow(10, "60 s"),
});
// create handler
const user_id = "user_id"; // should be a method which gets the user id
const handler = new UpstashRatelimitHandler(user_id, {
requestRatelimit: ratelimit,
});
// create mock chain
const chain = new RunnableLambda({ func: (str: string): string => str });
try {
const response = await chain.invoke("hello world", {
callbacks: [handler],
});
console.log(response);
} catch (err) {
if (err instanceof UpstashRatelimitError) {
console.log("Handling ratelimit.");
}
}
请注意,我们将处理程序传递给 invoke
方法,而不是在定义链时传递处理程序。
对于除 FixedWindow
之外的其他速率限制算法,请参见 upstash-ratelimit 文档。
在执行管道中的任何步骤之前,速率限制将检查用户是否超过了请求限制。如果是,则会引发 UpstashRatelimitError
。
每令牌速率限制
另一个选项是基于以下内容对链调用进行速率限制:
- 提示中的令牌数
- 提示和 LLM 完成中的令牌数
这只有在链中包含 LLM 的情况下才有效。另一个要求是您使用的 LLM 应该在其 LLMOutput
中返回令牌使用情况。返回的令牌使用情况字典的格式取决于 LLM。要了解有关根据您的 LLM 配置处理程序的方式,请参阅下面配置部分的结尾。
工作原理
该处理程序将在调用 LLM 之前获取剩余令牌。如果剩余令牌大于 0,则将调用 LLM。否则,将引发 UpstashRatelimitError
。
调用 LLM 后,将使用令牌使用情况信息从用户的剩余令牌中减去。在此阶段的链中不会引发错误。
配置
对于第一个配置,只需像这样初始化处理程序即可
const user_id = "user_id"; // should be a method which gets the user id
const handler = new UpstashRatelimitHandler(user_id, {
requestRatelimit: ratelimit,
});
对于第二个配置,以下是如何初始化处理程序
const user_id = "user_id"; // should be a method which gets the user id
const handler = new UpstashRatelimitHandler(user_id, {
tokenRatelimit: ratelimit,
});
您还可以通过同时传递 request_ratelimit
和 token_ratelimit
参数来同时使用基于请求和令牌的速率限制。
要使令牌使用情况正常工作,LangChain.js 中的 LLM 步骤应以以下格式返回令牌使用情况字段
{
"tokenUsage": {
"totalTokens": 123,
"promptTokens": 456,
"otherFields: "..."
},
"otherFields: "..."
}
但是,并非 LangChain.js 中的所有 LLM 都符合此格式。如果您的 LLM 以不同的键返回相同的值,您可以通过将 llmOutputTokenUsageField
、llmOutputTotalTokenField
和 llmOutputPromptTokenField
参数传递给处理程序来使用这些参数
const handler = new UpstashRatelimitHandler(
user_id,
{
requestRatelimit: ratelimit
llmOutputTokenUsageField: "usage",
llmOutputTotalTokenField: "total",
llmOutputPromptTokenField: "prompt"
}
)
以下是一个使用 LLM 的链示例
const UPSTASH_REDIS_REST_URL = "****";
const UPSTASH_REDIS_REST_TOKEN = "****";
const OPENAI_API_KEY = "****";
import {
UpstashRatelimitHandler,
UpstashRatelimitError,
} from "@langchain/community/callbacks/handlers/upstash_ratelimit";
import { RunnableLambda, RunnableSequence } from "@langchain/core/runnables";
import { OpenAI } from "@langchain/openai";
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
// create ratelimit
const ratelimit = new Ratelimit({
redis: new Redis({
url: UPSTASH_REDIS_REST_URL,
token: UPSTASH_REDIS_REST_TOKEN,
}),
// 500 tokens per window, where window size is 60 seconds:
limiter: Ratelimit.fixedWindow(500, "60 s"),
});
// create handler
const user_id = "user_id"; // should be a method which gets the user id
const handler = new UpstashRatelimitHandler(user_id, {
tokenRatelimit: ratelimit,
});
// create mock chain
const asStr = new RunnableLambda({ func: (str: string): string => str });
const model = new OpenAI({
apiKey: OPENAI_API_KEY,
});
const chain = RunnableSequence.from([asStr, model]);
// invoke chain with handler:
try {
const response = await chain.invoke("hello world", {
callbacks: [handler],
});
console.log(response);
} catch (err) {
if (err instanceof UpstashRatelimitError) {
console.log("Handling ratelimit.");
}
}