Taste of Tech Topics

Acroquest Technology株式会社のエンジニアが書く技術ブログ

Amazon Bedrock Knowledge Base は OpenSearch にどのようなインデックスを作成するのか?

こんにちは、機械学習チーム YAMALEX の駿です。
YAMALEX は Acroquest 社内で発足した、会社の未来の技術を創る、機械学習がメインテーマのデータサイエンスチームです。
(詳細はリンク先をご覧ください。)

寒くなってきたので、暖房をつけてしまいました。

今回は、Bedrock Knowledge Base のベクトルデータベースとして OpenSearch Serverless を使ったときに、 自動で作成される OpenSearch Serverless のインデックスには何が保存されるのか確認しました。

1. Bedrock Knowledge Base とは

Bedrock Knowledge BaseAmazon Bedrock が提供する簡単に RAG を実現するためのサービスです。

詳細はこちらの記事で紹介しています。

acro-engineer.hatenablog.com

2. OpenSearch Serverless とは

今回は Knowledge Base のベクトルデータベースとして OpenSearch Serverless を用います。

docs.aws.amazon.com

Bedrock KnowledgeBase はデフォルトのベクトルストアとして OpenSearch Serverless を用意しており、既存の OpenSearch Serverless のインデックスがない場合に、自動で作成してくれます。

OpenSearch Serverless を用いることで、Bedrock Knowledge Base の検索時にハイブリッド検索を利用できるようになります。

ハイブリッド検索では、ベクトル検索だけではなく、キーワード検索も行い正確な一致を補完するため、特にユーザーが特定のキーワードや地名などを検索したいときに優位性が見られます。

また、チャンキング戦略も柔軟に設定でき、セマンティックチャンキングや階層チャンキングを自前で実装することなく、設定変更だけで使用できます。

チャンクの設定は RAG を行う上で、精度に大きく影響する部分なので、簡単に変更できるのはうれしいです。

docs.aws.amazon.com

3. 中身を確認する

IPA が発行している DX 白書 を S3 に置き、それを取り込んだ結果を、デフォルトの固定チャンキング/セマンティックチャンキング/階層チャンキングを使った場合で比べてみます。

それぞれ下記手順で実施しました。

  1. ベクトルストアとして新規作成の OpenSearch Serverless を設定し、 Bedrock Knowledge Base を作成
  2. Bedrock Knowledge Base のデータソースに、対象の S3 バケットとチャンキング戦略を設定
  3. OpenSearch Serverless の DevTools から、インデックスに保存されたドキュメントを確認

※以下、出力内容を、見やすいように省略・整形を行っています。実際の内容とは異なりますが、ご了承ください。

まずは、作成されたコレクション・インデックスを確認してみます。

作成されたコレクション

インデックスは bedrock-knowledge-base-default-index という名前で作成されていました。

default-index 部分は作成した Bedrock Knowledge Base 名というわけではなく、固定値のようです。
同様にベクトルプロパティーdefault-vector 部分も Bedrock Knowledge Base 名に関わらず、固定値でこの値になります。

ベクトル検索のエンジンには FAISS を利用しているようです。
ディメンションに設定されている 1024 は作成時に設定した Titan Text Embeddings v2 の 次元数となっています。

また、複数の Bedrock Knowledge Base を作成した場合は、新しいコレクションを作成することが分かりました。

OpenSearch Serverless の課金単位の OCU は複数コレクション間で共有されるため、複数のコレクションが作成されることで必要以上に課金されてしまう、ということは無いので安心できます。

{
  "bedrock-knowledge-base-default-index": {
    "aliases": {},
    "mappings": {
      "dynamic_templates": [
        {
          "strings": {
            "match_mapping_type": "string",
            "mapping": {
              "fields": {
                "keyword": {
                  "ignore_above": 2147483647,
                  "type": "keyword"
                }
              },
              "type": "text"
            }
          }
        }
      ],
      "properties": {
        "AMAZON_BEDROCK_METADATA": {
          "type": "text",
          "index": false
        },
        "AMAZON_BEDROCK_TEXT_CHUNK": {
          "type": "text"
        },
        "bedrock-knowledge-base-default-vector": {
          "type": "knn_vector",
          "dimension": 1024,
          "method": {
            "engine": "faiss",
            "space_type": "l2",
            "name": "hnsw",
            "parameters": {}
          }
        }
      }
    },
    "settings": {
      "index": {
        "number_of_shards": "2",
        "provided_name": "bedrock-knowledge-base-default-index",
        "knn": "true",
        "creation_date": "1728124297900",
        "number_of_replicas": "0",
        "uuid": "4Us8XJIBvOt5ziw6InSg",
        "version": {
          "created": "136327827"
        }
      }
    }
  }
}

3.1. デフォルト(固定チャンキング)

デフォルト設定でデータソースを作成

ベクトルフィールドとして指定した bedrock-knowledge-base-default-vector に 1024 次元のベクトルが、テキストフィールドとして指定した AMAZON_BEDROCK_TEXT_CHUNK にチャンクの本文が保存されていました。
Bedrock Knowledge Base でハイブリッド検索を行う際は、これらのフィールドに対してクエリが発行されます。

また、元ドキュメントの URIx-amz-bedrock-kb-source-uri もしくは AMAZON_BEDROCK_METADATA.source から取得できます。

{
  "_index": "bedrock-knowledge-base-default-index",
  "_id": "1%3A0%3AHo6UGJIBPr4GtWZKo1_n",
  "_score": 1,
  "_source": {
    "bedrock-knowledge-base-default-vector": [
      -0.060821593,
      -0.019813094,
      -0.021656172,
      ......
    ],
    "x-amz-bedrock-kb-source-uri": "s3://bedockknowledgebaseindextest/DX白書2023.pdf",
    "AMAZON_BEDROCK_METADATA": "{\"source\":\"s3://bedockknowledgebaseindextest/DX白書2023.pdf\"}",
    "x-amz-bedrock-kb-data-source-id": "AZVXAGUKDE",
    "id": "9ea53e99-9de4-4845-a10a-d041e4845cac",
    "AMAZON_BEDROCK_TEXT_CHUNK": "独 立 行 政 法 人 情 報 処 理 推 進 機 構   進 み 始 め た「 デ ジ タ ル 」、進 ま な い「 ト ラ ン ス フ ォ ー メ ー シ ョ ン 」   ISBN978-4-905318-78-1 C0004¥3000E   定価 3,000 円(税別)......"
  }
}

3.2. セマンティックチャンキング

セマンティックチャンキングを指定して作成

チャンクの区切り位置が異なるだけで、保存されるフィールドなどは固定チャンキングの場合と同様でした。

{
  "_index": "bedrock-knowledge-base-default-index",
  "_id": "1%3A0%3A6iGuGJIBB-x3T8xG_KDI",
  "_score": 1,
  "_source": {
    "bedrock-knowledge-base-default-vector": [
      -0.023106523,
      0.06026018,
      0.03623754,
      ......
    ],
    "x-amz-bedrock-kb-source-uri": "s3://bedockknowledgebaseindextest/DX白書2023.pdf",
    "AMAZON_BEDROCK_METADATA": "{\"source\":\"s3://bedockknowledgebaseindextest/DX白書2023.pdf\"}",
    "x-amz-bedrock-kb-data-source-id": "2FC3G7Z7LK",
    "id": "4cc7f820-a014-47a0-baf5-7f6848d1427e",
    "AMAZON_BEDROCK_TEXT_CHUNK": "経済産業省がとりまとめた「DX推進指標」を用\nいて各企業が自己診断した結果を独立行政法人情報処理推進機構(IPA)が収集し、分析したレポート......"
  }
}

3.3. 階層チャンキング

階層チャンキングを指定して作成

階層チャンキングを指定した場合は、 AMAZON_BEDROCK_METADATA.parentText が追加されました。

検索するときは他のチャンキング戦略と同様に AMAZON_BEDROCK_TEXT_CHUNK フィールドを使用し、返却する文字列が AMAZON_BEDROCK_TEXT_CHUNK フィールドではなく AMAZON_BEDROCK_METADATA.parentText になるようです。

親チャンクの内容は複数回インデックスに含まれることになるため、固定チャンキング・セマンティックチャンキングよりも消費するデータ量が多くなりそうです。

{
  "_index": "bedrock-knowledge-base-default-index",
  "_id": "1%3A0%3AnSGYGJIBB-x3T8xGX5zG",
  "_score": 1,
  "_source": {
    "bedrock-knowledge-base-default-vector": [
      -0.060821593,
      -0.019813094,
      -0.021656172,
      ......
    ],
    "x-amz-bedrock-kb-source-uri": "s3://bedockknowledgebaseindextest/DX白書2023.pdf",
    "AMAZON_BEDROCK_METADATA": "{
      \"source\":\"s3://bedockknowledgebaseindextest/DX白書2023.pdf\",
      \"parentText\":\"また、2022年9月には、経済産業省により「デジタルガバナンスコード」の改 訂版として時勢の変化に対応した「デジタルガバナンス・コード2.0」が公表され、企業によるDXの更な る促進が期待されています......\"
    }",
    "x-amz-bedrock-kb-data-source-id": "IYDKX62IHR",
    "id": "58564fd7-fc27-41c6-9e33-785e7e3ad0f5",
    "AMAZON_BEDROCK_TEXT_CHUNK": "独 立 行 政 法 人 情 報 処 理 推 進 機 構   進 み 始 め た「 デ ジ タ ル 」、進 ま な い「 ト ラ ン ス フ ォ ー メ ー シ ョ ン 」   ISBN978-4-905318-78-1 C0004¥3000E   定価 3,000 円(税別)......"
  }
}

階層チャンキングの仕組み

以上、各チャンク戦略において、インデックスに含まれる情報をまとめると下記の表のようになります。

No チャンク戦略 ベクトル テキスト ソースURI 親テキスト
1 固定(デフォルト)
2 セマンティック
3 階層
  • ベクトル: bedrock-knowledge-base-default-vector
  • テキスト: AMAZON_BEDROCK_TEXT_CHUNK
  • ソース URIAMAZON_BEDROCK_METADATA.source
  • 親テキスト: AMAZON_BEDROCK_METADATA.parentText

4. OpenSearch Serverless に直接クエリを投げる

Bedrock Knowledge Base に作ってもらったインデックスですが、当然、直接 API リクエストを投げることも可能です。

今回は『DX白書』に記載されているOded Galor氏の著書の内容を知りたいものとして、テキスト検索・ベクトル検索・ハイブリッド検索を順番に試してみます。

下記文章が検索でヒットさせたい内容です。

ブラウン大学経済学教授のOded Galorが書いた「格差の起源*2」によると、人類の進歩は多様性と共にあるが、日本人は同一性が高く内側に閉じているので、世界で最もこの輪の中に加われていない可能性が高い。」

4.1. テキスト検索

下記手順で検索を実行しました。

  1. リクエストを投げるためのユーザーをロールを作成する

    aoss:APIAccessAll の権限が必要です。

  2. OpenSearch Serverless のコレクションに紐づけられているデータアクセスコントロールポリシーを編集し、 プリンシパルとして、作成したロールを追加する

    プリンシパルを追加

  3. 作成したロールを assume し、認証情報を取得する

     session=$(aws sts assume-role \
       --role-arn ${role_arn} \
       --role-session-name "role_session"
     )
    
     aws_access_key_id=$(echo "${session}" | jq -r ".Credentials.AccessKeyId")
     aws_secret_access_key=$(echo "${session}" | jq -r ".Credentials.SecretAccessKey")
     aws_session_token=$(echo "${session}" | jq -r ".Credentials.SessionToken")
    
  4. AWS Signature V4 認証を使ってリクエストを投げる

     region=us-west-2
     service=aoss
    
     curl -v -k -X GET "${opensearch_serverless_endpoint}/bedrock-knowledge-base-default-index/_search?pretty" \
     -H "Content-Type: application/json" \
     -H "X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \
     -H "X-Amz-Security-Token: ${aws_session_token}" \
     --aws-sigv4 "aws:amz:${region}:${service}" \
     --user "${aws_access_key_id}:${aws_secret_access_key}" \
     -d '
     {
       "_source": ["AMAZON_BEDROCK_TEXT_CHUNK", "AMAZON_BEDROCK_METADATA"],
       "query": {
         "match": {
           "AMAZON_BEDROCK_TEXT_CHUNK": " オデッド・ガロー 著書"
         }
       }
     }'
    

下記のようにレスポンスを受け取ることができました。

{
  "took" : 20,
  "timed_out" : false,
  "_shards" : {
    "total" : 0,
    "successful" : 0,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 575,
      "relation" : "eq"
    },
    "max_score" : 20.662754,
    "hits" : [
      {
        "_index" : "bedrock-knowledge-base-default-index",
        "_id" : "1%3A0%3AR1T795IBG2d6FmmHb-K4",
        "_score" : 20.662754,
        "_source" : {
          "AMAZON_BEDROCK_METADATA" : "{\"source\":\"s3://bedockknowledgebaseindextest/DX白書2023.pdf\"}",
          "AMAZON_BEDROCK_TEXT_CHUNK" : "* 2  オデッド・ガロー著、柴田裕之監訳、森内薫翻訳、『格差の起源......"
        }
      },
      {
        "_index" : "bedrock-knowledge-base-default-index",
        "_id" : "1%3A0%3ApVT795IBG2d6FmmHjuST",
        "_score" : 7.843234,
        "_source" : {
          "AMAZON_BEDROCK_METADATA" : "{\"source\":\"s3://bedockknowledgebaseindextest/DX白書2023.pdf\"}",
          "AMAZON_BEDROCK_TEXT_CHUNK" : "Agency, Japan.     ・本白書は著作権法上の保護を受けています......"
        }
      },
      ......
    ]
  }
}

引用情報は取得できましたが、内容が書かれた部分はヒットしませんでした。

該当部分はアルファベット表記のため、文字列が一致せず、検索に引っかからなかったものと思われます。

4.2. ベクトル検索

  1. 検索したいテキストを Titan Text Embeddings V2 ( Bedrock Knowledge Base 作成時に選択したモデル)でベクトル化し、ファイルに保存する

    vector.txt (「Oded Galor 著書」 をベクトル化したもの)

     [-0.09754358977079391, 0.004242392256855965, -0.024888699874281883, ......]
    
  2. 「4.1.」 と同様に認証情報を取得する

  3. ベクトルを使った検索を行う

     vector=$(cat vector.txt)
    
     curl -v -k -X GET "${opensearch_serverless_endpoint}/bedrock-knowledge-base-default-index/_search?pretty" \
     -H "Content-Type: application/json" \
     -H "X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \
     -H "X-Amz-Security-Token: ${aws_session_token}" \
     --aws-sigv4 "aws:amz:${region}:${service}" \
     --user "${aws_access_key_id}:${aws_secret_access_key}" \
     -d '
     {
       "_source": ["AMAZON_BEDROCK_TEXT_CHUNK", "AMAZON_BEDROCK_METADATA"],
       "query": {
         "knn": {
           "bedrock-knowledge-base-default-vector": {
             "vector": '"$vector"',
             "k": 10
           }
         }
       }
     }'
    

下記のレスポンスを得られました。

{
  "took" : 20,
  "timed_out" : false,
  "_shards" : {
    "total" : 0,
    "successful" : 0,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 20,
      "relation" : "eq"
    },
    "max_score" : 0.37559095,
    "hits" : [
      {
        "_index" : "bedrock-knowledge-base-default-index",
        "_id" : "1%3A0%3AKkb795IB38U8vDmpYXU0",
        "_score" : 0.37559095,
        "_source" : {
          "AMAZON_BEDROCK_METADATA" : "{\"source\":\"s3://bedockknowledgebaseindextest/DX白書2023.pdf\"}",
          "AMAZON_BEDROCK_TEXT_CHUNK" : "また、売上規模が大きくなるほど、受発注や物流のプ ラットフォームサービスなど、......"
        }
      },
      {
        "_index" : "bedrock-knowledge-base-default-index",
        "_id" : "1%3A0%3A0kb795IB38U8vDmphXe1",
        "_score" : 0.37314636,
        "_source" : {
          "AMAZON_BEDROCK_METADATA" : "{\"source\":\"s3://bedockknowledgebaseindextest/DX白書2023.pdf\"}",
          "AMAZON_BEDROCK_TEXT_CHUNK" : "製品・サービスの開発     製造工程、製造設備     ロジスティクス・調達・物流......"
        }
      },
      ......
    ]
  }
}

ベクトル検索でも、欲しい文章はヒットしませんでした。

ベクトル検索では、人名や機種名などの記号的な内容は、検索でヒットさせるのが難しいです。

4.3. ハイブリッド検索

  1. 「4.2.」 と同様に検索したいベクトルをファイルに保存する

  2. 「4.1.」 と同様に認証情報を取得する

  3. ベクトルと文字列を使った検索を行う

     vector=$(cat vector.txt)
    
     curl -v -k -X GET "${opensearch_serverless_endpoint}/bedrock-knowledge-base-default-index/_search?pretty" \
     -H "Content-Type: application/json" \
     -H "X-Amz-Content-Sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" \
     -H "X-Amz-Security-Token: ${aws_session_token}" \
     --aws-sigv4 "aws:amz:${region}:${service}" \
     --user "${aws_access_key_id}:${aws_secret_access_key}" \
     -d '
     {
       "_source": ["AMAZON_BEDROCK_TEXT_CHUNK", "AMAZON_BEDROCK_METADATA"],
       "query": {
         "knn": {
           "bedrock-knowledge-base-default-vector": {
             "vector": '"$vector"',
             "k": 10,
             "filter": {
               "match": {
                 "AMAZON_BEDROCK_TEXT_CHUNK": "Oded Galor 著書"
               }
             }
           }
         }
       }
     }'
    

下記のようにレスポンスを得られました。

{
  "took" : 18,
  "timed_out" : false,
  "_shards" : {
    "total" : 0,
    "successful" : 0,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 20,
      "relation" : "eq"
    },
    "max_score" : 0.40019944,
    "hits" : [
      {
        "_index" : "bedrock-knowledge-base-default-index",
        "_id" : "1%3A0%3AR1T795IBG2d6FmmHb-K4",
        "_score" : 0.40019944,
        "_source" : {
          "AMAZON_BEDROCK_METADATA" : "{\"source\":\"s3://bedockknowledgebaseindextest/DX白書2023.pdf\"}",
          "AMAZON_BEDROCK_TEXT_CHUNK" : "* 2  オデッド・ガロー著、柴田裕之監訳、森内薫翻訳、『格差の起源......"
        }
      },
      {
        "_index" : "bedrock-knowledge-base-default-index",
        "_id" : "1%3A0%3ARFT795IBG2d6FmmHb-K4",
        "_score" : 0.36775848,
        "_source" : {
          "AMAZON_BEDROCK_METADATA" : "{\"source\":\"s3://bedockknowledgebaseindextest/DX白書2023.pdf\"}",
          "AMAZON_BEDROCK_TEXT_CHUNK" : "ブラウン大学経済学教授のOded Galorが書いた「格差の起源*2」によると、......"
        }
      },
      ......
    ]
  }
}

テキスト検索とベクトル検索を組み合わせたハイブリッド検索を行うことで、テキスト検索でヒットしていた引用部分に加え、著書の内容が書かれている部分もヒットするようになり、求めているドキュメントを取得することができました。

文字列での検索と意味的な検索の良いとこ取りができています。

まとめ

Bedrock Knowledge Base が OpenSearch Serverless のインデックスにどのような情報を保存しているのかを確認しました。

特に階層チャンキングがどのように実現しているのかはあまり気にしていなかったのですが、データ量とのトレードオフがあることが分かりました。

メリット・デメリットを考えながら、適切なチャンキング戦略を選択したいですね。

Acroquest Technologyでは、キャリア採用を行っています。
  • Azure OpenAI/Amazon Bedrock等を使った生成AIソリューションの開発
  • ディープラーニング等を使った自然言語/画像/音声/動画解析の研究開発
  • マイクロサービス、DevOps、最新のOSSクラウドサービスを利用する開発プロジェクト
  • 書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。 www.wantedly.com