[ PROMPT_NODE_24408 ]
Vectorize 设计模式
[ SKILL_DOCUMENTATION ]
# Vectorize 模式
## Workers AI 集成
typescript
// 生成嵌入 + 查询
const result = await env.AI.run("@cf/baai/bge-base-en-v1.5", { text: [query] });
const matches = await env.VECTORIZE.query(result.data[0], { topK: 5 }); // 传递 data[0]!
| 模型 | 维度 |
|-------|------------|
| `@cf/baai/bge-small-en-v1.5` | 384 |
| `@cf/baai/bge-base-en-v1.5` | 768 (推荐) |
| `@cf/baai/bge-large-en-v1.5` | 1024 |
## OpenAI 集成
typescript
const response = await openai.embeddings.create({ model: "text-embedding-ada-002", input: query });
const matches = await env.VECTORIZE.query(response.data[0].embedding, { topK: 5 });
## RAG 模式
typescript
// 1. 嵌入查询
const emb = await env.AI.run("@cf/baai/bge-base-en-v1.5", { text: [query] });
// 2. 搜索向量
const matches = await env.VECTORIZE.query(emb.data[0], { topK: 5, returnMetadata: "indexed" });
// 3. 从 R2/D1/KV 获取完整文档
const docs = await Promise.all(matches.matches.map(m => env.R2.get(m.metadata.key).then(o => o?.text())));
// 4. 使用上下文生成
const answer = await env.AI.run("@cf/meta/llama-3-8b-instruct", {
prompt: `Context:n${docs.filter(Boolean).join("nn")}nnQuestion: ${query}nnAnswer:`
});
## 多租户
### 命名空间 ( 50K 租户)
bash
wrangler vectorize create-metadata-index my-index --property-name=tenantId --type=string
typescript
await env.VECTORIZE.upsert([{ id: "1", values: emb, metadata: { tenantId: id } }]);
await env.VECTORIZE.query(vec, { filter: { tenantId: id }, topK: 10 });
## 混合搜索
typescript
const matches = await env.VECTORIZE.query(vec, {
topK: 20,
filter: {
category: { $in: ["tech", "science"] },
published: { $gte: lastMonthTimestamp }
}
});
## 批量摄入
typescript
const BATCH = 500;
for (let i = 0; i < vectors.length; i += BATCH) {
await env.VECTORIZE.upsert(vectors.slice(i, i + BATCH));
}
## 最佳实践
1. **传递 `data[0]`** 而非 `data` 或完整响应
2. **每批次 500** 个向量进行更新
3. **先创建元数据索引**再插入
4. **使用命名空间**进行租户隔离(比过滤器更快)
5. **使用 `returnMetadata: "indexed"`** 以获得速度与数据的最佳平衡
6. **处理 5-10 秒的异步变更延迟**