Using AWS SDK with TypeScript to Query a Bedrock Knowledge Base

Jason Conway-Williams
6 min readFeb 21, 2025

--

Introduction

In this blog post, we’ll walk through how to retrieve a document from an AWS Bedrock Knowledge Base, extract relevant context using Amazon OpenSearch Serverless, and send a context-aware query to Claude Sonnet (via Amazon Bedrock).

This post walks through the manual setup of an AWS OpenSearch Serverless vector store via the AWS Console and the creation of a single TypeScript script to retrieve data from the vector database and invoke a model in Amazon Bedrock. The goal is to provide a simple, standalone code example demonstrating how to use the AWS SDK to interact with both a Bedrock Knowledge Base and a foundation model.

In a production environment, infrastructure would typically be provisioned using Infrastructure as Code (IaC), such as AWS CDK, and integrated into a service layer that encapsulates business logic — potentially exposed via an API for structured access. However, this post focuses purely on a basic reference implementation to illustrate the core concepts.

We’ll use The DynamoDB book PDF stored in Amazon S3 as the knowledge source, configure Amazon OpenSearch Serverless as a vector database, and leverage Bedrock Knowledge Bases for retrieval.

What is RAG (Retrieval-Augmented Generation)?

Retrieval-Augmented Generation (RAG) is an advanced AI technique that combines retrieval-based search with generative AI models to improve response accuracy and relevance. Instead of relying solely on a model’s pre-trained knowledge, RAG dynamically retrieves external documents or domain-specific data and integrates this information into the model’s response.

How RAG Works

  1. User Prompt — The user submits a query to the AI model.
  2. Context Retrieval — The system searches a knowledge base (e.g., OpenSearch or other vector databases) for relevant documents.
  3. Context-Enhanced Prompt — The retrieved information is injected into the prompt to provide additional context.
  4. Model Response Generation — The AI model processes the augmented prompt and generates a more accurate, grounded, and relevant response.

By enriching prompts with real-time, authoritative data, RAG overcomes hallucination (incorrect AI-generated information) and extends the model’s knowledge beyond its pre-trained dataset.

How RAG Augments a Prompt

A standard AI model generates responses based solely on its training data, which remains static. With RAG, the model dynamically integrates external knowledge into its reasoning process.

Example Without RAG:

🚀 User Input: “What is AWS Bedrock?”
🤖 Model Response: “AWS Bedrock is a managed AI service by Amazon that hosts foundation models.” (May lack real-time updates)

Example With RAG:

🚀 User Input: “What is AWS Bedrock?”
📚 Knowledge Base Search (retrieved document from AWS Docs):
“Amazon Bedrock is a managed service that allows users to build and scale generative AI applications with foundation models from various providers. It supports RAG, knowledge bases, and model fine-tuning.”
🤖 Final Model Response (Augmented):
“AWS Bedrock is a fully managed AI service that enables enterprises to build generative AI applications with multiple foundation models, including support for RAG, knowledge bases, and fine-tuning. You can integrate it with OpenSearch Serverless for vector search and real-time document retrieval.”

By augmenting the prompt with real-time context, RAG ensures responses remain accurate, complete, and domain-specific.

Benefits of Using RAG with Amazon Bedrock

Real-Time Knowledge — Fetch the latest company documents, FAQs, or industry updates.
Domain-Specific Intelligence — Provide custom knowledge tailored to business needs.
Reduced Hallucination — Ensure AI-generated responses are grounded in factual data.
Scalable & Automated — Amazon Bedrock automates data ingestion, retrieval, and integration with AI models.

Let’s explore how to leverage AWS Bedrock to create a vector data store and utilise the AWS SDK to implement a Retrieval-Augmented Generation (RAG) workflow efficiently.

1️⃣ Pre-requisites: Setting Up OpenSearch Vector Database via AWS Bedrock Console

To use a Bedrock Knowledge Base, we need to:

  • Store the DynamoDB book PDF in Amazon S3.
  • Create an OpenSearch Serverless vector database through the AWS Bedrock Console.
  • Enable automatic document ingestion from S3 to OpenSearch.

Step 1: Upload the DynamoDB Book PDF to S3

  1. Go to the AWS S3 Console.
  2. Create a new S3 Bucket (e.g., dynamodb-book-knowledge).
  3. Upload the DynamoDB Book PDF to this bucket.
  4. Copy the S3 URI (e.g., s3://dynamodb-book-knowledge/dynamodb-book.pdf).

Step 2: Create a Bedrock Knowledge Base with OpenSearch Serverless

Now, we’ll set up a Bedrock Knowledge Base that automatically ingests documents into an OpenSearch vector database.

Open the AWS Bedrock Console

  • Go to the AWS Bedrock ConsoleKnowledge Bases.
  • Click Create -> Knowledge Base with vector store.

Configure Knowledge Base Details

  • Name: DynamoDBBookKB
  • Description: Knowledge Base for DynamoDB book

Configure Data Source

  • Under Data Source, select:
  • “Amazon S3” as the data source.
  • Click the Browse S3 bucket and select the DynamoDB book bucket (s3://dynamodb-book-knowledge).
  • Choose the Amazon Bedrock default parser.
  • Choose “Automatic Sync” to keep OpenSearch updated with new files.

Set IAM Permissions

  • Allow Bedrock to access OpenSearch and S3.
  • Click Create.

Select Embedding Model

  • Under Embedding Model, select:
  • “Amazon Titan Embeddings G1” (recommended for OpenSearch).
  • This converts PDF text into vector embeddings for search.

Select Vector Database

  • Under the Vector Database section select:
  • Quick create a new vector store.
  • Select Amazon OpenSearch Serverless as the vector store database.

Copy the Knowledge Base ID

  • Firstly, manually sync the knowledge base to ensure the document is indexed in the vector database by selecting the Sync button in the AWS Console.
  • Once sync’d, copy the Knowledge Base ID (e.g., "34MADLGRCJ").
  • We’ll use this in our TypeScript script.

2️⃣ Setting Up AWS SDK Clients

Now that our vector database is ready, we create a Typescript script. For this example I have chosen to create a single script that can be run in the console but for production systems we would look at creating a service, potentially with AWS Lambda.

With our script create, we configure the AWS SDK to interact with Amazon Bedrock.

import { BedrockRuntimeClient, InvokeModelCommand } from "@aws-sdk/client-bedrock-runtime";
import { BedrockAgentRuntimeClient, RetrieveCommand } from "@aws-sdk/client-bedrock-agent-runtime";

// Configure AWS SDK
const config = { region: "us-east-1" };
const bedrockRuntimeClient = new BedrockRuntimeClient(config);
const bedrockAgentRuntimeClient = new BedrockAgentRuntimeClient(config);
const jsonContentType = "application/json";

3️⃣ Define Knowledge Base & Model Details

Next, we specify the Knowledge Base ID and Claude Sonnet model ID.

// Replace with your Knowledge Base ID
const KNOWLEDGE_BASE_ID: string = "REPLACE WITH YOUR KNOWLEDGE BASE ID";
// Replace with your Bedrock model (e.g., Claude, Titan)
const MODEL_ID: string = "anthropic.claude-v2";

4️⃣ Retrieve Data from the Knowledge Base

The script defines a function to query the Bedrock Knowledge Base. We use the bedrockAgentRuntimeClient to send a RetrieveCommand to bedrock to query the vector data store.

async function queryBedrockKnowledgeBase(userInput: string, maxTokens: number = 300): Promise<void> {
try {
// Step 1: Retrieve relevant context from the Knowledge Base
const retrieveCommand = new RetrieveCommand({
knowledgeBaseId: KNOWLEDGE_BASE_ID,
retrievalQuery: userInput,
});

const retrievalResponse = await bedrockAgentRuntimeClient.send(retrieveCommand);
console.log("Retrieved Context:", retrievalResponse);

5️⃣ Extract Retrieved Documents

Once the Knowledge Base returns relevant documents, we extract the content.

      // Step 2: Extract relevant retrieved documents
const retrievedDocuments = retrievalResponse.retrievalResults?.map(doc => doc.content).join("\n") || "";
console.log("Retrieved Documents:", retrievedDocuments);

6️⃣ Send Prompt to Claude Sonnet

After retrieving relevant context, we send a context-aware query to Claude Sonnet.

        // Step 3: Construct the prompt for the foundation model
const prompt: string =
`Human: Use the following context to answer the user question:

Context:
${retrievedDocuments}

User Question:
${userInput}

Assistant:
`;
// Step 4: Send the prompt to the Bedrock model
const invokeCommand = new InvokeModelCommand({
modelId: MODEL_ID,
contentType: jsonContentType,
accept: jsonContentType,
body: JSON.stringify({ prompt, max_tokens: maxTokens }),
});
const modelResponse = await bedrockRuntimeClient.send(invokeCommand);
const modelOutput = JSON.parse(new TextDecoder().decode(modelResponse.body));
console.log("AI Response:", modelOutput);
} catch (error) {
console.error("Error querying Bedrock Knowledge Base:", error);
}
}

7️⃣ Example Usage

Finally, the function is called with user input asking to “Summarise single table design”.

queryBedrockKnowledgeBase("Summarize single table design");

The function calls retrieves relevant data from the vector store before using it in the contextual prompt to Amazon Bedrock, resulting in the following response.

AI Response: {
type: 'completion',
completion: ' Here is a summary of single table design based on the given context:\n' +
'\n' +
'- Single table design involves using as few tables as possible in DynamoDB, ideally just one table per application or microservice. \n' +
'\n' +
'- It originated due to the need to model data differently in DynamoDB compared to relational databases, which typically use multiple normalized tables.\n' +
'\n' +
'- The main benefit of single table design is faster performance by retrieving all needed items in one request. Other smaller benefits are reduced operations burden and potentially lower costs.\n' +
'\n' +
'- Downsides include a steep learning curve, inflexibility in adding new access patterns, and difficulty exporting data for analytics. \n' +
'\n' +
'- Single table design may not be suitable when query flexibility and ease of analytics are more important than raw performance.\n' +
'\n' +
'- Overall, single table design is a powerful and scalable pattern for DynamoDB, but requires learning a new modeling approach compared to traditional normalized databases.',
stop_reason: 'stop_sequence',
stop: '\n\nHuman:'
}

🎯 Summary

✅ What We Did

  1. Configured OpenSearch Serverless via AWS Bedrock Console.
  2. Ingested the DynamoDB book PDF from S3.
  3. Set up Bedrock Knowledge Base with Titan Embeddings.
  4. Queried the Knowledge Base using the AWS SDK (RetrieveCommand).
  5. Sent the retrieved data as part of a structured prompt to Claude Sonnet.
  6. Retrieved an AI-generated summary of the query.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Jason Conway-Williams
Jason Conway-Williams

Written by Jason Conway-Williams

Cloud Solutions Architect at City Electrical Factors (CEF)

No responses yet

Write a response