Amazon S3 Vectors: Insert & Query Embeddings with Indian Snacks (Titan + Bedrock Demo)

Welcome back, doston! 👋

In Part 1 and Part 2, We created our Vector Bucket and Vector Index using the AWS Console. Now in Part 3, it’s time to make the vector index actually useful — by inserting embeddings into it and then querying it to find the most relevant matches!

And what better way to explain this than using your favorite Indian snacks: Samosa, Vada Pav, and Masala Dosa? 🥔🌶️🥪

🍽️ Goal of This Post

We’ll:

  • Generate embeddings for snack descriptions using Amazon Bedrock (Titan Model).
  • Insert those embeddings into our S3 Vector Index.
  • Attach metadata (like the region or original text) for smarter querying later.
  • Query the index with new text inputs and retrieve the most similar snacks based on vector similarity.

⚠️ Important Note Before You Begin

Currently, AWS Lambda does not support the required version of boto3 (1.39.9) needed to interact with the Amazon S3 Vector Index service. Since this feature is very new, the latest boto3 features (like s3vectors client) aren’t yet available in the Lambda execution environment.

🧠 So for this hands-on demo, we’ll use an Amazon SageMaker Notebook, which gives us the flexibility to install the latest boto3 version and test Bedrock + S3 Vector integrations smoothly.

Once AWS Lambda supports this version, you can port the logic there using the similar IAM Role and code logic.

🛠 Step 1: Setup IAM Role for Using CloudFormation

Before our SageMaker Notebook can communicate with Amazon Bedrock and insert vectors into the S3 Vector Index, we need to set up an IAM Role with all the required permissions.

📜 Why IAM Role?

IAM role gives secure access to your Lambda function so it can invoke models from Bedrock and interact with your S3 Vector bucket/index.

AWSTemplateFormatVersion: "2010-09-09"
Description: IAM role used in the S3Vectors project.

Parameters:
  SagemakerRoleName:
    Type: String
    Default: bedrock-s3vectors-sagemaker-role
    Description: Lambda role for S3Vectors and Bedrock

Resources:
  SagemakerRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Ref SagemakerRoleName
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: sagemaker.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSageMakerFullAccess
        - arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
      Policies:
        - PolicyName: BedrockAndS3VectorsPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - bedrock:*
                Resource: "*"
              - Effect: Allow
                Action:
                  - s3vectors:*
                Resource: "*"
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: "*"
      Tags:
        - Key: Project
          Value: S3Vectors
        - Key: Owner
          Value: UtkarshR

🧪 Step 2: Deploy IAM Role with CloudFormation via AWS CLI

Now that we have our IAM role template ready in a file (e.g., iam-role-s3vector.yaml), let’s deploy it using the AWS CLI.

✅ Prerequisites

Make sure you have:

  • AWS CLI installed and configured with appropriate permissions
  • The CloudFormation YAML file saved locally (e.g., iam-role-s3vector.yaml)

🚀 Run the Deployment Command

aws cloudformation deploy 
  --template-file iam-role-s3vector.yaml 
  --stack-name S3Vectors-Sagemaker-IAM-Stack 
  --capabilities CAPABILITY_NAMED_IAM

🧠 Step 3: Launch SageMaker Notebook in us-east-1

Create a SageMaker notebook instance (ml.t3.medium) in us-east-1, attach the IAM role from Step 2,

🔧 Step 4: Install Updated boto3 in SageMaker

In your SageMaker notebook cell, run the following to install the required boto3 version:

pip install boto3==1.39.9

First

pip install botocore==1.39.9

Second

✅ Step 5: Enable Access to the Titan Embedding Model

Before using amazon.titan-embed-text-v1, ensure you’ve enabled access to this model in your Bedrock console:

  • Go to Amazon Bedrock → Model access in the us-east-1 region.
  • Enable access to amazon.titan-embed-text-v1.

🔐 Without this, your SageMaker code will fail with AccessDeniedException.

🪄 Step 6: Insert Vector Embeddings into S3 Vector Index via SageMaker

Run the following code in your SageMaker notebook to:

  • Generate a vector embedding using Amazon Bedrock (Titan)
  • Insert the embedding into your S3 Vector Index
import boto3
import json

bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
s3vectors = boto3.client("s3vectors", region_name="us-east-1")


try:
    # Desi snacks to embed
    snacks = [
        "Samosa: A spicy deep-fried snack filled with potato masala.",
        "Vada Pav: Mumbai's favorite street food – a batata vada in a pav.",
        "Masala Dosa: A crispy South Indian crepe with spicy potato stuffing."
    ]

    # Step 1: Generate vector embeddings using Amazon Titan
    embeddings = []
    for snack in snacks:
        response = bedrock.invoke_model(
            modelId="amazon.titan-embed-text-v1",
            body=json.dumps({"inputText": snack})
        )
        response_body = json.loads(response["body"].read())
        embeddings.append(response_body["embedding"])

    # print(f"Embedding: {embeddings}")
    # Step 2: Insert vectors into the vector index with metadata
    s3vectors.put_vectors(
        vectorBucketName="awslearner-vector-bucket",
        indexName="snack-index",
        vectors=[
            {
                "key": "Samosa",
                "data": {"float32": embeddings[0]},
                "metadata": {"source_text": snacks[0], "region": "North India"}
            },
            {
                "key": "Vada Pav",
                "data": {"float32": embeddings[1]},
                "metadata": {"source_text": snacks[1], "region": "Maharashtra"}
            },
            {
                "key": "Masala Dosa",
                "data": {"float32": embeddings[2]},
                "metadata": {"source_text": snacks[2], "region": "South India"}
            }
        ]
    )

    print(f"Process Completed")
except Exception as e:
    print(f"Error occurred: {str(e)}")

Insert

🔍 Step 7: Query S3 Vector Index and Retrieve Similar Results

Now let’s query the vector index using a sample input, get the embedding using Bedrock Titan, and find the most similar items from the S3 Vector Index:

import boto3
import json


bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
s3vectors = boto3.client("s3vectors", region_name="us-east-1")

# Desi snack to search
input_text = "crispy spicy street food with potato filling"

# Step 1: Generate embedding using Amazon Titan
response = bedrock.invoke_model(
    modelId="amazon.titan-embed-text-v1",
    body=json.dumps({"inputText": input_text})
)

model_response = json.loads(response["body"].read())
embedding = model_response["embedding"]

# print(f"embedding:{embedding}")

# Step 2: Query the vector index
print("Top 3 closest matches for snack query:")
response = s3vectors.query_vectors(
    vectorBucketName="awslearner-vector-bucket",
    indexName="snack-index",
    queryVector={"float32": embedding},
    topK=3,
    returnDistance=True,
    returnMetadata=True
)
print(json.dumps(response["vectors"], indent=2))

# Step 3: Query with metadata filter (e.g., region = North India)
print("nTop 3 matches from North India only:")
response = s3vectors.query_vectors(
    vectorBucketName="awslearner-vector-bucket",
    indexName="snack-index",
    queryVector={"float32": embedding},
    topK=3,
    filter={"region": "North India"},
    returnDistance=True,
    returnMetadata=True
)
print(json.dumps(response["vectors"], indent=2))

Select

🧾 Wrap-Up

In this part, we explored how to:

✅ Generate text embeddings using Amazon Bedrock’s Titan model
✅ Insert those embeddings into an S3 Vector Index using SageMaker Notebook
✅ Attach meaningful metadata (like snack names and regions)
✅ Perform a query on the index to find similar snacks based on user input!

This hands-on demo shows the real power of combining Bedrock, S3 Vector Indexing, and modern vector search for practical, intelligent search experiences.

📚 More Learning

👨‍💻 About Me

Hi! I’m Utkarsh, a Cloud Specialist & AWS Community Builder who loves turning complex AWS topics into fun chai-time stories

👉 Explore more

Leave a Reply