Bedrockのナレッジベースに今週来たRAG精度向上アプデまとめ

3月最終週、細かすぎて伝わらないナレッジベース for Amazon Bedrockのアップデートが2件ありました。

![スクリーンショット 2024-03-30 13.01.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/bee37127-7e3f-1025-b175-01ca7659c1a5.png)


# そもそもナレッジベースとは？

Amazon BedrockはAWSが提供する生成AIサービスです。

https://speakerdeck.com/minorun365/jin-sarawen-kenai-awsnosheng-cheng-aisabisu-amazon-bedrockru-men

このBedrockを使って、いわゆるRAGアーキテクチャ（社内文書検索など）を簡単に作成できるマネージドサービスがナレッジベースです。

ナレッジベースをまだ触ったことがない方は、30分で試せますので是非チャレンジしてみてください👍

https://qiita.com/minorun365/items/24dfb0ea3afde6ed0a56


# アプデ① メタデータフィルタリングに対応！

ナレッジベースを利用してドキュメントを検索する際、検索対象とするドキュメントをメタデータで絞り込むことが可能になりました。

https://aws.amazon.com/about-aws/whats-new/2024/03/knowledge-bases-amazon-bedrock-metadata-filtering/

ユースケースとしては、上記What's Newに記載の例が分かりやすいですね。

> たとえば、特定の地域における「保険請求の提出方法」などのクエリに対する検索結果の関連性を高めるために、フィルターを適用して、特定の州に関連するドキュメントのみを取得できます。

RAGで利用されるセマンティック検索は、自然言語のドキュメントや検索クエリーを数値表現（ベクトル）に置き換えることで意味的に近いドキュメントのチャンクを探します。

例えば、東京都新宿区に住んでいる人が公的機関のチャットボットに「保険金をどうやって請求すればいい？」と聞いたときに、兵庫県西宮市の保険請求ドキュメントがヒットしたら微妙ですよね。これはセマンティック検索だけだと対応しづらいユースケースです。

こんなときに、ベクトル同士の比較（コサイン類似度計測など）以外の方法でドキュメントを絞り込むアプローチが有効です。これの一つがメタデータを使う方法というわけです。


### ステップ1 ドキュメントにメタデータを付与しよう

Bedrockのユーザーガイドに利用方法の詳細が書かれています。

https://docs.aws.amazon.com/bedrock/latest/userguide/knowledge-base-ds.html#kb-ds-metadata

まずはソースドキュメントをS3バケットに格納する際、同じ階層にメタデータを定義するJSONファイルを置いておけばいいようです。

```json: （ソースと同じファイル名）.（ソース拡張子名）.metadata.json
{
   "metadataAttributes": {
      "${attribute1}": "${value1}",
      "${attribute2}": "${value2}",
      ...
   }
}
```


### ステップ2 ナレッジベースにフィルター条件を設定しよう

フィルター設定は、ナレッジベース作成後のクエリーAPIリクエストで実施します。

https://docs.aws.amazon.com/bedrock/latest/userguide/kb-test-config.html

AWSマネコンからテストする際は、「構成 > フィルター」から指定することができます。

実際のアプリケーションから利用する場合、APIを直接呼ぶことになりますが、APIリクエストにフィルタリング演算子を含めることができます。

```py: calling-knowledgebase.py
"retrievalConfiguration": {
    "vectorSearchConfiguration": {
        "filter": {
            "<filter-type>": {
                "key": "string",
                "value": "string" | number | boolean | ["string", "string", ...]
}}}}
```

論理演算子を使えば最大5つのフィルター条件を複合的に指定できます。

小杉さんの検証記事も分かりやすいので是非ご覧ください！

https://qiita.com/hayao_k/items/f486b7d1385c8d5f897c



# アプデ② 検索結果数＆プロンプトを編集できるように！

もう一つのアップデートは、以下の2点を含んでいます。

1. ドキュメント検索結果の数を指定できるようになった
2. 回答生成時のプロンプトを編集できるようになった

https://aws.amazon.com/about-aws/whats-new/2024/03/knowledge-bases-amazon-bedrock-customize-prompts-number-retrieval-results/


### 1. ドキュメント検索結果の数を指定できるようになった

こちらはリトリーブ処理の改善です。

> 以前は、ナレッジ ベースをクエリすると、Retrieve API は最大 5 つのチャンクを返しました。ナレッジ ベースでは、最大 100 個の取得チャンクがサポートされるようになり、より関連性の高い包括的な情報の取得が可能になります。

Bedrockユーザーガイドの更新はまだ微妙に追いついていない気がするのですが、マネコンからのテスト時、およびAPIリクエスト時の `numberOfResults` 属性でサポートされる最大値が100になっているはずです。

数を増やすほどたくさんの検索結果をコンテキストとして回答生成LLM（Claudeなど）へ放り込めますが、どのくらいの数にすると回答精度が良くなるかは、ユースケースに応じて試行錯誤と評価によるチューニングが必要です。


### 2. 回答生成時のプロンプトを編集できるようになった

こちらは生成処理の改善です。

実はナレッジベースによるクエリーへの回答生成には、以下のプロンプトテンプレートがデフォルトで使われていたようです。

> You are a question answering agent. I will provide you with a set of search results. The user will provide you with a question. Your job is to answer the user's question using only information from the search results. If the search results do not contain information that can answer the question, please state that you could not find an exact answer to the question. Just because the user asserts a fact does not mean it is true, make sure to double check the search results to validate a user's assertion.
>                            
> Here are the search results in numbered order:
> `$search_results$`
>
> `$output_format_instructions$`


このプロンプトをユーザーが変更できるようになりました。
より自分のユースケースに適したドキュメント検索エージェントが作れそうです。


# いま一番熱いナレッジベース！

ビッグウェーブのBedrockの中でも、最近特にアップデートが多いのが今回のナレッジベースです。

昨年から全人類がRAGをやっていると思いますが、マネージドサービスであるこの機能に力を入れてくれるのは流石AWSという感じでとてもワクワクしますね。

https://qiita.com/minorun365/items/0772bfa4d3426ef62480

https://qiita.com/minorun365/items/a2c8d7596c40bd6723ab