1 はじめに
CX事業本部製造ビジネステクノロジー部の平内(SIN)です。
Knowledge bases for Amazon Bedrockを使用すると、非常に簡単にRAGを構築することができまが、今回は、これを更に手軽にデプロイ出来るようにとCDK化してみました。
サンプルとして作成したナレッジベースは、架空の居酒屋の案内をするものです。 最初に、動作している様子をご確認ください。
2 データ
架空の居酒屋のデータとして用意したのは、以下の2つです。
- お店の案内 izakaya_guidance.pdf
- メニュー izakaya_menu.txt
どちらも、GPT-4oに作成してもらいました。
架空の居酒屋の説明文を考えてください。
架空の居酒屋は、焼き鳥とおでんがおすすめで、その他に、ご飯もの、魚料理、サイドメニューもあります
各メニューは、リーズナブルで、250円から600円の範囲となっています
説明文には、以下を含めてください。
1. 営業時間
2. お休み
3. お店の特徴(200文字程度)
4. アクセス
5. その他注意事項
架空の居酒屋のメニューを100種類考えてください
メニューは、一覧形式で出力してください
各メニューには、メニュー番号、名前、価格、説明、分類を含めてください
分類は、「ご飯もの」「焼き鳥」「おでん」「魚料理」「サイドメニュー」の5種類です
各メニューの説明は、それぞれ独創的で、面白みのあるものにしてください
価格は、250円から600円の範囲としてください
3 Pinecone
Pineconeのインデックスデータベースは、手動で作成しています。 設定値は、以下の通りで、作成後にHOST(エンドポイント)をCDKデプロイ時に使用できるようコピーしておきます。
- 名前: kb-izakaya
- Dimensions: 1,536
- Metric: Cosine
- Capacity mode: SERVERRESS
- Region: us-east-1
なお、AWSから接続するためには、PineconeのAPIキーをSecretManagerに保存する必要があります。
シークレットのARNもCDKデプロイ時に必要となります。
4 CDK
(1) コード
CDKの主なコードは、以下のとおりです。
データソース用のS3バケット、必要なRole そして、Pineconeをストレージとするナレッジベースとデータソースが定義されています。
lib/amazon-bedrock-kb-izakaya-stack.ts
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import { CfnOutput, RemovalPolicy } from "aws-cdk-lib";
import { aws_iam, aws_s3, aws_bedrock } from "aws-cdk-lib";
export class AmazonBedrockKbIzakayaStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const tag = "kb-izakaya";
const bucketName = `${tag}-${this.account}`;
const embeddingModelArn = this.node.tryGetContext("embeddingModelArn");
const pineconeEndpoint = this.node.tryGetContext("pineconeEndpoint");
const pineconeSecretArn = this.node.tryGetContext("pineconeSecretArn");
// S3 bucket for the data source
const dataSourceBucket = new aws_s3.Bucket(this, "DataSourceBucket", {
bucketName: bucketName,
removalPolicy: RemovalPolicy.DESTROY,
});
// Role for the knowledge base
const knowledgeBaseRole = new aws_iam.Role(this, `KnowledgeBaseRole`, {
roleName: `${tag}_role`,
assumedBy: new aws_iam.ServicePrincipal("bedrock.amazonaws.com"),
inlinePolicies: {
inlinePolicy1: new aws_iam.PolicyDocument({
statements: [
new aws_iam.PolicyStatement({
resources: [pineconeSecretArn],
actions: ["secretsmanager:GetSecretValue"],
}),
new aws_iam.PolicyStatement({
resources: [embeddingModelArn],
actions: ["bedrock:InvokeModel"],
}),
new aws_iam.PolicyStatement({
resources: [
`arn:aws:s3:::${bucketName}`,
`arn:aws:s3:::${bucketName}/*`,
],
actions: ["s3:ListBucket", "s3:GetObject"],
}),
],
}),
},
});
// knowledge Base
const knowledgeBase = new aws_bedrock.CfnKnowledgeBase(
this,
"KnowledgeBase",
{
knowledgeBaseConfiguration: {
type: "VECTOR",
vectorKnowledgeBaseConfiguration: {
embeddingModelArn: embeddingModelArn,
},
},
name: tag,
roleArn: knowledgeBaseRole.roleArn,
storageConfiguration: {
type: "PINECONE",
pineconeConfiguration: {
connectionString: pineconeEndpoint,
credentialsSecretArn: pineconeSecretArn,
fieldMapping: {
metadataField: "metadata",
textField: "text",
},
},
},
description: "IZAKAYA knowledge base",
}
);
// data source
new aws_bedrock.CfnDataSource(this, "BedrockKnowledgeBaseDataStore", {
name: `${tag}-data-source`,
knowledgeBaseId: knowledgeBase.ref,
dataSourceConfiguration: {
s3Configuration: {
bucketArn: dataSourceBucket.bucketArn,
},
type: "S3",
},
});
// Output the AWS CLI command to upload a file to the S3 bucket
const dataSourceFiles: string[] = [
"izakaya_menu.txt",
"izakaya_guidance.pdf",
];
dataSourceFiles.forEach((dataSourceFile) => {
const uploadCommand = `aws s3 cp assets/${dataSourceFile} s3://${bucketName}/${dataSourceFile}`;
new CfnOutput(this, `UploadCommand_${dataSourceFile}`, {
value: uploadCommand,
description: `AWS CLI command to upload a file to the S3 bucket`,
});
});
}
}
(2) デプロイ
CDKのコードは、Githubにあり、以下の手順でデプロイできます。
https://github.com/furuya02/amazon-bedrock-kb-izakaya
% git clone https://github.com/furuya02/amazon-bedrock-kb-izakaya.git
% cd amazon-bedrock-kb-izakaya
% npm install
cdk.jsonにPineconeに関する設定がありますので、エンドポイント及びシークレットのARNを編集します。
"context": {
"pineconeEndpoint": "https://xxxxxxx.pinecone.io",
"pineconeSecretArn": "arn:aws:secretsmanager:us-east-1:xxxxxxxx",
CDKデプロイは、以下のとおりです。
% export AWS_DEFAULT_REGION=us-east-1
% npx cdk deploy
Githubリポジトリの、assetsフォルダに今回使用したデータがありますので、作成されたバケットにアップロード してください。
% aws s3 cp assets/izakaya_guidance.pdf s3://kb-izakaya-xxxxxxxx/izakaya_guidance.pdf
% aws s3 cp assets/izakaya_menu.txt s3://kb-izakaya-xxxxxxxx/izakaya_menu.txt
5 同期
CDKデプロイ及び、データのアップロード後、「同期」することで、データは、ベクトル化され保存されます。
Pinecodeのコンソールでは、ベクトル化されたデータを確認することもできます。
6 動作確認
テストには、Anthropic Claude v2.1を使用しました。
アップロードしたデータを元に、質問に答えていることが確認できます
7 最後に
今回は、PineconeをストレージとしたKnowledge bases for Amazon BedrockをCDKで作成してみました。
作業中少し戸惑ったのは、以下の2点でした。
(1) Embedding ModelのARN
コンソール上には、ARNが出てこないので、CLIで列挙して確認しました。
% export AWS_DEFAULT_REGION=us-east-1
% % aws bedrock list-foundation-models | grep modelArn | grep titan-embed-text
"modelArn": "arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-text-v1:2:8k",
"modelArn": "arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-text-v1",
"modelArn": "arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-text-v2:0:8k",
"modelArn": "arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-text-v2:0",
(2) 依存関係
最後までよく分からなかったのですが、ロールを先に作成するように、明示的に指定しないと、デプロイに失敗してました。
knowledgeBase.node.addDependency(knowledgeBaseRole);
「(2) 依存関係」 の問題は、Roleの作成時に addPolidy() を使用していたことが原因でした。 aws_iam.Role.inlinePolicies に修正することでaddDependency()は、必要なくなりました。
addPolidy()は、CDK上別のオブジェクトとなるため、タイミングによって、CfnKnowledgeBaseの生成時にポリシー不足が指摘されていたようです。
CfnKnowledgeBaseのプロパティ roleArnは、生成時に検証されているようなので注意が必要のようです。
やまたつさんに教えて頂きました。m(_._)m
元々、Knowledge bases for Amazon Bedrockの構築は、非常に簡単ですが、 ランニングコストが比較的低いPineconeを使用したものをCDK化しておくことで、更に手軽に利用できるのでは?と妄想しています。
8 参考にさせて頂いたリンク
Set up a vector index for your knowledge base in a supported vector store
AWS Marketplace の Pinecone を Amazon Bedrock のナレッジベースとして利用する