AWSAWS Certified Generative AI Developer - Professional2026-101.5 Design retrieval mechanisms for FM augmentation
Keep batch embeddings compatible with queries
Completed by the knowledge check
Learning objective
Generate batch embeddings with Lambda while enforcing compatible embedding model versions, vector dimensions, and index similarity settings.
Core idea
A batch is a unit of work, not a compatibility guarantee. Every stored vector must belong to the same embedding coordinate system that the query path uses. Matching array lengths prevents one kind of schema error; it does not make vectors from different models comparable.
Use Lambda to process bounded sets of chunks, validate the outputs, and publish only batches that satisfy an explicit embedding contract. The contract is application-owned: model identity, model-specific input behavior, dimensions, output representation, normalization, and target index settings. Amazon Bedrock and the database expose the mechanisms; your pipeline enforces that they agree.
How it works
Freeze the contract before dispatch
Record the exact embedding modelId, not a label such as “the preferred embedding model.” For Amazon Titan Text Embeddings V2, that identifier is amazon.titan-embed-text-v2:0. Also record dimensions, normalize, and embeddingTypes. Make the worker read the batch’s declared configuration rather than whatever default configuration happens to be active when it starts.
Titan V2 accepts dimensions of 1,024, 512, or 256, with 1,024 as the default. Its normalize default is true, and embeddingTypes defaults to float. Explicit settings prevent a code change that omits dimensions from sending 1,024-element vectors into a 512-dimensional index. Model selection and quality comparisons belong to 1.5.3; this lesson assumes you have selected a configuration.
Version the application contract alongside the corpus release. This version is your own identifier for the complete representation and preprocessing configuration; it is not a separate Bedrock API parameter. A model change with the same dimensionality still creates a different coordinate system. Re-embed the corpus into a separate target and switch the query path only after that target passes validation.
Bound the Lambda work unit
For ordinary Lambda functions, AWS documents a maximum timeout of 900 seconds, memory from 128 MB to 10,240 MB, and configurable /tmp storage from 512 MB to 10,240 MB. The same page documents a longer timeout exception for qualifying Lambda Managed Instances invocations; do not assume that exception applies to an ordinary batch worker.
Lambda’s synchronous invocation request and response limits are 6 MB each; its asynchronous invocation payload limit is 1 MB. Pass compact batch identifiers or object references instead of carrying a large corpus or all output vectors in the invocation payload. Size each batch from measured embedding latency, vector serialization size, database write time, and the worker’s remaining timeout budget.
A batch of many Titan chunks is an application loop over model calls. Titan’s request contains one inputText, not an arbitrary array of passages. Do not describe your Lambda batch as a model-native multi-text request. Amazon Bedrock batch inference through CreateModelInvocationJob is a distinct alternative; AWS lists amazon.titan-embed-text-v2:0 as supported by Region, so verify the target Region before selecting it.
Give each input chunk a stable identity derived from its source revision and chunk boundary. Record which identities completed embedding and which completed database publication. This checkpoint is your pipeline’s state, not a service-generated guarantee that all items in a batch committed together.
Validate the model response
Call Bedrock Runtime InvokeModel with the pinned modelId, contentType: application/json, and the Titan request body. The minimal body for a 512-dimensional float configuration is:
{
"inputText": "TEXT_CHUNK",
"dimensions": 512,
"normalize": true,
"embeddingTypes": ["float"]
}Replace TEXT_CHUNK with the prepared passage. Titan accepts a nonempty input within its documented token and character limits; enforce those boundaries during chunk preparation rather than assuming every file fits.
Validate that the returned float vector has exactly 512 finite numeric elements before writing it. This finite-number check is an application validation rule. Retain inputTextTokenCount as evidence of actual input consumption. If you request only binary embeddings, read embeddingsByType.binary; AWS states that the ordinary embedding field is absent in that case.
Treat a failed call or invalid representation as an incomplete item. Do not write an empty vector as a success placeholder. For an SQS event source, assign one bounded chunk work unit to each message so its retry boundary matches the item. Enable ReportBatchItemFailures in the event source mapping’s FunctionResponseTypes and return batchItemFailures entries whose itemIdentifier is each failed message ID. This makes only failed messages visible again instead of retrying successful records. Catch item-level failures: throwing an exception makes the entire batch fail. With FIFO queues, stop after the first failure and include failed and unprocessed messages to preserve ordering. Keep retry handling within the declared batch budget. Bounded error handling follows the general principles in 1.2.5; here its purpose is to avoid publishing a partially valid embedding release.
Only a validated vector reaches the target, and only a failed message becomes visible again.
Match dimensions and similarity at the target
Match the target vector field’s dimensions to the model output and use the same embedding contract for indexed documents and queries. See 1.5.5 for OpenSearch mappings, query settings, and Aurora schema setup.
The Knowledge Bases OpenSearch managed-cluster setup documents a Faiss HNSW configuration using space_type: l2 for float embeddings and hamming for binary embeddings. Its binary mapping also uses data_type: binary. Do not combine a binary output with a float-only interpretation merely because both are serialized as arrays.
For Aurora PostgreSQL integration, the HNSW index uses vector_cosine_ops. The operator class names the cosine comparison used by that index. Choosing a different operator class in a custom SQL path is an index-contract change, not a harmless naming change.
Euclidean distance, cosine similarity, and binary Hamming distance express different comparisons. Preserve the selected normalization and representation when preparing queries, and validate retrieval against the actual configured index. A dimensionality check alone cannot detect a wrong similarity configuration.
Key distinctions and trade-offs
Separate the checks that detect different failures:
| Check | What it catches | What it does not prove |
|---|---|---|
| Exact model identity | Accidental model substitution | Domain retrieval quality |
| Output dimension | Shape incompatible with index schema | Same coordinate system across models |
| Representation and normalization | Float/binary or preprocessing mismatch | Complete source extraction |
| Index similarity settings | Wrong distance or operator configuration | Sufficient evidence for every query |
| Publication checkpoint | Missing or failed batch items | Correct answers from the generator |
Smaller batches limit retry scope and timeout risk but increase orchestration overhead. Larger batches reduce that overhead but amplify partial-failure handling and memory needs. Select the size from observed work-unit behavior, not from the maximum Lambda timeout alone.
Architecture / decision scenario
A document assistant has a 1,024-dimensional Titan index and wants a tested 512-dimensional representation. Its corpus is too large for one Lambda invocation, so the team dispatches bounded batches with a declared target contract.
Each worker generates 512-dimensional float vectors, checks their shape and numeric values, and writes them to the separate release target. For OpenSearch, the target mapping declares dimension: 512 and the selected float similarity configuration. An Aurora deployment would instead use vector(512) with the appropriate cosine HNSW index. Neither target receives vectors from the previous release.
A resumed worker accidentally uses the model’s default dimensions. Its response validation rejects the 1,024-element vectors before publication. The team completes the corpus checkpoints, runs retrieval comparisons, and switches queries to the matching 512-dimensional contract. Until that switch, production queries continue to use the original corpus representation.
Common exam traps
- Treating equal dimensions as proof that different embedding models are compatible.
- Sending an array of chunks to Titan’s single-
inputTextinterface. - Passing a corpus through Lambda’s invocation payload instead of bounded references.
- Assuming the maximum timeout makes an unbounded batch safe.
- Writing binary vectors to a float mapping or reading a missing
embeddingfield. - Re-embedding documents while queries still use the wrong representation.
What to remember
- Freeze the model, representation, dimensions, and index comparison together.
- Lambda processes bounded work; it does not make batch publication atomic.
- Validate each model response before writing it.
- Rebuild a separate corpus target for incompatible embedding changes.
- Switch document and query representation as one validated release.
Knowledge check
A team replaces its embedding model with a different one that also returns 1,024-dimensional vectors, matching the existing index. How should the rollout proceed?
A resumed embedding worker omits dimensions, so Titan V2 returns 1,024-element vectors for a release declared at 512 dimensions. Which control stops those vectors before they are written?
inputTextTokenCount stays within Titan’s input limitdimensions falls back to Titan’s default of 1,024, and the call still succeeds. Only validation against the batch’s pinned representation, including the exact element count, catches the mismatch before publication.Lambda workers must embed a corpus of several gigabytes with Titan V2. Which work-unit design fits both the model and the function contracts?
inputText , so a batch is an application loop over model calls, not one multi-text request.An SQS event source mapping has ReportBatchItemFailures enabled, and each message carries one chunk. In a batch of ten, one Titan call fails. What should the handler do so that only that chunk is retried?
batchItemFailuresbatchItemFailuresitemIdentifier , so only those messages become visible again. A thrown exception fails the entire batch, and an empty vector would publish an invalid embedding as a success.