【RAGで社内情報を活用！？】ベクトル検索精度の課題と試したこと

# はじめに

### 導入
ある程度のことなら答えてくれる生成AI。
業務利用されている方は、「社内情報に関しても回答してくれたらな」と感じたことがある方も多いのではないでしょうか。:thinking:

その場合、生成AIに回答させるには事前に社内情報を教える必要があります。

じゃあ教えちゃおう、と言いたいところですが`Gemini`や`ChatGPT`などのオープンモデルは個人で学習させることができません。<font color="red">(**※社内情報は機密情報です。取り扱いには注意しましょう。**)</font>
学習可能なオープンモデルも存在しますが、学習データ量が膨大であるため大規模なマシンスペックを必要とします。
以上のことから現実的でないのが現状です。

そこで、少し前から話題の**RAG(Retrieval-Augmented Generation)** が登場します。

### RAG(検索拡張生成)
簡単に言うと、検索（Retrieval）した情報をもとに、生成AI（Generation）が回答を作る仕組みのことです。ベクトル検索＋生成AIとも表現できると思います。

https://aws.amazon.com/jp/what-is/retrieval-augmented-generation/


RAGはデータベースから関連情報を検索するため、モデル学習の手間が省けます。
また、データベースに対する検索方法が全文検索でなくベクトル検索だと、曖昧表現で検索できることもメリットです。
一方で関連情報の検索精度の問題がもれなくついてきます。

![プレゼンテーション1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941230/238b79ab-9a3c-4bbb-9786-af44195353b6.png)


検索の仕組みはざっくり以下の通りです。

1.データベースに文章をベクトル化(数値化)した状態で登録
2.データベースに対する検索文も同様にベクトル化
3.登録した文章の中から、検索文と類似するベクトル(文章)を取得

この方法で、生成AIのモデルを学習させる事なく特定分野に関する回答を期待できます。
検索結果の精度が重要そうですね。

ということで実際に触ってみました。

#  RAGを触ってみよう
### 環境情報
- 登録データ
![スクリーンショット 2025-03-21 15.31.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941230/b60b3e94-01b7-4c35-a78b-cab84797cf9f.png)

- ベクトルデータベース：[ChromaDB](https://www.trychroma.com/)
- 埋め込みモデル：sentence-transformers/LaBSE
- 類似度の計算方法：コサイン類似度
- 生成AI：[Gemini(gemini-1.5-pro)](https://ai.google.dev/gemini-api/docs/models?hl=ja#gemini-1.5-pro)


### まずはベクトル検索結果のみ出力
- 質問：ログインできないなんで

- 結果
```
- 社内システムのログインIDは通常、社員番号やメールアドレスの一部が含まれています。
正しい形式で入力しているか確認してください。
IDが不明な場合は、人事部またはITサポートにお問い合わせください..（類似度: 55.85 %）

- パスワードをリセットするには...（類似度: 47.66 %）

- VPN接続エラーの原因として（類似度: 41.23 %）
```

ログインIDに関する質問を検索できていて、その質問に対する回答を出力してくれています。（類似度: 55.85 %）
とはいえ、<font color="red">類似度や回答内容に大きな差がないように見受けられます。</font>
他に類似度の高い回答内容も回答に含めて欲しかったり、高い類似度であっても関係無い内容は回答に含めて欲しくありません。

そこで、検索結果の上位n件を生成AIにプロンプトとして送信し、適切な回答データを生成してもらうようにしてみました。

### 検索結果の上位n件とプロンプトを生成AIに送信(今回は3件）

- 質問：ログインできないなんで

- プロンプト
```
あなたは質問応答AIです。以下のユーザーの質問に答えてください。類似質問とその回答のペアデータを参考に、入力される質問に対する回答を出力してください。また、一般的な回答も簡単に出力してください。
```

- 結果(検索結果、および類似度は上述のものと同様です)

```
回答：
 「ログインできないなんで」という質問は、情報が不足しており、具体的な問題点が分かりません。ログインできない原因は様々考えられるため、より詳細な情報を提供いただく必要があります。

例えば、以下の点を教えていただけると、問題解決に役立ちます。

* どのようなシステムにログインしようとしていますか？（例：社内システム、Webサービス、メールアカウントなど）
* どのようなエラーメッセージが表示されていますか？（例：「ユーザーが存在しません」「パスワードが違います」「アクセスが拒否されました」など）
* 以前はログインできていましたか？
* 何か設定を変更しましたか？
* どのような端末からログインしようとしていますか？（例：パソコン、スマートフォン、タブレットなど）

**考えられる原因と対応策:**

* **ID やパスワードが間違っている:** 入力内容を再度確認してください。大文字・小文字、全角・半角にも注意してください。
* **ID が存在しない:** 社員番号やメールアドレスが正しく登録されているか確認してください。人事部やシステム管理者へお問い合わせください。
* **パスワードを忘れた:** パスワードリセットの手続きを行ってください。多くのシステムでは、リセット用のリンクやボタンが用意されています。
* **ネットワークに問題がある:** インターネット接続を確認してください。Wi-Fi ルーターの再起動や、有線接続への切り替えを試してみてください。
* **システム側の問題:** システムメンテナンスなどが行われている可能性があります。システム管理者へお問い合わせください。
* **アカウントがロックされている:** 複数回パスワードを間違えると、アカウントがロックされる場合があります。システム管理者へお問い合わせください。
* **VPN接続が必要:** 社内システムにアクセスする場合は、VPN 接続が必要な場合があります。VPN が正しく設定されているか、接続されているか確認してください。

**一般的な回答:**

ログインでお困りのようですが、情報が不足しているため具体的な対応策を提示できません。どのようなシステムにログインしようとしていて、どのようなエラーが発生しているかなど、詳細を教えていただけますか？
```

回答の前半部分は質問の情報量が少なくて怒られていますが、<font color="red">後半部分では登録した回答内容や補足情報になっていますね。</font>(補足情報が多いですが...)

ベクトル検索だけで良いのでは、と思っていましたが、検索精度を考慮すると生成AIを加えるRAGの方がある程度使いやすそうに感じました。

また、少し詳しめの文章で質問したときの結果はこちらです。

- 質問：パスワードを忘れてしまい、システムにログインできなくなった

- プロンプト：上述と同様

- 結果

```
- パスワードをリセットするには、社内ポータルサイトにアクセスし、リセット申請を行ってください。
リセット後は、新しいパスワードでログインできることを確認し、必要に応じて IT 部門に報告してください。
（類似度: 67.81 %）

- パスワードが正しく入力されているか確認してください。
Caps Lock や Num Lock が有効になっていないかチェックし、それでもログインできない場合は、社内ポータルサイトからパスワードリセットを行ってください。
（類似度: 58.04 %）

- 社内システムのログイン ID は通常、社員番号やメールアドレスの一部が含まれています。
正しい形式で入力しているか確認してください。
ID が不明な場合は、人事部または IT サポートにお問い合わせください（類似度: 56.60 %）
```

```
回答：

システムにログインできなくなったとのこと、ご不便をおかけしております。パスワードをリセットするには、以下の手順をお試しください。

1. システムに関連付けられたポータルサイト、またはログイン画面を探します。多くの場合、「パスワードを忘れた場合」や「パスワードリセット」といったリンクが用意されています。
2. リンクをクリックし、画面の指示に従ってパスワードリセットの手続きを進めてください。多くの場合、登録済みのメールアドレスやセキュリティ質問への回答が必要になります。
3. 新しいパスワードを設定し、ログインできることを確認してください。

もし上記の手順で解決しない場合、または関連するポータルサイトやリンクが見つからない場合は、システム管理者またはITサポートデスクに連絡してください。


**一般的な回答:**

パスワードを忘れた場合は、システムのパスワードリセット機能を利用してください。通常、ログイン画面に「パスワードを忘れた場合」などのリンクがあります。
リンクをクリックし、画面の指示に従って操作することでパスワードを再設定できます。それでも解決しない場合は、システム管理者にお問い合わせください。
```

今回は曖昧な質問ではないため、欲しい回答が簡潔に返ってきていますね。


# おわりに
検索精度の調整には多くの時間と労力を費やすことになるため、検索結果の評価に重きを置いた「検索結果の上位n件とプロンプトを生成AIに送信」を試してみました。
精度改善方法は他にもありますので、随時試してみたいと思います。
下記にコラムも記載しましたので、よろしければご覧ください。

# コラム1：検索精度を上げる方法
- ベクトル化に用いる埋め込みモデルを変えるなど、文章を数値化する計算方法を見直す

- 定型表現を除く・要約するなど、登録する文章を整形する

- コサイン類似度・ユークリッド距離など、類似度の計算方法を見直す

https://www.ogis-ri.co.jp/otc/hiroba/technical/similar-document-search/part1.html

https://zenn.dev/welmo/articles/a79b8b45573383


# コラム2：長文になると意味が異なる文章でも類似度が高くなる理由
短文であれば、そこそこの検索精度が得られるのですが、
実務ではもっと複雑な長文と向き合うことになるかと思います。

例えば、以下の4つの文章の類似度を計算してみます。

![スクリーンショット 2025-03-21 16.05.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941230/064a7405-8e37-4638-a6fa-cd7a68434124.png)

- コサイン類似度
短文（天気） vs 短文（ラーメン）: 0.5584
短文（天気） vs 長文（天気）: 0.6846
短文（ラーメン） vs 長文（ラーメン）: 0.6627
長文（天気） vs 長文（ラーメン）: 0.6157

長文では、「とても〜」「多くの〜」「すばらしい〜」といった表現が類似しており、短文同士の類似度と比べ少し高くなっていますね。<font color="red">文章の意味が違っていても、要所に似た文字列が存在すると類似度が高くなる傾向にあります...</font>
長文は短文に比べて文章を構成する単語の数が多いため、そのような状況になりやすくベクトル検索の精度が落ちやすいです。
また、コサイン類似度を用いたときは「次元の呪い」という問題も潜んでいます。
ベクトル要素が増えるほど、ベクトル同士の類似度に差がなくなってくるという問題です。:sob:

https://gen-ai-media.guga.or.jp/glossary/curse-of-dimensionality/

https://note.com/oldharukaeru2011/n/n88f1593ca2c6