AWS Builder Center

Building a Lightweight RAG Workflow Using Amazon Bedrock and AWS Lambda

Learn how to build a serverless Retrieval-Augmented Generation (RAG) pipeline on AWS. This guide walks through ingesting documents into Amazon Bedrock Knowledge Bases and querying them via an event-driven AWS Lambda function.

Student Builder | Aspiring Data Scientist & Cloud Practitioner
Retrieval-Augmented Generation (RAG) allows Large Language Models (LLMs) to answer queries using private, dynamic organizational data without requiring expensive model fine-tuning.
While building a self-hosted RAG architecture usually requires managing vector databases, embedding pipelines, and chunking strategies, Amazon Bedrock Knowledge Bases fully abstracts this infrastructure. In this tutorial, we will build a serverless RAG pipeline connected to an AWS Lambda function that retrieves context and generates grounded responses.

Architecture Overview

  1. Storage Layer: Raw PDF/Markdown documents stored in an Amazon S3 bucket.
  2. Retrieval Engine: Amazon Bedrock Knowledge Base vectorizes files using Titan Text Embeddings and indexes them into OpenSearch Serverless.
  3. Compute Layer: An AWS Lambda function (Python 3.12) queries the Knowledge Base via the Bedrock Agent Runtime SDK and streams answers to client applications.
1
2
3
4
5
6
7
8
9
[ User Request ]
│
▼
[ AWS Lambda ] ──( RetrieveAndGenerate API )──▶ [ Amazon Bedrock Knowledge Base ]
│
┌─────────────────┴─────────────────┐
▼ ▼
[ OpenSearch Serverless ] [ Foundation Model ]
(Vector Index) (Claude 3.5 Sonnet)

Step 1: Set Up the Amazon Bedrock Knowledge Base

  1. Navigate to the Amazon Bedrock console and select Knowledge bases under the Builder tools sidebar.
  2. Click Create knowledge base.
  3. Under Data source, choose Amazon S3 and point it to your document bucket (s3://your-rag-docs-bucket/).
  4. Select your Embeddings model (e.g., Titan Embeddings G1 - Text).
  5. For the vector store, select Quick create a new vector store (Amazon OpenSearch Serverless).
  6. Review and create. Once provisioned, click Sync on your data source to trigger the chunking and embedding pipeline.
  7. Note down your Knowledge Base ID (a 10-character alphanumeric string).

Step 2: Configure Lambda IAM Permissions

Your Lambda function requires permissions to invoke Bedrock models and query the Knowledge Base. Attach the following inline policy to your Lambda execution role:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"bedrock:RetrieveAndGenerate",
"bedrock:Retrieve"
],
"Resource": "arn:aws:bedrock:*:*:knowledge-base/*"
},
{
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel"
],
"Resource": "arn:aws:bedrock:*::foundation-model/*"
}
]
}

Step 3: Implement the Query Handler

Create an AWS Lambda function using the Python 3.12 runtime and configure an environment variable:
  • KNOWLEDGE_BASE_ID: YOUR_KB_ID
Use the following function code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import json
import os
import boto3

# Initialize the Bedrock Agent Runtime client
bedrock_agent_runtime = boto3.client('bedrock-agent-runtime')

KNOWLEDGE_BASE_ID = os.environ.get('KNOWLEDGE_BASE_ID')
MODEL_ARN = "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-5-sonnet-20240620-v1:0"

def lambda_handler(event, context):
try:
body = json.loads(event.get('body', '{}'))
query = body.get('prompt')

if not query:
return {
'statusCode': 400,
'body': json.dumps({'error': 'Missing prompt in request body.'})
}

# Query the Knowledge Base and generate the response
response = bedrock_agent_runtime.retrieve_and_generate(
input={'text': query},
retrieveAndGenerateConfiguration={
'type': 'KNOWLEDGE_BASE',
'knowledgeBaseConfiguration': {
'knowledgeBaseId': KNOWLEDGE_BASE_ID,
'modelArn': MODEL_ARN
}
}
)

output_text = response.get('output', {}).get('text', '')
citations = response.get('citations', [])

return {
'statusCode': 200,
'headers': {'Content-Type': 'application/json'},
'body': json.dumps({
'answer': output_text,
'citation_count': len(citations)
})
}

except Exception as e:
return {
'statusCode': 500,
'body': json.dumps({'error': str(e)})
}

Key Takeaways & Best Practices

  • Chunking Strategy: By default, Bedrock uses fixed-size chunking (300 tokens with 20% overlap). For structured documents or tabular data, configure hierarchical or semantic chunking.
  • Cold Starts: Keep Lambda deployment packages lean. Since boto3 is pre-installed in the AWS Lambda runtime, you don't need external heavy vector packages like LangChain or Chroma.
  • Cost Optimization: Sync data sources only when updates occur via S3 event notifications rather than periodic polling.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article