---
title: "Cloudflare AI Search で多言語サイトのサイト内検索を実装"
date: 2026-09-01
categories: column
author: 二俣
canonical: https://www.liberogic.jp/topics/20260902-Cloudflare-AI-Search/
---

# Cloudflare AI Search で多言語サイトのサイト内検索を実装

![](https://images.microcms-assets.io/assets/4b13731f29254025b91c8d846198ffc9/9047ce32fa8b46928490f91b161e77d0/cover.png)

Astro SSG + ヘッドレスCMSという構成の自社サイトにCloudflare AI Search で多言語サイトのサイト内検索を実装してみました。

Astro SSG + ヘッドレスCMSという構成の自社サイトに実装してみました。  
導入手順そのものは割とシンプルだったのですが、弊サイトは多言語構成のため、いくつかハマりどころがありました。

## Cloudflare AI Search とは

旧称AutoRAGで、2025年9月に改称されました。検索して出てくる記事は旧名・旧APIのものが多いので注意。

やってくれるのはこの一連です。

**クロール → Markdown 変換 → チャンク分割 → 埋め込み → ベクトル + キーワードのインデックス構築**

API は2系統。検索結果一覧を返す`search`と、RAGで回答を生成する`chat/completions`。今回は前者のみ使います。

## 設定のポイント

インスタンスを以下のように作成します。

- データソースはWebCrawlを選択
- クロール対象に公開URL
- 解析タイプをサイトマップ
- コンテンツセレクタにmain要素を指定
- 解析モード：静的サイト
- 特定のサイトマップでsitemap.xmlを指定
- 埋め込みモデルを`@cf/baai/bge-m3`に（日本語サイトのため）

あとは基本デフォルトで問題ないです。

## 認証と環境変数

アカウントからAPIトークンを作成します。  
注意点は「AI Search: 読み取り」だけではなく、**「編集」と「実行」も必要**です。  
作成したトークンは、環境変数AI_SEARCH_TOKENで読み込みます。

![](https://images.microcms-assets.io/assets/4b13731f29254025b91c8d846198ffc9/1f65ae3b266b4fb4874853f4de655367/Screen%20Shot%202026-08-31%2017.40.51.png)

## 構成：APIルート1本 + コンポーネント1つ

検索はAstroのAPIルート（Pages Functionsとして動く）からREST APIを叩きます。APIトークンをブラウザに出せないので、サーバー側でプロキシする形は必須です。なおPages FunctionsにはAI Searchのbindingがないため、SDKではなく素のfetchを使っています。

```
`// Astro の API ルート（Pages Functions として動く）
const res = await fetch(
  `https://api.cloudflare.com/client/v4/accounts/${id}/ai-search/instances/${name}/search`,
  {
    method: 'POST',
    headers: { Authorization: `Bearer ${token}` },
    body: JSON.stringify({
      query,
      ai_search_options: {
        retrieval: {
          retrieval_type: 'hybrid',
          max_num_results: 50
        },
      },
    }),
  }
);
`
```

実装したのは APIルートと検索UIコンポーネントの2ファイルだけ。SSGへの後付けとしてはかなり軽く済みました。

## 多言語サイトでは検索対象を表示言語に絞る

普通のサイト内検索であれば、これでいいのですが、多言語の場合は全言語が書かれたsitemap.xmlを読んでいるため、検索結果が混ざってしまいます。

解決策は、カスタムメタデータ `locale` を定義して検索時に `filters` で絞ること。これにより、見ている言語のみが検索結果として出力されるようになりました。  
※ htmlのlang属性や、`og:locale` からは判定できないので要注意です。

```
`<meta name="locale" content="ja_JP">
`
```

## SEO用サイトマップと検索用サイトマップを分ける

AI Search（Website データソース）はサイトマップ経由でクロールします。

ところが弊サイトの公開用サイトマップは、SEO上の判断で一部の言語を意図的に除外していました。結果、その言語では検索結果が常に 0件という問題が発生。

`@astrojs/sitemap` でサイトマップを生成しているので、全言語を含むサイトマップを検索用に別途出力する方法をとりました。

## 検索結果はどう並んでいるのか

「AI 検索」という語から想像する姿とは結構違います。

AI Searchが日本語で300〜450文字くらいのチャンクに分割します。  
関連するチャンクが最大50個ピックアップされ、それが含まれるページが結果で出てきます。  
関連度が高いと判断されたチャンクを含むページが上位にきます。1ページから複数のチャンクが選ばれることもあるため、検索件数は50件よりも少なくなります。

ページ単位への集約はフロント側でやっています。そしてこの一連の処理では、生成AIは1回も動いていないです。

## まとめ

導入するにはドメインのゾーンがCloudflareにあり、Pages / Workersで運用している事が前提となりますが、実装はお手軽で簡易的にサイト内検索を実装したい場合にはかなり使えるのではと思いました。

逆に、インフラに触れず検索だけ後付けしたい場合や、全件出したい場合、検索ログ分析・サジェスト・同義語辞書といった運用者向けの管理機能が必要な場合は、従来型ASPの方が強いです。

とはいえ、ASPを入れるには重い、けれど検索は欲しい。そういう規模のサイトにはかなり刺さる選択肢だと思います。
