このブログの検索ページには、キーワード検索とは別に「AIに聞く」という RAG(Retrieval-Augmented Generation)ベースの自然言語検索を用意しています。 この記事では使い方と、裏側でどう動いているかを簡単にまとめます。
使い方
/search/を開くページ上部の既存キーワード検索(PaperMod標準のfuse.js)とは別に、 「AIに聞く」の質問欄が表示される
自然文で質問を入力する
例:「CloudFrontで直下じゃないディレクトリのindex.htmlが403になるのはなぜ?」
送信するとCloudflare Turnstileによるボット検証が裏で走り、 検証を通過するとバックエンドに問い合わせが飛ぶ
数秒待つと回答と、根拠にした記事へのリンク(sources)が表示される
質問がこのブログの記事でカバーされていない内容の場合は、 外部知識で答えるのではなく「記事に情報がない」と正直に返す設計になっています。 あくまでこのブログの内容だけを根拠に回答する検索機能です。
裏側の仕組み
インデックス作成(ビルド時)
rag-index/(Java 17 / Maven製CLI)が、content/posts/配下の非draft記事を
すべて読み込み、##見出し単位(見出しが無い/長すぎる場合は約1500文字の
スライディングウィンドウ)でチャンクに分割します。各チャンクをVoyage AIの
埋め込みAPI(voyage-3-lite)でベクトル化し、{id, slug, title, url, chunkText, embedding}
の配列としてindex.jsonにまとめ、専用のS3バケット
(www.kanjtomi1967.net-rag-index)へアップロードします。
このインデックス作成はJenkinsのデプロイパイプラインでBuildとDeployの間に
毎回実行される(Rebuild RAG Indexステージ)ため、記事を追加・更新して
git pushすれば、次のデプロイで自動的に検索対象へ反映されます。
質問応答(実行時)
質問はAPI Gateway経由でLambda(blog-rag、lambda-rag/、Java 17)の
POST /askが受け取ります。
- Cloudflare Turnstileトークンをサーバー側で検証
- コールドスタート時に
index.jsonをS3からダウンロードし、 ウォーム状態の間はメモリ上に保持 - 質問文をVoyage AIで埋め込み、全チャンクとのコサイン類似度で ブルートフォースにランキング(このコーパス規模ならベクトルDBは不要)
- 上位4チャンクを取得
- 取得したチャンクを根拠としてClaude(
claude-haiku-4-5)に渡し、 その内容に基づいて回答を生成 {answer, sources: [{title, url}]}を返す
API Gatewayのステージには控えめなスロットル(burst 5 / rate 2)もかけてあり、 スクリプトによる乱用でClaude APIの課金が跳ね上がらないよう二重に対策しています。
まとめ
- 記事本文だけを根拠にするので、ハルシネーションのリスクを抑えつつ 「このブログのどこに書いてあったか忘れた」を解消できる
- 記事を書いて
pushすれば自動でインデックスが更新される - Turnstile + スロットリングでコストと乱用を両方抑えている
気になる記事を検索キーワードで思い出せないときは、ぜひ「AIに聞く」を 試してみてください。
コメント