Convex 动作缓存组件
有时你的应用需要从第三方API那里获取信息,即
缓慢或花钱。 夹克可以帮助! 这是一个可缓存的 Convex 组件
并设置了可选的 TTL。 过期的条目为
一天一次通过工作清理干净 缓存键是 ActionCache名称
(默认为函数名称)和生成
缓存值 .
import { action } from "./_generated/server";
import { components } from "./_generated/api";
import { ActionCache } from "@convex-dev/action-cache";
const cache = new ActionCache(components.actionCache, {
action: internal.example.myExpensiveAction,
});
export const myFunction = action({
// NOTE: If we're returning the result, we need explicitly type the return value.
// Refer to https://docs.convex.dev/functions/actions#dealing-with-circular-type-inference for more info.
handler: async (ctx, args): Promise<{ text: string }> => {
// Call it with the parameters to `myExpensiveAction`
const result = await cache.fetch(ctx, { foo: "bar" });
// Do something with the result or just return it
return result;
},
});
export const myExpensiveAction = internalAction({
args: { foo: v.string() },
handler: async (ctx, args): Promise<{ text: string }> {
const data = await generateLLMResponse(ctx, args);
return data;
}
})
要取消缓存, 您可以设置一个明确和( 或) 清除缓存的新名称 以名称表示值.
预先要求: Convex
你需要一个现有的 Convex 项目来使用组件。 Convex 是一个主机 后端平台,包括数据库、无服务器功能和多一个吨 可以学习 这里。 。 。 .
运行 npm create convex 或遵循其中任何一条
快速启动 来设置一个.
安装
安装组件包 :
npm install @convex-dev/action-cache
创建一个 convex.config.ts 应用程序中的文件 convex/ 文件夹并安装
通过调用 use数字 :
// convex/convex.config.ts
import { defineApp } from "convex/server";
import cache from "@convex-dev/action-cache/convex.config.js";
const app = defineApp();
app.use(cache);
export default app;
最后,创建一个新的 ActionCache 带有可选名称,并在
您的 Convex 工程,并将其指向已安装的组件.
- 这个
name字段可用于识别函数或版本 用于创建缓存中的值并可用于分组 要删除的条目. - 这个
ttl(Time-to-Live)字段决定缓存条目的长度 有效,以毫秒计.- 若无
ttl中提供了缓存项. - 如果一个
ttl中提供了已过期的缓存项 找了个工作.
- 若无
import { ActionCache } from "@convex-dev/action-cache";
import { components } from "./_generated/api";
const cache = new ActionCache(components.actionCache, {
action: internal.example.myExpensiveAction,
name: "myExpensiveActionV1",
ttl: 1000 * 60 * 60 * 24 * 7, // 7 days
});
示例
如果你正在制造一个应用软件 向量搜索计算 嵌入往往很贵——就我们而言,我们使用的是OpenAI的API 给每一次搜索增加耐用性 并花钱使用。 我们可以减少数量 API呼叫通过缓冲结果!
从定义开始 凸起动作
它要求API创建嵌入. 随便换换你最喜欢的
嵌入 API. 您可能需要调整图中的矢量维度
example/schema.ts 相应.
设置您的 API 密钥 环境变量
npx convex env set OPENAI_API_KEY <your-api-key>
export const embed = internalAction({
args: { text: v.string() },
handler: async (_ctx, { text }) => {
const apiKey = process.env.OPENAI_API_KEY;
if (!apiKey) {
throw new Error("OPENAI_API_KEY environment variable not set!");
}
const req = { input: text, model: "text-embedding-ada-002" };
const resp = await fetch("https://api.openai.com/v1/embeddings", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify(req),
});
if (!resp.ok) {
const msg = await resp.text();
throw new Error(`OpenAI API error: ${msg}`);
}
const json = await resp.json();
const vector = json["data"][0]["embedding"];
console.log(`Computed embedding of "${text}": ${vector.length} dimensions`);
return vector as number[];
},
});
创建嵌入缓存 :
const embeddingsCache = new ActionCache(components.actionCache, {
action: internal.example.embed,
name: "embed-v1",
});
运行向量搜索时使用缓存 :
export const vectorSearch = action({
args: { query: v.string(), cuisines: v.array(v.string()) },
handler: async (ctx, args) => {
const embedding = await embeddingsCache.fetch(ctx, {
text: args.query,
});
const results = await ctx.vectorSearch("foods", "by_embedding", {
vector: embedding,
limit: 16,
filter: (q) =>
q.or(...args.cuisines.map((cuisine) => q.eq("cuisine", cuisine))),
});
const rows: SearchResult[] = await ctx.runQuery(
internal.example.fetchResults,
{ results },
);
return rows;
},
});
定义多个缓存
您可以在多个动作中使用相同的组件,或者多个版本的
同样的动作。 您可以指定自定义 name 表示哪个缓存的参数
想要使用, 或更改名称以开始新鲜, 如 embed-v2。 。 。 .
如果返回值发生变化,必须更改名称,以免得到 意外值 .
在缓存到期前更新缓存
当出现缓存误差时,懒散运行动作是方便的. 不过, 这意味着有些请求会很慢,许多竞争请求可能 竞相运行动作并充入缓存.
你可以打个电话避开这个 fetch 与 force 选项。 这将会迫使
运行和更新缓存的动作,即使有缓存命中。 在那个
同时,其他请求会得到缓存命中.
如果您从 cron 工作调用, 缓存将总是有一个条目( 除非 动作失败).
清除值
要清除旧的价值观,你可以:
-
通过参数删除一个条目.
await embeddingsCache.remove(ctx, { text: "target text" }); -
删除当前名称的所有条目( 默认为函数名称) 。 这是 如果您更新了执行并想要清除
await embeddingsCache.removeAllForName(ctx); -
删除组件中的所有条目,包括所有名称.
await embeddingsCache.removeAll(ctx);
更多实例使用 实例.ts。 。 。 .