ANTIGRAVITY LABEN
記事一覧/アプリ開発
アプリ開発/2026-04-29上級

Antigravity × Cloudflare Vectorize:エッジで動く本番 RAG パイプラインを構築する

Cloudflare Vectorize を使ったエッジ RAG パイプラインを Antigravity で構築する本番ガイド。チャンク分割・ハイブリッド検索・コスト設計・観測まで個人開発で運用できる粒度で解説します。

antigravity435cloudflare6vectorizerag8vector-databaseworkers3

プレミアム記事

「ベクトル検索を本番投入したいけれど、どこから始めればいいか分からない」——個人開発で SaaS や知識ベースを作る人が必ずぶつかる壁です。私自身、Cloudflare Workers 上で動く小さな質問応答ボットを Vectorize で組み直した時、最初の数日はチャンク分割の長さ一つで検索精度が大きく変わることに振り回されました。

Cloudflare Vectorize は 2024 年末に GA となり、Workers AI と統合されたエッジ最適化のベクトルデータベースです。Pinecone や Weaviate と違って Cloudflare のコントロールプレーンに統合されており、Workers と同じリージョンでベクトル検索を実行できる点が個人開発者にとって魅力的です。月額無料枠と従量課金が組み合わさっているので、初期コストを抑えながら本番運用に踏み切りやすい。

ここで扱うのはAntigravity の AI エージェントを使って RAG パイプラインのひな形を素早く生成し、それを本番品質に育てていく手順を、私が実際にハマった落とし穴と一緒に共有します。読み終わるころには、自分のドキュメントを取り込み、検索精度を測定し、コストとレイテンシを把握した状態で Cloudflare Workers 上にデプロイできるようになっているはずです。

なぜ Cloudflare Vectorize なのか — エッジで動かす意味

Pinecone・Weaviate・Qdrant・Chroma と、ベクトルデータベースの選択肢は急速に増えました。それでも Vectorize を選ぶ価値があるのは、Workers と同じインフラに乗っているという一点に集約されます。

Workers から Vectorize を呼ぶ場合、HTTP API ではなくバインディング経由で接続します。これはローカル関数呼び出しに近い遅延で動くため、外部 API 呼び出しに伴う TCP ハンドシェイクや認証ヘッダの作成コストがゼロです。私の手元の計測では、東京リージョンの Workers から Pinecone(米国)へクエリすると往復で 180–250 ms かかっていたものが、Vectorize に置き換えてからは 20–40 ms に収まりました。エッジで RAG を動かすときに、この一桁差は応答全体の体感速度を大きく変えます。

ただし万能ではありません。Vectorize はインデックス当たり最大 500 万ベクトル、メタデータインデックスのカーディナリティに制限があり、複雑なベクトル数演算(PQ 量子化、IVF などの細かなチューニング)を自分で触れません。「クエリ精度をミリ秒単位で詰めたい」「数億ベクトルの研究的データセットを動かしたい」というケースでは Pinecone Pod や自前の Qdrant の方が向いています。個人開発で 10 万〜数百万ベクトル規模を Cloudflare 一式で完結させたい、という用途にこそ最も力を発揮するサービスです。

私はこのサイト群(4 つのブログ)の全記事を Vectorize にインデックスして、サイト内検索と「関連記事」推薦に使っています。月額数百円のコストで、外部 API への依存をひとつ減らせるのは精神衛生上も大きなメリットでした。

5 分で動く最小 RAG:Antigravity でひな形を生成する

具体的な構築手順に入ります。Antigravity の Manager Surface でプロジェクトを開き、AI エージェントに対して以下のようなプロンプトを与えるところから始めます。

Cloudflare Workers + Vectorize で動く RAG パイプラインのひな形を作ってください。
要件:
- TypeScript / Hono を使う
- /ingest エンドポイントで Markdown ドキュメントを受け取り、チャンク分割→Workers AI で埋め込み→Vectorize に upsert
- /query エンドポイントで質問を受け取り、Vectorize で類似検索→上位 5 件を context として Workers AI の text-generation モデルに渡す
- wrangler.toml も生成する
- 環境変数は VECTORIZE_INDEX, AI bindings として定義

Antigravity がプロジェクト構造を作ってくれたら、まずは生成されたコードに目を通します。生成された雛形をそのまま動かすと、後で必ずチャンク分割や埋め込みモデルの切り替えで詰まるので、最初の数時間は「自分が読んで理解できる粒度に整える」ことに使います。

以下は、整理後の src/index.ts の中核部分です。これは私が実際に運用しているコードを Antigravity 用に最小化したものです。

// src/index.ts
import { Hono } from "hono";
 
type Bindings = {
  AI: Ai;
  VECTORIZE_INDEX: VectorizeIndex;
};
 
const app = new Hono<{ Bindings: Bindings }>();
 
// チャンク分割:見出しと段落の境界を尊重して 800 文字前後に揃える
function chunk(text: string, target = 800, overlap = 120): string[] {
  const blocks = text.split(/\n{2,}/); // 段落区切り
  const out: string[] = [];
  let buf = "";
 
  for (const block of blocks) {
    if ((buf + "\n\n" + block).length > target && buf) {
      out.push(buf.trim());
      // 直前 chunk の末尾を overlap として引き継ぐ(文脈の途切れを防ぐ)
      const tail = buf.slice(Math.max(0, buf.length - overlap));
      buf = tail + "\n\n" + block;
    } else {
      buf = buf ? `${buf}\n\n${block}` : block;
    }
  }
  if (buf.trim()) out.push(buf.trim());
  return out;
}
 
app.post("/ingest", async (c) => {
  const { docId, title, body } = await c.req.json<{
    docId: string;
    title: string;
    body: string;
  }>();
 
  const chunks = chunk(body);
  const vectors = await Promise.all(
    chunks.map(async (text, i) => {
      const { data } = await c.env.AI.run("@cf/baai/bge-small-en-v1.5", {
        text: [text],
      });
      return {
        id: `${docId}#${i}`,
        values: data[0],
        metadata: { docId, title, chunkIndex: i, text },
      };
    })
  );
 
  // upsert は最大 1,000 ベクトルまで一括で投げられる
  await c.env.VECTORIZE_INDEX.upsert(vectors);
  return c.json({ ok: true, chunks: chunks.length });
});
 
app.post("/query", async (c) => {
  const { question, topK = 5 } = await c.req.json<{
    question: string;
    topK?: number;
  }>();
 
  const { data } = await c.env.AI.run("@cf/baai/bge-small-en-v1.5", {
    text: [question],
  });
 
  const result = await c.env.VECTORIZE_INDEX.query(data[0], {
    topK,
    returnMetadata: "all",
  });
 
  const context = result.matches
    .map((m, i) => `[doc ${i + 1}: ${m.metadata?.title}]\n${m.metadata?.text}`)
    .join("\n\n---\n\n");
 
  const answer = await c.env.AI.run("@cf/meta/llama-3.1-8b-instruct", {
    messages: [
      {
        role: "system",
        content:
          "あなたは提供されたドキュメントだけを根拠に回答するアシスタントです。根拠が無い場合は『分かりません』と返してください。",
      },
      {
        role: "user",
        content: `# 質問\n${question}\n\n# 参考ドキュメント\n${context}`,
      },
    ],
  });
 
  return c.json({ answer, sources: result.matches });
});
 
export default app;

wrangler.toml 側ではバインディングを宣言しておきます。

# wrangler.toml
name = "vectorize-rag"
main = "src/index.ts"
compatibility_date = "2026-04-01"
 
[ai]
binding = "AI"
 
[[vectorize]]
binding = "VECTORIZE_INDEX"
index_name = "blog-knowledge"

インデックス作成は CLI から行います。

# 768 次元(bge-small-en-v1.5 の出力次元)
wrangler vectorize create blog-knowledge --dimensions=768 --metric=cosine
# 検索するメタデータには事前にメタデータインデックスを作る
wrangler vectorize create-metadata-index blog-knowledge --property-name=docId --type=string
wrangler vectorize create-metadata-index blog-knowledge --property-name=title --type=string

ここまでで wrangler dev を叩けば、ローカルで /ingest/query が動きます。期待される動作は、/ingest で 1 記事(5,000 文字程度)を投入したとき 6〜8 個のチャンクが作られ、/query で関連スコアの高い 5 件が返ってくる、という流れです。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
「Vectorize の使い方が分からない」状態から、本番品質の RAG パイプラインを Antigravity で組み立てて Cloudflare Workers にデプロイできる
ベクトル検索の精度を本番レベルに引き上げるためのハイブリッド検索・リランキング・メタデータフィルタリングを実装するテクニックを習得できる
エッジで動く RAG 特有のコールドスタート対策・トークンコスト管理・観測の本番設計を、自分のプロダクトにそのまま応用できる
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

アプリ開発2026-04-26
Antigravity × Cloudflare エッジSaaS設計ガイド: D1・Workers・R2・Workers AIを統合した本番アーキテクチャ
Antigravityを使ってCloudflare D1・Workers・R2・Workers AIを統合したエッジSaaSを本番で動かすための設計ガイド。N+1問題・CPU制限・コスト管理など実際の落とし穴と解決策を網羅します。
アプリ開発2026-03-28
Antigravity × Cloudflare R2 でファイルアップロード&画像最適化パイプラインを構築する
Antigravity の AI エージェントを活用して Cloudflare R2 へのファイルアップロード機能と画像最適化パイプラインを構築する方法を、コード例付きで実践的に解説します。
アプリ開発2026-06-14
エッジキャッシュが Next.js の空ページを固定化していた原因と、cache-worker のガード設計
ユーザーから「時々読み込みエラーになる」と報告されるのに手元では再現しない。SSR の例外が HTTP 200 で配信され、それをエッジキャッシュが固定化していた原因を Antigravity のエージェントで切り分け、cache-worker にキャッシュ拒否ガードを実装した記録です。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →