View a markdown version of this page

チュートリアル: 初めてのベクトル検索 - Amazon DynamoDB

チュートリアル: 初めてのベクトル検索

正確なキーワードを照合するのではなく、買い物客が自分の言葉で必要なものを説明できる製品カタログを想像してみてください。各製品説明のベクトル埋め込みを DynamoDB に保存し、ベクトルインデックスをクエリして最も近い一致を見つけることができます。

このチュートリアルでは、ベクトルインデックスを持つテーブルを作成し、Amazon Bedrock Titan Text Embeddings V2 を使用して 1024 次元の埋め込みを生成し、50 個の製品をロードして、類似度の高い上位 5 件を返す類似度検索を実行します。すべてのコマンドは、ターミナルに直接貼り付けることができます。DynamoDB での埋め込みの仕組みに関する背景情報については、「ベクトル埋め込みの生成」を参照してください。

スケールと再現率について

本番環境のベクトルインデックスは、数百万から数十億個のベクトルを保持します。ベクトルインデックスは近似最近傍検索を使用し、そのアプローチの再現率特性は、はるかに大きな規模でのみ観測可能になります。ここでは、50 項目のカタログをメカニズムのデモンストレーションとして扱います。サイズ設定と調整のガイダンスについては、「ベクトルインデックスのベストプラクティス」を参照してください。

前提条件

作業を開始する前に、次の項目があることを確認します。

  • AWS CLI バージョン 2.36.16 以降 2026 年 8 月 4 日にリリースされたサービスモデルの更新で、ベクトルインデックスのサポートが AWS CLI および AWS SDK に追加されました。以前のバージョンでは、--vector-indexes パラメータまたは search-vectors コマンドは認識されません。aws --version でバージョンを確認し、必要に応じてアップグレードします。AWS CLI の代わりに AWS SDK を使用する場合は、botocore 1.43.64 以降、または使用する言語の SDK の同等のリリースが必要です。

  • DynamoDB の CreateTableDescribeTablePutItemBatchWriteItemScanSearchVectorsUpdateTable、および DeleteTable アクションと、Amazon Bedrock の InvokeModel アクションを実行するアクセス許可を持つ認証情報。dynamodb:SearchVectors は新しいアクションであるため、DynamoDB への読み取りアクセスを許可する既存のポリシーには含まれません。

  • お客様のアカウントおよびリージョンにおいて、Amazon Bedrock の Titan Text Embeddings V2 モデルへのアクセスが有効になっています。Amazon Bedrock のモデルへのアクセスはアカウントおよびリージョンごとに付与されるため、モデルを呼び出す前に有効にする必要があります。

  • モデルの出力を DynamoDB 形式に整形するために jq をインストールしました。

  • DynamoDB ベクトルインデックスと Amazon Bedrock Titan Text Embeddings V2 の両方が利用可能なリージョン。Amazon Bedrock モデルの可用性はリージョンによって異なり、一般的に DynamoDB のリージョンカバレッジよりも狭いため、リージョンを選択する前に両方を確認してください。Amazon Bedrock のモデルの可用性については、「Amazon Bedrock ユーザーガイド」の、「AWS リージョン別のモデルサポート」を参照してください。

料金

このチュートリアルでは、Amazon Bedrock のモデル呼び出しと DynamoDB ストレージの料金が発生します。短い単一文入力に対して、それぞれが Amazon Bedrock 推論リクエストとして請求される 51 の埋め込み呼び出しを行います。DynamoDB ストレージ料金は、テーブルとベクトルインデックスが存在する限り適用されます。

使用しているリージョンを確認する

このチュートリアルのすべてのコマンドは、同じリージョンで実行する必要があります。AWS_REGIONAWS_DEFAULT_REGION よりも優先され、どちらも AWS CLI 設定ファイルの region 設定よりも優先されるため、起動前に AWS CLI が実際に使用するリージョンを確認します。シェルで意図しない AWS_REGION 値が設定されていると、意図したリージョン以外の場所にテーブルが作成され、Amazon Bedrock モデルが有効になっていない可能性があります。疑問をすべて解消するには、各コマンドで --region region を明示的に渡します。

SearchVectors は別のエンドポイントを使用します

SearchVectors は、標準の DynamoDB エンドポイントではなく、専用の検索エンドポイントに解決されます。商用リージョンでは、リクエストは search-dynamodb.region.amazonaws.com に送信され、このチュートリアルの他のすべてのオペレーションは dynamodb.region.amazonaws.com に送信されます。FIPS とデュアルスタックのバリアントも、同じパターンに従います。これには 2 つの影響があります。

  • ネットワークが VPC エンドポイント、プロキシ、または出力許可リストを介してアウトバウンドトラフィックを制限する場合は、検索ホスト名も許可する必要があります。そうでない場合、CreateTable や書き込みオペレーションは成功し、SearchVectors のみが失敗します。通常は、原因が特定できない接続エラーが発生します。

  • --endpoint-url を使用して、これらのコマンドの DynamoDB エンドポイントを上書きしないでください。単一のオーバーライドでは両方のホスト名を処理することはできず、検索ルーティングが中断されます。

  1. ベクトルインデックスを持つテーブルを作成します。これにより、DescriptionVector 属性に DescriptionIndex という名前のベクトルインデックスを持つ Products テーブルが作成されます。このインデックスは、Titan Text Embeddings V2 の出力と整合させるため、1024 次元の COSINE 距離関数を使用しています。ベクトルインデックスのパーティションキーが定義されていないため、検索に SearchConditionExpression は必要ありません。

    aws dynamodb create-table \ --table-name Products \ --attribute-definitions AttributeName=ProductId,AttributeType=S \ --key-schema AttributeName=ProductId,KeyType=HASH \ --billing-mode PAY_PER_REQUEST \ --vector-indexes \ "[ { \"IndexName\": \"DescriptionIndex\", \"VectorAttribute\": {\"AttributeName\": \"DescriptionVector\"}, \"Projection\": {\"ProjectionType\": \"ALL\"}, \"Dimensions\": 1024, \"DistanceFunction\": \"COSINE\" } ]"

    この例では、検索結果ですべての属性が使用できるように、ProjectionTypeALL を使用しています。代わりに INCLUDE を使用する場合は、射影された非キー属性の上限が共有されることに注意してください。ベクトル属性は 1 つの属性としてカウントされ、各 INLINE_FILTER 検索スキーマ要素は 1 つの属性としてカウントされます。HASH 検索スキーマ要素は制限にカウントされません。

  2. インデックスがアクティブになるまで待ちます。IndexStatusACTIVE になるまでこれを実行します。

    aws dynamodb describe-table \ --table-name Products \ --query 'Table.VectorIndexes[0].[IndexName,IndexStatus,Backfilling]'

    このチュートリアルのように CreateTable の一部として作成されたインデックスの場合、Backfilling は報告されず、コマンドはそのインデックスに対して null を返します。この場合、シグナルとして IndexStatus 単独で使用してください。

    UpdateTable を使用して既存のテーブルに追加するベクトルインデックスについて、Backfilling が報告されます。この場合、完全な検索結果を信頼する前に、IndexStatusACTIVE になり、Backfillingfalse になるまで待ちます。

    テーブルだけでなくインデックスを待機する

    aws dynamodb wait table-exists を検索の実行条件として使用しないでください。そのウェーターは Table.TableStatus に基づいてマッチングを行い、ベクトルインデックスがまだ CREATING であっても ACTIVE になります。ベクトルインデックスの準備状況のウェーターがないため、次に示すように DescribeTable をポーリングする必要があります。まだ ACTIVE になっていないインデックスを検索すると失敗し、バックフィル中に検索すると不完全な結果が返される可能性があります。

    同じ理由で、すべてのベクトルインデックスの作成が完了するまでテーブルを削除することはできません。DeleteTable は、「インデックスの作成、更新、削除中にテーブルを削除することはできません」というメッセージとともに ResourceInUseException を返します。

  3. 製品カタログを作成します。次の 50 個の製品を products.tsv という名前のタブ区切りファイルに保存します。各行には、製品 ID、名前、および 1 文の説明が含まれます。カタログには、5 つの関連製品からなる 10 個のグループが含まれており、最終段階での検索結果を簡単に解釈できます。

    p01 Insulated Travel Mug A vacuum insulated stainless steel mug that keeps hot drinks warm for up to twelve hours. p02 Stovetop Espresso Maker A compact aluminum pot that brews strong espresso style coffee directly on a gas or electric burner. p03 Manual Burr Coffee Grinder A hand cranked grinder with adjustable ceramic burrs for consistent coffee grounds. p04 Pour Over Coffee Dripper A ceramic cone that sits on a mug and brews a single cup of filter coffee. p05 Electric Milk Frother A handheld battery powered whisk that creates dense foam for lattes and cappuccinos. p06 Lightweight Running Shoe A breathable mesh road shoe with cushioned foam midsole for daily training runs. p07 Trail Running Shoe An aggressive lugged outsole shoe built for grip on loose gravel and muddy trails. p08 Moisture Wicking Running Socks Ankle height socks knitted from synthetic yarn that pulls sweat away from the skin. p09 Reflective Running Vest A lightweight vest with high visibility strips for running safely after dark. p10 Hydration Waist Belt An elastic belt that holds two small water flasks and a phone during long runs. p11 Ergonomic Mesh Office Chair An adjustable desk chair with breathable mesh back and lumbar support for long work sessions. p12 Sit Stand Desk Converter A height adjustable platform that raises a monitor and keyboard for standing work. p13 Monitor Arm Mount A clamp mounted articulating arm that lifts a display off the desk surface. p14 Under Desk Footrest An angled cushioned platform that supports the feet and improves seated posture. p15 Wireless Split Keyboard A two piece keyboard that separates for a natural shoulder width typing position. p16 Noise Cancelling Headphones Over ear wireless headphones that actively silence engine noise on long flights. p17 Wireless Earbuds Compact in ear buds with a charging case and multi hour battery for commuting. p18 Portable Bluetooth Speaker A water resistant rechargeable speaker sized to fit in a backpack side pocket. p19 Studio Monitor Headphones Wired closed back headphones with flat frequency response for audio mixing. p20 Wired Lapel Microphone A small clip on microphone for recording clear speech during interviews. p21 Four Season Backpacking Tent A double wall tent with an aluminum pole set rated for wind and heavy rain. p22 Down Sleeping Bag A mummy shaped bag filled with compressible down insulation for cold weather camping. p23 Inflatable Sleeping Pad A lightweight pad that inflates in a few breaths and packs down to bottle size. p24 Canister Camping Stove A screw on burner that boils water quickly using a compact fuel canister. p25 Rechargeable Camp Lantern A collapsible lantern with adjustable brightness and a built in battery. p26 Cast Iron Skillet A preseasoned heavy pan that holds heat evenly for searing and oven baking. p27 Nonstick Frying Pan A coated aluminum pan that releases eggs and fish without added oil. p28 Stainless Steel Stock Pot A tall wide pot for boiling pasta and simmering large batches of soup. p29 Enameled Dutch Oven A heavy lidded pot that moves from stovetop to oven for slow braising. p30 Bamboo Cutting Board A large reversible board with a juice groove around the edge. p31 Padded Laptop Backpack A water resistant pack with a suspended sleeve that protects a fifteen inch laptop. p32 Slim Laptop Sleeve A close fitting neoprene case that shields a notebook inside a larger bag. p33 Rolling Carry On Suitcase A hard shell four wheel case sized to fit most overhead cabin bins. p34 Packing Cube Set Zippered fabric cubes that compress clothing and organize a suitcase. p35 Leather Messenger Bag A single strap shoulder bag with a padded compartment and interior pockets. p36 Daily Facial Moisturizer A light lotion with humectants that hydrates skin without leaving residue. p37 Mineral Sunscreen Lotion A broad spectrum zinc based sunscreen formulated for sensitive facial skin. p38 Gentle Foaming Cleanser A low pH face wash that removes oil and sunscreen without stripping the skin. p39 Vitamin C Serum A brightening serum applied before moisturizer to even skin tone over time. p40 Overnight Repair Cream A rich night cream with ceramides that restores the skin barrier while sleeping. p41 Stainless Steel Dog Bowl A weighted nonslip bowl that resists tipping during enthusiastic feeding. p42 Padded Dog Harness An adjustable chest harness that distributes pull away from the neck on walks. p43 Retractable Dog Leash A spring loaded leash that extends and locks at several walking lengths. p44 Interactive Cat Puzzle Feeder A slow feed tray that makes a cat work for dry food and eat more slowly. p45 Self Cleaning Litter Box An enclosed box with a raking mechanism that sifts waste after each use. p46 Bypass Pruning Shears Sharp hardened blades that make clean cuts on green stems and small branches. p47 Long Handled Garden Spade A steel bladed spade with a wooden shaft for turning soil and digging beds. p48 Adjustable Hose Spray Nozzle A metal nozzle that shifts from a fine mist to a strong jet stream. p49 Raised Garden Bed Kit Interlocking cedar panels that assemble into an elevated planting box. p50 Drip Irrigation Starter Kit Tubing and emitters that deliver water slowly to the base of each plant.

    3 つのフィールド間の区切り文字はリテラルのタブ文字である必要があります。ブラウザからカタログをコピーする場合は、続行する前にタブが保持されていることを確認してください。

  4. 1 つの製品の埋め込みを生成します。最初に、埋め込み呼び出しを 1 回実行して、Amazon Bedrock モデルへのアクセスが機能することを確認します。inputText フィールドには埋め込むテキストが含まれ、dimensions には出力サイズ (有効な値は 256、512、または 1024) を設定します。normalize は単位長ベクトルを生成しますが、これはコサイン類似度検索に推奨されます。

    mkdir -p emb aws bedrock-runtime invoke-model \ --model-id amazon.titan-embed-text-v2:0 \ --body '{"inputText":"A vacuum insulated stainless steel mug that keeps hot drinks warm for up to twelve hours.","dimensions":1024,"normalize":true}' \ --cli-binary-format raw-in-base64-out \ --content-type application/json \ --accept application/json \ emb/p01.json

    --cli-binary-format raw-in-base64-out フラグは必須です。AWS CLI v2 はバイナリパラメータの base64 エンコーディングをデフォルトとしているため、このフラグがないと raw JSON 本文が正しく送信されません。レスポンスは emb/p01.json に書き込まれ、1024 個の浮動小数点数の embedding 配列が含まれます。ディメンション数を確認します。

    jq '.embedding | length' emb/p01.json

    この出力は 1024 です。

  5. 最初の製品を書き込みます。埋め込みを DynamoDB 項目形式に変換して書き込みます。保存されたベクトル属性は、DynamoDB L (リスト) 型を使用して、各数値を N 型でラップします。

    jq '{"ProductId":{"S":"p01"},"Title":{"S":"Insulated Travel Mug"},"DescriptionVector":{"L":[.embedding[]|{"N":(.|tostring)}]}}' emb/p01.json > item-p01.json aws dynamodb put-item --table-name Products --item file://item-p01.json
    ベクトルサイズと項目の制限

    1024 次元ベクトルは、リクエストペイロードに約 32 KB、保存される項目に約 5 KB を追加しますが、これは DynamoDB 項目のサイズ制限である 400 KB の範囲内です。ディメンション数は、埋め込みを保存するときの項目サイズの主な要因です。

  6. 残りの製品を埋め込みます。このループは、残りの各製品について埋め込みを生成します。既存のファイルはスキップされるため、呼び出しが失敗した場合でも安全に再実行できます。

    while IFS=$'\t' read -r id title description; do [ -s "emb/$id.json" ] && continue body=$(jq -n --arg t "$description" '{inputText:$t,dimensions:1024,normalize:true}') aws bedrock-runtime invoke-model \ --model-id amazon.titan-embed-text-v2:0 \ --body "$body" \ --cli-binary-format raw-in-base64-out \ --content-type application/json \ --accept application/json \ "emb/$id.json" >/dev/null || echo "FAILED $id" done < products.tsv ls emb/*.json | wc -l

    続行する前に、カウントが 50 になっている必要があります。いずれかの呼び出しが FAILED を出力した場合は、ループを再度実行します。欠落しているファイルのみが再試行されます。

    InvokeModel レートクォータ

    Amazon Bedrock は、InvokeModel に対してリクエストレートクォータを適用します。このループを変更して呼び出しを並行して発行する場合は、一部の呼び出しでスロットリング例外が発生することを想定し、すべての呼び出しが成功したと仮定するのではなく、常に最終的なファイル数を確認してください。部分的に埋め込まれたカタログはエラーなしでロードされ、欠落している製品をサイレントに省略した検索結果を生成します。

  7. 残りの製品をロードします。BatchWriteItem が受け入れる最大値である 25 項目ずつのリクエストペイロードを作成します。

    batch=0 count=0 echo -n '{"Products":[' > batch-0.json while IFS=$'\t' read -r id title description; do if [ "$count" -eq 25 ]; then echo ']}' >> "batch-$batch.json" batch=$((batch+1)); count=0 echo -n '{"Products":[' > "batch-$batch.json" fi [ "$count" -gt 0 ] && echo -n ',' >> "batch-$batch.json" jq -c --arg id "$id" --arg title "$title" \ '{PutRequest:{Item:{ProductId:{S:$id},Title:{S:$title}, DescriptionVector:{L:[.embedding[]|{"N":(.|tostring)}]}}}}' \ "emb/$id.json" >> "batch-$batch.json" count=$((count+1)) done < <(tail -n +2 products.tsv) echo ']}' >> "batch-$batch.json"

    パイプされた while ループが一部のシェルのサブシェルで実行され、batch および count の値が破棄されて不正な形式のバッチファイルが生成されるため、ループはパイプではなくリダイレクトから読み取ります。

    各バッチを送信します。BatchWriteItem は部分的に成功する場合があるため、UnprocessedItems で返されたものを再送信します。

    for f in batch-*.json; do cp "$f" pending.json for attempt in 1 2 3 4 5; do aws dynamodb batch-write-item \ --request-items file://pending.json \ --output json > resp.json left=$(jq '(.UnprocessedItems.Products // []) | length' resp.json) echo "$f attempt $attempt: unprocessed=$left" [ "$left" -eq 0 ] && break jq '.UnprocessedItems' resp.json > pending.json sleep 2 done done

    50 項目すべてが存在することを確認します。

    aws dynamodb scan --table-name Products --select COUNT --query 'Count'
    ItemCount の更新が遅延する

    DescribeTable がベクトルインデックスについて報告する ItemCount および IndexSizeBytes の値は、約 6 時間ごとに更新されるため、すべての項目が書き込まれた場合でも、ロード直後は 0 と読み取られることがあります。次に示すように、--select COUNT を指定して Scan を使用して、ロードを検証します。ItemCount がゼロであっても、失敗したロードとして処理しないでください。

  8. クエリの埋め込みを生成して検索します。保存された項目に使用したのと同じモデルとディメンション数で検索フレーズを埋め込みます。

    aws bedrock-runtime invoke-model \ --model-id amazon.titan-embed-text-v2:0 \ --body '{"inputText":"How can I make my desk more comfortable to work at","dimensions":1024,"normalize":true}' \ --cli-binary-format raw-in-base64-out \ --content-type application/json \ --accept application/json \ embedding-query.json
    SearchVector 形式が保存されたベクトル形式と異なる

    ベクトルを項目属性に保存するときは、L (リスト) 型でラップします (例: {"L":[{"N":"0.123"},...]})。クエリベクトルを SearchVectors に渡すときは、L ラッパーなしで N 値のプレーン配列を使用します (例: [{"N":"0.123"},...])。この理由により、次の jq 変換は、保存された項目に使用した変換とは異なります。詳細については、「基本的な検索」を参照してください。

    jq '[.embedding[]|{"N":(.|tostring)}]' embedding-query.json > query-vector.json aws dynamodb search-vectors \ --table-name Products \ --index-name DescriptionIndex \ --search-vector file://query-vector.json \ --top-k 5 \ --projection-expression "ProductId, Title" \ --return-consumed-capacity TOTAL

    クエリベクトルと保存されたベクトルは、同じ埋め込みモデルから取得され、同じ数のディメンションを持つ必要があります。異なるモデルまたはディメンション数を使用すると、意味のない結果または検証エラーが発生します。

  9. 結果を読み取ります。DynamoDB は、類似度でソートされた結果を返します。最も類似度の高い項目が先頭に表示されます。各結果には、射影された Item 属性と Score が含まれます。

    { "SearchResults": [ { "Item": { "ProductId": { "S": "p11" }, "Title": { "S": "Ergonomic Mesh Office Chair" } }, "Score": 0.6130197048187256 }, { "Item": { "ProductId": { "S": "p12" }, "Title": { "S": "Sit Stand Desk Converter" } }, "Score": 0.781868577003479 }, { "Item": { "ProductId": { "S": "p14" }, "Title": { "S": "Under Desk Footrest" } }, "Score": 0.816369354724884 }, { "Item": { "ProductId": { "S": "p13" }, "Title": { "S": "Monitor Arm Mount" } }, "Score": 0.8283305168151855 }, { "Item": { "ProductId": { "S": "p15" }, "Title": { "S": "Wireless Split Keyboard" } }, "Score": 0.8469693064689636 } ], "ConsumedCapacity": { "VectorSearchRequestBytes": 31449.0 } }

    スコアは埋め込みモデルと正確な入力テキストに依存するため、値はわずかに異なります。重要なのは、どの項目がどの順序で選択されたかです。クエリには、椅子、モニター、キーボードという単語が含まれていませんでしたが、検索では、カタログ内の他の 45 項目よりも先に、デスクおよびオフィス関連製品 5 件がすべて返されました。コーヒー、キャンプ、ペットグループからは何も表示されません。

    他のクエリを試して、異なるグループでも同様の動作になるか確認します。"Something to brew fresh coffee at home" という条件で同様の手順を繰り返します。上位の結果はエスプレッソメーカー、プアオーバードリッパー、ミルクフローサーです。"Keeping my dog safe on walks" で同様に行うと、リードとハーネスが最初に来て、その後に関連性があまり高くない項目が続きます。カタログには、ほぼ一致する製品が 2 つしか含まれていないためです。最後のケースは注目に値します。カタログに条件に合う項目がそれほど多く含まれていない場合でも、検索は常にリクエストした数だけの項目を返します。一致の質を判断するには、結果の数ではなく Score 値を使用します。

    スコアの読み方は、インデックスが使用する距離関数によって異なります。

    • COSINEEUCLIDEAN はスコアが最も小さい項目を返すため、低いほど似ています。コサインスコアは、同一方向の場合の 0 から、反対方向の場合の 2 までの範囲をとります。

    • DOT_PRODUCT はスコアが最も高い項目を返すため、高いほど似ています。

    このインデックスは COSINE を使用するため、最初の結果のスコアが最も低くなります。保存された説明と同一のテキストで検索すると、最初にその項目が返され、スコアはゼロまたはゼロに近い値になります。

クリーンアップ

このチュートリアルで作成したリソースは、継続的な料金の発生を回避するために削除してください。ベクトルインデックスのストレージは、検索を実行するかどうかにかかわらず、インデックスが存在する限り課金されます。

ベクトルインデックスを削除し、Products テーブルとその項目を保持するには、UpdateTable を使用します。項目はテーブルに残り、インデックスのみが削除されます。

aws dynamodb update-table \ --table-name Products \ --vector-index-updates \ "[ {\"Delete\": {\"IndexName\": \"DescriptionIndex\"}} ]"

テーブルとそのベクトルインデックスを一緒に削除するには、テーブルを削除します。

aws dynamodb delete-table --table-name Products

テーブルがなくなったことを確認します。次のコマンドは、削除が完了すると ResourceNotFoundException を返します。

aws dynamodb describe-table --table-name Products

保持するテーブルからベクトルインデックスを削除する方法の詳細については、「ベクトルインデックスの削除」を参照してください。

次のステップ

この基本的なベクトル検索が完了したら、これらの関連トピックを確認してください。