言語を切り替える
テーマを切り替える

ベクトル DB は高すぎる? Vectorize 無料版で 30 分セマンティック検索

ブログにスマート検索を追加しようとすると、Pinecone の最安プランでも月 50 ドル。ベクトル DB は意味を理解し、類似コンテンツを見つけ、AI にナレッジを与えられる——個人プロジェクトには高すぎる。

Cloudflare Vectorize の無料枠なら十分。100 万ベクトルに 3 万回クエリでも 0.31 ドル。この記事では Vectorize とは何か、なぜ安いか、どう使うかを解説し、30 分で完全なセマンティック検索デモを動かします。

第 1 部:概念編

ベクトル DB とは? 3 文で説明

初めて「768 次元ベクトル」を見たとき、高校数学の悪夢を思い出しました。でも大丈夫——そんなに難しくありません。

従来の DB は文字、数字、日付など直感的なデータを保存します。ベクトル DB は「意味」——言葉の裏にある意図——を保存します。例えば検索窓に「Apple スマホ」と入力すると、従来の検索は「Apple スマホ」という 4 文字に完全一致する結果しか返しません。ベクトル検索なら「iPhone」「Apple 最新機種」「Apple フラッグシップ」が同じ話だと理解します。

魔法の仕組みはこうです:テキストを AI モデル(OpenAI の埋め込みモデルなど)に渡すと、[0.23, -0.45, 0.78, ...] のような数字の列——合計 768 個——が返ってきます。これが「ベクトル」で、言葉の意味を座標として数値化したものです。意味が近い 2 つのテキストは、数学的にも近いベクトルになります。

具体例:ブログで「安いノート PC」と検索すると、キーワードが 1 つも一致していない「コスパの良い laptop」という記事にマッチしました。意味が合っている——これがセマンティック検索の力です。

なぜ Vectorize? 3 大サービスとの比較

Pinecone、Weaviate、Milvus——どれも専門的に聞こえます。なぜ Vectorize? 私も迷いましたが、小規模プロジェクトや個人開発者には Vectorize が圧倒的に使いやすいと分かりました。

まずコスト——これが一番リアル

Pinecone は有名ですが、価格で敬遠されがち。Standard プランは月最低 50 ドル、100 万ベクトル保存で月約 41 ドル。Weaviate のサーバーレス版は月 25 ドルから。100 万件の 1536 次元ベクトルを保存して検索すると、請求は 153 ドルまで跳ね上がります(圧縮版なら 25 ドル)。

Vectorize は? 実測:100 万件の 768 次元ベクトル、毎日 1000 回検索(月 3 万回)で合計 0.31 ドル。間違いなく 0.31 ドル。Cloudflare 公式ブログは検索コスト 75% 削減、ストレージコスト 98% 削減と述べており、誇張ではありません。

0.31 ドル
100 万ベクトル・3 万回クエリのコスト
Pinecone 最安月 50 ドル、Weaviate 月 25 ドルから。Vectorize 実測 0.31 ドルで Pinecone より月 50 ドル節約

さらに Vectorize には無料枠があり、小規模プロジェクトや MVP 検証に十分。本当に使い始めてから課金を考えればいい——良心的です。

次に統合のしやすさ

Pinecone と Weaviate は別アカウント登録、API キー管理、ネットワーク設定が必要です。すでに Cloudflare Workers でアプリをデプロイしているなら、Vectorize は「そのまま入居」—— wrangler.toml に数行足すだけでバインド完了。コードから env.VECTORIZE_INDEX を直接呼べ、環境変数すら不要。

Pinecone を Workers に載せようとしたとき、API キーを安全に保存する方法だけで 30 分かかりました。Vectorize にはその手間がありません。

最後に向いているシーン

正直に言うと、Vectorize は万能ではありません:

  • 小規模プロジェクト、MVP、個人ブログ:Vectorize が圧勝。低コストで始めやすい
  • エンタープライズ、超大規模(億単位のベクトル):Pinecone の方がインフラとエンタープライズサポートが成熟
  • マルチモーダル(画像・動画・音声):Weaviate の方が機能が充実、ネイティブでマルチモーダル入力に対応

Cloudflare 公式データによると、Vectorize は最大 500 万ベクトルのインデックスに対応。多くのアプリに 500 万件は十分——個人ブログを 3 年書いても 200 本強で、上限にはまだ余裕があります。

500 万ベクトル
無料枠
最大 500 万ベクトルのインデックスに対応
300 万回/月
クエリ無料枠
月約 300 万回クエリ
Pinecone より月 50 ドル節約
コスト比較
100 万ベクトル・3 万回クエリで 0.31 ドル

まとめると:ベクトル検索を試し始めたばかり、または予算が限られているなら、Vectorize が最良の出発点。ビジネスが本当に大きくなってから移行を検討しても遅くありません。

Vectorize で何ができる? 4 つの実戦シナリオ

理論ばかりでは物足りないでしょう。私が見た、または試した実例を 4 つ挙げます。どれも実用的です。

1. スマートドキュメント検索

最も一般的な使い方。社内の技術文書、製品マニュアル、法規文が数百件ある場合、従来の Ctrl+F では当たりがつきません。Vectorize でセマンティック検索を構築すれば、「経費精算の申請方法」と入力するだけで「経費精算フロー」「出張費提出ガイド」などにマッチ。以前チーム向けに社内ナレッジベースを作った際、初週から「その文書どこ?」という繰り返し質問がかなり減りました。

2. 記事レコメンド

「関連記事」はよく見ますが、多くのサイトはタグのハードコードかランダム表示。Vectorize なら現在の記事内容から本当に関連する記事を自動で見つけられます。例:「React Hooks ベストプラクティス」を読んでいるユーザーに「useEffect の落とし穴」を推薦し、「Vue 入門」ではなく。私のブログで 1 か月運用したところ、以前のランダム推薦よりクリック率が 40% 向上しました。

3. RAG アプリ(AI にナレッジベースを与える)

RAG は Retrieval-Augmented Generation の略。言い換えると、ChatGPT に自社データの質問をさせる仕組み。製品ドキュメント 100 編があるとき、ユーザーが「一括インポートは対応?」と聞けば、まず Vectorize から関連文書を取得し、内容を GPT に渡して回答を生成。AI がでたらめを言わず、実際の文書に基づく回答になります。多くのカスタマーサポートボットがこの方式です。

4. コンテンツの重複排除と分類

ユーザーフィードバック管理で 1 日数百件のコメントを受け取る場合、同じ問題が繰り返されます。Vectorize で「ログイン失敗」「ログインできない」「入れない」を自動で同一カテゴリに分類でき、手作業で 1 件ずつ見る必要がありません。コンテンツ審査でも、重複投稿や類似マーケ文書を素早く検出できます。

これら 4 つでベクトル DB の大半の用途をカバーします。要するに「類似コンテンツを見つけたい」場面なら、ベクトル DB が活きます。

第 2 部:ハンズオン実戦

準備:5 分で環境構築

理論はここまで。コードの前に環境を整えましょう。全体で 5 分、順に進めれば大丈夫です。

ステップ 1:Cloudflare アカウント登録

cloudflare.com で無料アカウントを作成。すでに CDN や DNS など Cloudflare の他サービスを使っているなら、既存アカウントで OK。

ステップ 2:Wrangler CLI のインストール

Wrangler は Cloudflare の CLI ツールで、Workers と Vectorize を管理します。ターミナルで実行:

npm install -g wrangler

yarn や pnpm を使っている場合は対応するコマンドに置き換えてください。インストール後、確認:

wrangler --version

バージョン番号が表示されれば OK。

ステップ 3:Cloudflare にログイン

ターミナルで実行:

wrangler login

ブラウザが自動で開き、認可を求められます。「Allow」をクリック。ターミナルに “Successfully logged in” と表示されれば成功。

ステップ 4:プロジェクト作成

作業用フォルダを作成:

mkdir vectorize-demo
cd vectorize-demo
wrangler init

Wrangler がいくつか質問しますが、Enter でデフォルト値で問題ありません。TypeScript を使うか聞かれたら “Yes” を推奨(JavaScript でも可)。

この時点でプロジェクトには次のファイルがあるはず:

  • wrangler.toml — 設定ファイル
  • src/index.ts — Workers コード
  • package.json — 依存関係管理

環境構築はここまで。思ったより簡単でしょう。次は最初のベクトルインデックスを作成します。

核心:最初のベクトルインデックス作成

インデックスはベクトルの「住まい」です。すべてのベクトルはインデックスに保存されます。作成はコマンド一発で済みます。

インデックス作成

プロジェクトディレクトリで実行:

wrangler vectorize create my-search-index --preset @cf/baai/bge-small-en-v1.5

my-search-index はインデックス名で、英字・数字・ハイフンなら自由に付けられます。--preset で埋め込みモデルを指定。ここでは Cloudflare 内蔵 BGE モデル(768 次元)を使用。

完了すると、次のような出力が表示されるはず:

✅ Successfully created index my-search-index

preset について:--preset は Cloudflare が内蔵する一般的な埋め込みモデルを指定します。OpenAI API を別途契約する必要はありません。bge-small-en-v1.5 は性能の良い小型モデルで、768 次元、高速かつ低コスト。日本語・中国語検索なら @cf/baai/bge-base-zh-v1.5 を推奨。

wrangler.toml の設定

Workers にインデックスの使い方を教えます。wrangler.toml を開き、末尾に追加:

[[vectorize]]
binding = "VECTORIZE_INDEX"
index_name = "my-search-index"

binding はコード内でインデックスを呼ぶ変数名、index_name は先ほど作成したインデックス名と一致させます。

動作確認

インデックスが作成されたか確認するには、一覧を表示:

wrangler vectorize list

先ほど作成した my-search-index が表示されれば OK。

よくあるエラー

最初の頃、私もいくつかハマりました。先に共有しておきます:

  • “Index already exists” と出たら、同名インデックスが既にある。名前を変えるか、wrangler vectorize delete で古いものを削除
  • wrangler.toml[[vectorize]] を忘れると、コードで env.VECTORIZE_INDEX を呼んだとき “undefined” エラー
  • preset のモデル名を間違えると失敗。Cloudflare ドキュメント に公式サポートモデル一覧あり

ここまででインデックス完成。次はコードでデータを入れて検索します。

コーディング:30 行でセマンティック検索

本番です。最もシンプルな方法で完全なセマンティック検索を実装します。コードはブロックごとに解説し、各ステップで動作確認できます。

ステップ 1:データ挿入

ブログ記事が数編あり、ユーザーがセマンティック検索できるようにしたいとします。まず記事内容をベクトルに変換して保存します。

src/index.ts を開き、次のコードを書きます:

export interface Env {
  VECTORIZE_INDEX: VectorizeIndex;
  AI: Ai; // Cloudflare Workers AI
}
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);
    // データ挿入 API
    if (url.pathname === '/insert') {
      const articles = [
        {
          id: '1',
          title: 'Cloudflare Workers 入門',
          content: 'Cloudflare Workers はエッジノードでコードを動かせるサーバーレスコンピューティング基盤です'
        },
        {
          id: '2',
          title: 'Serverless アーキテクチャガイド',
          content: 'Serverless computing によりデプロイとスケールが非常にシンプルになり、サーバー管理が不要です'
        },
        {
          id: '3',
          title: 'JavaScript 非同期プログラミング',
          content: 'Promise と async/await は非同期処理を扱う現代的な方法です'
        }
      ];
      // ベクトルを一括生成
      const embeddings = await Promise.all(
        articles.map(async (article) => {
          const embedding = await env.AI.run('@cf/baai/bge-small-en-v1.5', {
            text: `${article.title} ${article.content}`
          });
          return {
            id: article.id,
            values: embedding.data[0], // 768 次元ベクトル
            metadata: {
              title: article.title,
              content: article.content
            }
          };
        })
      );
      // Vectorize に挿入
      await env.VECTORIZE_INDEX.upsert(embeddings);
      return new Response('挿入成功!', { status: 200 });
    }
    return new Response('Not found', { status: 404 });
  }
};

このコードの流れ:

  1. サンプル記事 3 編を定義
  2. Cloudflare AI モデルで各記事を 768 次元ベクトルに変換
  3. upsert で Vectorize インデックスに保存

metadata フィールドには元のタイトルと本文を保存でき、検索時にそのまま取得できます。

ステップ 2:検索クエリ

データが入ったので、検索 API を追加します:

// fetch 関数内に追加
if (url.pathname === '/search') {
  const query = url.searchParams.get('q');
  if (!query) {
    return new Response('クエリパラメータ q が不足しています', { status: 400 });
  }
  // クエリテキストをベクトル化
  const queryEmbedding = await env.AI.run('@cf/baai/bge-small-en-v1.5', {
    text: query
  });
  // インデックス内で最も類似した 5 件を検索
  const results = await env.VECTORIZE_INDEX.query(queryEmbedding.data[0], {
    topK: 5,
    returnMetadata: true
  });
  // 結果を整形
  const formattedResults = results.matches.map((match) => ({
    id: match.id,
    score: match.score, // 類似度スコア(0〜1)
    title: match.metadata?.title,
    content: match.metadata?.content
  }));
  return new Response(JSON.stringify(formattedResults, null, 2), {
    headers: { 'Content-Type': 'application/json' }
  });
}

この API の流れ:

  1. クエリパラメータ q を受け取る(例:ユーザー入力「サーバーレス」)
  2. クエリテキストをベクトル化
  3. query で最も類似した 5 件を取得
  4. スコア付きの検索結果を返す

ステップ 3:ローカルテスト

コードが書けたら、動かしてみましょう:

wrangler dev

Wrangler がローカルサーバーを起動。通常は http://localhost:8787

まずデータを挿入:

curl http://localhost:8787/insert

「挿入成功!」と表示されれば OK。

次に検索:

curl "http://localhost:8787/search?q=サーバーレスプラットフォーム"

次のような結果が返るはず:

[
  {
    "id": "1",
    "score": 0.89,
    "title": "Cloudflare Workers 入門",
    "content": "Cloudflare Workers はエッジノードでコードを動かせるサーバーレスコンピューティング基盤です..."
  },
  {
    "id": "2",
    "score": 0.85,
    "title": "Serverless アーキテクチャガイド",
    "content": "Serverless computing によりデプロイとスケールが非常にシンプルになり..."
  }
]

score は類似度スコア。高いほど関連性が高い。クエリは「サーバーレスプラットフォーム」なのに、「Cloudflare Workers」と「Serverless」関連の記事にマッチ——これがセマンティック検索の力です。

コードの補足

気になる点をいくつか:

  • なぜ OpenAI API を使わない? Cloudflare Workers AI に埋め込みモデルが内蔵。無料枠で十分、API キー管理も不要
  • upsert とは? 「更新または挿入」。ID が存在すれば更新、なければ新規挿入
  • topK はいくつが適切? 一般に 5〜10 件で十分。多すぎてもユーザーは見ません

ここまでで核心の 80% は押さえました。次は検索精度を上げる上級テクニックです。

上級テクニック:3 つの最適化

基本機能が動いたら、検索品質を上げる小技を試す価値があります。

1. メタデータフィルタ:検索範囲を絞る

ブログに「技術」「生活」「読書メモ」などカテゴリがある場合、ユーザーが「Python」と検索するとき技術記事だけ見たいでしょう。メタデータフィルタが使えます。

挿入コードを修正し、各記事にカテゴリを追加:

metadata: {
  title: article.title,
  content: article.content,
  category: 'tech' // カテゴリフィールドを追加
}

検索時にフィルタ条件を追加:

const results = await env.VECTORIZE_INDEX.query(queryEmbedding.data[0], {
  topK: 5,
  returnMetadata: true,
  filter: { category: 'tech' } // 技術カテゴリのみ検索
});

これで「Python」検索時に「大蛇を飼っている」ような生活記事が混ざるのを防げます。

2. ハイブリッド検索:セマンティック+キーワードの二段構え

純粋なセマンティック検索だと、完全一致結果を取りこぼすことがあります。例:「React 18」と検索したら、タイトルに「React 18」がある記事を上位に出したい。

従来のキーワード絞り込みと組み合わせ:

// まずセマンティック検索
const vectorResults = await env.VECTORIZE_INDEX.query(queryEmbedding.data[0], {
  topK: 20, // 候補を多めに取得
  returnMetadata: true
});
// キーワードフィルタとスコア加算
const finalResults = vectorResults.matches
  .map((match) => {
    let boostedScore = match.score;
    // タイトルがキーワードと完全一致なら加点
    if (match.metadata?.title.includes(query)) {
      boostedScore += 0.2;
    }
    return { ...match, score: boostedScore };
  })
  .sort((a, b) => b.score - a.score)
  .slice(0, 5); // 上位 5 件

「意味で関連を探す+キーワードで加点」——この組み合わせで検索結果がより納得感のあるものになります。

3. バッチ操作:パフォーマンス向上

数百〜数千件を 1 件ずつ insert すると遅い。Vectorize はバッチ操作に対応し、数倍の性能向上が期待できます。

// 記事を 100 件ずつバッチ処理
const batchSize = 100;
for (let i = 0; i < allArticles.length; i += batchSize) {
  const batch = allArticles.slice(i, i + batchSize);
  const embeddings = await Promise.all(
    batch.map(async (article) => {
      // ... ベクトル生成
    })
  );
  await env.VECTORIZE_INDEX.upsert(embeddings);
}

500 記事を 1 件ずつ挿入すると 20 分かかりましたが、バッチに変えたら 3 分で完了。Workers KV に人気クエリの結果をキャッシュしておけば、繰り返しクエリは KV から読み出し、毎回ベクトル計算を省略できます。

第 3 部:落とし穴回避

よくある問題と対処法

Vectorize 利用中に踏んだ落とし穴をまとめます。よくある問題を先に知っておけば、遠回りを減らせます。

問題 1:ベクトル次元の不一致エラー

エラー:Dimension mismatch: expected 768, got 1536

原因はシンプル:インデックス作成時は 768 次元モデル(bge-small)だったのに、ベクトル生成時に 1536 次元モデル(OpenAI の text-embedding-3-small など)に変えた。Vectorize では同一インデックス内のベクトル次元はすべて一致する必要があります。

対処法

  • 方法 1:インデックスを作り直し、埋め込みモデルに合った preset を使う
  • 方法 2:埋め込みモデルを変更し、次元を揃える

最初からどのモデルを使うか決めておくのがおすすめ。途中で変えない。

問題 2:無料枠は本当に足りるか

多くの人が気にする点。Cloudflare 公式は無料枠の明確な数字を出していませんが、料金式から算出できます:

ストレージ:768 次元ベクトル約 500 万件
クエリ:月約 300 万回

多そうに聞こえますが、小規模プロジェクトなら十分。私のブログ 200 記事、日次 PV 300、検索 1 日約 30 回——1 か月 0 ドル(無料枠内)。

超えても従量課金は安い——100 万ベクトルに 3 万回クエリで 0.31 ドル。

問題 3:どの埋め込みモデルを選ぶか

Cloudflare は複数の内蔵モデルをサポート。用途で選びます:

  • 中国語コンテンツ@cf/baai/bge-base-zh-v1.5(中国語向け最適化)
  • 英語コンテンツ@cf/baai/bge-small-en-v1.5(性能とコストのバランス)
  • 多言語混合@cf/baai/bge-m3(100 以上の言語対応)

最高精度を求めるなら OpenAI の text-embedding-3-small(1536 次元)も可。ただし API を自前で呼び、コストはやや高め。

経験上、多くの場合 Cloudflare 内蔵 BGE で十分。品質もかなり良い。

問題 4:他のベクトル DB からデータ移行

Pinecone から Vectorize に移行してコストを下げたい場合:

手順はシンプル:

  1. Pinecone からすべてのベクトルと metadata をエクスポート
  2. Vectorize 形式に変換
  3. 新インデックスにバッチ upsert

簡単な移行スクリプト(疑似コード):

// Pinecone からすべてのベクトルを取得
const pineconeVectors = await pineconeIndex.fetch({ ids: allIds });
// 形式を変換
const vectorizeFormat = Object.entries(pineconeVectors.vectors).map(
  ([id, vector]) => ({
    id,
    values: vector.values,
    metadata: vector.metadata
  })
);
// Vectorize にバッチ挿入
const batchSize = 100;
for (let i = 0; i < vectorizeFormat.length; i += batchSize) {
  const batch = vectorizeFormat.slice(i, i + batchSize);
  await env.VECTORIZE_INDEX.upsert(batch);
}

注意:ベクトル次元は一致させること。Pinecone が 1536 次元なら、Vectorize インデックスも 1536 次元の preset を使う。

問題 5:検索結果が期待とずれる

検索結果が想定と大きくずれる場合、考えられる原因:

  1. 埋め込みモデルがドメインに合わない:医療コンテンツなら汎用モデルは弱い。ドメイン特化モデルを検討
  2. 入力テキストが短すぎる:ベクトルは十分な文脈が必要。タイトル+要約はタイトルのみより効果的
  3. データクレンジング未実施:HTML タグや特殊文字が多いとベクトル品質が下がる

私のやり方:タイトル、要約、本文先頭 200 文字を合わせてベクトル化。タイトルのみより明らかに改善。

いつ上位プランへ移行すべきか

Vectorize は魅力的ですが、万能ではありません。次のような場合は他の選択肢を検討してください。

シグナル 1:ベクトル数が 500 万を超える

Vectorize は現在 1 インデックスあたり最大 500 万ベクトル。EC サイトで数千万商品など、規模がそれ以上なら Pinecone や Milvus クラスターの自前構築を検討。ただし正直、多くのアプリはこの規模に達しません。

シグナル 2:マルチモーダル検索が必要

テキストに加え画像・音声・動画も検索したい場合、Vectorize は現時点でテキストベクトルのみ。Weaviate が適切。マルチモーダルデータをネイティブサポート。

シグナル 3:複雑なグラフ DB 要件

ナレッジグラフと組み合わせ、「XX に関連し、2024 年公開、著者 YY の記事をすべて」といった複雑クエリには Vectorize だけでは不足。GraphRAG と Neo4j などのグラフ DB + ベクトル検索を検討。

シグナル 4:レイテンシ要求が極端に高い

Vectorize のクエリレイテンシはおおむね 50〜200ms。多くのアプリには十分速い。リアルタイムレコメンドで 10ms 以内が必要なら、Redis + Faiss などのインメモリ構成が必要かも。

私の提案

最初から完璧な構成を目指さない。まず Vectorize で機能を動かし、プロダクト方向を検証。ビジネスが大きくなりボトルネックが出てから移行を考える。早すぎる最適化は諸悪の根源——移行コストも高くない。ベクトルデータ形式はほぼ同じで、スクリプト数時間で移行可能。

選定だけ 1 か月悩んでプロジェクトが始まらない人も見ました。まず手を動かし、問題が出たら調整しましょう。

結論

最初の疑問に戻りましょう:ベクトル DB は高いのか?

答えは選ぶサービス次第。Pinecone は最低月 50 ドル。Vectorize の無料枠なら、ある程度の規模のアプリを無料で運用できます。私のブログのセマンティック検索は 2 か月運用しても請求 0 ドル。

この記事では概念から実戦、基本から上級テクニックまで解説しました。プロジェクトにセマンティック検索を追加したいなら、試してみてください——30 分でデモが動き、コストはほぼゼロ。試行錯誤のコストはコーヒー 1 杯より安い。

次にできること

  1. Cloudflare 公式サンプル を参考に、5 分で動作確認
  2. Cloudflare Discord に参加し、疑問を質問
  3. 自分のデータを接続し、実用的なアプリを作る——社内ナレッジ検索、個人メモ検索、スマートカスタマーサポートなど

セマンティック検索は思ったほど難しくありません。第一歩を踏み出すことが大切。実際に使い始めると、多くの実問題を解決できるツールだと分かるはずです。

最後に——この記事が役に立ったら、AI アプリを試している友人にもシェアしてください。一緒に節約し、一緒に前進しましょう。

30 分で Vectorize セマンティック検索を実装する完全フロー

環境構築からベクトルインデックス作成、30 行のコードによる完全なセマンティック検索、上級テクニックと落とし穴回避まで

Estimated time: PT30M

  1. 1

    Step 1: 5 分の環境構築:Cloudflare 登録と Wrangler CLI インストール

    ステップ 1:Cloudflare アカウント登録
  2. 2

    Step 2: 最初のベクトルインデックス作成:コマンド一発

    インデックス作成:
  3. 3

    Step 3: 30 行のコードでセマンティック検索:データ挿入と検索クエリ

    ステップ 1 データ挿入:src/index.ts を開き、サンプル記事 3 編を定義。Cloudflare AI モデルで各記事を 768 次元ベクトルに変換し、upsert で Vectorize インデックスに保存。metadata に元のタイトルと本文を保存し、検索時に直接取得可能。ステップ 2 検索クエリ:fetch 関数に検索 API を追加。クエリパラメータ q を受け取り(例:「サーバーレス」)、テキストをベクトル化し、query で最も類似した 5 件を取得、スコア付き結果を返す。ステップ 3 ローカルテスト:wrangler dev を実行。Wrangler がローカルサーバーを起動(通常 http://localhost:8787)。データ挿入:curl http://localhost:8787/insert、「挿入成功!」と表示されれば OK。検索:curl “http://localhost:8787/search?q=サーバーレスプラットフォーム”。JSON 形式の結果(id、score(0〜1 の類似度)、title、content)が返る。score が高いほど関連性が高い。「サーバーレスプラットフォーム」で「Cloudflare Workers」と「Serverless」関連記事にマッチ——セマンティック検索の力。コード補足:OpenAI API を使わない理由——Workers AI に埋め込みモデル内蔵、無料枠十分、API キー不要。upsert とは「更新または挿入」。topK は一般に 5〜10 件。
  4. 4

    Step 4: 上級テクニック:メタデータフィルタ、ハイブリッド検索、バッチ操作

    1. メタデータフィルタ:検索範囲を絞る。ブログに「技術」「生活」「読書メモ」などカテゴリがある場合、metadata に category フィールドを追加。検索時 query に filter パラメータを追加し、技術カテゴリのみ検索。「Python」検索で生活記事が混ざるのを防止。2. ハイブリッド検索:セマンティック+キーワード。純粋なセマンティック検索だと完全一致を取りこぼすことがある。「React 18」検索でタイトル完全一致を上位に。まずセマンティック検索(topK 20 など候補多め)、キーワード一致でスコア加点、ソートして上位 5 件。「意味で関連+キーワード加点」でより納得感のある結果。3. バッチ操作:数百〜数千件を 1 件ずつ insert すると遅い。100 件ずつバッチ処理。500 記事を 1 件ずつで 20 分→バッチで 3 分。Workers KV に人気クエリをキャッシュすれば、繰り返しクエリは KV から読み出し、ベクトル計算を省略。
  5. 5

    Step 5: 落とし穴回避:よくある問題と対処法

    問題 1 ベクトル次元不一致:Dimension mismatch: expected 768, got 1536。インデックス作成時とベクトル生成時でモデル次元が異なる。対処:インデックス作り直し(preset 合わせ)または埋め込みモデル変更。最初からモデルを決める。問題 2 無料枠:ストレージ約 500 万件(768 次元)、クエリ月約 300 万回。小規模プロジェクトなら十分。超えても 100 万ベクトル・3 万回で 0.31 ドル。問題 3 埋め込みモデル選択:中国語 @cf/baai/bge-base-zh-v1.5、英語 @cf/baai/bge-small-en-v1.5、多言語 @cf/baai/bge-m3。最高精度は OpenAI text-embedding-3-small(1536 次元、API 自前、コストやや高)。多くの場合 Cloudflare 内蔵 BGE で十分。問題 4 検索結果がずれる:1) モデルがドメインに合わない 2) 入力が短すぎる 3) データクレンジング未実施。タイトル+要約+本文先頭 200 文字を合わせてベクトル化が効果的。

FAQ

Vectorize と Pinecone、Weaviate 比べてどんな強みがある? コストは?
コスト比較:

Pinecone:
• 最安でも月 50 ドル
• 100 万ベクトル保存で月約 41 ドル

Weaviate:
• サーバーレス版は月 25 ドルから
• 100 万件の 1536 次元ベクトルを保存して検索すると、請求は 153 ドルまで跳ね上がる(圧縮版なら 25 ドル)

Vectorize 実測:
• 100 万件の 768 次元ベクトル、毎日 1000 回検索(月 3 万回)で合計 0.31 ドル
• 間違いなく、0.31 ドル
• Cloudflare 公式ブログによると、検索コスト 75% 削減、ストレージコスト 98% 削減——数字は誇張ではない
• さらに Vectorize には無料枠があり、小規模プロジェクトや MVP 検証に十分

統合のしやすさ:
• Pinecone と Weaviate は別アカウント登録、API キー管理、ネットワーク設定が必要
• すでに Cloudflare Workers でアプリをデプロイしているなら、Vectorize は「そのまま入居」—— wrangler.toml に数行足すだけでバインド完了。コードから env.VECTORIZE_INDEX を直接呼べ、環境変数すら不要

向いているシーン:
• 小規模プロジェクト、MVP、個人ブログ → Vectorize が圧勝。低コストで始めやすい
• エンタープライズ、超大規模(億単位のベクトル) → Pinecone の方がインフラとサポートが成熟
• マルチモーダル(画像・動画・音声) → Weaviate の方が機能が充実、ネイティブでマルチモーダル入力に対応
Vectorize の無料枠はどれくらい? 足りる?
無料枠:
• ストレージは 768 次元ベクトル約 500 万件まで
• クエリは月約 300 万回

多そうに聞こえますが、小規模プロジェクトなら十分です。私のブログは記事 200 本、日次 PV 300、検索は 1 日約 30 回——1 か月運用して請求 0 ドル(無料枠内)でした。

無料枠を超えても従量課金は驚くほど安い——100 万ベクトルに 3 万回クエリで 0.31 ドル。

Cloudflare 公式データによると、Vectorize は最大 500 万ベクトルのインデックスに対応。多くのアプリにとって 500 万件は十分——個人ブログを 3 年書いても 200 本強で、上限にはまだ余裕があります。

ベクトル検索を試し始めたばかり、または予算が限られているなら、Vectorize が最良の出発点。ビジネスが本当に大きくなってから移行を検討しても遅くありません。
30 分でセマンティック検索を実装する具体的手順は?
5 分の環境構築:

ステップ 1:Cloudflare アカウント登録(cloudflare.com で無料登録)
ステップ 2:Wrangler CLI インストール(npm install -g wrangler を実行、wrangler --version で確認)
ステップ 3:Cloudflare にログイン(ターミナルで wrangler login、ブラウザで認可)
ステップ 4:プロジェクト作成(mkdir vectorize-demo、cd vectorize-demo、wrangler init)

最初のベクトルインデックス作成:
• プロジェクトディレクトリで wrangler vectorize create my-search-index --preset @cf/baai/bge-small-en-v1.5 を実行

wrangler.toml の設定:
• wrangler.toml を開き、末尾に [[vectorize]] を追加
• binding = "VECTORIZE_INDEX"
• index_name = "my-search-index"

30 行のコードでセマンティック検索:

ステップ 1:データ挿入
• サンプル記事を定義し、Cloudflare の AI モデルで各記事を 768 次元ベクトルに変換
• upsert メソッドで Vectorize インデックスに保存

ステップ 2:検索クエリ
• クエリパラメータ q を受け取り、テキストをベクトル化
• query メソッドで最も類似した 5 件を取得
• スコア付きの検索結果を返す

ステップ 3:ローカルテスト
• wrangler dev を実行
• データ挿入:curl http://localhost:8787/insert
• 検索テスト:curl "http://localhost:8787/search?q=サーバーレスプラットフォーム"
Vectorize で何ができる? 実戦シナリオは?
1. スマートドキュメント検索:
• 最も一般的な使い方
• 社内の技術文書、製品マニュアル、法規文が数百件ある場合、従来の Ctrl+F では当たりがつかない
• Vectorize でセマンティック検索を構築すれば、「経費精算の申請方法」と入力するだけで「経費精算フロー」「出張費提出ガイド」など関連文書にマッチ
• 以前チーム向けに社内ナレッジベースを作った際、初週から「その文書どこ?」という繰り返し質問がかなり減った

2. 記事レコメンド:
• 「関連記事」機能はよく見るが、多くのサイトはタグのハードコードかランダム表示
• Vectorize なら現在の記事内容から本当に関連する記事を自動で見つけられる
• 例:「React Hooks ベストプラクティス」を読んでいるユーザーに「useEffect の落とし穴」を推薦し、「Vue 入門」ではなく
• 私のブログで 1 か月運用したところ、以前のランダム推薦よりクリック率が 40% 向上

3. RAG アプリ(AI にナレッジベースを与える):
• RAG は Retrieval-Augmented Generation の略。言い換えると、ChatGPT に自社データの質問をさせる仕組み
• 製品ドキュメント 100 編があるとき、ユーザーが「一括インポートは対応?」と聞けば、まず Vectorize から関連文書を取得し、内容を GPT に渡して回答を生成
• AI がでたらめを言わず、実際の文書に基づく回答になる
• 多くのカスタマーサポートボットがこの方式

4. コンテンツの重複排除と分類:
• ユーザーフィードバック管理で 1 日数百件のコメントを受け取る場合、同じ問題が繰り返される
• Vectorize で「ログイン失敗」「ログインできない」「入れない」を自動で同一カテゴリに分類でき、手作業で 1 件ずつ見る必要がない
• コンテンツ審査でも、重複投稿や類似マーケ文書を素早く検出できる
Vectorize 利用時のよくある問題と対処法は?
問題 1:ベクトル次元の不一致エラー
• エラー:Dimension mismatch: expected 768, got 1536
• 原因はシンプル:インデックス作成時は 768 次元モデル(bge-small)だったのに、ベクトル生成時に 1536 次元モデル(OpenAI の text-embedding-3-small など)に変えた
• Vectorize では同一インデックス内のベクトル次元はすべて一致する必要がある
• 対処:
方法 1:インデックスを作り直し、埋め込みモデルに合った preset を使う
方法 2:埋め込みモデルを変更し、次元を揃える
• 最初からどのモデルを使うか決めておくのがおすすめ。途中で変えない

問題 2:無料枠は本当に足りるか
• Cloudflare 公式は無料枠の明確な数字を出していないが、料金式から算出できる
• ストレージ:768 次元ベクトル約 500 万件
• クエリ:月約 300 万回
• 小規模プロジェクトなら十分。私のブログ 200 記事、日次 PV 300、検索 1 日約 30 回——1 か月 0 ドル(無料枠内)
• 超えても従量課金は安い——100 万ベクトルに 3 万回クエリで 0.31 ドル

問題 3:どの埋め込みモデルを選ぶか
• Cloudflare は複数の内蔵モデルをサポート。用途で選ぶ
• 中国語コンテンツ:@cf/baai/bge-base-zh-v1.5(中国語向け最適化)
• 英語コンテンツ:@cf/baai/bge-small-en-v1.5(性能とコストのバランス)
• 多言語混合:@cf/baai/bge-m3(100 以上の言語対応)
• 最高精度を求めるなら OpenAI の text-embedding-3-small(1536 次元)も可。ただし API を自前で呼び、コストはやや高め
• 経験上、多くの場合 Cloudflare 内蔵 BGE で十分。品質もかなり良い

問題 4:検索結果が期待とずれる
• 考えられる原因:
1) 埋め込みモデルがドメインに合わない(医療コンテンツなら汎用モデルは弱い。ドメイン特化モデルを検討)
2) 入力テキストが短すぎる(ベクトルは十分な文脈が必要。タイトル+要約はタイトルのみより効果的)
3) データクレンジング未実施(HTML タグや特殊文字が多いとベクトル品質が下がる)
• 私のやり方:タイトル、要約、本文先頭 200 文字を合わせてベクトル化。タイトルのみより明らかに改善
いつ上位プランへ移行すべき? Vectorize の制限は?
シグナル 1:ベクトル数が 500 万を超える
• Vectorize は現在 1 インデックスあたり最大 500 万ベクトル
• EC サイトで数千万商品など、規模がそれ以上なら Pinecone や Milvus クラスターの自前構築を検討
• ただし正直、多くのアプリはこの規模に達しない

シグナル 2:マルチモーダル検索が必要
• テキストに加え画像・音声・動画も検索したい場合、Vectorize は現時点でテキストベクトルのみ
• この場合 Weaviate が適切。マルチモーダルデータをネイティブサポート

シグナル 3:複雑なグラフ DB 要件
• ナレッジグラフと組み合わせ、「XX に関連し、2024 年公開、著者 YY の記事をすべて」といった複雑クエリには Vectorize だけでは不足
• GraphRAG と Neo4j などのグラフ DB + ベクトル検索を検討

シグナル 4:レイテンシ要求が極端に高い
• Vectorize のクエリレイテンシはおおむね 50〜200ms。多くのアプリには十分速い
• リアルタイムレコメンドで 10ms 以内が必要なら、Redis + Faiss などのインメモリ構成が必要かも

私の提案:最初から完璧な構成を目指さない。まず Vectorize で機能を動かし、プロダクト方向を検証。ビジネスが大きくなりボトルネックが出てから移行を考える。早すぎる最適化は諸悪の根源——移行コストも高くない。ベクトルデータ形式はほぼ同じで、スクリプト数時間で移行可能。選定だけ 1 か月悩んでプロジェクトが始まらない人も見た。まず手を動かし、問題が出たら調整しよう。

10分で読めます · 公開日: 2025年12月1日 · 更新日: 2026年6月8日

関連記事

コメント

GitHubアカウントでログインしてコメントできます