Spring AI Spring Boot Auto Configuration modules providing automatic setup for AI models, vector stores, MCP, and retry capabilities
Step-by-step guide for implementing Retrieval-Augmented Generation (RAG) with Spring AI.
RAG combines:
<dependencies>
<!-- Chat model -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.1.2</version>
</dependency>
<!-- Vector store -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies># Chat model
spring.ai.openai.api-key=${OPENAI_API_KEY}
spring.ai.openai.chat.options.model=gpt-4
# Vector store
spring.ai.vectorstore.pgvector.initialize-schema=true
spring.ai.vectorstore.pgvector.index-type=HNSW
spring.datasource.url=jdbc:postgresql://localhost:5432/vectordb@Service
public class RAGService {
private final ChatClient chatClient;
private final VectorStore vectorStore;
public RAGService(
ChatClient.Builder chatClientBuilder,
VectorStore vectorStore) {
this.chatClient = chatClientBuilder.build();
this.vectorStore = vectorStore;
}
public String answerQuestion(String question) {
// 1. Retrieve relevant documents
List<Document> docs = vectorStore.similaritySearch(
SearchRequest.query(question)
.withTopK(3)
.withSimilarityThreshold(0.7)
);
// 2. Build context
String context = docs.stream()
.map(Document::getContent)
.collect(Collectors.joining("\n\n"));
// 3. Generate answer
return chatClient.prompt()
.user("""
Context: %s
Question: %s
Answer based on the context above:
""".formatted(context, question))
.call()
.content();
}
}@Service
public class DocumentIndexer {
private final VectorStore vectorStore;
private final TextSplitter textSplitter;
public DocumentIndexer(VectorStore vectorStore) {
this.vectorStore = vectorStore;
this.textSplitter = new TokenTextSplitter(500, 100);
}
public void indexDocument(String content, Map<String, Object> metadata) {
List<Document> chunks = textSplitter.apply(
List.of(new Document(content, metadata))
);
vectorStore.add(chunks);
}
}public String answerWithReranking(String question) {
// 1. Retrieve more candidates
List<Document> candidates = vectorStore.similaritySearch(
SearchRequest.query(question).withTopK(10)
);
// 2. Re-rank using AI
List<Document> reranked = rerankDocuments(question, candidates);
// 3. Use top results
String context = reranked.stream()
.limit(3)
.map(Document::getContent)
.collect(Collectors.joining("\n\n"));
return generateAnswer(question, context);
}public String answerWithFilter(String question, String category) {
List<Document> docs = vectorStore.similaritySearch(
SearchRequest.query(question)
.withTopK(5)
.withFilterExpression(
Filter.expression("category == '" + category + "'")
)
);
// Generate answer from filtered docs
return generateAnswer(question, buildContext(docs));
}