Blog

小さな社内システムのRAGは、ベクトルDBから始めなくていい

社内システムに質問できるAIを作ろうとすると、かなりの確率で「まず全部の文書を細かく分けて、文章の意味を数字にして、専用のデータベースへ入れましょう」という話になります。

いや、質問を見よう。

Beekle CRMのような小さな社内システムで聞かれるのは、「今月の確定売上はいくらか」「未対応の問い合わせは何件あるか」「この案件の担当者は誰か」「来月入金予定の案件を出して」といった質問です。これらの多くは、意味が近い文章を探す問題ではありません。すでにあるデータベースから、正しい条件で正しい行を取る問題です。

社内の情報を探し、その根拠を生成AIへ渡して答えさせる仕組みは、一般にRAGと呼ばれます。また、文章の意味を数字に変え、意味が近い文章を探すためのデータベースは、ベクトルDBと呼ばれます。ただ、小規模な社内システムでは、最初からすべてをベクトルDBへ入れなくても、かなりの質問に答えられるんですよね。

最初から全部を意味検索にする話になっていました

この記事を書くきっかけになったのは、Lighthouse AIの「RAG Is Simpler Than You Think」という記事です。記事では、最初に全文検索だけを作り、必要なら利用者の質問を検索語へ直し、それでも足りない場合に意味検索を加え、データ量や利用回数が増えてから全文書の事前処理へ進む、という順番が紹介されています。

この方向性はかなり正しいと思います。ただ、タイトルどおり「RAGは単純です」という話ではありません。正確には、検索方法を一つに決めず、質問の種類に応じて使い分けるという話です。

ベクトルDBを入れることが目的になってしまうと、文書をどこで区切るか、更新時にどう作り直すか、古い情報をどう消すか、検索精度をどう測るかまで、一気に運用対象が増えます。必要ならやればいい。でも、まだ必要か分からない段階から全部やるのは、普通に重いです。自分も技術が面白いと、普通にそっちへ行きます。質問は「未対応は何件?」なのに、検索基盤だけ宇宙開発になる。俺が一番危ない。

でも、社内で聞かれることはかなり普通です

小さな社内システムでは、質問の多くがすでに構造化されています。顧客、案件、担当者、金額、状態、予定日、入金日といった項目が、データベースの列として存在しているからです。

  • 今月の確定売上はいくらか
  • 未対応の問い合わせは何件あるか
  • 株式会社〇〇の進行中案件を見せて
  • 来月入金予定の案件を、金額が大きい順に出して
  • 次の対応日を過ぎている案件はどれか

これらに必要なのは、似た文章を探す能力より、金額・日付・状態・会社名を正しく絞る能力です。売上を聞かれているのに、売上と意味が近い議事録を探してもしょうがない。数字を聞かれたら、数字を取りにいく。 まずはそれでいいんだと思います。

売上を聞かれているのに、似た文章を探してもしょうがない

質問に合う探し方を整理すると、かなり単純になります。全部を同じ検索へ流すのではなく、欲しい答えの型から逆算します。

質問の種類

最初に使う探し方

金額・日付・状態

通常のデータベース検索

今月の売上、来月の入金予定、未対応件数

会社名・案件名・番号

完全一致や全文検索

顧客名、請求書番号、エラー番号

情報同士のつながり

既存の関連情報をたどる

顧客から案件、案件から担当者、要求からテスト結果

表現の違う似た内容

意味の近さで探す検索

似た失注理由、近い相談、類似する議事録

RAGという名前を付けると、全部を文章検索の問題として扱いたくなります。でも、社内システムの正本がデータベースにあるなら、まずそこへ聞けばいい。生成AIは検索の代わりではなく、利用者の曖昧な質問を、どこへ何を聞けばよいかへ整理する役に置く方が自然です。

会社名や案件番号は、意味より文字が合っている方が強い

社内検索では、固有名詞がかなり重要です。会社名、担当者名、案件名、請求書番号、画面名、機能名、エラー番号のような情報は、意味が似ていることより、文字が正確に一致することの方が大切です。

たとえば社内に「Atlas」という独自機能があったとして、一般的な意味検索は地図やギリシャ神話へ寄せるかもしれません。一方、全文検索なら、社内文書に書かれた「Atlas」をそのまま探せます。元記事も、社内固有の用語では正確な文字列検索が強いと説明しています。

もちろん、表記揺れはあります。「ビーくる」「Beekle」「株式会社Beekle」のような違いです。ここは同義語の辞書や会社名の別名を管理すればよく、必ずしも全文書を意味の数字へ変える必要はありません。固有名詞を探しているのに、AIが気を利かせて別の意味へ連れていく。親切の方向が違う。 まず正確に当てる方が先です。

質問だけAIに整理させると、かなり遠くまで行ける

利用者は、データベースの項目名どおりには質問しません。「来月入ってくるお金、何がある?」のように聞きます。そこで文章を扱う生成AIに、質問を検索計画へ変えさせます。

利用者の質問
来月入ってくる予定のお金を、会社ごとに見せて

検索計画
・対象:案件または入金予定
・期間:翌月の初日から末日
・状態:予定、確定
・表示:会社名、案件名、金額、入金予定日
・並び順:入金予定日が早い順

生成AIがやるのは、利用者の言い方を理解して、検索条件へ変えるところまでです。実際の金額や状態はデータベースから取得し、回答には案件番号や更新日時を添えます。これなら、AIが金額をそれっぽく作る余地も減らせます。

文章の検索でも同じです。「メールを送ったあと、もう一回押しても二重に送られないやつ」と聞かれたら、「メール送信、再実行、二重送信、重複防止」のような語へ直して全文検索できます。検索対象を全部作り変える前に、質問側を整える。ここだけでも普通に効くことがあります。

小さいうちは、候補だけAIに読ませればいい

対象データが数十件から数百件程度で、利用者も社内の数人なら、最初から大規模な検索基盤を作る必要はありません。まず通常のデータベース検索や全文検索で候補を絞り、その候補だけを生成AIへ渡して回答を整理させます。

  1. 利用者の質問を、対象・期間・状態・検索語へ分解する
  2. 通常のデータベース検索と全文検索で候補を取る
  3. 候補の中から、質問へ答えるのに必要な情報だけを生成AIへ渡す
  4. 回答に、根拠となった顧客・案件・文書の番号を付ける

この構成なら、情報を更新した瞬間に最新データを読めます。別の検索用データを作って同期する処理も、最初は要りません。ただし、権限の確認、現行情報と履歴の分離、回答に使った根拠の記録は必要です。小さいから雑でいいのではなく、小さいうちは正本へ直接聞けるということです。

似た案件を探したくなったら、その部分だけ追加する

意味の近さで探す検索が有効になる場面も、もちろんあります。営業メモ、議事録、問い合わせ本文、失注理由のように、同じ内容でも表現が毎回変わる情報です。

  • 過去の似た案件を探したい
  • 今回の相談と近い失注理由を見つけたい
  • 言い方は違うが、同じ問題を扱った議事録を探したい
  • 顧客の相談文から、参考になる過去事例を出したい

この領域で検索漏れが増えたら、その部分だけ文章の意味を数字に変えて探せるようにします。さらに必要なら、文字が一致した結果と意味が近い結果を別々に取り、上位に出たものを一つの順位へまとめます。Elasticsearchの公式資料でも、正確な単語の検索と意味検索を組み合わせ、順位を統合する方法が案内されています。

大事なのは、最初から全データへ入れることではありません。曖昧な意味検索が必要だと実測できた場所へ足す。 検索基盤を豪華にする順番ではなく、見つからなかった質問を減らす順番で作ります。

「似ている」ではなく「どうつながっている」を聞く仕事がある

ここまで読むと、通常のデータベース検索と全文検索で、かなりの質問へ答えられそうに見えます。では、情報同士の関係をつないだ仕組みは、いつ本気で必要になるのか。

答えは、一件の文書を見つければ終わるのではなく、複数種類の情報を何段もたどり、その経路自体を根拠として答える必要があるときです。こうした関係を生成AIがたどり、必要な根拠を集めて回答する仕組みを、GraphRAGと呼びます。

「似たものはどれ?」なら意味検索。
「何と何が、どの経路でつながっている?」なら関係をたどる検索。

特に、次の条件が重なるほど、通常の検索だけでは厳しくなります。

  • 答えが、顧客・製品・契約・作業など複数種類の情報にまたがる
  • 何段たどれば答えが出るかが、質問ごとに変わる
  • 似ている上位数件ではなく、影響対象を漏れなく出す必要がある
  • 「なぜその結論になったか」を、つながりの経路で説明する必要がある

ここで、グラフ型データベースとGraphRAGは分けた方がいいです。部品から製品、製品から顧客まで、決まった関係をたどって一覧を返すだけなら、通常のデータベース検索やグラフ検索で足ります。生成AIまで呼ぶ必要はありません。

GraphRAGが必要になるのは、規程、会議記録、障害報告、契約書のような文章と、顧客・製品・作業の関係をまたぎ、質問ごとに違う経路を選び、集めた根拠を人が読める説明へまとめるときです。全部をグラフにすればよいわけではありません。

データが多いから必要になるわけではありません。件数が少なくても、関係が深く、抜け漏れが事故につながるなら、グラフが効きます。

不良部品から、回収すべき製品と顧客までたどる

製造業で、ある部品の製造番号に不良が見つかったとします。知りたいのは、その番号が書かれた報告書ではありません。その部品がどの部品群へ組み込まれ、どの完成品に使われ、どこへ出荷され、誰へ届いたかです。

不良部品の製造番号
↓ 組み込まれた
部品群
↓ 搭載された
完成品の製造番号
↓ 出荷された
倉庫・店舗
↓ 購入した
顧客

全文検索なら、不良部品の番号が書かれた資料を見つけられます。意味検索なら、似た故障報告も探せます。でも、回収対象を出すときに必要なのは「似ている順の上位50件」ではありません。影響を受ける全件です。

この場合は、部品から製品、出荷、顧客までの関係を正確にたどる必要があります。Neo4jの公式資料でも、供給網における原材料・製品・出荷先の依存関係や、障害が広がる範囲の把握が、グラフ型データベースの代表的な用途として紹介されています。

法改正から、直すべき規程・画面・研修資料までたどる

法令や社内規程が変わったときも、変更した文書だけを見つければ終わりではありません。その規程を前提にしている業務手順、申請書、システムの入力条件、確認項目、研修資料まで直す必要があります。

法改正
↓ 根拠にしている
社内規程
↓ 具体化している
業務手順・申請書
↓ 実装している
システムの画面・入力条件
↓ 確認している
テスト・研修資料

関連文書に同じ言葉が書かれているとは限りません。規程には「保存期間を7年とする」とあり、システム側には単に削除可能日を計算する処理だけがあるかもしれない。文字列が一致しなくても、前提として依存しています。

ここで必要なのは、変更された言葉を探すことではなく、その変更を前提にしているものをたどることです。法改正、規程、業務、システム、確認項目の関係を持っていれば、影響範囲を一つの経路として出せます。

システム障害から、原因となった変更までたどる

たとえば、利用者が突然ログインできなくなったとします。エラーメッセージを検索すれば、似た障害記録は出てきます。でも、本当に知りたいのは、現在の障害がどのサービスに始まり、何へ依存し、直前のどの変更と関係しているかです。

ログイン障害
↓ 利用している
認証サービス
↓ 依存している
証明書・設定
↓ 変更した
公開作業
↓ 含まれていた
コード変更・作業・担当者

このつながりがあれば、「似た障害が以前にもあった」だけでなく、「今回影響している機能はどれか」「何を戻せばよいか」「誰が状況を確認できるか」まで答えられます。

実際には、監視記録、構成情報、公開履歴、作業記録をそれぞれ正式な情報として管理し、生成AIはその関係を読んで説明する形が安全です。全部を文章から推測し直す必要はありません。

一件ずつ見ると普通な不正利用を、つながりで見つける

不正利用は、一件だけ見ると普通に見えることがあります。別名義の複数アカウントが、同じ端末、電話番号、住所、振込先を少しずつ共有していた場合、個別の記録だけでは気づきにくいです。

アカウントA ─ 同じ端末 ─ アカウントB
│ │
同じ住所 同じ振込先
│ │
アカウントC ─ 同じ電話番号 ─ アカウントD

関係をつなぐと、別々に見えた利用者が一つの集団として見えてきます。Neo4jも、不正集団、資金の循環、共有された端末や口座など、個別記録だけでは見えにくい関係をたどる用途を紹介しています。

ただし、不正かどうかの最終判断を生成AIだけへ任せる話ではありません。怪しいつながりの候補と、その根拠となる経路を出し、人が確認できるようにする。ここで重要なのは回答の派手さではなく、調査経路が残ることです。

大型の法人営業で、意思決定のつながりをたどる

法人営業も、案件が大きくなるほど関係の問題になります。窓口担当者だけで決まるとは限らず、利用部門、部門長、経営企画、経理、法務、情報システムなどが、それぞれ別の条件を持っています。

窓口担当者
↓ 説明する
部門長
↓ 承認を求める
経営企画・経理
↓ 確認を求める
法務・情報システム
↓ 判断へ影響する
最終的な発注

通常の顧客管理表で担当者や商談段階を管理するだけなら、グラフは要りません。でも、複数回の打ち合わせ記録、組織図、過去案件、各関係者の懸念、社内承認の順番まで横断して、「誰のどの懸念が止めているのか」「次に誰へ何を説明すべきか」を出すなら、関係をたどる価値が出ます。

つまり、GraphRAGがガッツリ必要になるのは、情報を見つけるだけでは仕事が終わらず、つながりをたどって影響・原因・経路を説明すること自体が業務になっている場合です。

PM on Railsでは、検索より関係の方が難しい

一方、PM on Railsでは事情が少し違います。PM on Railsは、何を実現したいか、利用者が何をしたいか、具体的にどう動けば正しいか、どの作業で実装し、どの確認結果で完了としたかをつないで管理する開発の仕組みです。

ここで知りたいのは、文章が似ているかだけではありません。「この確認項目はどの要求に属するか」「この変更で影響を受ける設計は何か」「このテスト結果は、どの変更内容と公開版を確認したものか」「今の仕様はどれで、過去の仕様はどれか」といった関係です。

これは文書検索より、情報同士のつながりを正確にたどる問題です。MicrosoftのGraphRAGも、文章から人物や対象、関係を取り出し、構造化した情報として検索へ利用する仕組みを案内しています。ただ、業務システムには最初から顧客と案件、要求と確認項目のような関係が保存されていることも多い。既にある関係まで、文章からもう一度推測して作り直す必要はありません。

顧客・案件管理では通常のデータベース検索が中心になる。PM on Railsでは関係をたどる検索が増える。議事録の類似検索には意味検索が効く。同じ会社の中でも、正解は一つじゃない。 だから全部をベクトルDBへ統一しない方がいいんだと思います。

元記事の数字は、そのまま信じない方がいい

元記事は考え方がかなり良い一方で、費用計算とモデルの説明には明確な矛盾があります。思想はいい。でも数字は普通に壊れています。

記事の前半では、同じ50文書を処理する費用を1回約0.0005ドルと計算しています。ところが後半では、同じ50件の処理が0.025ドルになっており、50倍違います。また、100万文書の事前処理を10ドルとする箇所と、更新時には1万ドルとする箇所があり、こちらは1000倍違います。

さらに、OpenAIが古い埋め込みモデルを廃止したと書かれていますが、OpenAIの現在の公式モデル一覧には、そのモデルが旧世代モデルとして掲載されています。新しいモデルの発表時にも、廃止しないと明記されていました。モデルを変えれば検索用データの作り直しが必要になる、という一般論は正しい。ただし、例として出した事実は違います。

最後に出てくる「60%は全文検索と質問の整理で十分」「25%は簡易的な組み合わせが必要」といった比率にも、調査方法は示されていません。経験則として読むなら参考になりますが、統計としては使えません。元記事から借りるべきなのは数字ではなく、簡単な方法から始め、実測してから複雑にするという順番です。

最初に作るべきなのは、ベクトルDBではなく評価表

どの検索方法から始めるにしても、先に用意したいのは実際の質問と正解です。検索基盤を作ってから「なんとなく良さそう」で確認すると、複雑にした効果が分かりません。

  • 社内で実際に聞かれそうな質問を20〜50件集める
  • 各質問で参照すべき顧客、案件、文書、版を決める
  • 権限上、見せてはいけない情報も決める
  • 答えがない質問では、無理に作らず「分からない」と返す条件を決める
  • 検索で正しい根拠を見つけたかと、その根拠どおりに回答したかを分けて見る

全文検索だけで十分に見つかるなら、そのままでいい。会社名の表記揺れで落ちるなら辞書を足す。質問の言い方が曖昧なら検索条件の作り方を直す。似た内容だけ見つからないなら、その部分へ意味検索を足す。この順番なら、複雑にするたびに何が改善したかを確認できます。

ベクトルDBを導入したかどうかは、成果ではありません。 利用者の質問へ、正しい根拠を、権限を守って、現行の情報から返せたか。それが成果です。

結局、質問ごとに探し方を変える

小さな社内システムのRAGでは、最初から最終形を作らなくてもいいんだと思います。金額・日付・状態は通常のデータベースへ聞く。会社名や番号は完全一致や全文検索で探す。情報同士のつながりは既存の関係をたどる。表現が違う似た内容だけ、意味の近さで探す。

複数の意図が混ざった質問なら、先に質問を分けます。「来月の入金予定と、遅れている案件と、担当者別の合計を出して」と聞かれたら、三つの検索に分けて最後にまとめればいい。全部を一発で見つける魔法の検索を作るより、その方が正確です。

RAGは、ベクトルDBを入れることではありません。質問に必要な正しい根拠を探し、生成AIへ渡し、根拠から外れない回答を返すことです。

Beekle CRMのような小さな社内システムなら、まず既存のデータベースを正しく検索するところから始められます。PM on Railsのように関係と履歴と証拠が重要なシステムでは、グラフ型の関係検索を使う。必要になった場所だけ意味検索を足す。結局、検索方式を一つに統一しないことが、一番単純なのかもしれません。


関連する記事・サービス

参考にした資料