こんにちは、つくぼし(tsukuboshi0755)です!
re:Invent 2023でVector engine for OpenSearch Service ServerlessがGAになりました。
このサービスとBedrockのKnowledge baseを組み合わせる事で、RAGシステムを作成できるようになります。
今回はVector engine for OpenSearch Service ServerlessをCloudFormationで構築し、利用する方法を紹介します!
テンプレート
今回は以下のテンプレートをベースに。コレクションの種類をベクトル検索に変更し作成していきます。
全体のコードは以下の通りです。
CloudFormationコード
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Vector engine for OpenSearch Service Serverless
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Parameters:
- SysName
- Env
- CollectionStandbyReplicas
- AossDataAccessPrincipalArn
Parameters:
SysName:
Type: String
Default: 'cm'
Description: 'System name for this stack.'
Env:
Type: String
Default: 'dev'
Description: 'Environment for this stack.'
AllowedValues:
- 'prd'
- 'stg'
- 'dev'
CollectionStandbyReplicas:
Type: String
Default: 'DISABLED'
Description: 'DISABLED is suitable for production environments. ENABLED is suitable for development environments.'
AllowedValues:
- 'DISABLED'
- 'ENABLED'
AossDataAccessPrincipalArn:
Type: String
Default: 'arn:aws:iam::123456789012:user/aoss-data-access-user'
Description: 'The ARN of the IAM user or role that has access to the data in the collection.'
Resources:
AossCollection:
Type: 'AWS::OpenSearchServerless::Collection'
Properties:
Name: !Sub '${SysName}-${Env}-collection'
Type: VECTORSEARCH
StandbyReplicas: !Ref CollectionStandbyReplicas
DependsOn: AossEncryptionPolicy
AossEncryptionPolicy:
Type: 'AWS::OpenSearchServerless::SecurityPolicy'
Properties:
Name: !Sub '${SysName}-${Env}-encryption-policy'
Type: encryption
Policy: !Sub >-
{
"Rules":[
{
"Resource":[
"collection/${SysName}-${Env}-collection"
],
"ResourceType": "collection"
}
],
"AWSOwnedKey": true
}
AossNetworkPolicy:
Type: 'AWS::OpenSearchServerless::SecurityPolicy'
Properties:
Name: !Sub '${SysName}-${Env}-network-policy'
Type: network
Policy: !Sub >-
[
{
"Rules":[
{
"Resource":[
"collection/${SysName}-${Env}-collection"
],
"ResourceType": "dashboard"
},
{
"Resource":[
"collection/${SysName}-${Env}-collection"
],
"ResourceType": "collection"
}
],
"AllowFromPublic": true
}
]
AossDataAccessPolicy:
Type: 'AWS::OpenSearchServerless::AccessPolicy'
Properties:
Name: !Sub '${SysName}-${Env}-data-access-policy'
Type: data
Policy: !Sub >-
[
{
"Rules":[
{
"Resource":[
"collection/${SysName}-${Env}-collection"
],
"Permission":[
"aoss:CreateCollectionItems",
"aoss:UpdateCollectionItems",
"aoss:DescribeCollectionItems"
],
"ResourceType": "collection"
},
{
"Resource":[
"index/${SysName}-${Env}-collection/*"
],
"Permission":[
"aoss:CreateIndex",
"aoss:UpdateIndex",
"aoss:DescribeIndex",
"aoss:ReadDocument",
"aoss:WriteDocument"
],
"ResourceType": "index"
}
],
"Principal":[
"${AossDataAccessPrincipalArn}"
],
"Description": ""
}
]
Outputs:
Endpoint:
Value: !GetAtt AossCollection.CollectionEndpoint
以下より、本テンプレートで作成される各リソースについて説明します。
コレクション
AossCollection:
Type: 'AWS::OpenSearchServerless::Collection'
Properties:
Name: !Sub '${SysName}-${Env}-collection'
Type: VECTORSEARCH
StandbyReplicas: !Ref CollectionStandbyReplicas
DependsOn: AossEncryptionPolicy
OpenSearch Serverlessのデータベースであるコレクションを作成します。
今回はベクトル検索を行うため、Type
をVECTORSEARCH
に指定します。
また、StandbyReplicas
はDISABLED
にする事で、開発/テストオプションが有効になり、スタンバイレプリカの無効化によりコストを削減できます。
なお本番環境等で可用性を重視する場合は、ENABLED
にしスタンバイレプリカを有効化する事を推奨します。
暗号化ポリシー
AossEncryptionPolicy:
Type: 'AWS::OpenSearchServerless::SecurityPolicy'
Properties:
Name: !Sub '${SysName}-${Env}-encryption-policy'
Type: encryption
Policy: !Sub >-
{
"Rules":[
{
"Resource":[
"collection/${SysName}-${Env}-collection"
],
"ResourceType": "collection"
}
],
"AWSOwnedKey": true
}
OpenSearch Serverlessのデータを暗号化するためポリシーを作成します。
今回はAWSが所有するKMSキーを使用するため、AWSOwnedKey
をtrue
に指定します。
なお代わりに自身が所有するKMSキーを使用したい場合は、以下の通りAWSOwnedKey
をfalse
にし、KmsARN
にKMSキーのARNを指定してください。
AossEncryptionPolicy:
Type: 'AWS::OpenSearchServerless::SecurityPolicy'
Properties:
Name: !Sub '${SysName}-${Env}-encryption-policy'
Type: encryption
Policy: !Sub >-
{
"Rules":[
{
"Resource":[
"collection/${SysName}-${Env}-collection"
],
"ResourceType": "collection"
}
],
"AWSOwnedKey": false,
"KmsARN": "<KMSキーのARN>"
}
ネットワークポリシー
AossNetworkPolicy:
Type: 'AWS::OpenSearchServerless::SecurityPolicy'
Properties:
Name: !Sub '${SysName}-${Env}-network-policy'
Type: network
Policy: !Sub >-
[
{
"Rules":[
{
"Resource":[
"collection/${SysName}-${Env}-collection"
],
"ResourceType": "dashboard"
},
{
"Resource":[
"collection/${SysName}-${Env}-collection"
],
"ResourceType": "collection"
}
],
"AllowFromPublic": true
}
]
OpenSearch Serverlessをネットワークからアクセスするためのポリシーを作成します。
今回はパブリックアクセスを使用するため、AllowFromPublic
をtrue
に指定します。
なおVPCアクセスを使用したい場合は、以下の通りAllowFromPublic
をfalse
にし、SourceVPCEs
にVPCのインタフェースエンドポイントIDを指定してください。
AossNetworkPolicy:
Type: 'AWS::OpenSearchServerless::SecurityPolicy'
Properties:
Name: !Sub '${SysName}-${Env}-network-policy'
Type: network
Policy: !Sub >-
[
{
"Rules":[
{
"Resource":[
"collection/${SysName}-${Env}-collection"
],
"ResourceType": "dashboard"
},
{
"Resource":[
"collection/${SysName}-${Env}-collection"
],
"ResourceType": "collection"
}
],
"AllowFromPublic": false,
"SourceVPCEs":[
"<OpenSearch ServerlessのインタフェースエンドポイントID>"
]
}
]
データアクセスポリシー
AossDataAccessPolicy:
Type: 'AWS::OpenSearchServerless::AccessPolicy'
Properties:
Name: !Sub '${SysName}-${Env}-data-access-policy'
Type: data
Policy: !Sub >-
[
{
"Rules":[
{
"Resource":[
"collection/${SysName}-${Env}-collection"
],
"Permission":[
"aoss:CreateCollectionItems",
"aoss:UpdateCollectionItems",
"aoss:DescribeCollectionItems"
],
"ResourceType": "collection"
},
{
"Resource":[
"index/${SysName}-${Env}-collection/*"
],
"Permission":[
"aoss:CreateIndex",
"aoss:UpdateIndex",
"aoss:DescribeIndex",
"aoss:ReadDocument",
"aoss:WriteDocument"
],
"ResourceType": "index"
}
],
"Principal":[
"${AossDataAccessPrincipalArn}"
],
"Description": ""
}
]
OpenSearch Serverlessのデータにアクセスするためのポリシーを作成します。
今回はPrincipal
にあるAossDataAccessPrincipalArn
に対して任意のIAMユーザまたはIAMロールのARNを指定し、データの作成/変更/閲覧をできるように設定します。
検索の確認
上記のテンプレートをデプロイする事で、OpenSearch Serverlessを用いて正常にデータをベクトル検索できるか確認します。
CloudFormationスタックのデプロイ
今回は以下のパラメータで、CloudFormationスタックをデプロイします。
AossDataAccessPrincipalArn
には、今回作成するコレクションにアクセスするIAMユーザまたはIAMロールのARNを指定してください。
スタックの作成が完了すると、以下の通りOpenSearch ServerlessのエンドポイントURLが出力されます。
このURLは後で使用するのでメモしておいてください。
データアップロード/ベクトル検索
今回の確認で使用するデータ及び確認手順としては、以下の公式ドキュメントを参照します。
上記の公式ドキュメントに記載されている検索を実施するには、Postman
やawscurl
といったHTTPツールを使用する必要があります。
今回はawscurl
を導入し、使用する場合の手順を紹介します。
代わりにPostman
を使用したい場合は、以下の記事をご参照ください。
また実行環境にはCloudShellを利用します。
初めにpip3コマンドでawscurl
をインストールします。
$ pip3 install awscurl
次に、以下のコマンドを実行し、先ほどメモしたOpenSearch ServerlessのエンドポイントURLを設定します。
$ AOSS_ENDPOINT=<OpenSearch ServerlessのエンドポイントURL>
それではOpenSearch Serverlessのインデックスを、以下のコマンドで作成しましょう。
$ awscurl --service aoss --region ${AWS_REGION} \
-X PUT \
-d '{"settings": {"index.knn": true}, "mappings": {"properties": {"housing-vector": {"type": "knn_vector", "dimension": 3}, "title": {"type": "text"}, "price": {"type": "long"}, "location": {"type": "geo_point"}}}}' \
${AOSS_ENDPOINT}/housing-index | jq -r .
インデックス作成が問題なく完了すると、以下のようなレスポンスが返ります。
# レスポンス例
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "housing-index"
}
続いて作成したOpenSearch Serverlessのインデックスに対して、以下のコマンドでサンプルドキュメントをアップロードしましょう。
$ awscurl --service aoss --region ${AWS_REGION} \
-X POST \
-d '{"housing-vector":[10, 20, 30], "title": "2 bedroom in downtown Seattle", "price": "2800", "location": "47.71, 122.00"}' \
${AOSS_ENDPOINT}/housing-index/_doc | jq -r .
ドキュメントアップロードが問題なく完了すると、以下のようなレスポンスが返ります。
# レスポンス例
{
"_index": "housing-index",
"_id": "1%3A0%3AqgCYL4wBz5Soks5im65k",
"_version": 1,
"result": "created",
"_shards": {
"total": 0,
"successful": 0,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 0
}
最後に作成したOpenSearch Serverlessのインデックスに対して、以下のコマンドで特定のプロパティに類似したデータをベクトル検索しましょう。
$ awscurl --service aoss --region ${AWS_REGION} \
-X GET \
-d '{"size": 5, "query": {"knn": {"housing-vector": {"vector":[10, 20, 30], "k": 5}}}}' \
${AOSS_ENDPOINT}/housing-index/_search | jq -r .
正しく手順が実施できていれば、以下のように先ほどアップロードしたデータがベクトル検索でヒットする事が分かります。
# レスポンス例
{
"took": 73,
"timed_out": false,
"_shards": {
"total": 0,
"successful": 0,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits":[
{
"_index": "housing-index",
"_id": "1%3A0%3AAHx3Q4wBwuFCx3ceGjz8",
"_score": 1.0,
"_source": {
"housing-vector":[
10,
20,
30
],
"title": "2 bedroom in downtown Seattle",
"price": "2800",
"location": "47.71, 122.00"
}
}
]
}
}
上記の手順を踏む事で、ベクトル検索が正常に実施できる事を確認できました!
なお、アクセスキー及びシークレットアクセスキーを使用する事で、CloudShellにプリインストールされているcurl
でもベクトル検索が可能です。
詳細は以下記事をご参照ください。
最後に
今回はVector engine for OpenSearch Service ServerlessをCloudFormationで構築し、利用する方法を紹介しました。
今後BedrockのKnowledge baseを利用する場合、こちらのサービスを合わせて構築する機会が増えていくのではないでしょうか。
そのような場合に、この記事が少しでもお役に立てれば幸いです。
以上、つくぼし(tsukuboshi0755)でした!