View a markdown version of this page

Tutorial: La primera búsqueda vectorial - Amazon DynamoDB

Tutorial: La primera búsqueda vectorial

Imagine un catálogo de productos en el que los compradores describen lo que quieren con sus propias palabras en lugar de hacer coincidir las palabras clave exactas. Puede almacenar una incrustación vectorial de cada descripción de producto en DynamoDB y, a continuación, consultar un índice vectorial para encontrar las coincidencias más cercanas.

En este tutorial, se crea una tabla con un índice vectorial, se generan incrustaciones de 1024 dimensiones con Amazon Bedrock Titan Text Embeddings V2, se cargan 50 productos y se ejecuta una búsqueda de similitudes que devuelve las 5 coincidencias más cercanas. Cada comando se puede pegar directamente en un terminal. Para obtener información sobre cómo funcionan las incrustaciones con DynamoDB, consulte Generación de incrustaciones vectoriales.

Acerca de la escala y la recuperación

Un índice vectorial de producción contiene de millones a miles de millones de vectores. Los índices vectoriales utilizan una búsqueda aproximada del vecino más cercano y las características de recuperación de ese enfoque solo se pueden observar a una escala mucho mayor. Considere el catálogo de 50 artículos que aparece aquí como una demostración de la mecánica. Para obtener información sobre el tamaño y el ajuste, consulte Prácticas recomendadas para índices vectoriales.

Requisitos previos

Antes de empezar, asegúrese de que tiene lo siguiente:

  • AWS CLI versión 2.36.16 o posterior. La compatibilidad con índices vectoriales se agregó a AWS CLI y AWS SDK en la actualización del modelo de servicio publicada el 4 de agosto de 2026. Las versiones anteriores no reconocen el parámetro --vector-indexes ni el comando search-vectors. Compruebe su versión con aws --version y actualícela si es necesario. Si utiliza un AWS SDK en lugar de la AWS CLI, necesitará la versión botocore 1.43.64 o posterior, o la versión equivalente del SDK del idioma.

  • Credenciales con permisos para las acciones de DynamoDB CreateTable, DescribeTable, PutItem, BatchWriteItem, Scan, SearchVectors, UpdateTable y DeleteTable, y para la acción de Amazon Bedrock InvokeModel. dynamodb:SearchVectors es una acción nueva, por lo que las políticas existentes que conceden acceso de lectura a DynamoDB no la incluyen.

  • Acceso al modelo Titan Text Embeddings V2 habilitado en Amazon Bedrock para la cuenta y región. El acceso al modelo de Amazon Bedrock se concede por cuenta y por región, por lo que debe habilitar el modelo antes de poder llamarlo.

  • Se ha instalado jq para cambiar la forma de la salida del modelo al formato DynamoDB.

  • Una región en la que están disponibles los índices vectoriales de DynamoDB y Amazon Bedrock Titan Text Embeddings V2. La disponibilidad del modelo de Amazon Bedrock varía según la región y, por lo general, es más limitada que la cobertura regional de DynamoDB, por lo que debe confirmar ambas opciones antes de elegir una región. Para obtener la disponibilidad del modelo de Amazon Bedrock, consulte Compatibilidad del modelo de la región de AWS en la Guía del usuario de Amazon Bedrock.

Cargos

Este tutorial conlleva cargos por las invocaciones del modelo de Amazon Bedrock y el almacenamiento de DynamoDB. Realiza 51 llamadas de incrustación, cada una facturada como una solicitud de inferencia de Amazon Bedrock, en entradas cortas de una sola frase. Los cargos de almacenamiento de DynamoDB se aplican mientras existan la tabla y el índice vectorial.

Confirmación de qué región se está utilizando

Todos los comandos de este tutorial se deben ejecutar en la misma región. Confirme la región que la AWS CLI utilizará realmente antes de empezar, ya que AWS_REGION tiene prioridad sobre AWS_DEFAULT_REGION y ambas tienen prioridad sobre la configuración de region en el archivo de configuración de AWS CLI. Un valor de AWS_REGION disperso en el intérprete de comandos crea la tabla en un lugar distinto de la región que pretendía, y es posible que el modelo de Amazon Bedrock no esté habilitado allí. Para eliminar cualquier duda, pase --region region de forma explícita en cada comando.

SearchVectors utiliza un punto de conexión independiente

SearchVectors se resuelve en un punto de conexión de búsqueda dedicado en lugar del punto de conexión estándar de DynamoDB. En una región comercial, las solicitudes van a search-dynamodb.region.amazonaws.com, mientras que todas las demás operaciones de este tutorial van a dynamodb.region.amazonaws.com. Las variantes de FIPS y de doble pila siguen el mismo patrón. Esto tiene dos consecuencias:

  • Si la red restringe el tráfico saliente a través de un punto de conexión de VPC, un proxy o una lista de permisos de salida, también debe permitir el nombre de host de búsqueda. De lo contrario, CreateTable y las operaciones de escritura se realizan correctamente y solo SearchVectors produce un error, normalmente con un error de conexión que no indica la causa.

  • No utilice --endpoint-url para invalidar el punto de conexión de DynamoDB para estos comandos. Una sola invalidación no puede servir para ambos nombres de host e interrumpirá el enrutamiento de búsqueda.

  1. Cree una tabla con un índice vectorial. Esto crea una tabla de Products con un índice vectorial denominado DescriptionIndex en el atributo DescriptionVector. El índice utiliza la función de distancia COSINE con 1024 dimensiones para que coincida con la salida de Titan Text Embeddings V2. Como no hay definida ninguna clave de partición de índice vectorial, no es necesaria una SearchConditionExpression para realizar la búsqueda.

    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\" } ]"

    En este ejemplo, se utiliza ProjectionType de ALL para que todos los atributos estén disponibles en los resultados de la búsqueda. Si utiliza INCLUDE en su lugar, tenga en cuenta que el presupuesto de atributos sin clave proyectado es compartido: el atributo vectorial cuenta como un atributo y cada elemento del esquema de búsqueda INLINE_FILTER cuenta como uno. Los elementos del esquema de búsqueda HASH no cuentan para el límite.

  2. Espere a que el índice pase a estar activo. Ejecute esto hasta que IndexStatus esté ACTIVE.

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

    Para un índice creado como parte de CreateTable, como en este tutorial, no se informa de Backfilling y el comando devuelve null para él. Use IndexStatus solo como señal en ese caso.

    Se informa de Backfilling para un índice vectorial que se agrega a una tabla existente con UpdateTable. En ese caso, espere a que IndexStatus sea ACTIVE y Backfilling sea false antes de confiar en los resultados de búsqueda completos.

    Espere al índice, no solo a la tabla

    No utilice aws dynamodb wait table-exists para impedir la búsqueda. Ese mecanismo de espera coincide con Table.TableStatus, que pasa a ser ACTIVE mientras que el índice vectorial aún puede ser CREATING. No hay ningún mecanismo de espera para la disponibilidad del índice vectorial, por lo que debe sondear DescribeTable tal y como se muestra. La búsqueda de un índice que aún no esté ACTIVE genera un error y la búsqueda durante el proceso de rellenado puede arrojar resultados incompletos.

    Por la misma razón, no puede eliminar la tabla hasta que se hayan terminado de crear todos los índices vectoriales. DeleteTable devuelve ResourceInUseException con el mensaje “No se puede eliminar la tabla mientras se crean, actualizan o eliminan los índices”.

  3. Cree el catálogo de productos. Guarde los siguientes 50 productos en un archivo separado por tabuladores llamado products.tsv. Cada línea contiene un ID de producto, un nombre y una descripción de una frase. El catálogo contiene diez grupos de cinco productos relacionados, lo que facilita la interpretación de los resultados de la búsqueda en el último paso.

    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.

    El separador entre los tres campos debe ser un carácter de tabulador literal. Si copia el catálogo desde un navegador, compruebe que las tabulaciones se han conservado antes de continuar.

  4. Genere una incrustación para un producto. Primero, realice una única llamada de incrustación para confirmar que el acceso al modelo de Amazon Bedrock funciona correctamente. El campo inputText contiene el texto que se va a incrustar, dimensions establece el tamaño de salida (los valores válidos son 256, 512 o 1024) y normalize produce vectores de longitud unitaria, lo que se recomienda para la búsqueda de similitud de coseno.

    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

    El indicador --cli-binary-format raw-in-base64-out es obligatorio. La versión 2 de la AWS CLI utiliza de forma predeterminada la codificación base64 para los parámetros binarios, por lo que, sin este indicador, el cuerpo del JSON sin procesar no se envía correctamente. La respuesta se escribe en emb/p01.json y contiene una matriz de embedding de 1024 números de punto flotante. Confirme el recuento de dimensiones.

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

    El resultado será 1024.

  5. Escriba el primer producto. Transforme la incrustación al formato de elemento de DynamoDB y escríbala. El atributo vectorial almacenado utiliza el tipo L de DynamoDB (lista) que envuelve cada número en un tipo 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
    Tamaño del vector y límites de elementos

    Un vector de 1024 dimensiones agrega aproximadamente 32 KB a la carga útil de la solicitud y unos 5 KB al elemento almacenado, dentro del límite de tamaño del elemento de DynamoDB de 400 KB. El número de dimensiones es el principal factor que determina el tamaño de los elementos cuando se almacenan incrustaciones.

  6. Incruste el resto de los productos. Este bucle genera una incrustación para cada producto restante. Omite cualquier archivo que ya exista, por lo que puede volver a ejecutarlo de forma segura si se produce un error en una llamada.

    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

    El recuento debe ser de 50 antes de continuar. Si alguna llamada imprime FAILED, vuelva a ejecutar el bucle; solo volverá a intentar los archivos que faltan.

    Cuotas de tarifas de InvokeModel

    Amazon Bedrock aplica cuotas de tarifas de solicitud a InvokeModel. Si modifica este bucle para emitir llamadas en paralelo, espere excepciones de limitación en algunas llamadas y compruebe siempre el recuento final de archivos en lugar de suponer que todas las llamadas se realizaron correctamente. Un catálogo parcialmente incrustado se carga sin errores y produce resultados de búsqueda que omiten silenciosamente los productos que faltan.

  7. Cargue los productos restantes. Cree cargas útiles de solicitudes de 25 elementos cada una, que es el máximo que acepta BatchWriteItem.

    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"

    El bucle se lee desde una redirección y no desde una canalización, ya que, en algunos intérpretes de comandos, un bucle while canalizado se ejecuta en un subshell, lo que descarta los valores batch y count y produce archivos por lotes con un formato incorrecto.

    Envíe cada lote. BatchWriteItem puede funcionar parcialmente, así que vuelva a enviar todo lo que devuelva en 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

    Confirme que los 50 elementos estén presentes.

    aws dynamodb scan --table-name Products --select COUNT --query 'Count'
    Las actualizaciones de ItemCount están retrasadas

    Los valores ItemCount y IndexSizeBytes de los que DescribeTable informa para un índice vectorial se actualizan aproximadamente cada seis horas, por lo que, inmediatamente después de cargarlos, se pueden leer 0 aunque se hayan escrito todos los elementos. Utilice Scan con --select COUNT, como se muestra, para verificar una carga. No trate un cero ItemCount como una carga errónea.

  8. Genere una incrustación de consulta y realice una búsqueda. Inserte la frase de búsqueda con el mismo modelo y número de dimensiones que utilizó para los elementos almacenados.

    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
    El formato de SearchVector es diferente del formato de vector almacenado

    Cuando almacena un vector en un atributo de elemento, lo envuelve en un tipo L (lista): {"L":[{"N":"0.123"},...]}. Cuando pasa un vector de consulta a SearchVectors, utilice una matriz simple de valores N sin el envoltorio L: [{"N":"0.123"},...]. Por este motivo, la transformación de jq siguiente es diferente a la utilizada para los elementos almacenados. Para obtener más información, consulte Búsqueda básica.

    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

    El vector de consulta y los vectores almacenados deben provenir del mismo modelo de incrustación y deben tener el mismo número de dimensiones. El uso de un modelo o un recuento de dimensiones diferente produce resultados sin sentido o un error de validación.

  9. Lea los resultados. DynamoDB devuelve los resultados ordenados por similitud, con el elemento más similar primero. Cada resultado contiene los atributos Item proyectados y una 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 } }

    Las puntuaciones dependen del modelo de incrustación y del texto de entrada exacto, por lo que los valores diferirán ligeramente. Lo que importa es qué elementos se seleccionaron y en qué orden. La consulta no contenía las palabras silla, monitor o teclado, pero la búsqueda arrojó los cinco productos de escritorio y oficina por delante de los otros 45 artículos del catálogo. No aparece nada de grupos de mascotas, acampada o café.

    Pruebe con otras consultas para ver el mismo comportamiento con diferentes grupos. Repita el paso anterior con "Something to brew fresh coffee at home" y los mejores resultados son la cafetera espresso, el gotero y el espumador de leche. Repítalo con "Keeping my dog safe on walks" y la correa y el arnés serán los primeros, seguidos de los artículos que estén ligeramente relacionados, ya que el catálogo contiene solo dos productos que se parecen mucho. Vale la pena señalar este último caso: la búsqueda siempre devuelve el número de artículos que ha solicitado, incluso cuando el catálogo no contiene muchas coincidencias buenas. Utilice los valores de Score, no el recuento de resultados, para juzgar la calidad de las coincidencias.

    La forma de leer una puntuación depende de la función de distancia que utilice el índice:

    • COSINE y EUCLIDEAN devuelven los elementos con las puntuaciones más bajas, por lo que las puntuaciones más bajas son más parecidas. Las puntuaciones del coseno van desde 0 para la dirección idéntica hasta 2 para la dirección opuesta.

    • DOT_PRODUCT devuelve los elementos con las puntuaciones más altas, por lo que las puntuaciones más altas son más parecidas.

    Este índice utiliza COSINE, por lo que el primer resultado tiene la puntuación más baja. Si se busca con un texto idéntico al de una descripción guardada, se obtiene primero el elemento con una puntuación igual o cercana a cero.

Limpieza

Para evitar cargos continuos, elimine los recursos que haya creado en este tutorial. El almacenamiento de índices vectoriales se facturará mientras exista el índice, tanto si se realizan búsquedas en él como si no.

Para eliminar el índice vectorial pero conservar la tabla Products y sus elementos, utilice UpdateTable. Los elementos permanecen en la tabla y solo se elimina el índice.

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

Para eliminar la tabla y su índice vectorial a la vez, elimine la tabla.

aws dynamodb delete-table --table-name Products

Confirme que la tabla haya desaparecido. El comando siguiente devuelve una ResourceNotFoundException cuando se complete la eliminación.

aws dynamodb describe-table --table-name Products

Para obtener más información sobre cómo eliminar un índice vectorial de una tabla que desee conservar, consulte Eliminación de un índice vectorial.

Siguientes pasos

Tras completar esta búsqueda vectorial básica, explore estos temas relacionados.