AWS 入門ブログリレー 2024 〜Knowledge bases for Amazon Bedrock編〜

Knowledge bases for Amazon Bedrock について2024年04月22日時点の情報をさらぁっとまとめてみました。AWSサービス入門記事として是非ご活用下さい。
2024.04.22

こんにちは! AWS 事業本部コンサルティング部のたかくに(@takakuni_) です。

当エントリは弊社 AWS 事業本部による『 AWS 入門ブログリレー 2024』の 29 日目のエントリです。

このブログリレーの企画は、普段 AWS サービスについて最新のネタ・深い/細かいテーマを主に書き連ねてきたメンバーの手によって、 今一度初心に返って、基本的な部分を見つめ直してみよう、解説してみようというコンセプトが含まれています。

AWS をこれから学ぼう!という方にとっては文字通りの入門記事として、またすでに AWS を活用されている方にとっても AWS サービスの再発見や 2024 年のサービスアップデートのキャッチアップの場となればと考えておりますので、ぜひ最後までお付合い頂ければ幸いです。

では、さっそくいってみましょう。今回のテーマは『 Knowledge bases for Amazon Bedrock 』です。

Knowledge bases for Amazon Bedrock とは

Knowledge bases for Amazon Bedrock とは、 Amazon Bedrock の機能の一つでフルマネージドなベクトル検索サービスです。自然言語で企業内の様々な場所に散らばっているドキュメントや情報を、効率的に検索できるようにします。

文字を読むことは意外と大変

Amazon Kendra 編でも同じことを書いていますが、あえて繰り返します。既に読んでるよーって方は読み飛ばしちゃってください。

このブログを含め、文字を読むのは人それぞれ、得意不得意あると思います。(私は不得意です。)

例えば以下のような、ドキュメントがあったとします。

株式会社サンプル企業 就業規則

第1章 総則

第1条 (目的)
この就業規則は、株式会社サンプル企業(以下「会社」という)の労働条件及び服務規律を定めることを目的とする。

第2条 (適用範囲)  
この就業規則は、会社に雇用される全ての従業員に適用される。ただし、別に定める場合はこの限りではない。

第2章 人事

第3条 (採用)
会社は、従業員の採用に際して、性別、年齢、国籍、信条等による不当な差別をしない。

第4条 (期間の定めのない労働契約と有期労働契約)
従業員の労働契約期間は、期間の定めのないものと有期のものとがある。有期労働契約の更新については別に定める。

第5条 (内定取消し)
次の各号の一つに該当する場合には、内定を取り消すことがある。
(1) 重大な虚偽の申告があった場合
(2) 会社の指示に従わない場合
(3) その他入社が不適当と認められる場合

第3章 勤務時間、休憩、休日

第6条 (所定労働時間)
1. 所定労働時間は、1週間につき40時間とし、始業・終業の時刻および休憩時間は、次のとおりとする。
   始業時刻 9:00
   終業時刻 17:30
   休憩時間 12:00 - 13:00

第7条 (フレックスタイム制)  
1. 業務の性質上必要がある場合には、フレックスタイム制を採用することがある。
2. フレックスタイム制における運用細則は別に定める。

第8条 (時間外労働)
1. 業務の都合上必要がある場合には、所定労働時間を超えて時間外労働を命ずることがある。
2. 時間外労働を行わせる場合には、法定の手続きに基づき割増賃金を支払う。

第9条 (休日)  
1. 休日は次のとおりとする。
   (1) 日曜日
   (2) 土曜日
   (3) 国民の祝日
   (4) 年末年始(12月29日から1月3日まで)
   (5) その他、臨時に指定する日
2. 業務の都合により、前項の休日を変更することがある。

第10条 (年次有給休暇)
1. 年次有給休暇の付与日数は、次のとおりとする。
   (1) 6ヶ月継続勤務した場合 10日
   (2) 1年6ヶ月継続勤務した場合 11日
   (3) 2年6ヶ月継続勤務した場合 12日
   (4) 以降、継続勤務1年ごとに1日ずつ加算し、最高20日を上限とする。
2. 年次有給休暇の取得については、原則として事前に所属長の承認を得なければならない。

さて、内定取消しとなる条件は何だったでしょうか? 僕が初見だったら、おそらく見返しているかと思います。

Knowledge bases for Amazon Bedrock では、ドキュメント(今回の場合だと就業規則)を読みこませ、 「内定取消しとなる条件は何?」 といった自然言語で検索できるようにするサービスです。とても便利ですよね。

それでは構成要素を深ぼっていきましょう。

エンベディングとは何か

「それでは構成要素を深ぼっていきましょう。」と言いつつも、いきなり Knowledge bases for Amazon Bedrock に行くとお腹いっぱいになるため、まずは エンベディングとは何か から入るのが吉です。

エンベディングとは、文字や画像、音声などのデータを数値ベクトルに変換する技術です。数値ベクトルに変換することで、コンピューターが扱いやすい形式に変換されるため、機械学習アルゴリズムで処理できるようになります。

生成系 AI アプリケーションでベクトルデータストアが果たす役割とは | Amazon Web Services ブログ より引用

変換された数値ベクトルは、次のようなベクトル空間でのマッピングに利用されます。エンベディングされた数値ベクトルデータは ベクトルデータベース に保管されます。

※ 図は 2 次元ですが、実際は 1024 次元などの高次元でベクトル空間が表現されています。

Amazon Bedrock では、エンベディング用のモデルに Titan Embeddings G1 や Cohere 社の Embed English や Embed Multilingual が使えます。

Bedrock コンソールの Modality が Embedding (埋め込み) になっているモデルがエンベディングで利用可能なモデルです。

ベクトル検索とは

ベクトル検索とは、一言で言うとエンベディングされたデータの類似度を計算することで関連性の高いデータを見つけ出す技術のことです。

ベクトル検索型の RAG システムでは、まず初めに文字や画像、音声などのデータを数値ベクトルに変換するエンベディングを行います。

再掲になりますが、エンベディングによってデータは数値ベクトルに変換され、ベクトル空間でのマッピングに利用されます

※ 図は 2 次元ですが、実際は 1024 次元などの高次元でベクトル空間が表現されています。

次にユーザーからの問い合わせです。問い合わせ内容に対しても同様にエンべディングを行い、ベクトルデータベースに対して数値ベクトルを利用して類似したデータを検索します。

今回の場合だと、「ブドウジュースがどんな飲み物なのか」をエンべディングし、他の飲み物の類似度が計算されます。図の例だと、赤ワインが一番類似度が高かったため、「赤ワイン(数値ベクトルではなく文字列)」が返さます。

最後にテキスト生成型 LLM にて文書を生成し回答します。

Knowledge bases for Amazon Bedrock では、上記のようなベクトル検索を中心とした RAG システムをマネージドに提供する機能です。

Knowledge Bases for Amazon Bedrock (RAG) を活用して設計開発や研究における特許検索を効率化しよう | Amazon Web Services ブログ

Knowledge bases for Amazon Bedrock の構成要素を Dive Deep していきます。

データソース

データソースはベクトル化を行うデータを保管する場所を指します。現在は、 Amazon S3 のみ対応しています。ベクトル化を行うデータは、以下の形式をサポート指定しています。

  • テキスト(.txt)
  • マークダウン(.md)
  • HTML(.html)
  • Word(.doc, .docx)
  • CSV(.csv)
  • Exel(.xls, .xlsx)
  • PDF(.pdf)

また、各データのサイズは 最大 50 MB までになっているため、 50 MB を超える場合はファイルの分割が必要です。

チャンキング戦略

Knowledge bases for Amazon Bedrock では、エンベディング処理を行う前にデータソースに登録されたファイルを小さなセグメントに分割します。このことをチャンキングと言います。エンベディングおよびベクトルデータベースへの登録は、チャンクごとに行われます。

チャンキングはとても大切な概念です。意味のある区切りごとにチャンキングができれば、回答がかなり変わってきます。

例えばですが、「就業規則の適用範囲」について質問したとします。ベクトルデータベースだと、赤線で囲った上部と中間のチャンクが該当する部分です。

返すチャンクの数にもよりますが 1 つだと仮定した場合、おそらく緑の文章が返されるでしょう。

緑が返されると言うことは、 水色に該当する 「し、別に定める場合はこの限りではない。」 の部分が抜けているため、回答精度が下がる可能性があります。そのため、チャンキングはとても大切な概念なのです。

「チャンキングとても大切なんだなぁ」と少なからず理解できたところで、 AWS が提供するチャンキング戦略に移っていきます。 Knowledge bases for Amazon Bedrock では以下のチャンキング戦略がサポートされています。

  • デフォルトのチャンキング
    • 自動的にチャンクに分割し、各チャンクに最大で約 300 個のトークンを含める
    • 300 個未満の場合、チャンクに分割されない
  • 固定サイズのチャンキング
    • 20 から 8192 の間でチャンクに区切る最大トークン数を指定
    • エンべディングモデルによって最大トークンがあるので注意。 Cohere Embed モデルは最大 512 トークンであるが、 512 トークン以上でチャンクを区切ろうとするパターン
    • オーバーラップを利用してチャンク間の重複率を定義
  • チャンキングなし
    • 各ファイルを 1 つのチャンクとして扱う
    • すでにデータの前処理が済んでいるケースで有効

オーバーラップとは

オーバーラップとは、各チャンクの最後の要素と次のチャンクの最初の要素を重複させ、チャンク間の関連性を強化できます。

チャンク間の関連性の強くすることで、上位 N 個を検索結果として取得した際に、取り出したい一連の情報がまとまって引っかかりやすくなります。

ただし、重複してデータを読み込ませるため、データ登録時のエンべディングで利用する インプットトークン数は増加します。

メタデータ

各ファイルには、以下のようなメタデータを追加できます。メタデータの値には、文字列、数字、 Bool を設定できます。

{
    "metadataAttributes": {
        "genre": "entertainment",
        "year": 2024
    }
}

ナレッジベースのデータソースを設定する - Amazon Bedrock

メタデータはメタデータファイルによって各ファイルに追加できます。同一フォルダ内に配置し、サフィックスに .metadata.json を設定してあげることで、メタデータファイルを認識します。

tree .
.
└── data # 同一フォルダ内にプレフィックスを合わせて配置
    ├── 就業規則.pdf.metadata.json
    └── 就業規則.pdf

Amazon Aurora をベクトルデータベースとして利用する場合は、エンべディングを行う前にメタデータファイルの属性に対してカラム追加が別途必要です。

ALTER TABLE bedrock_integration.bedrock_kb
  ADD COLUMN genre VARCHAR(128),
  ADD COLUMN year SMALLINT;

メタデータを利用することで以下のようにフィルターを追加してから、クエリを実行できます。アプリ側でユーザーごとに表示可能なコンテンツを振り分ける場合に便利そうですね。

import boto3

def main():
    client = boto3.client("bedrock-agent-runtime")
    
    response = client.retrieve_and_generate(
        input={"text": "ナレッジベースから回答を得るにはどうしたらいいですか?"},
        retrieveAndGenerateConfiguration={
            "type": 'KNOWLEDGE_BASE',
            "knowledgeBaseConfiguration": {
                "knowledgeBaseId": "KB12345678", 
                "modelArn": "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0",
                "retrievalConfiguration": {
                    "vectorSearchConfiguration": {
                        "numberOfResults": 5,
                        "filter": {
                            "equals": {
                                "key": "category",
                                "value": "API Reference"
                            }
                        }
                    }
                }
            }
        }
    )
    
    print(f'Answer: {response["output"]["text"]}')
    print(f'\nMetadata: {response["citations"][0]["retrievedReferences"][0]["metadata"]}')

if __name__ == "__main__":
    main()

Knowledge Base for Amazon Bedrock でメタデータフィルタリングが可能に #AWS - Qiita

ベクトルデータベース

ベクトルデータベースは、エンべディングされたデータを格納するデータベースです。

Knowledge bases for Amazon Bedrock では現在、以下のベクトルデータベースをサポートしています。

  • Amazon OpenSearch Serverless
  • Amazon Aurora
  • Pinecone
  • Redis Enterprise Cloud

小ネタですが、 re:Invent recap で MongoDB のサポートも近日中に追加予定と記載がありました。

AWS re:Invent 2023 recap

細かくは触れませんが、各ベクトルデータベースでベクトルインデックスの作り方が異なります。各データベースごとに以下をサポートしています。

  • Amazon OpenSearch Serverless 1
    • HNSW
  • Amazon Aurora 2
    • HNSW
    • IVFFlat
  • Pinecone 3
    • PGA
  • Redis Enterprise Cloud 4
    • FLAT
    • HNSW

各インデックスにも一長一短があるため、各インデックスの違いについては以下を参考にしていただけますと幸いです。

ベクトルデータベースがベクトル検索型 RAG でコストを占めてくる要素の1つです。安易に料金をケチって変な回答精度になるのは本末転倒ですので、概念検証をしっかりやった上でコスト最適化していきましょう。

ハイブリッド検索

ベクトルデータベースが OpenSearch Serverless の場合、 ベクトル検索に加えキーワード検索を行う、ハイブリッド検索をサポートしています。

OpenSearch Serverless の場合、次のクエリオプションが選択できます。

  • Default
    • Bedrock 側で、ベクターデータベースの構成に最適な検索方法を決定してクエリを実行
  • Hybrid
    • ベクトル検索とキーワード検索の両方を利用してクエリを実行
  • Semantic
    • ベクトル検索のみでクエリを実行

Query configurations - Amazon Bedrock

クエリオプションは以下のように overrideSearchType で指定します。

import boto3

def main():
    client = boto3.client("bedrock-agent-runtime")

    response = client.retrieve_and_generate(
        input={"text": "ナレッジベースから回答を得るにはどうしたらいいですか?"},
        retrieveAndGenerateConfiguration={
            "type": "KNOWLEDGE_BASE",
            "knowledgeBaseConfiguration": {
                "knowledgeBaseId": "KB12345678",
                "modelArn": "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0",
                "retrievalConfiguration": {
                    "vectorSearchConfiguration": {
                        "overrideSearchType": "HYBRID"  # or SEMANTIC
                    }
                },
            },
        },
    )

    print(f'Answer: {response["output"]["text"]}')
    print(
        f'\nMetadata: {response["citations"][0]["retrievedReferences"][0]["metadata"]}'
    )

if __name__ == "__main__":
    main()

同期処理

データソースとベクトルデータベースの同期には StartIngestionJob - Amazon Bedrock API を実行します。

Amazon Kendra のように自動同期機能がないため、 EventBridge Scheduler + Step Functions の組み合わせなどを利用して自動同期を行う必要があります。

EventBridge Scheduler から直接 StartIngestionJob API が叩けないため、アップデートに乞うご期待ですね。(エラーハンドリング考えるのであれば、 Step Functions を噛ませた方が良さそうです。)

IAM ロール

Knowledge bases for Amazon Bedrock では、 IAM ロールを使用して各種サービスへのアクセスを行います。

ざっくりですが、以下の操作を IAM で行います。

  • Bedrock へモデルの呼び出し(エンべディングとテキスト生成)
  • データベースへのアクセス
  • Secrets Manager へのアクセス(データベースへの認証)
  • データソースへのアクセス
  • KMS へのアクセス(必要に応じて)

このブログを書いてて気がついたのですが、先週くらいまではロール名に AmazonBedrockExecutionRoleForKnowledgeBase_ をつけないといけなかったのですが、どうやらその規則が撤廃されたようです。

roleArn The Amazon Resource Name (ARN) of the IAM role with permissions to invoke API operations on the knowledge base.

Type: String

Length Constraints: Minimum length of 0. Maximum length of 2048.

Pattern: ^arn:aws(-[^:]+)?:iam::([0-9]{12})?:role/.+$

Required: Yes

KnowledgeBase - Amazon Bedrock

マネージドポリシーは用意されておらず、各種データベースによって許可する権限が異なるため構成に応じて、カスタムポリシーを設計する必要があります。

Amazon Bedrock のナレッジベースのサービスロールを作成する - Amazon Bedrock

ログ記録

ログは 大きく分けると 2 種類あります。

  • Bedrock
    • モデル呼び出しのログ記録
  • CloudTrail
    • 標準イベント: InvokeModelInvokeModelWithResponseStream API
    • データイベント: RetrieveRetrieveAndGenerate API

Bedrock が提供する モデル呼び出しのログ記録 は、別途ログを記録するよう IAM ロールやバケットポリシーを設定する必要があります。

モデル呼び出しのログ記録 - Amazon Bedrock

ログは以下のようにトークン数など詳細な情報が記録されています。

{
	"schemaType": "ModelInvocationLog",
	"schemaVersion": "1.0",
	"timestamp": "2024-04-22T13:31:51Z",
	"accountId": "XXXXXXXXXXXX",
	"identity": {
		"arn": "arn:aws:sts::XXXXXXXXXXXX:assumed-role/takakuni-dev-role/NJFEZMFQTP-EmbeddingTask-dfeb2520-55bd-4a36-aed5-132758014cd0"
	},
	"region": "us-east-1",
	"requestId": "6de2b9f2-61d5-4565-8736-901087bf5501",
	"operation": "InvokeModel",
	"modelId": "arn:aws:bedrock:us-east-1::foundation-model/cohere.embed-multilingual-v3",
	"input": {
		"inputContentType": "application/json",
		"inputBodyJson": {
			"texts": [
				"株式会社サンプル企業 就業規則  第 1 章 総則  第 1 条 (目的) この就業規則は、株式会社サンプル企業(以下「会社」という)の労働条件及び服務規律を定めることを目的とする。  第 2 条 (適用範囲)   この就業規則は、会社に雇用される全ての従業員に適用される。ただし、別に定める場合はこの限りではない。  第 2 章 人事  第 3 条 (採用) 会社は、従業員の採用に際して、性別、年齢、国籍、信条等による不当な差別をしない。  第 4 条 (期間の定めのない労働契約と有期労働契約) 従業員の労働契約期間は、期間の定めのないものと有期のものとがある。有期労働契約の更新については別に定める。"
			],
			"input_type": "search_document",
			"truncate": "NONE"
		},
		"inputTokenCount": 170
	},
	"output": {
		"outputContentType": "application/json",
		"outputBodyJson": {
			"embeddings": [
				[
					0.013999939, 0.032714844, -0.057800293, 0.015129089, 0.018737793,
					-0.0064048767, -0.0079193115, -0.058563232, -0.005554199, -0.02658081
				]
			],
			"id": "6de2b9f2-61d5-4565-8736-901087bf5501",
			"response_type": "embeddings_floats",
			"texts": [
				"株式会社サンプル企業 就業規則 第 1 章 総則 第 1 条 (目的) この就業規則は、株式会社サンプル企業(以下「会社」という)の労働条件及び服務規律を定めることを目的とする。 第 2 条 (適用範囲) この就業規則は、会社に雇用される全ての従業員に適用される。ただし、別に定める場合はこの限りではない。 第 2 章 人事 第 3 条 (採用) 会社は、従業員の採用に際して、性別、年齢、国籍、信条等による不当な差別をしない。 第 4 条 (期間の定めのない労働契約と有期労働契約) 従業員の労働契約期間は、期間の定めのないものと有期のものとがある。有期労働契約の更新については別に定める。"
			]
		}
	}
}

対して、 CloudTrail の InvokeModel です。以下のようにトークン数は記載されていないようです。

{
	"eventVersion": "1.09",
	"userIdentity": {
		"type": "AssumedRole",
		"principalId": "AROAZCAS4AKS5W745M2VD:NJFEZMFQTP-EmbeddingTask-dfeb2520-55bd-4a36-aed5-132758014cd0",
		"arn": "arn:aws:sts::XXXXXXXXXXXX:assumed-role/takakuni-dev-role/NJFEZMFQTP-EmbeddingTask-dfeb2520-55bd-4a36-aed5-132758014cd0",
		"accountId": "XXXXXXXXXXXX",
		"accessKeyId": "ASIAZCAS4AKSV6TCITB5",
		"sessionContext": {
			"sessionIssuer": {
				"type": "Role",
				"principalId": "AROAZCAS4AKS5W745M2VD",
				"arn": "arn:aws:iam::XXXXXXXXXXXX:role/takakuni-dev-role",
				"accountId": "XXXXXXXXXXXX",
				"userName": "takakuni-dev-role"
			},
			"attributes": {
				"creationDate": "2024-04-22T13:31:51Z",
				"mfaAuthenticated": "false"
			}
		},
		"invokedBy": "bedrock.amazonaws.com"
	},
	"eventTime": "2024-04-22T13:31:51Z",
	"eventSource": "bedrock.amazonaws.com",
	"eventName": "InvokeModel",
	"awsRegion": "us-east-1",
	"sourceIPAddress": "bedrock.amazonaws.com",
	"userAgent": "bedrock.amazonaws.com",
	"requestParameters": {
		"modelId": "arn:aws:bedrock:us-east-1::foundation-model/cohere.embed-multilingual-v3"
	},
	"responseElements": null,
	"requestID": "6de2b9f2-61d5-4565-8736-901087bf5501",
	"eventID": "2981e4fc-3600-4f0b-bb3f-c554357cf9a9",
	"readOnly": true,
	"eventType": "AwsApiCall",
	"managementEvent": true,
	"recipientAccountId": "XXXXXXXXXXXX",
	"eventCategory": "Management"
}

チャンキング戦略を PoC で練る際は モデル呼び出しのログ記録 を有効にしてもいいかもですが、コストが跳ねやすいので利用は計画的に行いましょう。

終わりに

以上、「AWS 入門ブログリレー 2024 〜Knowledge bases for Amazon Bedrock編〜」でした。

チャンキングが異常に厚めに書かれてますが、それくらい他の要素がマネージドになっている機能です。(みんなでチャンキングマスター目指しましょう!)

この観点知りたいとかあれば、ぜひ たかくに(@takakuni_)) までご連絡ください。後日、追記します。

次回、 04/23 は弊社 青柳 さん による 「 Agents for Amazon Bedrock 編」 の予定です!

このエントリが誰かの助けになれば幸いです。

AWS 事業本部コンサルティング部のたかくに(@takakuni_) でした!