mcpField
C
cloudflare-vectorize

cloudflare-vectorize

github.com/jezweb数据与数据库1.1k326 次安装3 周前更新
代码仓库

关于 cloudflare-vectorize

面向开发者的 Cloudflare Vectorize 实现指南,用于在 Workers 应用中管理向量并构建语义搜索与 RAG 流程。内容涵盖元数据过滤、向量摄取、嵌入和测试配置。

主要功能

  1. 01创建和管理向量索引
  2. 02插入、查询及删除向量
  3. 03按元数据过滤搜索结果
  4. 04构建语义搜索与 RAG 流程
  5. 05文档分块和批量摄取

适用场景

  1. 01为 Workers 应用添加语义搜索
  2. 02搭建基于检索的问答流程
  3. 03分块并批量导入文档向量
  4. 04按类别或状态筛选搜索结果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jezweb/claude-skills --skill cloudflare-vectorize

安装后在 Claude Code 中输入/cloudflare-vectorize确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
.claude-plugin/
plugin.json
references/
embedding-models.md
index-operations.md
integration-openai-embeddings.md
integration-workers-ai-bge-base.md
metadata-guide.md
vector-operations.md
wrangler-commands.md
rules/
cloudflare-vectorize.md
templates/
basic-search.ts
document-ingestion.ts
metadata-filtering.ts
rag-chat.ts

详细介绍

Cloudflare Vectorize

Cloudflare Vectorize 完整实现指南——借助 Cloudflare Workers 构建语义搜索、RAG(检索增强生成)和 AI 驱动应用的全球分布式向量数据库。

状态:已可用于生产环境 ✅ 最后更新:2026-01-21 依赖项:cloudflare-worker-base(用于 Worker 设置)、cloudflare-workers-ai(用于嵌入) 最新版本:[email protected]、@cloudflare/[email protected] 节省令牌:约 70% 避免的错误:14 节省的开发时间:约 4 小时

此技能提供的内容

核心功能
  • ✅ 索引管理:创建、配置和管理向量索引
  • ✅ 向量操作:插入、更新、查询、删除和列出向量(2025 年 8 月新增列出向量功能)
  • ✅ 元数据筛选:每个索引支持 10 个元数据索引的高级筛选
  • ✅ 语义搜索:使用余弦、欧几里得或点积指标查找相似向量
  • ✅ RAG 模式:完整的检索增强生成工作流
  • ✅ Workers AI 集成:使用 @cf/baai/bge-base-en-v1.5 原生生成嵌入
  • ✅ OpenAI 集成:支持 text-embedding-3-small/large 模型
  • ✅ 文档处理:文本分块和批量导入管道
  • ✅ 测试设置:配置带有 Vectorize 绑定的 Vitest
包含的模板
  1. basic-search.ts - 使用 Workers AI 的简单向量搜索
  2. rag-chat.ts - 具备上下文检索功能的完整 RAG 聊天机器人
  3. document-ingestion.ts - 文档分块和嵌入管道
  4. metadata-filtering.ts - 高级筛选模式

⚠️ Vectorize V2 破坏性变更(2024 年 9 月)

重要:Vectorize V2 于 2024 年 9 月正式发布,并带来了重大破坏性变更。

V2 中的变更

性能改进:

  • 索引容量:每个索引从 200,000 增至 500 万个向量
  • 查询延迟:中位数从 549ms 降至 31ms(快 18 倍)
  • TopK 限制:每次查询的结果数从 20 增至 100
  • 扩展限制:每个账户的索引数从 100 增至 50,000
  • 命名空间限制:每个索引的命名空间数从 100 增至 50,000

API 破坏性变更:

  1. 异步变更操作 - 所有变更操作现在均为异步:

    // V2: Returns mutationId
    const result = await env.VECTORIZE_INDEX.insert(vectors);
    console.log(result.mutationId); // "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    
    // Vector inserts/deletes may take a few seconds to be reflected
    
  2. returnMetadata 参数 - 从布尔值改为字符串枚举:

    // ❌ V1 (deprecated)
    { returnMetadata: true }
    
    // ✅ V2 (required)
    { returnMetadata: 'all' | 'indexed' | 'none' }
    
  3. 插入前必须创建元数据索引:

    • V2 要求在插入向量之前创建元数据索引
    • 在创建元数据索引之前添加的向量不会被编入索引
    • 创建元数据索引后,必须重新更新向量

V1 弃用时间表:

  • 2024 年 12 月:无法再创建 V1 索引
  • 现有 V1 索引:继续正常工作(其他操作不受影响)
  • 迁移:对 V1 操作使用 wrangler vectorize --deprecated-v1 标志

所需 Wrangler 版本:

检查变更状态
// Get index info to check last mutation processed
const info = await env.VECTORIZE_INDEX.describe();
console.log(info.mutationId); // Last mutation ID
console.log(info.processedUpToMutation); // Last processed timestamp

关键设置规则

⚠️ 必须在插入向量之前执行
# 1. Create the index with FIXED dimensions and metric
npx wrangler vectorize create my-index \
  --dimensions=768 \
  --metric=cosine

# 2. Create metadata indexes IMMEDIATELY (before inserting vectors!)
npx wrangler vectorize create-metadata-index my-index \
  --property-name=category \
  --type=string

npx wrangler vectorize create-metadata-index my-index \
  --property-name=timestamp \
  --type=number

原因:插入向量之前,必须先创建元数据索引。在创建元数据索引之前添加的向量,无法按该属性进行筛选。

索引配置(之后无法更改)
# Dimensions MUST match your embedding model output:
# - Workers AI @cf/baai/bge-base-en-v1.5: 768 dimensions
# - OpenAI text-embedding-3-small: 1536 dimensions
# - OpenAI text-embedding-3-large: 3072 dimensions

# Metrics determine similarity calculation:
# - cosine: Best for normalized embeddings (most common)
# - euclidean: Absolute distance between vectors
# - dot-product: For non-normalized vectors

Wrangler 配置

wrangler.jsonc:

{
  "name": "my-vectorize-worker",
  "main": "src/index.ts",
  "compatibility_date": "2025-10-21",
  "vectorize": [
    {
      "binding": "VECTORIZE_INDEX",
      "index_name": "my-index"
    }
  ],
  "ai": {
    "binding": "AI"
  }
}

TypeScript 类型

export interface Env {
  VECTORIZE_INDEX: VectorizeIndex;
  AI: Ai;
}

interface VectorizeVector {
  id: string;
  values: number[] | Float32Array | Float64Array;
  namespace?: string;
  metadata?: Record<string, string | number | boolean | string[]>;
}

interface VectorizeMatches {
  matches: Array<{
    id: string;
    score: number;
    values?: number[];
    metadata?: Record<string, any>;
    namespace?: string;
  }>;
  count: number;
}

元数据筛选运算符(V2)

Vectorize V2 支持使用范围查询进行高级元数据筛选:

// Equality (implicit $eq)
{ category: "docs" }

// Not equals
{ status: { $ne: "archived" } }

// In/Not in arrays
{ category: { $in: ["docs", "tutorials"] } }
{ category: { $nin: ["deprecated", "draft"] } }

// Range queries (numbers) - NEW in V2
{ timestamp: { $gte: 1704067200, $lt: 1735689600 } }

// Range queries (strings) - prefix searching
{ url: { $gte: "/docs/workers", $lt: "/docs/workersz" } }

// Nested metadata with dot notation
{ "author.id": "user123" }

// Multiple conditions (implicit AND)
{ category: "docs", language: "en", "metadata.published": true }

元数据最佳实践

1. 基数注意事项

低基数(适合 $eq 筛选):

// Few unique values - efficient filtering
metadata: {
  category: "docs",        // ~10 categories
  language: "en",          // ~5 languages
  published: true          // 2 values (boolean)
}

高基数(避免用于范围查询):

// Many unique values - avoid large range scans
metadata: {
  user_id: "uuid-v4...",         // Millions of unique values
  timestamp_ms: 1704067200123    // Use seconds instead
}
2. 元数据限制
  • 元数据索引最多 10 个(每个 Vectorize 索引)
  • 每个向量的元数据最多 10 KiB
  • 字符串索引:前 64 字节(UTF-8)
  • 数字索引:Float64 精度
  • 筛选器大小:最多 2048 字节(紧凑 JSON)
3. 向量维度限制

当前限制:每个向量最多 1536 维 来源:GitHub Issue #8729

支持的嵌入模型:

  • Workers AI @cf/baai/bge-base-en-v1.5:768 维 ✅
  • OpenAI text-embedding-3-small:1536 维 ✅
  • OpenAI text-embedding-3-large:3072 维 ❌(需要降维)

不支持的模型(>1536 维):

  • nomic-embed-code:3584 维
  • Qodo-Embed-1-7B:>1536 维

解决方法: 使用降维方法(例如 PCA)将嵌入压缩至 1536 维或更少,但这可能会降低语义质量。

功能请求:目前正在考虑支持更高维度。如果这会阻碍你的使用场景,请使用限制提升申请表。

4. 关键限制
// ❌ INVALID metadata keys
metadata: {
  "": "value",              // Empty key
  "user.name": "John",      // Contains dot (reserved for nesting)
  "$admin": true,           // Starts with $
  "key\"with\"quotes": 1    // Contains quotes
}

// ✅ VALID metadata keys
metadata: {
  "user_name": "John",
  "isAdmin": true,
  "nested": { "allowed": true }  // Access as "nested.allowed" in filters
}

最佳实践

批量插入性能

关键提示:使用 5000 个向量的批次大小,以获得最佳性能。

性能数据:

  • 单独插入:250 万个向量耗时 36 小时以上(未完成)
  • 批量插入(5000):400 万个向量约耗时 12 小时
  • 正确分批后快 18 倍

为什么是 5000?

  • Vectorize 的内部预写日志(WAL)针对该大小进行了优化
  • 避免触发 Cloudflare API 速率限制
  • 平衡吞吐量与内存使用

最佳模式:

const BATCH_SIZE = 5000;

async function insertVectors(vectors: VectorizeVector[]) {
  for (let i = 0; i < vectors.length; i += BATCH_SIZE) {
    const batch = vectors.slice(i, i + BATCH_SIZE);
    const result = await env.VECTORIZE.insert(batch);
    console.log(`Inserted batch ${i / BATCH_SIZE + 1}, mutationId: ${result.mutationId}`);

    // Optional: Rate limiting delay
    if (i + BATCH_SIZE < vectors.length) {
      await new Promise(resolve => setTimeout(resolve, 100));
    }
  }
}

来源:


查询准确度模式

Vectorize 默认使用近似最近邻(ANN)搜索,与精确搜索相比,准确度约为 80%。

默认模式:近似评分(准确度约为 80%)

  • 延迟更低
  • 适用于 RAG、搜索和推荐
  • topK 最高为 100

高精度模式:准确度接近 100%

  • 通过 returnValues: true 启用
  • 延迟更高
  • topK 限制为 20

权衡示例:

// Fast, ~80% accuracy, topK up to 100
const results = await env.VECTORIZE.query(embedding, {
  topK: 50,
  returnValues: false  // Default
});

// Slower, ~100% accuracy, topK max 20
const preciseResults = await env.VECTORIZE.query(embedding, {
  topK: 10,
  returnValues: true   // High-precision scoring
});

何时使用高精度模式:

  • 关键应用(欺诈检测、法律合规)
  • 结果集较小(topK < 20)
  • 准确度优先于延迟

来源:Cloudflare 博客 - 构建 Vectorize


常见错误与解决方法

错误 1:插入向量后才创建元数据索引
Problem: Filtering doesn't work on existing vectors
Solution: Delete and re-insert vectors OR create metadata indexes BEFORE inserting
错误 2:维度不匹配
Problem: "Vector dimensions do not match index configuration"
Solution: Ensure embedding model output matches index dimensions:
  - Workers AI bge-base: 768
  - OpenAI small: 1536
  - OpenAI large: 3072
错误 3:元数据键无效
Problem: "Invalid metadata key"
Solution: Keys cannot:
  - Be empty
  - Contain . (dot)
  - Contain " (quote)
  - Start with $ (dollar sign)
错误 4:筛选条件过大
Problem: "Filter exceeds 2048 bytes"
Solution: Simplify filter or split into multiple queries
错误 5:对高基数数据执行范围查询
Problem: Slow queries or reduced accuracy
Solution: Use lower cardinality fields for range queries, or use seconds instead of milliseconds for timestamps
错误 6:混淆 insert 与 upsert
Problem: Updates not reflecting in index
Solution: Use upsert() to overwrite existing vectors, not insert()
错误 7:缺少绑定
Problem: "VECTORIZE_INDEX is not defined"
Solution: Add [[vectorize]] binding to wrangler.jsonc
错误 8:混淆命名空间与元数据
Problem: Unclear when to use namespace vs metadata filtering
Solution:
  - Namespace: Partition key, applied BEFORE metadata filters
  - Metadata: Flexible key-value filtering within namespace
错误 9:V2 异步变更时序(V2 中新增)
Problem: Inserted vectors not immediately queryable
Solution: V2 mutations are asynchronous - vectors may take a few seconds to be reflected
  - Use mutationId to track mutation status
  - Check env.VECTORIZE_INDEX.describe() for processedUpToMutation timestamp
错误 10:V1 的 returnMetadata 布尔值(V2 中为破坏性变更)
Problem: "returnMetadata must be 'all', 'indexed', or 'none'"
Solution: V2 changed returnMetadata from boolean to string enum:
  - ❌ V1: { returnMetadata: true }
  - ✅ V2: { returnMetadata: 'all' }
错误 11:Wrangler --json 输出包含日志前缀

错误:wrangler vectorize list --json 的输出以日志消息开头,导致 JSON 解析失败 来源:GitHub Issue #11011

受影响的命令:

  • wrangler vectorize list --json
  • wrangler vectorize list-metadata-index --json

问题:

$ wrangler vectorize list --json
📋 Listing Vectorize indexes...
[
  { "created_on": "2025-10-18T13:28:30.259277Z", ... }
]

日志消息会导致输出不是有效的 JSON,因此无法将输出通过管道传递给 jq 或其他工具。

解决方法:解析前移除第一行:

# Using tail
wrangler vectorize list --json | tail -n +2 | jq '.'

# Using sed
wrangler vectorize list --json | sed '1d' | jq '.'

错误 12:TypeScript 类型缺少筛选运算符

错误:wrangler types 生成的 VectorizeVectorMetadataFilterOp 类型不完整 来源:GitHub Issue #10092 状态:OPEN(内部跟踪编号为 VS-461)

问题: 生成的类型仅包含 $eq 和 $ne,缺少 V2 运算符:$in、$nin、$lt、$lte、$gt、$gte

影响: 使用有效的 V2 元数据筛选运算符时,TypeScript 会显示误报错误:

const vectorizeRes = env.VECTORIZE.queryById(imgId, {
  filter: { gender: { $in: genderFilters } }, // ❌ TS error but works!
  topK,
  returnMetadata: 'indexed',
});

解决方法:在修复 wrangler types 之前手动覆盖类型:

// Add to your types file
type VectorizeMetadataFilter = Record<string,
  | string
  | number
  | boolean
  | {
      $eq?: string | number | boolean;
      $ne?: string | number | boolean;
      $in?: (string | number | boolean)[];
      $nin?: (string | number | boolean)[];
      $lt?: number | string;
      $lte?: number | string;
      $gt?: number | string;
      $gte?: number | string;
    }
>;

错误 13:Windows 开发注册表故障(已修复)

错误:在 Windows 上运行 wrangler dev 时出现 ENOENT: no such file or directory 来源:GitHub Issue #10383 状态:已在 [email protected] 中修复

问题: Wrangler 尝试创建文件名中包含冒号的外部 Worker 文件(在 Windows 上无效):

Error: ENOENT: ... '__WRANGLER_EXTERNAL_VECTORIZE_WORKER:<project>:<binding>'

解决方案: 更新到 [email protected] 或更高版本:

npm install -g wrangler@latest

错误 14:topK 限制取决于 returnValues/returnMetadata

错误:topK exceeds maximum allowed value 来源:Vectorize 限制

问题:topK 的最大值会根据查询选项而变化:

配置topK 最大值
returnValues: false、returnMetadata: 'none'100
returnValues: true 或 returnMetadata: 'all'20
returnMetadata: 'indexed'100

常见错误:

// ❌ ERROR - topK too high with returnValues
query(embedding, {
  topK: 100,            // Exceeds limit!
  returnValues: true    // Max topK=20 when true
});

解决方案:

// ✅ OK - respects conditional limit
query(embedding, {
  topK: 20,
  returnValues: true
});

// ✅ OK - higher topK without values
query(embedding, {
  topK: 100,
  returnValues: false,
  returnMetadata: 'indexed'
});

V2 迁移清单

如果从 V1 迁移到 V2:

  1. ✅ 将 wrangler 更新到 3.71.0+(npm install -g wrangler@latest)
  2. ✅ 创建新的 V2 索引(无法将 V1 升级为 V2)
  3. ✅ 在插入向量之前创建元数据索引
  4. ✅ 将 returnMetadata 从布尔值改为字符串枚举('all'、'indexed'、'none')
  5. ✅ 处理异步变更(预期响应中会包含 mutationId)
  6. ✅ 按 V2 限制进行测试(topK 最高为 100,每个索引最多 5M 个向量)
  7. ✅ 更新错误处理以适应异步行为

V1 弃用:

  • 2024 年 12 月之后:无法创建新的 V1 索引
  • 现有 V1 索引:继续可用
  • 使用 wrangler vectorize --deprecated-v1 执行 V1 操作

测试注意事项

使用 Vectorize 绑定的 Vitest

问题:将 @cloudflare/vitest-pool-workers 与 Vectorize 或 Workers AI 绑定搭配使用会导致运行时故障。 来源:GitHub Issue #7434

错误:wrapped binding module can't be resolved

解决方法:

  1. 创建不包含 Vectorize/AI 绑定的 wrangler-test.jsonc
  2. 将 vitest 配置指向专用于测试的 wrangler 文件
  3. 在测试中模拟绑定

示例:

// wrangler-test.jsonc (no Vectorize binding)
{
  "name": "my-worker-test",
  "main": "src/index.ts",
  "compatibility_date": "2025-10-21"
  // No vectorize binding
}

// vitest.config.ts
import { defineWorkersProject } from '@cloudflare/vitest-pool-workers/config';

export default defineWorkersProject({
  test: {
    poolOptions: {
      workers: {
        wrangler: {
          configPath: "./wrangler-test.jsonc"
        }
      }
    }
  }
});

// Mock in tests
import { vi } from 'vitest';

const mockVectorize = {
  query: vi.fn().mockResolvedValue({
    matches: [
      { id: 'test-1', score: 0.95, metadata: { category: 'docs' } }
    ],
    count: 1
  }),
  insert: vi.fn().mockResolvedValue({ mutationId: "test-mutation-id" }),
  upsert: vi.fn().mockResolvedValue({ mutationId: "test-mutation-id" })
};

// Use mock in tests
test('vector search', async () => {
  const env = { VECTORIZE_INDEX: mockVectorize };
  // ... test logic
});

社区提示

注意:这些提示来自社区讨论和官方博客文章。请根据你的 Vectorize 版本进行核实。

提示 1:大规模范围查询的准确性可能会降低(来源:社区)

来源:查询最佳实践 可信度:中 适用于:包含约 10M+ 个向量的数据集

大型数据集上的范围查询($lt、$lte、$gt、$gte)可能会出现准确性下降。

优化策略:

// ❌ High-cardinality range at scale
metadata: {
  timestamp_ms: 1704067200123
}
filter: { timestamp_ms: { $gte: 1704067200000 } }

// ✅ Bucketed into discrete values
metadata: {
  timestamp_bucket: "2025-01-01-00:00",  // 1-hour buckets
  timestamp_ms: 1704067200123  // Original (non-indexed)
}
filter: {
  timestamp_bucket: {
    $in: ["2025-01-01-00:00", "2025-01-01-01:00"]
  }
}

适用场景:

  • 按时间筛选数月或数年的数据
  • 用户 ID、交易 ID(UUID 范围)
  • 任何高基数连续数据

替代方案:使用相等筛选($eq、$in)和分桶值。


提示 2:列出向量操作(2025 年 8 月新增)

来源:Vectorize 更新日志

Vectorize V2 新增了对 list-vectors 操作的支持,可分页遍历向量 ID。

使用场景:

  • 审计向量集合
  • 批量向量操作
  • 调试索引内容

API:

const result = await env.VECTORIZE_INDEX.list({
  limit: 1000,  // Max 1000 per page
  cursor?: string
});

// result.vectors: Array<{ id: string }>
// result.cursor: string | undefined
// result.count: number

// Pagination example
let cursor: string | undefined;
const allVectorIds: string[] = [];

do {
  const result = await env.VECTORIZE_INDEX.list({
    limit: 1000,
    cursor
  });
  allVectorIds.push(...result.vectors.map(v => v.id));
  cursor = result.cursor;
} while (cursor);

限制:

  • 仅返回 ID(不返回值或元数据)
  • 每页最多 1000 个向量
  • 使用游标进行分页

官方文档


状态:可用于生产 ✅(Vectorize V2 正式发布 - 2024 年 9 月) 最后更新:2026-01-21 Token 节省:约 70% 避免的错误:14 项(包括 V2 破坏性变更、测试设置、TypeScript 类型) 变更:新增 4 项错误(wrangler --json、TypeScript 类型、Windows 开发、topK 限制),批处理性能最佳实践、查询准确度模式、测试设置,以及社区分享的范围查询和 list-vectors 操作技巧。

评论

支持 Markdown