DEV Community

Cover image for RAG Made Serverless - Amazon Bedrock Knowledge Base with Spring AI
Yuriy Bezsonov
Yuriy Bezsonov

Posted on

RAG Made Serverless - Amazon Bedrock Knowledge Base with Spring AI

What if you could build an AI assistant with access to your own data in under 40 lines of Java? That's now possible with my contribution to the just-released Spring AI 2.0.0 M2 - Amazon Bedrock Knowledge Base support. It's a fully managed RAG (Retrieval-Augmented Generation) service that handles document ingestion, embeddings, and vector storage for you - and now you can use it with Spring AI!
RAG lets AI models answer questions using your own documents instead of relying solely on their training data.

In this post, I'll show you how to build a working AI agent with RAG in minutes using JBang - no Maven project setup required. You'll have an AI assistant answering questions from your company documents with minimal code.

Why Bedrock Knowledge Base?

Three things make this integration compelling:

  1. Fully Managed: AWS handles document chunking, embeddings, and vector storage. No PGVector or OpenSearch to manage.
  2. Read-Only from Spring AI: Documents sync via AWS - your app just queries. Simple.
  3. Fast Setup: Connect S3, Confluence, or SharePoint as data sources. Sync and go.

Key features:

  • Search Types: SEMANTIC uses vector similarity; HYBRID combines semantic with keyword search for better recall
  • Reranking: Re-scores results using Bedrock reranking models to surface the most relevant documents
  • Metadata Filtering: Narrows results by document attributes (e.g., department == 'HR' && year >= 2024)
  • Similarity Threshold: Filters out low-relevance matches below a minimum score

For full configuration options, see the Spring AI Bedrock Knowledge Base documentation.

Prerequisites

You'll need:

What is JBang?

JBang lets you run Java files directly - no pom.xml, no project structure. Perfect for quick experiments and demos. Dependencies are declared as comments in the source file.

Install JBang:

# macOS
brew install jbang
Enter fullscreen mode Exit fullscreen mode
# Linux/Windows
curl -Ls https://sh.jbang.dev | bash -s - app setup
Enter fullscreen mode Exit fullscreen mode

AWS Credentials

Configure AWS CLI with credentials that have Bedrock access:

aws configure
Enter fullscreen mode Exit fullscreen mode

Verify access:

aws bedrock list-foundation-models --query 'modelSummaries[0].modelId' --output text
Enter fullscreen mode Exit fullscreen mode

The Knowledge Base

Let's create a Knowledge Base with sample company policies. Copy and run in terminal:

ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text --no-cli-pager)
BUCKET="kb-demo-${ACCOUNT_ID}"
VECTOR_BUCKET="kb-demo-vectors-${ACCOUNT_ID}"

# Buckets
aws s3 mb s3://${BUCKET} --no-cli-pager 2>/dev/null || true
aws s3vectors create-vector-bucket --vector-bucket-name ${VECTOR_BUCKET} --no-cli-pager 2>/dev/null || true
aws s3vectors create-index --vector-bucket-name ${VECTOR_BUCKET} --index-name kb-demo-index \
  --data-type float32 --dimension 1024 --distance-metric cosine --no-cli-pager 2>/dev/null || true

# Sample policies
echo "Travel: Europe accommodation €130/night. Manager approval required." | aws s3 cp - s3://${BUCKET}/travel.txt --no-cli-pager
echo "IT: Home office budget \$500/year. VPN required for remote work." | aws s3 cp - s3://${BUCKET}/it.txt --no-cli-pager

# IAM role
aws iam create-role --role-name kb-demo-role --no-cli-pager \
  --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"bedrock.amazonaws.com"},"Action":"sts:AssumeRole"}]}' 2>/dev/null || true
aws iam attach-role-policy --role-name kb-demo-role --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess --no-cli-pager 2>/dev/null || true
aws iam attach-role-policy --role-name kb-demo-role --policy-arn arn:aws:iam::aws:policy/AmazonBedrockFullAccess --no-cli-pager 2>/dev/null || true
aws iam put-role-policy --role-name kb-demo-role --policy-name s3vectors \
  --policy-document "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"s3vectors:*\",\"Resource\":\"arn:aws:s3vectors:us-east-1:${ACCOUNT_ID}:bucket/${VECTOR_BUCKET}/*\"}]}" --no-cli-pager
sleep 10

# Knowledge Base
KB_ID=$(aws bedrock-agent create-knowledge-base --name kb-demo --role-arn arn:aws:iam::${ACCOUNT_ID}:role/kb-demo-role \
  --knowledge-base-configuration '{"type":"VECTOR","vectorKnowledgeBaseConfiguration":{"embeddingModelArn":"arn:aws:bedrock:us-east-1::foundation-model/amazon.titan-embed-text-v2:0"}}' \
  --storage-configuration "{\"type\":\"S3_VECTORS\",\"s3VectorsConfiguration\":{\"vectorBucketArn\":\"arn:aws:s3vectors:us-east-1:${ACCOUNT_ID}:bucket/${VECTOR_BUCKET}\",\"indexName\":\"kb-demo-index\"}}" \
  --no-cli-pager --query 'knowledgeBase.knowledgeBaseId' --output text)

sleep 30
DS_ID=$(aws bedrock-agent create-data-source --knowledge-base-id ${KB_ID} --name policies \
  --data-source-configuration "{\"type\":\"S3\",\"s3Configuration\":{\"bucketArn\":\"arn:aws:s3:::${BUCKET}\"}}" \
  --no-cli-pager --query 'dataSource.dataSourceId' --output text)

aws bedrock-agent start-ingestion-job --knowledge-base-id ${KB_ID} --data-source-id ${DS_ID} --no-cli-pager >/dev/null
echo "KB: ${KB_ID}"
Enter fullscreen mode Exit fullscreen mode

This creates:

  • S3 bucket with two policy documents
  • S3 Vectors bucket for vector storage
  • IAM role for Bedrock to access your data
  • Knowledge Base with Titan embeddings
  • Data source pointing to your S3 bucket

The script uses S3 Vectors - a cost-effective serverless vector storage option. You can also use OpenSearch Serverless or Aurora PostgreSQL.

The Application

Here's the complete AI agent - 40 lines of Java. Save as KbAgent.java:

///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS org.springframework.boot:spring-boot-starter-web:4.0.1
//DEPS org.springframework.ai:spring-ai-starter-model-bedrock-converse:2.0.0-M2
//DEPS org.springframework.ai:spring-ai-starter-vector-store-bedrock-knowledgebase:2.0.0-M2
//DEPS org.springframework.ai:spring-ai-advisors-vector-store:2.0.0-M2

//JAVA_OPTIONS -Dspring.ai.bedrock.aws.region=us-east-1
//JAVA_OPTIONS -Dspring.ai.bedrock.converse.chat.options.model=global.anthropic.claude-sonnet-4-20250514-v1:0

package com.example;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;

@SpringBootApplication
@RestController
public class KbAgent {

    private final ChatClient chatClient;

    public KbAgent(ChatClient.Builder builder, VectorStore vectorStore) {
        this.chatClient = builder
                .defaultAdvisors(QuestionAnswerAdvisor.builder(vectorStore).build())
                .build();
    }

    @PostMapping("/chat")
    public String chat(@RequestBody String prompt) {
        return chatClient.prompt().user(prompt).call().content();
    }

    public static void main(String[] args) {
        SpringApplication.run(KbAgent.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

That's it. The JBang header declares dependencies, Spring AI auto-configures the VectorStore bean from the environment variable, and QuestionAnswerAdvisor handles RAG automatically.

Key Points

  • No EmbeddingModel needed: Unlike PGVector, Bedrock KB handles embeddings internally. If you'd like to build RAG with PostgreSQL and PGVector instead, check out my previous post.
  • Auto-configuration: Just set SPRING_AI_VECTORSTORE_BEDROCK_KNOWLEDGE_BASE_KNOWLEDGE_BASE_ID
  • QuestionAnswerAdvisor: Automatically retrieves relevant documents and adds them to the prompt

Run the Application

KB_ID=$(aws bedrock-agent list-knowledge-bases --query "knowledgeBaseSummaries[?name=='kb-demo'].knowledgeBaseId|[0]" --output text --no-cli-pager)
echo "KB: ${KB_ID}"
SPRING_AI_VECTORSTORE_BEDROCK_KNOWLEDGE_BASE_KNOWLEDGE_BASE_ID=${KB_ID} jbang KbAgent.java
Enter fullscreen mode Exit fullscreen mode

JBang downloads dependencies on first run, then starts the Spring Boot application.

Test the Application

In another terminal:

# Test travel policy
curl -s -X POST http://localhost:8080/chat -H "Content-Type: text/plain" \
  -d "What is the accommodation limit for Europe?"

# Test IT policy
curl -s -X POST http://localhost:8080/chat -H "Content-Type: text/plain" \
  -d "What is the home office equipment budget?"
Enter fullscreen mode Exit fullscreen mode

Expected output:

Based on the context information provided, the accommodation limit for Europe is €130 per night, and manager approval is required.

Based on the context information provided, the home office equipment budget is **$500 per year**.
Enter fullscreen mode Exit fullscreen mode

The AI responds with information from your company documents - not generic training data.

Cleanup

ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text --no-cli-pager)
KB_ID=$(aws bedrock-agent list-knowledge-bases --query "knowledgeBaseSummaries[?name=='kb-demo'].knowledgeBaseId|[0]" --output text --no-cli-pager)

[ "${KB_ID}" != "None" ] && aws bedrock-agent delete-knowledge-base --knowledge-base-id ${KB_ID} --no-cli-pager 2>/dev/null
aws s3 rb s3://kb-demo-${ACCOUNT_ID} --force --no-cli-pager 2>/dev/null
aws s3vectors delete-index --vector-bucket-name kb-demo-vectors-${ACCOUNT_ID} --index-name kb-demo-index --no-cli-pager 2>/dev/null
aws s3vectors delete-vector-bucket --vector-bucket-name kb-demo-vectors-${ACCOUNT_ID} --no-cli-pager 2>/dev/null
aws iam delete-role-policy --role-name kb-demo-role --policy-name s3vectors --no-cli-pager 2>/dev/null
aws iam detach-role-policy --role-name kb-demo-role --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess --no-cli-pager 2>/dev/null
aws iam detach-role-policy --role-name kb-demo-role --policy-arn arn:aws:iam::aws:policy/AmazonBedrockFullAccess --no-cli-pager 2>/dev/null
aws iam delete-role --role-name kb-demo-role --no-cli-pager 2>/dev/null
Enter fullscreen mode Exit fullscreen mode

What's Next?

This demo uses S3 with text files, but Bedrock Knowledge Base supports:

  • Multiple data sources: Confluence, SharePoint, Salesforce, web crawlers
  • Advanced search: Hybrid search combining semantic and keyword matching
  • Reranking: Improve relevance with Bedrock reranking models
  • Metadata filtering: Filter results by document attributes

See the Spring AI documentation for configuration options.

Conclusion

With minimal setup - one Java file and a few shell commands - you have an AI assistant grounded in your own data. No vector database to manage, no embedding pipeline to build.

I'm proud to have contributed this integration to Spring AI 2.0.0 M2. The source is available on GitHub if you want to see how it works under the hood.

Learn More

Top comments (0)