Amazon Bedrock RAG 環境用 AWS CloudFormation テンプレート series 2 Aurora 編

こんにちは、広野です。

本記事はシリーズもので、以下の記事の続編です。

以前、以下の記事で Amazon Bedrock や Agents for Amazon Bedrock を使用した最小構成 RAG 環境構築を紹介しておりました。当時はAmazon Bedrock 関連のリソースを一部 AWS CloudFormation ではデプロイできなかったのですが、今はサポートされたためにできるようになりました。

当時の構成を現在は変更しており、Knowledge Base に使用するデータベースを Amazon OpenSearch Serverless から Aurora Serverless v2 Postgresql に変更したり、モデルを Claude 3.5 Sonnet に変更したりしています。

本シリーズ記事では、環境構築用の AWS CloudFormation のサンプルテンプレートを 3 記事に分けて紹介します。説明を分割するため、テンプレートを3つに分けていますのでご了承ください。

2回目は Amazon Aurora Serverless v2 Postgresql 編です。

本記事で取り扱う構成

RAG 環境全体の構成

以下のアーキテクチャで RAG アプリケーションを構築しています。このうち、赤枠の部分が本シリーズ記事で取り扱う箇所です。series 2 Aurora 編では、Knowledge Base のベクトルデータベースとなる Amazon Aurora Serverless v2 Postgresql と、それに取り込むドキュメントを格納する Amazon S3 バケットについて説明します。

  • 今回は Agents for Amazon Bedrock がアクセスするリソース、Amazon Aurora Serverless v2 Postgresql と Amazon S3 バケットをデプロイします。
  • Amazon S3 バケットは RAG の参照先にしたいドキュメントを放り込むだけなので、特別なオプションはありません。

Amazon Aurora の構成 (前回のおさらい含む)

Amazon Aurora Serverless v2 をデプロイするためには VPC が必要になります。サーバーレスなんですが、VPC リソースからアクセス可能にするためにそのような仕様にしているのだと思います。

  • Aurora Serverless はプライベートサブネットに配置します。リーダーインスタンスやレプリカは設定していません。
  • Aurora Serverless を配置するときに、RDS サブネットグループが必要になります。任意の 2 つ以上のサブネットをグループに登録します。これが Aurora Serverless の設定で必要になるため、マルチ AZ 構成が必須になります。
  • データベースなので、プライベートサブネットに配置します。選択したサブネットに、VPC 内からアクセスするためのエンドポイントが作成されます。ただし Agents for Amazon Bedrock からは Data API 経由で接続するため、VPC は通りません。
  • エンドポイントにはセキュリティグループを関連付けます。ここでは、サブネットの CIDR から Postgresql に接続するためのデフォルトポート番号を開けておきます。
  • Agents for Amazon Bedrock が Aurora Serverless に接続するときのクレデンシャルは、Secrets Manager から取得します。Postgresql のマスターユーザのパスワードは自動で Secrets Manager に作成されます。Agents for Amazon Bedrock が使用するユーザを bedrock_user とし、パスワードは自動生成させています。自動生成にあたり、パスワードに使用できない記号が入ることを避けるため、ExcludePunctuation のオプションを true にしています。この CloudFormation テンプレートでは、bedrock_user は作成されません。作成されるのはパスワードです。後述する手動によるベクトルデータベース構築コマンド実行の際にユーザを作成します。
  • Amazon Aurora Serverless のキャパシティやメンテナンスの設定は適当に入れているので、適宜変更してください。

AWS CloudFormation テンプレート

図に掲載している Amazon VPC は前回のテンプレートで作成しています。Amazon Aurora Serverless で使用する RDS サブネットグループとセキュリティグループは前回のテンプレートでエクスポートした情報をインポートしています。また、今回のテンプレートで、次のテンプレートで使用する Amazon Aurora、Amazon S3、IAM ロールの情報をエクスポートしています。

IAM ロールは Agents for Amazon Bedrock 用のものです。以下の許可が入っています。

  • Amazon Aurora、Amazon S3、Secrets Manager へのアクセス
  • ドキュメントの内容をベクトルデータに変換する AI モデル (Amazon Titan Text Embeddings) へのアクセス
AWSTemplateFormatVersion: 2010-09-09
Description: The CloudFormation template that creates an Aurora Serverless v2 cluster and a S3 bucket as a RAG Knowledge base.

# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
Parameters:
  SubName:
    Type: String
    Description: System sub name of sample. (e.g. test)
    Default: test
    MaxLength: 10
    MinLength: 1

Resources:
# ------------------------------------------------------------#
# S3
# ------------------------------------------------------------#
  S3BucketKbDatasource:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub sample-${SubName}-kbdatasource
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      Tags:
        - Key: Cost
          Value: !Sub sample-${SubName}

# ------------------------------------------------------------#
# Secrets Manager for Aurora
# ------------------------------------------------------------#
  SecretAurora:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: !Sub aurora-database-user-sample-${SubName}
      Description: !Sub Aurora database credential for sample-${SubName}
      GenerateSecretString:
        SecretStringTemplate: '{"username": "bedrock_user"}'
        GenerateStringKey: password
        PasswordLength: 28
        ExcludePunctuation: true
      Tags:
        - Key: Cost
          Value: !Sub sample-${SubName}

# ------------------------------------------------------------#
# Aurora Serverless v2 PostgreSQL
# ------------------------------------------------------------#
  AuroraDBCluster:
    Type: AWS::RDS::DBCluster
    Properties:
      DatabaseName: bedrockragkb
      DBClusterIdentifier: !Sub bedrock-rag-kb-sample-${SubName}-cluster
      Engine: aurora-postgresql
      EngineVersion: 16.2
      EngineMode: provisioned
      DBSubnetGroupName:
        Fn::ImportValue:
          !Sub sample-${SubName}-PrivateSubnetGroupName
      MasterUsername: postgresql
      ManageMasterUserPassword: true
      ServerlessV2ScalingConfiguration:
        MinCapacity: 0.5
        MaxCapacity: 2.0
      EnableHttpEndpoint: true
      AutoMinorVersionUpgrade: true
      BackupRetentionPeriod: 1
      CopyTagsToSnapshot: true
      DeletionProtection: true
      EngineLifecycleSupport: open-source-rds-extended-support-disabled
      NetworkType: IPV4
      Port: 5432
      PreferredBackupWindow: "15:00-18:00"
      PreferredMaintenanceWindow: "Sun:01:00-Sun:14:00"
      VpcSecurityGroupIds:
        - Fn::ImportValue:
            !Sub sample-${SubName}-AuroraSecurityGroupId
      Tags:
        - Key: Cost
          Value: !Sub sample-${SubName}

  AuroraDBInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      Engine: aurora-postgresql
      DBInstanceClass: db.serverless
      DBClusterIdentifier: !Ref AuroraDBCluster
      DBInstanceIdentifier: !Sub bedrock-rag-kb-sample-${SubName}
      Tags:
        - Key: Cost
          Value: !Sub sample-${SubName}

# ------------------------------------------------------------#
# IAM Role for Bedrock KB
# ------------------------------------------------------------#
  IAMRoleBedrockKb:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub AmazonBedrockExecutionRoleForKnowledgeBase_sample-${SubName}
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action:
              - sts:AssumeRole
            Principal:
              Service:
                - bedrock.amazonaws.com
            Condition:
              StringEquals:
                "aws:SourceAccount": !Sub ${AWS::AccountId}
              ArnLike:
                "aws:SourceArn": !Sub "arn:aws:bedrock:${AWS::Region}:${AWS::AccountId}:knowledge-base/*"
      Policies:
        - PolicyName: AmazonBedrockRDSClusterPolicyForKnowledgeBase
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - rds:DescribeDBClusters
                  - rds-data:BatchExecuteStatement
                  - rds-data:ExecuteStatement
                Resource: !GetAtt AuroraDBCluster.DBClusterArn
        - PolicyName: AmazonBedrockS3PolicyForKnowledgeBase
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - "s3:GetObject"
                  - "s3:ListBucket"
                Resource:
                  - !GetAtt S3BucketKbDatasource.Arn
                  - !Sub ${S3BucketKbDatasource.Arn}/*
                Condition:
                  StringEquals:
                    "aws:PrincipalAccount": !Sub ${AWS::AccountId}
        - PolicyName: AmazonBedrockSecretsPolicyForKnowledgeBase
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - "secretsmanager:GetSecretValue"
                Resource: !Ref SecretAurora
        - PolicyName: AmazonBedrockFoundationModelPolicyForKnowledgeBase
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - "bedrock:ListFoundationModels"
                  - "bedrock:ListCustomModels"
                  - "bedrock:RetrieveAndGenerate"
                Resource: "*"
              - Effect: Allow
                Action:
                  - "bedrock:InvokeModel"
                Resource:
                  - !Sub arn:aws:bedrock:${AWS::Region}::foundation-model/amazon.titan-embed-text-v1
    DependsOn:
      - AuroraDBCluster
      - S3BucketKbDatasource
      - SecretAurora

# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
# S3
  KbDatasourceBucketName:
    Value: !Ref S3BucketKbDatasource
  KbDatasourceBucketArn:
    Value: !GetAtt S3BucketKbDatasource.Arn
    Export:
      Name: !Sub sample-${SubName}-S3BucketKbDatasourceArn
# Aurora
  AuroraDBClusterArn:
    Value: !GetAtt AuroraDBCluster.DBClusterArn
    Export:
      Name: !Sub sample-${SubName}-AuroraDBClusterArn
  AuroraDBClusterIdentifier:
    Value: !Ref AuroraDBCluster
    Export:
      Name: !Sub sample-${SubName}-AuroraDBClusterIdentifier
  AuroraAdminUserSecretArn:
    Value: !GetAtt AuroraDBCluster.MasterUserSecret.SecretArn
  AuroraBedrockUserSecretArn:
    Value: !Ref SecretAurora
    Export:
      Name: !Sub sample-${SubName}-SecretAurora
  IAMRoleBedrockKbArn:
    Value: !GetAtt IAMRoleBedrockKb.Arn
    Export:
      Name: !Sub sample-${SubName}-IAMRoleBedrockKbArn

ベクトルデータベース構築 (手動)

上述の AWS CloudFormation テンプレートを流しただけでは、Amazon Aurora Serverless の箱だけが出来上がった状態ですので、ユーザやテーブルがありません。Agents for Amazon Bedrock の Knowledge Base として使用できるようにするため、AWS 提供の手順を実行する必要があります。

私は AWS マネジメントコンソールの RDS の画面から該当の Amazon Aurora Serverless のインスタンスを選択して、Data API 経由で SQL を入力しています。

SQL を実行するにあたり、Postgresql の Admin ユーザを確認する必要があります。AWS CloudFormation で Secrets Manager 内にパスワードが自動生成されていますので、それを確認しておきます。

手順内で、bedrock_user を作成しますが、そのときのパスワードも Secrets Manager 内に自動生成されていますので、そちらも確認しておきます。いずれも、一度構築してしまえばほぼほぼ今後使用することはありません。

本記事の範囲はこれで終了です。

まとめ

いかがでしたでしょうか?

Amazon Aurora Serverless 作成テンプレートはどこにでもある情報だと思いますが、一度できるようになると他の案件にも応用できるので便利です。

次回は Agents for Amazon Bedrock や周辺の AWS Lambda 関数のデプロイがテーマです。

本記事が皆様のお役に立てれば幸いです。

謝辞

本記事の構成作成にあたり、以下 AWS Ambassador 2 名の方のご知見が大変参考になりました。

  • ソニービズネットワークス 濱田様
  • サーバーワークス 福島様

濱田様には、以前お会いしたときに「RAG の Knowledge Base を最も安く構築するなら Aurora Serverless 一択ですよ、いろいろ検証してそれに落ち着きました」とお聞きして、私が OpenSearch から Aurora Serverless に乗り換えるきっかけになりました。

福島様には、Aurora Serverless v2 Postgresql でベクトルデータベースを構築する際の手順 (コマンド) が AWS の公式ドキュメントのままではエラーになってしまうところ、ドンピシャな回避策をブログ記事で紹介してくれていました。大変助かりました。おそらく SQL 実行時に途中でユーザを切り替えずにコマンドを実行すると権限不足のエラーになってしまうものと想像します。

濱田様には今度 AWS Ambassador コミュニティでお会いしたときに御礼を言いたいと思います。福島様にもそうしたいと思っていたのですが、AWS Ambassador をご勇退されていたことに気付き、直接御礼を言う機会がありません。この場を借りて、御礼申し上げます。

本当にありがとうございました。

著者について
広野 祐司

AWS サーバーレスアーキテクチャを駆使して社内クラウド人材育成アプリとコンテンツづくりに勤しんでいます。React で SPA を書き始めたら快適すぎて、他の言語には戻れなくなりました。サーバーレス & React 仲間を増やしたいです。AWSは好きですが、それよりもフロントエンド開発の方が好きでして、バックエンド構築を簡単にしてくれたAWSには感謝の気持ちの方が強いです。
取得資格:AWS 認定は13資格、ITサービスマネージャ、ITIL v3 Expert 等
2020 - 2024 Japan AWS Top Engineer 受賞
2022 - 2024 AWS Ambassador 受賞
2023 当社初代フルスタックエンジニア認定
好きなAWSサービス:AWS Amplify / AWS AppSync / Amazon Cognito / AWS Step Functions / AWS CloudFormation

広野 祐司をフォローする

クラウドに強いによるエンジニアブログです。

SCSKクラウドサービス(AWS)は、企業価値の向上につながるAWS 導入を全面支援するオールインワンサービスです。AWS最上位パートナーとして、多種多様な業界のシステム構築実績を持つSCSKが、お客様のDX推進を強力にサポートします。

AI・MLAWSクラウドソリューションデータベース
シェアする
タイトルとURLをコピーしました