はじめに
Fusicのレオナです。本ブログでは2025年7月にプレビュー発表されたAmazon S3 Vectorsを用いて、Amazon S3のみでRAGにおける検索の方法を紹介します。従来、RAGシステムではAmazon KendraやAmazon Bedrock Knowledge Bases、OpenSearchやPineconeなどの専用ベクトルストアを用意するのが一般的でしたが、S3 Vectorsの登場により、S3だけでベクトルの保存と検索ができるようになりました。
解説
Amazon S3 Vectorsとは
Amazon S3 Vectorsは、Amazon S3にベクトル検索機能をネイティブに追加した新しいサービスです。S3を単なるオブジェクトストレージとして使うだけでなく、ベクトルデータを直接格納・検索できるようになりました。
大きな特徴のひとつは、コスト削減とシンプルなアーキテクチャです。従来の専用のベクトルデータベースを別途構築する必要がなく、最大で90%のストレージやクエリにかかるコストを削減できる可能性があります。
S3 Vectorsでは、S3内に新しい形式の「ベクトルバケット(Vector Bucket)」を作成し、その中に最大10,000個まで「ベクトルインデックス(Vector Index)」を配置できます。各インデックスには数千万規模のベクトルを格納でき、APIを通じてベクトルの追加や検索が可能です。また、各ベクトルにはキーと値の形式でメタデータを付与でき、たとえば「year > 2023」や「category = ‘finance’」といった条件で効率的に絞り込み検索を行うこともできます。
さらに、ベクトルデータをAmazon OpenSearch Service、Amazon BedrockのKnowledge Basesと統合されているため、RAGアプリケーションを簡単に構築できる点も大きな利点です。
Amazon S3 Vectors 料金モデル (バージニア北部)
項目 | 料金 | 単位 |
---|---|---|
ストレージ保管 | $0.06 | 1GB・1ヶ月 |
PUTリクエスト | $0.20 | 1GB |
GET、LIST等 | $0.055 | 1,000リクエスト |
クエリリクエスト | $0.0025 | 1,000リクエスト |
データ処理(最初の10万個) | $0.0040 | 1TB |
データ処理(10万個超) | $0.0020 | 1TB |
コスト比較
概算になりますが、簡単なコスト比較表を記載します。
小規模構成での料金概算
サービス名 | 構成条件例 | 月額目安(USD) | 備考 |
---|---|---|---|
Amazon RDS for PostgreSQL + pgvector | db.t4g.micro(2vCPU, 1GB RAM)、20GB GP2 | 約 $13〜15 | 最安値構成 |
Amazon Aurora PostgreSQL + pgvector | db.t3.medium(2vCPU, 4GB RAM)、10GB ストレージ | 約 $60〜80 | Auroraはt4g.micro非対応 |
Amazon MemoryDB for Redis | db.t4g.small(2vCPU, 2GB RAM)、1ノード | 約 $35〜40 | ベクトル検索対応 |
Amazon DocumentDB (MongoDB互換) | db.t3.medium(2vCPU, 4GB RAM)、30GB | 約 $57〜60 | 最大16,000次元サポート |
Amazon OpenSearch Serverless | 1 OCU (開発モード:0.5 indexing + 0.5 search) | 約 $175 | 本番は2 OCU(約$350) |
Amazon Neptune Analytics | 32 m-NCU(32GB メモリ) | 約 $180〜200 | 2024年7月から小規模構成追加 |
Amazon Kendra | Basic Developer Edition (1 Index) | 約 $821 | $1.125/時間、本番非推奨 |
Amazon Bedrock Knowledge Bases | 利用するベクトルDB次第 | ベクトルDB料金のみ | KB機能自体は無料 |
Amazon S3 Vectors(プレビュー) | 1,000万ベクトル格納(推定) | 約 $10〜20前後 | 正式料金未発表 |
構築
マネジメントコンソールでS3 Vectorsを作成
- バージニア北部リージョンで
ベクトルバケット
をクリック -
ベクトルバケットを作成
ボタンをクリック - バケット名を入力して
ベクトルバケットを作成
ボタンをクリック。今回はtest-s3-vector-bucket-724629
としています - 作成したバケット名をクリック
-
ベクトルインデックスを作成
ボタンをクリック - ベクトルインデックス名、ディメンション、距離メトリックを設定
- 設定後、
ベクトルインデックスを作成
ボタンをクリック
Vector indexにベクトル化したテキストを挿入する
PutVectors API
を使用して、ベクトルインデックスにベクトルを追加できます。各ベクトルはキーで構成され、このキーはベクトルインデックス内の各ベクトルを一意に識別します。今回はBoto3で試してみます。またベクトル化をする際に基盤モデルのTitan Text Embeddings V2
を使うのでモデルの有効化をしましょう。Amazon Bedrock -> モデルアクセスからモデルの有効化ができます。
実装
ベクトル化するテキストは弊社のニュースページの1つからテキストを使用します。[こちら]。
put_s3.py
import boto3
import json
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
s3vectors = boto3.client("s3vectors", region_name="us-east-1")
texts = [
"ブランドスローガンを定めた背景と目的",
"ブランドスローガンを定めた背景には、当社が掲げるミッション・ビジョンに立ち返り、「私たちは世の中に対して何を成すのか」という意思や約束を、あらためて定義しようという想いがありました。社内インタビューやワークショップを重ね、丁寧に向き合い、こだわり抜いて、少しずつ言葉を紡ぎだしていった結果、生まれたのがこのブランドスローガンです。",
"▼ミッション",
"「Why we do」自分たちの在り方",
"“人に多様な道を 世の中に爪跡を”",
"▼ビジョン",
"「What we do」日々の心得",
"“個性をかき集めて、驚きの角度から世の中をアップデートしつづける。”",
"ブランドスローガンを定める目的は、スローガンという共通言語を持つことによって、メンバー全員が同じ目線で会話できるようにし、Fusicブランドを世の中に適切な形で届けることです。",
"ブランドスローガンに込めた想いと意味",
"「OSEKKAI × TECHNOLOGY」",
"このブランドスローガンは、Fusic の本質的な価値を表したものです。自分たちの在り方である「Why we do」を実現するために、日々の心得である「What we do」を実行し、その結果として社会に貢献している価値を表現しています。",
"「ココロと技術で、ぴったりも、びっくりも。」",
"このサブコピーは、ブランドスローガンを補強する言葉として、お客さま一人ひとりと丁寧に向き合い、伴走しながら、求められているもの以上のプラスαを提供していくという私たちの姿勢を表しています。",
"ブランドスローガンの価値観や目指す方向性をまとめた「ブランドステートメント」も定めました。"
]
vectors_to_put = []
for i, text in enumerate(texts):
response = bedrock.invoke_model(
modelId="amazon.titan-embed-text-v2:0",
body=json.dumps({"inputText": text})
)
response_body = json.loads(response["body"].read())
embedding = response_body["embedding"]
vectors_to_put.append({
"key": f"text_{i}",
"data": {"float32": embedding},
"metadata": {"text": text}
})
result = s3vectors.put_vectors(
vectorBucketName="test-s3-vector-bucket-724629",
indexName="test-s3-vector-bucket-724629-index",
vectors=vectors_to_put
)
print(json.dumps(result, indent=4))
結果
Terminal
{
"ResponseMetadata": {
"RequestId": "f9267d08-02cc-4ac7-8791-10ba927cbff1",
"HostId": "",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"date": "Mon, 25 Aug 2025 09:50:54 GMT",
"content-type": "application/json",
"content-length": "2",
"connection": "keep-alive",
"x-amz-request-id": "f9267d08-02cc-4ac7-8791-10ba927cbff1",
"access-control-allow-origin": "*",
"vary": "origin, access-control-request-method, access-control-request-headers",
"access-control-expose-headers": "*"
},
"RetryAttempts": 0
}
}
実際にクエリで検索してみる
実装
query.py
import boto3
import json
def query(question: str) -> None:
bedrock_client = boto3.client("bedrock-runtime", "us-east-1")
response = bedrock_client.invoke_model(
modelId="amazon.titan-embed-text-v2:0",
body=json.dumps({"inputText": question})
)
response_body = json.loads(response['body'].read())
embedding = response_body['embedding']
s3vectors_client = boto3.client("s3vectors", "us-east-1")
try:
response = s3vectors_client.query_vectors(
vectorBucketName="test-s3-vector-bucket-724629",
indexName="test-s3-vector-bucket-724629-index",
queryVector={
"float32": embedding,
},
topK=3,
returnMetadata=True,
returnDistance=True,
)
if 'vectors' not in response or len(response['vectors']) == 0:
print("検索結果が見つかりませんでした。")
return
for i, vector in enumerate(response["vectors"], 1):
key = vector.get('key', 'unknown')
metadata = vector.get('metadata', {})
text_content = metadata.get('text', '')
distance = vector.get('distance', 0)
print(f"結果 {i}: キー={key}, 距離={distance:.4f}")
if text_content:
print(f"テキスト: {text_content}")
else:
print("(テキストメタデータなし)")
print("-" * 50)
except Exception as e:
print(f"クエリ実行中にエラーが発生しました: {e}")
if __name__ == "__main__":
query("ブランドスローガンを定めた背景")
結果
Terminal
結果 1: キー=text_0, 距離=0.0672
テキスト: ブランドスローガンを定めた背景と目的
--------------------------------------------------
結果 2: キー=text_1, 距離=0.1717
テキスト: ブランドスローガンを定めた背景には、当社が掲げるミッション・ビジョンに立ち返り、「私たちは世の中に対して何を成すのか」という意思や約束を、あらためて定義しようという想いがありました。社内インタビューやワークショップを重ね、丁寧に向き合い、こだわり抜いて、少しずつ言葉を紡ぎだしていった結果、生まれたのがこのブランドスローガンです。
--------------------------------------------------
結果 3: キー=text_9, 距離=0.3217
テキスト: ブランドスローガンに込めた想いと意味
--------------------------------------------------
ベクトルバケット・インデックスを削除する
ベクトルバケット・インデックスは、マネジメントコンソールから削除することができません。 (2025年 8月 25日時点)削除する場合は、AWS CLI
を使用して削除する必要があります。ベクトルバケット内にベクトルインデックスが存在する場合は、事前にすべて削除する必要があります。
- ベクトルインデックスを削除
aws s3vectors delete-index \
--vector-bucket-name "ベクトルバケット名" \
--index-name "ベクトルインデックス名" \
--region "リージョン名"
- ベクトルインデックスが削除されていることを確認、ベクトルバケットを削除
--vector-bucket-name "ベクトルバケット名" \
--region "リージョン名"
3. マネジメントコンソールで確認
最後に
Amazon S3 Vectorsにより、RAG構築において安くベクトルデータを用意することができるようになり、これまで以上にシンプルになりました。またAmazon Bedrock Knowledge Basesとの統合を活用すれば、用途に応じたRAG基盤を構築できるでしょう。
Views: 0