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. 01Workersアプリケーションにセマンティック検索を追加
  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 Workers を使用して、セマンティック検索、RAG(検索拡張生成)、AI 搭載アプリケーションを構築するための、グローバルに分散されたベクトルデータベース、Cloudflare Vectorize の完全な実装ガイドです。

ステータス: 本番環境対応 ✅ 最終更新日: 2026-01-21 依存関係: cloudflare-worker-base(Worker のセットアップ用)、cloudflare-workers-ai(埋め込み用) 最新バージョン: [email protected]、@cloudflare/[email protected] トークン削減率: 約70% 防止できるエラー: 14 節約できる開発時間: 約4時間

このスキルでできること

主な機能
  • ✅ インデックス管理:ベクトルインデックスの作成、設定、管理
  • ✅ ベクトル操作:ベクトルの挿入、アップサート、クエリ、削除、一覧表示(list-vectors は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 パラメーター - Boolean から String 列挙型に変更:

    // ❌ 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の内部Write-Ahead Log(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 Boolean(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 の Dev レジストリでの失敗(修正済み)

エラー: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 Limits

問題:最大 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 インデックス:引き続き動作します
  • V1 の操作には wrangler vectorize --deprecated-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:大規模な範囲クエリでは精度が低下する可能性があります(コミュニティ発)

ソース:Query Best Practices 信頼度:中 対象:ベクトル数が約 1,000 万個以上のデータセット

大規模なデータセットに対する範囲クエリ($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: List Vectors 操作 (2025年8月追加)

出典: Vectorize Changelog

Vectorize V2 では、ベクター ID をページ単位で反復処理するための list-vectors 操作のサポートが追加されました。

ユースケース:

  • ベクターコレクションの監査
  • ベクターの一括操作
  • インデックス内容のデバッグ

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 のみを返します (値やメタデータは返しません)
  • 1ページあたり最大 1000 ベクター
  • ページネーションにはカーソルを使用してください

公式ドキュメント


ステータス: 本番環境対応 ✅ (Vectorize V2 GA - 2024年9月) 最終更新: 2026-01-21 トークン削減: 約70% 防止したエラー: 14件 (V2 の破壊的変更、テスト設定、TypeScript の型を含む) 変更点: 4件の新しいエラー (wrangler --json、TypeScript の型、Windows での開発、topK の制限)、バッチパフォーマンスのベストプラクティス、クエリ精度モード、テスト設定、範囲クエリと list-vectors 操作に関するコミュニティのヒントを追加しました。

コメント