Mutliple Vector によるプロジェクトドキュメント検索の精度向上

# はじめに

RAG（Retrieval-Augmented Generation）を利用してプロジェクトドキュメントを検索する際、Mutliple Vector の手法を用いることで、どのように検索精度が向上するかを検証しました。本記事では、その手法と結果について説明します。


# Mutliple Vector による検索の基本概念

Multivector Retrieverは、文書ごとに複数のベクトルを保存し、異なる視点からの検索を行う手法です。この手法をうまく適用することで、従来の単一ベクトル検索より精度高く求めている情報を含む箇所を見つけることができます。[LangChain の MultiVectorRetriever](https://python.langchain.com/docs/how_to/multi_vector/) では3つの手法を紹介しています。

- Smaller Chunks: 文書をより細かく分割したチャンクを検索対象とする。
- Summary: 文書全体を要約し、その要約を検索対象とする。
- Hypothetical Questions: 文書に対して想定される質問を作成し検索対象とする


# プロジェクトドキュメントを検索するに関する課題

プロジェクトドキュメント（設計資料や運用資料など）は、ExcelやPowerPointといった形式で管理されていることが多いです。これらの文書を単純にチャンクに分割してベクターDBに投入することには問題があります。

- チャンク分割されることで前後の文脈が分断され類似検索にかからない箇所が生じる。（表形式のデータなど）
- 標準化されたフォーマットにより、同じ内容が異なる箇所で繰り返されるため、求めていない情報が検索結果に含まれる（例: 異なるバージョンのAPI仕様書）
- 図を含むデータを正確に読み取ることは難しく断片的な情報がベクターDBに投入される

Multiple Vectorの手法を適用し、精度改善が期待されます。

- 図や表から断片的な情報を要約をすることで、それを含む部分が意図する内容に対し類似検索する
- 文書全体の要約に対して類似検索し、まず関連するファイルやシートを特定し、その範囲で詳細な情報を探す


# 検証

## 検証で使用したドキュメント
標準化されたフォーマットのサンプルとして、[デジタル庁 地方公共団体の基幹業務システムの統一・標準化 共通機能の標準仕様](https://www.digital.go.jp/policies/local_governments/common-feature-specification) のExcelの11ファイルを用いました。

- 機能要件
- 申請管理_項目定義書
- 住登外者宛名番号管理_項目定義書
- 団体内統合宛名_項目定義書
- 統合収納管理_項目定義書
- 統合滞納管理_項目定義書
- 住登外者宛名基本情報照会API仕様書
- 住登外者宛名番号付番API仕様書
- OAuth2.0アクセストークン発行API仕様書
- OAuth2.0アクセストークン情報取得API仕様書
- OAuth2.0アクセストークン無効化API仕様書


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1590551/8699d6d0-ccf6-8b8b-a90f-2bc54f70f6ee.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1590551/d3b7bbbe-c137-ca5d-573c-9b910cb7a64a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1590551/152fea5f-fd3e-159c-7351-eed5ab735eed.png)



## データの前処理とベクターDBへの投入

[Unstructured API](https://qiita.com/vko/private/75b64523d835ddaa1f93) を使用してExcelからテキストを取り出し、ページ単位にまとめたものをインデクス化しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1590551/11037248-7cd5-7f16-0994-abad83e06ade.png)

上記に加え、ファイル単位、ページ単位でそれぞれ250文字程度のテキストを要約したものをインデクス化しました。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1590551/c23840cd-18b3-d478-0114-f600a846c453.png)

結果、3通りのインデクスが作成されました。
1. `raw_text` - Excelから抽出した未処理のテキスト
1. `file_summary` - ファイル全体の要約 (250文字程度）したテキスト
1. `page_summary` - ファイル全体の要約（50文字程度）+ページ単位の要約（200文字程度）したテキスト


それぞれのインデクスにはメタデータを付与しておきます。
- file_name - 文書のファイル名
- page_name - Unstructuredで抽出したファイル内のページ（シート）名
- content_format - `raw_text`, `file_summary`, `page_summary`のいずれかを示す



## 検索処理

2通りの検索処理を用意しました。
（この検証では、LangChainのMultiVectorRetrieverは用いていません）

#### 非要約インデクスからのみ1ステップの類似検索
`raw_text`から検索を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1590551/4b83b934-b9d2-0861-0303-500b93d30cc7.png)

#### Multiple Vectorによる2ステップの検索類似検索
2段階の類似検索をします。
1. 要約（`file_summary`、`page_summay`）に対して類似検索を行う。 要約を含むファイル名、ページ名を取得する。
1. 1の結果から得られる範囲において、非要約のテキスト（`raw_text`)対して類似検索をする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1590551/235a8766-e6df-f44a-6e35-39def325b910.png)


## 検索に使用した質問文

以下の10の質問を用意して検索を行いました。

1. OAuth2.0アクセストークン発行APIのリクエストパラメータの一覧
1. OAuth2.0アクセストークン発行APIのscopeパラメータの記述例を教えて
1. OAuth2.0アクセストークン発行APIで、unsupported_grant_typeのエラーを説明して
1. OAuth2.0アクセストークン発行APIの呼び出しのシーケンスを教えて
1. 地方公共団体情報システムで、団体内統合宛名で団体内統合宛名番号履歴番号とは何か
1. 地方公共団体情報システムの統合滞納管理で、氏名の項目を説明して
1. 住登外者宛名番号付番APIでE0004のエラーは何か
1. 住登外者宛名基本情報照会APIのAPIコール名は
1. 地方公共団体情報システムの申請管理で、手続きコードのフォーマットのサンプルを教えて
1. OAuth2.0アクセストークン無効化APIで、アサーションJWTのエンコード方法を教えて

## 結果

Multiple Vectorによる多段階の類似検索を導入することで、HitRateおよびMMRのスコアが改善されました。

| Content Format  | HitRate@4 | MMR@4  |
|-----------------|-----------|--------|
| raw_text のみ        | 50.0%     | 20.8%  |
| file_summary -> raw_text    | 50.0%     | 21.7%  |
| page_summary -> raw_text   | 60.0%     | 27.5%  |

質問の意図に合致しないものが効果的に除外され、正しい回答を含むチャンクの順位が向上しました。

例えば、「住登外者**宛名番号付番**APIでE0004のエラーは何か」という質問では、
- 1ステップの検索では「住登外者宛名**基本情報照会**API仕様書」から結果を返してしまう（誤り）
- 2ステップの検索では「住登外者**宛名番号付番**API仕様書」からのみ結果を返す（正解）

また、「OAuth2.0アクセストークン発行APIの呼び出しシーケンスを教えて」という質問に対しては、`raw_text`, `file_summary`では関係ないシーケンス情報を返すことがありましたが、 `page_summary`のケースは図の情報を読み取れないにも関わらず、正確に関連ファイルとページを特定していました。

Page SummaryがFile Summaryよりも精度を向上させた理由は以下の点が考えられます:
- ファイルの大きさ: 大きなファイルは要約が不十分となり、関連のない内容も含まれるため、検索精度が低下する。
- サンプルの偏り: 使用したサンプルデータが少なく、関連性の低いファイル要約も検索対象に含まれてしまうことがあった。


# まとめ

Multiple Vector の手法を適用することで、特にページ要約を活用した場合に、Excelドキュメントからの類似検索の精度が改善されました。この手法は、設計資料や運用資料などの標準化されたドキュメントを扱うのに有効です。

また、ファイルとページが正確に特定されることは、次の点において有用です:
- 完全な回答が得られない場合でも、正しいファイルやページへのリンクを提供することで、ユーザーは迅速に目的の資料にたどり着くことができます。
- 特定されたファイルやページのテキスト全文をLLMで処理することで、チャンク分割の影響を受けずに、より完全な回答を返すことが可能です。