Spring Boot application that demonstrates different Retrieval-Augmented Generation (RAG) patterns using Spring AI, Ollama, and PostgreSQL pgvector.
- Java 25 with virtual threads
- Spring Boot 4.0.3 + Spring AI 2.0.0-M2
- Ollama —
granite4:3b(chat) andgranite-embedding:278m(embeddings) - PostgreSQL + pgvector — vector store with HNSW indexing
- Docling Serve — PDF document parsing and chunking
- Arconia 0.22.0 — dev services and Docling integration
- OpenTelemetry — observability via Grafana LGTM stack
The project showcases four RAG strategies through different endpoints:
Basic retrieval-augmented generation. Searches the vector store for relevant documents and augments the LLM response.
Expands the user query into 3 variations using MultiQueryExpander, executes them in parallel, and combines the retrieved documents for a more comprehensive answer.
Translates the query to English (supports multilingual input), then applies multi-query expansion for improved retrieval quality.
Agentic approach where the LLM selects the appropriate retrieval tool based on query semantics:
- Iorek & Pingu Retriever — searches North Pole story documents
- Lucio & Balosso Retriever — searches Italian Alps story documents
- Web Search Retriever — searches the web via Tavily API
Two ingestion pipelines run automatically on startup:
| Pipeline | Source | Strategy |
|---|---|---|
IngestionPipelineDocling |
Designing Machine Learning Systems (PDF, ~390 pages) | Splits into 5-page batches, processes via Docling Serve |
IngestionPipelineBranching |
story1.md, story2.md |
Markdown reader with location metadata tagging |
- Docker Desktop (for dev services: Docling, PostgreSQL, Ollama, Grafana LGTM)
- Java 25+
- Tavily API key (optional, for web search routing) — set
TAVILY_SEARCH_API_KEYenv var
./gradlew bootRunDev services (Docling Serve, PostgreSQL + pgvector, Ollama, Grafana LGTM) start automatically via Arconia/Testcontainers.
src/main/java/com/marcos/ragarchitectureexample/
├── RagArchitectureExampleApplication.java
├── ragDocling/
│ ├── ChatController.java # Simple RAG endpoint
│ └── IngestionPipelineDocling.java # PDF ingestion via Docling
├── ragBranchingOllama/
│ ├── RagControllerMultiQuery.java # Multi-query RAG endpoint
│ ├── RagControllerOptimization.java # Translation + expansion RAG endpoint
│ └── IngestionPipelineBranching.java # Markdown ingestion with metadata
└── ragQueryRouting/
├── RagControllerQueryRouting.java # Tool-based routing RAG endpoint
└── SearchEngineDocumentRetriever.java # Tavily web search integration
Key settings in application.yaml:
| Property | Value | Description |
|---|---|---|
spring.ai.ollama.chat.options.model |
granite4:3b |
Chat model |
spring.ai.ollama.embedding.options.model |
granite-embedding:278m |
Embedding model |
spring.ai.vectorstore.pgvector.dimensions |
768 |
Embedding dimensions |
spring.ai.vectorstore.pgvector.index-type |
HNSW |
Vector index type |
arconia.docling.read-timeout |
300s |
Docling API read timeout |