MyHyetaek RAG運用記 — 11,600件の政府支援制度を検索可能にするまで
GRAXELが政府支援制度データをどのように整理し、検索とAI回答につなげているかを紹介します。
MyHyetaek RAG運用記 — 11,600件の政府支援制度を検索可能にするまで
あるユーザーが検索窓に「青年貯蓄口座」と入力した時、検索結果のトップに全く無関係な高齢者向けの支援策が表示されているのを見た瞬間、私は自分のシステムの構造的欠陥を悟りました。GRAXELの主力サービス「MyHyetaek」は、11,600件の韓国の政府・自治体支援制度をAIで横断検索できるRAG(Retrieval-Augmented Generation)システムです。この膨大なデータをどのように扱い、いかにして「使える」システムへと昇華させたのか、その生々しい運用記録です。
バッチ処理の悲劇:OpenAI APIからの撤退
初期のプロトタイプでは、すべての政策文書のエンベディング(ベクトル化)にOpenAIのAPIを使用していました。しかし、11,600件という数は想像以上でした。日々のデータの追加や、チャンク分割(テキストを細かい単位に区切る)アルゴリズムを変更するたびに、全データを再エンベディングする必要があります。その度にバッチ処理を回すと、瞬く間に数万トークンを消費し、APIコストが雪だるま式に膨れ上がりました。
そこで私はコスト削減のため、エンベディング処理をローカル環境のOllama(nomic-embed-textモデル)へと完全に移行しました。しかしここでも失敗が待ち受けていました。ローカルのモデルに対して、長すぎるテキストチャンクを一度に大量に送りすぎた結果、OllamaのHTTPサーバーがパニックを起こし、連続してタイムアウトエラー(504 Gateway Timeout)を吐き出したのです。テキストのチャンクサイズを適切に制限し、同時実行数を抑えるバッチ制御ロジックをRust側で書き直すまでに、数日間の試行錯誤を要しました。
ハイブリッド検索の真価
コスト問題は解決しましたが、冒頭で述べた「検索精度の問題」は残っていました。ベクトル検索は「意味の近さ」を測るには優れていますが、固有名詞や特定の地域名(例: 「ソウル特別市」)の厳密な一致には驚くほど弱いのです。
これを克服するため、PostgreSQLの全文検索(Full-Text Search)機能を導入しました。ユーザーの質問をAIが解析し、ベクトル検索用のエンベディングと、全文検索用のキーワードに分解します。そして、双方の検索結果上位50件を取得し、RRFアルゴリズムを用いてスコアを合成します。この仕組みにより、意味的な関連性とキーワードの正確性の両方を担保できるようになりました。
ユーザー体験の最適化
最終的に、ユーザーが質問を投げてから、データベースから関連政策を5件抽出し、LLM(現在は高速なGroqのllama-3.3モデルを採用)が読みやすい回答を生成して画面に出力し終えるまでの時間は、平均して約2秒に収まっています。この「2秒」という壁を超えるために、データベースのインデックスチューニングからバックエンドAPIの非同期処理まで、ありとあらゆる最適化を行いました。
RAGシステムは、単にツールを組み合わせるだけでなく、ドメインデータ(この場合は難解な政府文書)の特性を深く理解し、泥臭い調整を繰り返すことでしか実用レベルに達しません。私たちがどのようにデータと向き合っているかについては、GRAXELのビジョンをご覧ください。また、本システムに関する技術的なご質問はコンタクトページやガイドセクションからも受け付けております。
共有
関連記事
同じテーマやタグに基づき、GRAXELの運用文脈を続けて確認できます。
韓国語政策データのハイブリッド検索 — pgvectorと全文検索を組み合わせる
MyHyetaekで意味検索とキーワード検索を組み合わせる理由を説明します。
Rust Axum + Cloudflare Tunnelでpolicy-api.graxel.aiを運用する
MyHyetaekの背後にある政策検索APIを安全に公開するための構成を解説します。
Next.js 15とnext-intlで韓国語・英語・日本語ページを運用する
GRAXELポータルの多言語ルーティング、メタデータ、検索エンジン向け整備についてまとめます。