← 戻る

Cloudflare AI Search: 設計からトラブルシューティングまで


設計判断: Webクロール vs R2同期

Markdownドキュメントサイト(VitePress等)にRAGチャットボット導入時、データソース戦略はR2が正解

観点WebクロールR2 + 同期
チャンク品質HTMLノイズ混入、低いMarkdownソース直接、高い
横断検索ページ単位で弱いfrontmatter活用で強い
導入コストURL指定だけ同期スクリプト保守が必要

判断基準: プロトタイプ以外はR2推奨。20-50ファイルでも品質差が大きく、数百ファイルではWebクロールが不安定化する。

アーキテクチャ

VitePress(チャットUI) → Workers API Proxy → Cloudflare AI Search

                                            R2 Bucket(Markdown)

AI Searchがチャンキング・Embedding・ベクトル検索・LLM回答生成を一気通貫で処理。自前でVectorize + Workers AIを組む必要がない。社内数十人規模なら月$5(Workers有料プラン)で運用可能。

API仕様

検索・回答API

  • /search - 自然言語検索(関連チャンクの取得)
  • /ai-search - AI回答生成付き検索
  • /ask - NLWeb統合(拡張子からの情報取得も可能)
  • /mcp - MCPサーバー経由のアクセス

内部最適化機能

  • 自動インデックス: ファイル変更を検知して再構築(R2ファイル削除時も自動反映)
  • クエリ書き換え: ユーザーの曖昧な質問を改善
  • リランキング: @cf/baai/bge-reranker-baseモデルで意味的に再スコア
  • 類似性キャッシング: 頻出クエリの高速化
  • 同期クールダウン: 3分、インデックス速度3-5x高速化

Workers呼び出し

const response = await env.AI.autorag("instance-name").aiSearch({
  query: "ユーザーの質問",
  model: "external-model-name" // オプション: AI Gateway経由で外部モデル使用可能
});

データソース

  • R2: Markdown, docx, odt の自動クローリング
  • Website: URLベースの自動クロール
  • AI Gateway経由でClaude API等の外部LLMに切り替え可能(設定のみ)

セットアップ

R2同期

# GitHub Actions で定期実行
# docs を R2 にアップロード → AI Search が検索インデックス自動更新

APIトークンの権限

R2操作に「Workers R2 Storage: Edit」だけでは不足。「Edit Cloudflare Workers」テンプレートから作成するのが確実(Account Settings Read等が含まれる)。

wrangler r2の --remote フラグ

  • ローカル開発・GitHub Actions ともに --remote が必須(デフォルトはlocal R2)
  • Resource location: local と表示されたら --remote が足りない

Embeddingモデル選定(日本語)

モデル特徴コスト
@cf/baai/bge-m3多言語・Dense+Sparse同時対応$0.012/MTok
@cf/preferred-networks/plamo-embedding-1b日本語特化$0.019/MTok

小規模ドキュメントならbge-m3のコスト効率が優る。

実装知見・トラブルシューティング

SSEストリーミングの罠

aiSearch({ stream: true }) の戻り値はReadableStreamではなく**Responseオブジェクト**。instanceof Responseでチェックしてbodyを転送する。

if (streamResult instanceof Response) {
  const headers = new Headers(streamResult.headers);
  return new Response(streamResult.body, { headers });
}

wrangler.tomlの [vars] が secret を上書きする

wrangler secret putで設定した値が、wrangler.toml[vars]に同名キーがあると上書きされる。ローカル開発用の値は.dev.varsファイルに分離すること。

CORS設定のセキュアデフォルト

ALLOWED_ORIGINS未設定時は**return false(全拒否)** にする。return true(全許可)だと本番で設定忘れ時に全オリジンからアクセス可能になる。