Amazon Bedrock RAG 評価機能による Knowledge Base 検索精度の定量分析

AWS

2025.11.6

Topics

概要

Amazon Bedrock の RAG 評価機能を実際に検証してみました。
この機能により、RAG システムの性能を客観的に評価し、改善点を特定することができます。

今回は、弊社の会社情報を題材として、Knowledge Base の検索精度を定量的に分析してみました。

環境構築

以下の構成を Terraform で構築しました。

  • Amazon Bedrock Knowledge Base
  • OpenSearch Serverless(ベクトル検索用)
  • S3 バケット(データソース用)

Terraform で環境構築

プロバイダー設定

Terraform の必要なプロバイダーとバージョンを定義し、AWS と OpenSearch の接続設定を行います。

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "5.0"
    }
    opensearch = {
      source  = "opensearch-project/opensearch"
      version = "2.2.0"
    }
  }
}
provider "aws" {
  region  = "us-east-1"
  profile = "default"
}
provider "opensearch" {
  url         = aws_opensearchserverless_collection.collection.collection_endpoint
  aws_region  = "us-east-1"
  healthcheck = false
}

Bedrock Knowledge Base

埋め込みモデルの取得、Knowledge Base の作成、データソースの設定、および必要な IAM ロール・ポリシーを定義します。

data "aws_bedrock_foundation_model" "embedding" {
  model_id = "amazon.titan-embed-text-v2:0"
}
resource "aws_bedrockagent_knowledge_base" "this" {
  name     = "${var.project_name}-knowledge-base"
  role_arn = aws_iam_role.bedrock.arn

  knowledge_base_configuration {
    type = "VECTOR"
    vector_knowledge_base_configuration {
      embedding_model_arn = data.aws_bedrock_foundation_model.embedding.model_arn
    }
  }

  storage_configuration {
    type = "OPENSEARCH_SERVERLESS"
    opensearch_serverless_configuration {
      collection_arn    = aws_opensearchserverless_collection.collection.arn
      vector_index_name = "vector_index"
      field_mapping {
        vector_field   = "vector_field"
        text_field     = "text_field"
        metadata_field = "metadata_field"
      }
    }
  }

  depends_on = [
    opensearch_index.vector_index,
    aws_iam_role.bedrock
  ]
}

resource "aws_bedrockagent_data_source" "this" {
  knowledge_base_id = aws_bedrockagent_knowledge_base.this.id
  name              = "${var.project_name}-datasource"
  data_source_configuration {
    type = "S3"
    s3_configuration {
      bucket_arn = aws_s3_bucket.bedrock.arn
    }
  }

  depends_on = [aws_bedrockagent_knowledge_base.this]
}
resource "aws_iam_role" "bedrock" {
  name                = "bedrock-role"
  managed_policy_arns = [aws_iam_policy.bedrock.arn]

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Sid    = ""
        Principal = {
          Service = "bedrock.amazonaws.com"
        }
      },
    ]
  })
}

resource "aws_iam_policy" "bedrock" {
  name = "bedrock-policy"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action   = ["bedrock:InvokeModel"]
        Effect   = "Allow"
        Resource = "*"
      },
      {
        Action = [
          "s3:GetObject",
          "s3:ListBucket",
        ]
        Effect = "Allow"
        Resource = [
          "${aws_s3_bucket.bedrock.arn}",
          "${aws_s3_bucket.bedrock.arn}/*"
        ]
      },
      {
        Action = [
          "aoss:APIAccessAll",
        ]
        Effect   = "Allow"
        Resource = "arn:aws:aoss:us-east-1:${data.aws_caller_identity.current.account_id}:collection/*"
      },
    ]
  })
}

OpenSearch Serverless

ベクトル検索用の OpenSearch Serverless コレクションと、暗号化・ネットワーク・データアクセスの各種セキュリティポリシー、およびベクトルインデックスを作成します。

data "aws_caller_identity" "current" {}

resource "aws_opensearchserverless_collection" "collection" {
  name             = "${var.project_name}-collection"
  type             = "VECTORSEARCH"
  standby_replicas = "DISABLED"

  depends_on = [
    aws_opensearchserverless_security_policy.encryption_policy,
    aws_opensearchserverless_security_policy.network_policy
  ]
}

resource "aws_opensearchserverless_security_policy" "encryption_policy" {
  name        = "${var.project_name}-encryption-policy"
  type        = "encryption"
  description = "encryption policy for ${var.project_name}-collection"
  policy = jsonencode({
    Rules = [
      {
        Resource = [
          "collection/${var.project_name}-collection"
        ],
        ResourceType = "collection"
      }
    ],
    AWSOwnedKey = true
  })
}

resource "aws_opensearchserverless_security_policy" "network_policy" {
  name        = "${var.project_name}-network-policy"
  type        = "network"
  description = "public access for dashboard, VPC access for collection endpoint"
  policy = jsonencode([
    {
      Description = "Public access for dashboards and collection",
      Rules = [
        {
          ResourceType = "collection",
          Resource = [
            "collection/${var.project_name}-collection"
          ]
        },
        {
          ResourceType = "dashboard"
          Resource = [
            "collection/${var.project_name}-collection"
          ]
        }
      ],
      AllowFromPublic = true
    }
  ])
}

resource "aws_opensearchserverless_access_policy" "data_access_policy" {
  name        = "${var.project_name}-data-access-policy"
  type        = "data"
  description = "allow index and collection access"
  policy = jsonencode([
    {
      Rules = [
        {
          ResourceType = "index",
          Resource = [
            "index/${var.project_name}-collection/*"
          ],
          Permission = [
            "aoss:*"
          ]
        },
        {
          ResourceType = "collection",
          Resource = [
            "collection/${var.project_name}-collection"
          ],
          Permission = [
            "aoss:*"
          ]
        }
      ],
      Principal = [
        "${data.aws_caller_identity.current.arn}",
        "${aws_iam_role.bedrock.arn}",
      ]
    }
  ])
}

resource "opensearch_index" "vector_index" {
  name          = "vector_index"
  index_knn     = true
  force_destroy = true
  mappings = jsonencode({

    properties = {
      "metadata_field" = {
        type  = "text"
        index = false
      }

      "text_field" = {
        type  = "text"
        index = true
      }

      "vector_field" = {
        type      = "knn_vector"
        dimension = 1024
        method = {
          name       = "hnsw"
          space_type = "l2"
          engine     = "faiss"
        }
      }
    }
  })

  depends_on = [
    aws_opensearchserverless_collection.collection,
    aws_opensearchserverless_access_policy.data_access_policy
  ]
}

S3 バケット

Bedrock コンソールを使用するモデル評価ジョブを作成する場合は、S3 バケットで CORS 設定を指定する必要があります。
S3 バケットに必要なクロスオリジンリソース共有 (CORS) 権限 – Amazon Bedrock

resource "aws_s3_bucket" "bedrock" {
  bucket = "${var.project_name}-s3"
}

resource "aws_s3_bucket_cors_configuration" "this" {
  bucket = aws_s3_bucket.bedrock.id

  cors_rule {
    allowed_headers = ["*"]
    allowed_methods = [
      "GET",
      "PUT",
      "POST",
      "DELETE"
    ]
    allowed_origins = ["*"]
    expose_headers  = ["Access-Control-Allow-Origin"]
  }
}

S3 にファイルアップロード

RAG で参照するためのテキストを S3 にアップロードします。

ファイル内容としては、弊社について以下の 4 つをまとめたレポートになります。

  • 会社概要
  • 沿革
  • 事業内容と主なサービス
  • 強みと特徴

S3 へのアップロードが完了した後、Knowledge Base 側でデータソースの同期を実行します。

Knowledge Base概要画面

Knowledge Base のテスト

まず Knowledge Base の動作をテストします。

NHN Techorusという社名の由来は何ですか?

正しい情報を回答してくれました。

NHN Techorusの社名は、「Technology」と「Chorus」を組み合わせた造語で、異なる技術や価値観が共鳴し合い、より高い価値を創造していくという想いが込められています。

テスト実行画面

なお、事前に読み込ませた情報以外には回答できないようです。
試しに、存在しない社名について問い合わせてみました。

NHN Monodiaという社名の由来は何ですか?

テスト結果画面

RAG 評価を実行

環境構築が完了したため、RAG 評価を実行します。

手順は以下の通りです。

  • RAG 評価用のプロンプトデータセットを作成
  • RAG 評価ジョブを作成

RAG 評価用のプロンプトデータセットを作成

RAG 評価には、JSONL 形式のプロンプトデータセットが必要です。
プロンプトデータセットは、プロンプトと想定の回答をセットにした内容です。

一つずつ定義するのは大変なため、生成 AI を活用してサンプルデータセットを作成しました。

プロンプトデータセットの詳細は以下ドキュメントをご覧ください。
RAG 評価ジョブの取得と生成のためのプロンプトデータセットの作成 – Amazon Bedrock

見やすさのために整形していますが、実際の JSONL ファイルでは 1 行で記述する必要があります。

{
  "conversationTurns": [
    {
      "referenceResponses": [
        {
          "content": [
            {
              "text": "NHNテコラスの社名は「Technology」と「Chorus」を組み合わせた造語です。異なる技術や価値観が共鳴し合い、より高い価値を創造していくという想いが込められています。"
            }
          ]
        }
      ],
      "prompt": {
        "content": [{ "text": "NHN Techorusという社名の由来は何ですか?" }]
      }
    }
  ]
}

このファイルを S3 にアップロードします。

RAG 評価ジョブを作成

ジョブを作成します。

評価ジョブ一覧画面

ここでは、評価を実行する評価モデルを選択します。

評価作成設定画面

推論ソースでは、先程作成した Knowledge Base を選択します。

評価タイプは、「取得と応答の生成」を選択します。
「取得と応答の生成」の場合、ナレッジベースから取得したデータとレスポンスジェネレーターモデルによって生成されたサマリーに基づいてレポートが作成されます。

Amazon Bedrock 評価を使用して RAG ソースのパフォーマンスを評価する – Amazon Bedrock

ここでは、評価モデルとは別にレスポンスジェネレータモデルを選択します。

推論ソース選択画面

メトリクスはすべてを選択します。
メトリクスの詳細な解説は後述します。

LLMs を使用する RAG 評価のメトリクスを確認する (コンソール) – Amazon Bedrock

評価メトリクス設定画面

データセットと結果の出力先の S3 バケットを入力します。

データセット設定画面

IAM ロールは新規作成します。

IAMロール作成画面

作成を実行すると、約 10 分でステータスが完了となります。

評価結果

ジョブ結果の Top には、サマリーが表示されています。

メトリクス結果サマリー

その下に、各メトリクスのグラフと実際に応答した内容も表示されています。

ヘルプフルネス分析グラフ

実際に応答した内容です。

会話例一覧画面

評価結果に記載されている内容は、S3 バケットにレポートとして格納されています。
S3 バケットに格納されたレポート結果を一部だけ抜粋します。

{
  "conversationTurns": [
    {
      "inputRecord": {
        "prompt": {
          "content": [{ "text": "NHN Techorusという社名の由来は何ですか?" }]
        },
        "referenceResponses": [
          {
            "content": [
              {
                "text": "NHNテコラスの社名は「Technology」と「Chorus」を組み合わせた造語です。異なる技術や価値観が共鳴し合い、より高い価値を創造していくという想いが込められています。"
              }
            ]
          }
        ]
      },
      "results": [
        {
          "metricName": "Builtin.Helpfulness",
          "evaluatorDetails": [
            {
              "modelIdentifier": "amazon.nova-pro-v1:0",
              "explanation": "The candidate response is directly addressing the question about the origin of the company name \"NHN Techorus.\" It provides a clear and concise explanation that aligns with the information given in the related passages. The response is sensible, coherent, and clear. It follows the instructions implicitly by extracting the relevant information from the provided passages. The genre, style, and modality are appropriate for the context of a company information query. The response is specific and concise, avoiding unnecessary content. It anticipates the user's need for a straightforward answer to the question about the company name's origin."
            }
          ],
          "result": 0.8333
        },
        {
          "metricName": "Builtin.Correctness",
          "evaluatorDetails": [
            {
              "modelIdentifier": "amazon.nova-pro-v1:0",
              "explanation": "The candidate response accurately reflects the information provided in the ground truth response. Both state that the name \"NHN Techorus\" is a combination of \"Technology\" and \"Chorus,\" and both convey the idea that the name embodies the concept of different technologies and values resonating together to create higher value. There are no significant deviations or additional incorrect information in the candidate response."
            }
          ],
          "result": 1.0
        },

RAG 評価のメトリクス解説

RAG 評価機能では、システムの性能を「検索(Retrieval)」と「回答生成(Generation)」の 2 つの観点から定量的に測定します。
各メトリクスは 0 から 1 のスコアで評価され、1 に近いほど高い性能を示します。

メトリクスを使用して RAG システムのパフォーマンスを理解する – Amazon Bedrock

検索メトリクス(Retrieval Metrics)

  • Context Relevance(コンテキスト関連性)
    • 検索されたテキストがユーザーの質問にどれだけ関連しているか
    • 高スコア:質問に対して的確な情報を検索
    • 低スコア:無関係な情報が混入
  • Context Coverage(コンテキスト網羅性)
    • 検索されたテキストが正解データをどれだけカバーしているか
    • 高スコア:必要な情報を包括的に取得
    • 低スコア:重要な情報が欠落

回答生成メトリクス(Generation Metrics)

品質関連

  • Correctness(正確性)
    • 生成された回答の事実的正確性
    • 質問に対する妥当な回答かを評価
  • Completeness(完全性)
    • 質問のすべての側面に対応しているか
    • 包括的で完全な回答かを評価
  • Helpfulness(有用性)
    • 質問者にとっての実用性と価値
    • 問題解決への貢献度を総合評価
  • Logical Coherence(論理一貫性)
    • 回答の論理的矛盾や不整合の有無
    • 筋の通った一貫性のある回答かを評価
  • Faithfulness(忠実性)
    • 検索情報に基づいた回答か
    • ハルシネーション(幻覚)の検出

引用関連

  • Citation Precision(引用精度)
    • 引用された文章の正確性
    • 適切な引用がされているかを評価
  • Citation Coverage(引用網羅性)
    • 回答が引用によってどれだけ裏付けされているか
    • Citation Precision と併用推奨

適切性関連

  • Harmfulness(有害性)
    • 有害コンテンツ(憎悪、暴力、性的内容等)の検出
    • 低スコアが良好(有害性が少ない)
  • Stereotyping(ステレオタイプ)
    • 個人・グループに対する一般化された記述の有無
    • 低スコアが良好(ステレオタイプ的表現が少ない)
  • Refusal(回避性)
    • 質問に対する回避的回答の傾向
    • 高スコア:質問回避傾向、低スコア:積極的回答傾向

Bedrock でレポートを要約

S3 からダウンロードしたファイルを、Bedrock で要約させた結果です。

# RAG評価レポート

## 概要
NHNテコラスに関するRAGシステムの評価を実施しました。10件の質問に対する回答の品質を、複数の評価指標で測定した結果をまとめます。

## 評価指標と結果

### 1. 有用性 (Helpfulness)
- **平均スコア**: 0.85
- **評価**: 全体的に高い有用性を示している
- **詳細**: 回答は明確で一貫性があり、ユーザーの質問に直接的に答えている

### 2. 正確性 (Correctness)
- **平均スコア**: 1.0
- **評価**: 完璧な正確性
- **詳細**: 全ての回答が参照回答と一致し、事実に基づいた正確な情報を提供

### 3. 論理的一貫性 (Logical Coherence)
- **平均スコア**: 1.0
- **評価**: 完璧な論理的一貫性
- **詳細**: 回答に矛盾や論理的な欠陥は見られない

### 4. 忠実性 (Faithfulness)
- **平均スコア**: 1.0
- **評価**: 完璧な忠実性
- **詳細**: 全ての回答がソース文書の内容に忠実で、情報の歪曲や追加はない

### 5. 完全性 (Completeness)
- **平均スコア**: 1.0
- **評価**: 完璧な完全性
- **詳細**: 参照回答に含まれる全ての重要な情報が適切に含まれている

### 6. 引用精度 (Citation Precision)
- **平均スコア**: 0.78
- **評価**: 良好だが改善の余地あり
- **詳細**: 引用された文書の多くが回答に有用だが、一部不適切な引用も存在

### 7. 引用カバレッジ (Citation Coverage)
- **平均スコア**: 1.0
- **評価**: 完璧な引用カバレッジ
- **詳細**: 回答の情報が適切にソース文書で裏付けられている

### 8. 有害性 (Harmfulness)
- **平均スコア**: 0.0
- **評価**: 有害なコンテンツなし
- **詳細**: 全ての回答が安全で適切

### 9. 拒否 (Refusal)
- **平均スコア**: 0.0
- **評価**: 適切な回答提供
- **詳細**: 質問に対して適切に回答し、不当な拒否はない

### 10. ステレオタイプ (Stereotyping)
- **平均スコア**: 0.0
- **評価**: バイアスなし
- **詳細**: 偏見やステレオタイプは含まれていない

## 主要な発見

### 強み
1. **高い正確性**: 全ての回答が事実に基づいており、誤情報は含まれていない
2. **完全性**: 必要な情報が漏れなく提供されている
3. **安全性**: 有害なコンテンツやバイアスは検出されていない
4. **一貫性**: 論理的に一貫した回答を提供

### 改善点
1. **引用精度**: 一部の引用で関連性の低い文書が含まれている(平均0.78)
2. **有用性**: わずかな改善の余地がある(平均0.85)

## 推奨事項

1. **引用システムの改善**: より関連性の高い文書のみを引用するよう、検索・ランキングアルゴリズムを調整
2. **回答の構造化**: より読みやすい形式での情報提示を検討
3. **継続的監視**: 定期的な評価を実施し、品質の維持・向上を図る

## 結論

NHNテコラスに関するRAGシステムは全体的に高い品質を示しており、特に正確性、完全性、安全性の面で優秀な結果を得ています。引用精度の改善により、さらに高品質なシステムへの向上が期待できます。

まとめ

Bedrock の RAG 評価機能を使用することで、Knowledge Base の性能を定量的に分析できました。
今回の評価では、特に正確性、完全性、安全性の面で優秀な結果を得られ、引用精度の改善により更なる品質向上が期待できることが分かりました。

この機能により、RAG システムの客観的な評価と継続的な改善が可能になり、より信頼性の高い AI アプリケーションの構築に役立てることができます。

参考情報

20240919-AWS-AIML-3-rag-evaluation.pdf
Amazon Bedrock での RAG 評価ジョブの作成 – Amazon Bedrock
Amazon Bedrock の新しい RAG 評価機能と LLM-as-a-Judge 機能 | Amazon Web Services ブログ
Amazon Bedrock ナレッジベース評価による RAG アプリケーションの評価 | 人工知能
Amazon Bedrock ナレッジベースデータの前提条件 – Amazon Bedrock

NHN テコラスの採用情報はこちら

テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!

Cold-Airflow

2021年新卒入社。インフラエンジニアです。RDBが三度の飯より好きです。 主にデータベースやAWSのサーバレスについて書く予定です。あと寒いのは苦手です。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら