AWS公式CLIツールs3vectors-embed-cliでAmazon S3 Vectorsへのベクトル登録・検索を試してみる
はじめに
データ事業本部のkobayashiです。
Amazon S3 VectorsはAIエージェントやRAG、セマンティック検索のためのベクトルストレージサービスです。開発でS3 Vectorsを使っていますが、AWSのマネジメントコンソールやAWS CLIでのベクトルの登録・クエリ操作がなかなか大変だと感じていました。
AWS CLIのput-vectorsではベクトルデータをfloat32の配列として直接指定する必要があり、テキストから埋め込みベクトルを生成してJSON形式で渡すという手間がかかります。query-vectorsも同様に、検索したいテキストを事前にベクトル化してからfloat32配列として渡す必要があります。
もっと手軽に操作できるツールがないかと探していたところ、AWSが公式に提供しているs3vectors-embed-cliを見つけたので試してみました。
s3vectors-embed-cliとは
s3vectors-embed-cliは、Amazon BedrockとAmazon S3 Vectorsを統合したスタンドアロンのCLIツールです。テキストや画像などの入力をベクトル化してS3 Vectorsに保存・検索する操作を、単一のコマンドで実行できます。
主な特徴としては以下になります。
- テキストを渡すだけで自動的にBedrockでベクトル化してS3 Vectorsに保存できる
- クエリもテキストを渡すだけで類似度検索が実行できる(ベクトルの手動生成が不要)
- テキスト、画像、ビデオ、オーディオなど複数の入力形式に対応
- ワイルドカードやS3 URIでの一括処理でバッチ操作が可能
- メタデータの付与やフィルタリングにも対応
では早速試してみます。
AWS CLIとs3vectors-embed-cliの比較
まず、AWS CLIでの操作がどれだけ大変かを確認し、s3vectors-embed-cliでどう改善されるかを見ていきます。
ベクトルの登録(Put)
AWS CLIの場合
AWS CLIのput-vectorsではベクトルデータをfloat32の配列として直接指定する必要があります。なので、テキストからベクトルを生成する処理は別途自分で行い、その結果のfloat32配列をJSONで渡さなければいけません。
# まずBedrock等でテキストをベクトル化する必要がある(別途実行)
# その後、生成されたベクトルをfloat32配列として渡す
$ aws s3vectors put-vectors \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--vectors '[
{
"key": "doc-1",
"data": {
"float32": [0.123, 0.456, 0.789, ..., 0.012]
},
"metadata": {
"category": "technology"
}
}
]'
ここで問題になるのは以下の点です。
- ベクトル化を自分で行う必要がある: テキストからfloat32配列を生成するために、Bedrock APIを別途呼び出すスクリプトを書く必要がある
- 生のfloat32配列を直接指定する: 数百次元のfloat32配列をCLIの引数に渡す必要があり、人間が扱うには非常に不便
- 複数ドキュメントを登録する場合: 各ドキュメントを個別にベクトル化してJSONを構築するスクリプトが必要
s3vectors-embed-cliの場合
s3vectors-embed-cliでは、テキストを渡すだけでBedrockによるベクトル化とS3 Vectorsへの保存が一つのコマンドで完了します。
# テキストを直接指定してベクトル化&保存
$ s3vectors-embed put \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--model-id amazon.titan-embed-text-v2:0 \
--text-value "Amazon S3 Vectorsはベクトルストレージサービスです"
テキストファイルからの登録やS3上のファイルの指定、ワイルドカードでの一括処理も可能です。
# ローカルのテキストファイルを指定
$ s3vectors-embed put \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--model-id amazon.titan-embed-text-v2:0 \
--text "./documents/sample.txt"
# ワイルドカードで複数ファイルを一括処理
$ s3vectors-embed put \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--model-id amazon.titan-embed-text-v2:0 \
--text "./documents/*.txt"
# S3上のファイルを指定(メタデータ付き)
$ s3vectors-embed put \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--model-id amazon.titan-embed-text-v2:0 \
--text "s3://my-data-bucket/documents/report.txt" \
--metadata '{"category": "technology", "version": "1.0"}'
ベクトルの検索(Query)
AWS CLIの場合
AWS CLIのquery-vectorsでは、検索クエリもfloat32配列として指定する必要があります。
# テキストで検索したい場合でも、事前にベクトル化してfloat32配列を生成する必要がある
$ aws s3vectors query-vectors \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--top-k 5 \
--query-vector '{"float32": [0.123, 0.456, 0.789, ..., 0.012]}' \
--return-metadata \
--return-distance
「このテキストに似たドキュメントを検索したい」という場合でも、検索テキストをまずベクトル化するスクリプトを別途用意し、その結果の数百次元のfloat32配列を--query-vectorに渡す必要があります。開発中にちょっとした確認をしたいだけでもこの手順が必要になるため、非常に手間がかかります。
s3vectors-embed-cliの場合
s3vectors-embed-cliでは、検索したいテキストをそのまま渡すだけで類似度検索が実行できます。
# テキストで直接クエリ
$ s3vectors-embed query \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--model-id amazon.titan-embed-text-v2:0 \
--text-value "ベクトルストレージ" \
--k 10 \
--return-metadata \
--return-distance
# メタデータフィルタ付きクエリ
$ s3vectors-embed query \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--model-id amazon.titan-embed-text-v2:0 \
--text-value "ベクトルストレージ" \
--filter '{"category": {"$eq": "technology"}}' \
--k 5 \
--return-metadata
# テーブル形式で出力
$ s3vectors-embed query \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--model-id amazon.titan-embed-text-v2:0 \
--text-value "ベクトルストレージ" \
--k 5 \
--output table
比較まとめ
AWS CLIとs3vectors-embed-cliの操作の違いをまとめると以下のようになります。
| 操作 | AWS CLI (s3vectors) |
s3vectors-embed-cli |
|---|---|---|
| ベクトルの登録 | 事前にベクトル化が必要。float32配列を直接指定 | テキストを渡すだけで自動ベクトル化&保存 |
| ベクトルの検索 | クエリもfloat32配列で指定が必要 | テキストを渡すだけで類似度検索 |
| 複数ファイルの一括処理 | スクリプトを自作する必要がある | ワイルドカードやS3 URIで一括処理可能 |
| 画像・ビデオの対応 | ベクトル化は完全に別処理 | --image、--videoオプションで直接対応 |
| メタデータ付与 | JSON形式で--vectorsに含める |
--metadataオプションで簡単に付与 |
| バッチ処理の最適化 | 自前で並列処理を実装 | --max-workersで並列ワーカー数を指定可能 |
s3vectors-embed-cliを使ってみる
環境
今回使用した環境は以下の通りです。
Python 3.12
s3vectors-embed-cli 0.1.0
前提条件として以下が必要です。
- AWS認証情報の設定
- Amazon Bedrockへのアクセス権(使用するモデルへのアクセスが有効化されていること)
- S3ベクトルバケットとインデックスが作成済みであること
インストール
pipでインストールします。
$ uv pip install s3vectors-embed-cli
S3 Vectorsの事前準備
s3vectors-embed-cliを使う前に、AWS CLIでベクトルバケットとインデックスを作成しておきます。
# ベクトルバケットの作成
$ aws s3vectors create-vector-bucket \
--vector-bucket-name {バケット名}
# ベクトルインデックスの作成(Titan Embed Text v2は1024次元)
$ aws s3vectors create-index \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--data-type float32 \
--dimension 1024 \
--distance-metric cosine
{
"indexArn": "arn:aws:s3vectors:ap-northeast-1:<account-id>:bucket/{}バケット名/index/{インデックス名}"
}
作成したインデックスはget-indexで確認できます。
$ aws s3vectors get-index \
--vector-bucket-name {バケット名} \
--index-name {インデックス名}
{
"index": {
"vectorBucketName": "{バケット名}",
"indexName": "{インデックス名}",
"indexArn": "arn:aws:s3vectors:ap-northeast-1:<account-id>:bucket/{}バケット名/index/{インデックス名}",
"creationTime": "2026-05-04T18:15:10+09:00",
"dataType": "float32",
"dimension": 1024,
"distanceMetric": "cosine",
"encryptionConfiguration": {
"sseType": "AES256"
}
}
}
テキストの登録
テキストを直接指定してベクトル化&保存します。
$ s3vectors-embed put \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--model-id amazon.titan-embed-text-v2:0 \
--text-value "Amazon S3 Vectorsはベクトルストレージサービスです" \
--key "doc-s3vectors"
{
"key": "doc-s3vectors",
"bucket": "{バケット名}",
"index": "{インデックス名}",
"model": "amazon.titan-embed-text-v2:0",
"contentType": "text",
"embeddingDimensions": 1024,
"metadata": {
"S3VECTORS-EMBED-SRC-CONTENT": "Amazon S3 Vectorsはベクトルストレージサービスです"
}
}
レスポンスのembeddingDimensionsがインデックス作成時のdimension(1024)と一致している点と、ソーステキストがS3VECTORS-EMBED-SRC-CONTENTメタデータとして自動保存される点が確認できます。--keyを省略するとUUIDが自動生成されます。ファイル名をキーにしたい場合は--filename-as-keyオプションが便利です。
複数ファイルの一括登録
ワイルドカードでローカルの複数テキストファイルを一括で登録できます。
$ s3vectors-embed put \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--model-id amazon.titan-embed-text-v2:0 \
--text "./documents/*.txt" \
--filename-as-key \
--metadata '{"source": "local-docs"}'
Starting streaming batch processing: ./documents/*.txt
Starting streaming processing of ./documents/*.txt
Processing chunk 1...
STORED BATCH: 3 vectors
Completed chunk 1: 3 processed, 0 failed
{
"type": "streaming_batch",
"bucket": "{バケット名}",
"index": "{インデックス名}",
"model": "amazon.titan-embed-text-v2:0",
"contentType": "text",
"totalFiles": 3,
"processedFiles": 3,
"failedFiles": 0,
"totalVectors": 3,
"vectorKeys": [
"sample3.txt",
"sample1.txt",
"sample2.txt"
]
}
ストリーミングバッチで処理が進み、最後に登録結果がJSONサマリで表示されます。複数ファイルの処理ではバッチプロセスで自動的にスループットが最適化されます。--max-workersオプションで並列ワーカー数(デフォルト: 4)、--batch-sizeオプションでバッチサイズ(デフォルト: 500)を調整することもできます。
類似度検索
テキストを渡すだけで類似度検索ができます。
$ s3vectors-embed query \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--model-id amazon.titan-embed-text-v2:0 \
--text-value "ベクトルデータベース" \
--k 5 \
--return-metadata \
--return-distance
{
"results": [
{
"Key": "sample1.txt",
"distance": 0.083915114402771,
"metadata": {
"S3VECTORS-EMBED-SRC-CONTENT": "ベクトルデータベースは大量のベクトルデータを高速に検索できるストレージシステムです。\nセマンティック検索やRAGの基盤として広く利用されています。\n",
"S3VECTORS-EMBED-SRC-LOCATION": "./documents/sample1.txt",
"source": "local-docs"
}
},
{
"Key": "doc-s3vectors",
"distance": 0.656830906867981,
"metadata": {
"S3VECTORS-EMBED-SRC-CONTENT": "Amazon S3 Vectorsはベクトルストレージサービスです"
}
},
{
"Key": "sample3.txt",
"distance": 0.726876974105835,
...
}
],
"summary": {
"queryType": "text",
"model": "amazon.titan-embed-text-v2:0",
"index": "{インデックス名}",
"resultsFound": 4,
"queryDimensions": 1024
}
}
distanceはcosine距離(小さいほど近い)です。クエリ「ベクトルデータベース」に最も近かったのはsample1.txt(0.084)で、これは「ベクトルデータベースは大量のベクトルデータを...」という内容のドキュメントです。意味的に近いものが上位に並んでいることが確認できます。
結果をテーブル形式で見やすく表示することもできます。
$ s3vectors-embed query \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--model-id amazon.titan-embed-text-v2:0 \
--text-value "ベクトルデータベース" \
--k 5 \
--output table
Query Results
┏━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Rank ┃ Vector Key ┃ Distance ┃ Metadata ┃
┡━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 1 │ sample1.txt │ N/A │ {"S3VECTORS-EMBED-SRC-CONTENT": "...", ... │
│ 2 │ doc-s3vectors │ N/A │ {"S3VECTORS-EMBED-SRC-CONTENT": "Amazon S3 │
│ 3 │ sample3.txt │ N/A │ {"S3VECTORS-EMBED-SRC-LOCATION": ...} │
│ 4 │ sample2.txt │ N/A │ {"S3VECTORS-EMBED-SRC-CONTENT": "RAG... │
└──────┴───────────────┴──────────┴────────────────────────────────────────────┘
Query Summary:
Model: amazon.titan-embed-text-v2:0
Results Found: 4
Query Dimensions: 1024
メタデータフィルタを使った検索
メタデータでフィルタリングして検索結果を絞り込むこともできます。例えば、ベクトル登録時にsourceというメタデータを付与しておいた場合、特定のソースに絞って検索することができます。
以下はGoogle Meetの文字起こしデータをソースとして登録しておき、「相談」というテキストで類似度検索を行う例です。
$ s3vectors-embed query \
--vector-bucket-name d01-ghost-vectors \
--index-name ghost-tenant-org-dcza72ilnmb32a3d \
--model-id amazon.titan-embed-text-v2:0 \
--text-value "相談" \
--filter '{"source": {"$eq": "google_meet_transcript"}}' \
--k 10 \
--return-metadata
--filterオプションにJSON形式でフィルタ条件を指定します。
実行例として、登録時に{"source": "local-docs"}メタデータを付けたドキュメントだけに絞って検索すると、doc-s3vectors(メタデータ未付与)が結果から除外されます。
$ s3vectors-embed query \
--vector-bucket-name {バケット名} \
--index-name {インデックス名} \
--model-id amazon.titan-embed-text-v2:0 \
--text-value "ベクトル" \
--filter '{"source": {"$eq": "local-docs"}}' \
--k 5 \
--return-metadata
{
"results": [
{
"Key": "sample1.txt",
"metadata": {
"source": "local-docs",
"S3VECTORS-EMBED-SRC-CONTENT": "ベクトルデータベースは大量のベクトルデータを高速に検索できるストレージシステムです。\nセマンティック検索やRAGの基盤として広く利用されています。\n",
"S3VECTORS-EMBED-SRC-LOCATION": "./documents/sample1.txt"
}
},
{
"Key": "sample3.txt",
"metadata": {
"S3VECTORS-EMBED-SRC-LOCATION": "./documents/sample3.txt",
"S3VECTORS-EMBED-SRC-CONTENT": "Amazon Titan Text Embeddings V2は1024次元の埋め込みベクトルを生成するモデルです。\n日本語にも対応しており、Bedrock経由でセマンティック検索やクラスタリングに活用できます。\n",
"source": "local-docs"
}
},
{
"Key": "sample2.txt",
"metadata": {
"S3VECTORS-EMBED-SRC-CONTENT": "RAG(Retrieval-Augmented Generation)は、検索とLLMによる生成を組み合わせた手法です。\n...",
"S3VECTORS-EMBED-SRC-LOCATION": "./documents/sample2.txt",
"source": "local-docs"
}
}
],
"summary": {
"queryType": "text",
"model": "amazon.titan-embed-text-v2:0",
"index": "{インデックス名}",
"resultsFound": 3,
"queryDimensions": 1024
}
}
resultsFound: 3となり、フィルタなしの4件からsourceメタデータが付いていないdoc-s3vectorsが除外されました。
$eq(等しい)の他に、$gte(以上)、$lte(以下)などの比較演算子や、$andで複数条件を組み合わせることもできます。
# 複数条件でフィルタ(AND)
$ s3vectors-embed query \
--vector-bucket-name d01-ghost-vectors \
--index-name ghost-tenant-org-dcza72ilnmb32a3d \
--model-id amazon.titan-embed-text-v2:0 \
--text-value "相談" \
--filter '{"$and": [{"source": {"$eq": "google_meet_transcript"}}, {"year": {"$gte": 2025}}]}' \
--k 10 \
--return-metadata
AWS CLIのquery-vectorsでもフィルタは使えますが、そもそもクエリベクトルをfloat32配列で渡す必要があるため、「ちょっとこのテキストで絞り込み検索してみよう」という気軽な操作はs3vectors-embed-cliならではの体験です。
サポートされる埋め込みモデル
s3vectors-embed-cliでは以下のBedrockモデルが利用できます。
| モデル | モデルID | 対応入力 |
|---|---|---|
| Amazon Titan Text Embeddings V2 | amazon.titan-embed-text-v2:0 |
テキスト |
| Amazon Titan Multimodal Embeddings | amazon.titan-embed-image-v1 |
テキスト、画像 |
| Cohere Embed English | cohere.embed-english-v3 |
テキスト |
| TwelveLabs Marengo | twelvelabs.marengo-embed-2-7-v1:0 |
テキスト、画像、ビデオ、オーディオ |
まとめ
Amazon S3 Vectorsの操作を簡単にするs3vectors-embed-cliを試してみました。
AWS CLIでは「テキスト → ベクトル化(Bedrock API呼び出し) → float32配列をJSONで構築 → put-vectors」という複数ステップが必要だった操作が、s3vectors-embed-cliでは「テキストを渡してputコマンドを実行」するだけで完了します。検索も同様に、テキストを渡すだけで類似度検索ができるため、開発中のちょっとした確認やデバッグが格段に楽になります。
特に複数ファイルのワイルドカード一括処理やバッチ処理の最適化など、AWS CLIでは自前のスクリプトが必要だった部分もCLIのオプションだけで対応できるのが便利です。
S3 Vectorsを使った開発をされている方は、ぜひ導入を検討してみてください。
最後まで読んで頂いてありがとうございました。




