「過去の似たような資料、どこかにあったはずなんだけど、誰のフォルダに入ってるか分からない」——社内でこういう会話、心当たりはないでしょうか。私たちにいただくご相談でも、ここ最近とくに増えているのが「社内に溜まっているナレッジを、もっと簡単に探せるようにしたい」というものです。
この記事では、実際に私が担当した「社内ナレッジをAIチャットで検索できるようにする」プロジェクトについて、導入前の課題、どう解決したのか、使った技術、そして実装で苦労した点・工夫した点を、できるだけ具体的にお話しします。背伸びした構成ではなく、実際に動いている等身大の作りをそのまま書きますので、「うちもまさに同じ状況だ」という方の参考になれば幸いです。
導入前にお客様が抱えていた課題
ご相談をいただいた時点で、社内のナレッジは「存在はしているのに、探せない」状態でした。具体的にはこんな状況です。
- 過去の資料やマニュアルが、いろいろな場所にバラバラに保存されている
- どこに何が書いてあるか把握しているのは、一部のベテランだけ
- 同じような質問が毎回その人に集中し、休むと業務が止まる
- 新しく入った人が、一人前になるまで「聞いて回る時間」を大量に必要とする
つまり、情報そのものはあるのに「たどり着けない」ことが問題でした。知識が特定の人に張り付いている、いわゆる属人化です。
「検索機能はあるのに、なぜ使われないのか」
掘り下げて分かったのは、キーワード検索の限界でした。たとえば社員が「部品が足りないときの対応」を知りたいとします。ところが資料側には「資材の欠品が発生した場合の手順」と書かれている。言いたいことは同じなのに、使っている単語が一つも一致しないため、キーワード検索では一件もヒットしません。
人間は毎回違う言い回しで質問します。検索する側と資料を書いた側で言葉が揃っていないと、従来の検索は途端に役に立たなくなる。これが「検索機能はあるのに使われない」根本的な理由でした。
解決策:ベクトル検索とキーワード検索を組み合わせたRAG
そこで採用したのが、ベクトル検索を使ったRAG(Retrieval-Augmented Generation)です。ひと言でいうと「社内ドキュメントの中から、質問に意味が近い箇所を探し出し、その内容をもとにAIが回答を作る」仕組みです。
ポイントは、単語の一致ではなく「意味の近さ」で探すこと。「部品が足りない」と「資材の欠品」は、文字は違っても意味は近い。これを数値の並び(ベクトル)に変換して比較することで、言い回しが違っても正しい資料にたどり着けます。
処理の流れは、ざっくり次のとおりです。
- 社内ドキュメントの各テキストを、AIで「意味を表すベクトル」に変換しておく(埋め込み・Embedding)
- そのベクトルをデータベースに保存しておく
- ユーザーが質問したら、質問も同じようにベクトルに変換する
- 保存済みベクトルと質問ベクトルの「近さ(コサイン類似度)」を計算し、近い文章を取り出す
- 同時に、従来どおりのキーワード一致検索も走らせる
- 両方の検索結果をまとめて「参考情報」としてAI(大規模言語モデル)に渡す
- AIが、その参考情報をふまえて自然な文章で回答する
ただのチャットAIではなく、社内資料を参考情報として渡したうえで答えさせるのがRAGの肝です。さらに今回は意味検索(ベクトル)と単語検索(キーワード)を併用しています。意味検索は言い換えに強い一方、型番や固有名詞のような「完全一致してほしい言葉」には弱い。逆にキーワード検索はそこが得意。両方の良いとこ取りをするハイブリッド検索にすることで、取りこぼしを減らしました。
使用した技術
お客様の既存システムがLaravelベースだったため、そこに自然に組み込める形を選びました。実際の構成はこうです。
- アプリケーション基盤:Laravel(既存の業務システムにチャット機能として追加)
- AIモデル:OpenAIの
gpt-4o(回答生成)とtext-embedding-3-small(テキストのベクトル化)。専用SDKは使わず、LaravelのHTTPクライアントからAPIを直接呼び出すシンプルな実装 - ベクトルの保存先:専用のベクトルデータベースは導入せず、既存のMySQLにJSON型のカラムとして埋め込みベクトルを保存
- 類似度の計算:保存したベクトルと質問ベクトルのコサイン類似度を、アプリケーション(PHP)側で計算
- キーワード検索:ナレッジテーブルに対するLIKE部分一致検索を併用
- 会話の文脈維持:直近の質問と回答の履歴をAIに渡し、話の流れをふまえて答えられるように
- フロント:既存画面に馴染むチャットUIをVue.jsで実装
あえて「専用ベクトルDB」を入れなかった理由
ここが、今回いちばんお伝えしたい工夫です。
ベクトル検索というと、Pineconeやpgvectorのような専用のベクトルデータベースを思い浮かべる方が多いと思います。たしかに大規模になればそれが正解です。ですが今回のナレッジ量を冷静に見積もったところ、専用基盤を新たに立てて運用するほどのデータ規模ではないと判断しました。
そこで、すでに動いているMySQLに埋め込みベクトルをJSONで持たせ、類似度の計算はアプリ側で行う構成にしました。これにより、
- 新しいミドルウェアを増やさず、既存DBの延長で運用できる(運用・監視の対象が増えない)
- 追加のインフラコストがほぼかからない
- 構成がシンプルなので、お客様側でも中身を把握・保守しやすい
といったメリットが得られました。AI案件は派手な構成に寄せがちですが、規模に対して過剰な作りにしないことも、受託として大事にしている判断だと考えています。
大変だったこと・工夫したこと
正直なところ、AIに質問を投げる部分そのものより、「いかに正しい参考情報を取り出すか」の調整に一番時間がかかりました。
1. 類似度のしきい値の調整
「どのくらい意味が近ければ参考情報として採用するか」のしきい値が、体感の精度を大きく左右しました。厳しくしすぎると、関連する資料があるのに「該当なし」になってしまう。逆に緩くしすぎると、見当違いの情報まで紛れ込む。実際の質問で何度も試しながら、必要な情報を取りこぼさないラインまでしきい値を下げて調整しました。
2. ベクトル検索だけでは固有名詞に弱い
意味検索は言い換えに強い反面、製品名・型番・社内用語のような固有名詞には弱いことが分かりました。ここで前述のハイブリッド検索が効いてきます。キーワード検索を併用することで、「意味は近いが言葉は違う資料」も「言葉がピタリと一致する資料」も、両方すくい上げられるようにしました。
3. アプリ側で類似度計算するうえでのメモリ対策
専用DBを使わずアプリ側で計算する構成のため、保存済みのベクトルを全部読み込んで比較する必要があります。データが増えても一度にメモリを食いつぶさないよう、一定件数ずつに区切って処理するようにし、安定して動くようにしました。
4. 会話の流れをふまえて答えさせる
一問一答だけだと「さっきの話の続き」が通じません。直近の質問と回答の履歴をAIに渡すことで、文脈を理解した自然なやり取りができるようにしました。
導入後の効果
運用が始まってから、お客様に特に喜ばれたのは次の点でした。
- 「言い回しが違ってもヒットする」ため、検索機能が今度こそ実際に使われるようになった
- ベテランへの「これどうやるんでしたっけ」という問い合わせが減った
- 新しく入った人が、人に聞かなくても自分で調べて進められる場面が増えた
情報は元々あったのに探せなかった、という最初の課題に対して、「探せる状態」を作れたことが一番の成果でした。
こんな課題をお持ちの方へ
もし次のどれかに心当たりがあれば、RAGによる社内ナレッジ検索は有効な選択肢になります。
- 社内に資料は溜まっているのに、必要なときに探し出せない
- 特定のベテランに質問が集中し、その人が抜けると業務が回らない
- 全文検索を入れたが、言い回しの違いでヒットせず使われていない
- AIは気になるが、いきなり大掛かりな基盤を入れるのは不安
RAGは「AIを入れること」自体が目的ではなく、自社のデータをどう正しく検索して答えさせるか、そして自社の規模に合った構成をどう選ぶかが成否を分けます。私たちは、既存の業務システムに自然な形でAIチャット検索を組み込み、運用・コスト面まで含めて現実的に回る構成をご提案できます。
「うちのこのデータで実現できる?」「まずは小さく試したい」という段階のご相談でも構いません。社内ナレッジの活用でお悩みでしたら、お気軽にお問い合わせください。