【ChatGPT API × WordPress】WordPressで「文脈検索」を実現する──Semantic Searchプラグイン
この記事のAI要約
WordPressの標準検索はキーワードの完全一致が基本で、多様な表記ゆれや文脈の違いを十分に汲み取れない課題があります。そこで、OpenAIのChatGPT APIを活用し、WordPress内で完結する意味検索プラグイン「WP Semantic Search」を自作しました。このプラグインは投稿の本文をベクトル化し、検索クエリと類似度を計算してユーザーの意図に沿った関連コンテンツを表示します。導入すれば、曖昧な表現や自然文での検索でも有用な結果が得られ、より高度な検索体験を実現できます。WordPressサイトの検索機能を強化したい開発者やサイト運営者に適しています。
gpt-4.1-miniによる自動要約
お客様と制作要件を詰めている時に、
- 「サイト内検索に◯◯は含められますか?」
- 「検索キーワードの表記ゆれをヒットさせる方法はない?」
- 「AIを使って検索結果をサジェストすることはできませんか?」
などなど、検索機能に関しては多様なご要望をいただきます。
確かにユーザー目線で考えてみれば、例えば「リフォーム」と「リノベーション」の違いのように、線引が曖昧なキーワードで検索することも多いと思います。それなのに完全一致じゃないとヒットしないとなれば、「そのくらい意図を汲み取ってよ…」となってしまいますよね。
そこで今回、OpenAI が提供する開発者向けインターフェース「OpenAI API(いわゆる ChatGPT API)」を使って意味検索(Semantic Search)を行うプラグイン「WP Semantic Search」を自作してみました。
INDEX
意味検索プラグイン「WP Semantic Search」
このプラグインは、RAG(Retrieval Augmented Generation:検索拡張生成)の“Retrieval”部分だけを、外部ソースを使用せずにWordPress内完結で組み込んだような形です。
同様のプラグインが無いか公式ディレクトリも探してみたものの、基本的に外部ベクトルDB(Pinecone/Typesense/Supabaseなど)との連携を前提にしているものが多い印象でした。
今回目指したのはWordPress内完結型の文脈検索プラグインで、運用・開発コストを抑えて、導入時のカスタマイズも柔軟に対応できるMVPです。
本記事では、この「WP Semantic Search」がどんなコンセプトで設計されているか、どのように実装しているかを、できるだけ実務目線で紹介していきます。
プラグインの設計
最終的には、検索結果に表示されたコンテンツに検索キーワード(または検索文)が全く含まれていなくても、ユーザーが意図した内容に近いコンテンツを表示させる、ということを目標にしています。
コンセプトと目的
- 目的:キーワード一致ではなく「質問や意図に近い記事」を上位に出す
- 前提:既存テーマ・投稿構造を壊さず、管理画面から設定・再構築できる
- スコープ:RAGの「生成(Generation)」は行わず、Retrievalに特化
アーキテクチャ概要
コンテンツ作成後のフローとしては…
WordPressで固定ページや記事を投稿した時に、OpenAI APIを使用して本文を要約してEmbeddingを作成。
→独自テーブルにインデックスを作成しておく
検索実行時の処理としては…
検索クエリをベクトル化して、コサイン類似度でスコアリング。
→投稿タイプ別(投稿・固定ページ・制作事例)に出力
という内容にしました。
その他の前提としては、
- 1投稿 = 1チャンク
- Embeddingモデル:text-embedding-3-large
- 検索時は意図正規化 → ベクトル照合 → MMR再ランクで上位8件抽出
- 検索結果はショートコードで出力 (関連記事/関連ページ/関連事例 の3セクション)
ひとまずこんな感じにしてみました。
主なファイル構成と役割
最終的にできあがったプラグインの主なファイル構成は以下の通りです。
| wp-semantic-search.php | プラグイン本体。定数・ロード・有効化時DB作成。 |
|---|---|
| includes/Config.php | 設定管理。対象投稿タイプ・除外ページ・TopK・APIキー等。 |
| includes/OpenAI.php | OpenAI API呼び出し(Embeddings・クエリの意図正規化)。 |
| includes/Indexer.php | 投稿保存時のEmbedding生成・DB登録・再インデックス機能。 |
| includes/Search.php | ベクトル検索のロジック(コサイン類似+KW補正)。 |
| admin/Settings.php | 管理画面(設定/一括再構築/履歴/除外ページ)。 |
| public/shortcodes.php | ショートコードによるフロント出力。 |
| uninstall.php | テーブル・オプション削除(アンインストール時の処理)。 |
管理画面機能
管理画面の機能は非常にミニマルな感じですが、何度かテストしてみて「最低限これは管理画面から設定したいな」と思う項目を追加していきました。
最終的な設定項目としては…
- OpenAI APIキーの設定
- 対象投稿タイプ/除外タクソノミー設定(チェックボックス)
- 固定ページの除外設定(チェックボックス)
- 再インデックスボタン(コンテンツ追加時)
- 全クリア再構築ボタン(設定変更時)
- インデックス実行履歴の表示
- 現在のインデックス件数表示
という感じになりました。
完成した管理画面がこちら↓
インデックス対象の選択は当初対象のみをチェックする形にしていたのですが、実際に使ってみて除外項目だけチェックする方が使いやすかったので、この形に変更しました。
弊社サイトではコンテンツがそこまで多くないのですが、実際のクライアントワークを想定した時に対象にチェックを入れていく作業ってかなり面倒だし、ページ追加やカテゴリーを追加するたびに設定変更→再インデックスの作業が発生するのは無駄が多いですよね。
このあたりは先に管理画面から作ればよかった、と勉強になりました…。
Embeddingモデルの選定
使用するAPIモデルは、「text-embedding-3-large」を選択しました。
Embeddingモデルとは、『文章を数値ベクトルに変換する専用エンジン』のことです。
前回の記事、
では、文章要約のために「gpt-4.1-mini」を使用しましたが、今回は文章生成を行うわけではないので用途が異なり、文章の意味を数値化(ベクトル化)する専用モデルを使用します。
ユーザーの検索文と記事の本文をそれぞれベクトル化し、似ている方向を計算して順位付けを行う、という流れで使っています。
| モデル | 日本語 | コスト | 次元 |
|---|---|---|---|
| text-embedding-3-large | ◎ | 安い | 3072 |
| text-embedding-3-small | ◯ | 激安 | 768 |
| OpenAI旧Ada | △ | 普通 | 1536 |
代替モデルと比較しても日本語の語彙力が圧倒的で、日本語のニュアンス理解に最も適していると感じました。
コストは text-embedding-3-small ほど激安ではないものの、1,000トークンあたり $0.00013 と十分安価です。
長文の記事をまるごと 1 回埋め込んでも、1 件あたり 0.05円前後のイメージなので、更新頻度が高いサイトでも現実的なコスト感で運用できます。
代償としてはベクトルを受け取るデータ量が増えるので、再インデックス時のOpenAI APIのレスポンス量が増大します。
コンテンツの少ない弊社ブログでも、全クリア再構築には数十秒程度の時間がかかる印象でした。
コンテンツ量の多い記事系サイトや製品数の多い顧客サイトで使用する場合には、候補件数の上限や再インデックスの頻度など、ある程度のチューニングが必要になりそうです。
逆に検索スピードそのものは、Embedding の次元数(768 / 3072)にほとんど影響されません。
類似度計算は純PHPのループ処理で完結しているため、次元数が増えても処理時間は誤差レベルでした。
ボトルネックになるのは「比較対象の件数」なので、管理画面から最大比較件数を調整できるようにしています。
実際に使ってみよう!
やっと完成したので、TOPページのキービジュアル内(Webサイトの一等地!)にデカデカと検索窓を設置してみました。
実際に文章っぽい検索ワードで検索してみると…
「AIの時代がやってくるぞ」
最初の1件は見事にChatGPTの記事がヒットしていますね。
その他は…気を取り直してもう1回!
「店舗の集客に困ったときはどうすればいい?」
う〜ん、どうなんでしょう…(汗)
なんだか弊社ブログのコンテンツの少なさが露呈してしまう結果となりましたが、どちらもWordPressの標準検索機能ではヒット0件となる検索ワード(というよりほぼ文章)です。
Googleビジネスの記事や、Shopifyの記事が表示されているので、まずまずの結果なのではないでしょうか。
開発後記
今回の開発では、サムネイルが全記事同一になったり、DBに重複行が増えてしまったり、除外設定が反映しなかったりと、細かいトラブルも含めて、ここには書ききれないほどいろいろありましたが、最終的には「AIが文脈を理解して検索意図に近いページを提示する検索体験」がWordPressの中だけで実現できました。
まだまだ改良の余地が大きいのと、フロントの出力テンプレートが汎用的ではないのでサンプルコードの公開などは予定しておりませんが、早速お客様から導入に向けたご相談もいただいております。
OpenAI APIはアイデア次第でWebサイトへの応用範囲も広いので、今後もRAG型ナレッジベースへの拡張や、お問い合わせフォームでの利用など、より実用性の高い機能を開発していきたいと思います。
この機能に限らずAI技術を導入してみたい企業様や、「こんな機能は作れない?」というご相談など、ぜひお気軽にお問い合わせください!