水曜日, 8月 27, 2025
水曜日, 8月 27, 2025
- Advertisment -
ホームニューステックニュースAmazon S3 Vectorsを試してみた

Amazon S3 Vectorsを試してみた


はじめに

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を作成

  1. バージニア北部リージョンでベクトルバケットをクリック
  2. ベクトルバケットを作成ボタンをクリック
  3. バケット名を入力してベクトルバケットを作成ボタンをクリック。今回はtest-s3-vector-bucket-724629としています
  4. 作成したバケット名をクリック
  5. ベクトルインデックスを作成ボタンをクリック
  6. ベクトルインデックス名、ディメンション、距離メトリックを設定
  7. 設定後、ベクトルインデックスを作成ボタンをクリック

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を使用して削除する必要があります。ベクトルバケット内にベクトルインデックスが存在する場合は、事前にすべて削除する必要があります。

  1. ベクトルインデックスを削除
aws s3vectors delete-index \
  --vector-bucket-name "ベクトルバケット名" \
  --index-name "ベクトルインデックス名" \
  --region "リージョン名"

  1. ベクトルインデックスが削除されていることを確認、ベクトルバケットを削除
  --vector-bucket-name "ベクトルバケット名" \
  --region "リージョン名"


3. マネジメントコンソールで確認

最後に

Amazon S3 Vectorsにより、RAG構築において安くベクトルデータを用意することができるようになり、これまで以上にシンプルになりました。またAmazon Bedrock Knowledge Basesとの統合を活用すれば、用途に応じたRAG基盤を構築できるでしょう。



Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -