- spring-ai-starter-model-ollama autoconfigures ChatModel/EmbeddingModel from spring.ai.ollama.* properties alone; no API key anywhere in this module. - org.testcontainers:ollama and org.testcontainers:junit-jupiter were both renamed in the Testcontainers 2.x line -- to org.testcontainers:testcontainers-ollama and org.testcontainers:testcontainers-junit-jupiter respectively -- confirmed by reading the real testcontainers-bom-2.0.5.pom that Spring Boot 4.1.1 imports (spring-boot-dependencies -> testcontainers.version=2.0.5). The pre-rename artifact IDs still exist on Maven Central but are stuck on the 1.x line. - Unlike every other module in this series, tests drive a real local model (qwen2.5:0.5b chat, all-minilm embeddings) via a Testcontainers-managed OllamaContainer started from a baked image (scripts/bake-image.sh), not a ScriptedChatModel -- the whole point of this post is a real model answering a real prompt. - LocalChatAndEmbeddingTest forces a genuine cold state with Ollama's keep_alive: 0 option (set via ChatModel.call(Prompt) -- ChatClient.options() does not carry a keepAlive override through to the request in this version) and confirms the unload actually happened via /api/ps before measuring a reload, rather than trusting whichever call happens to run first. - On this quiet sandbox host, even a confirmed-cold reload of the 500MB model came back in single-digit milliseconds once the underlying image layers were cached -- eval (generation) time dominates total latency here, not loading. Captured, not asserted as universal: readers get scripts/bake-image.sh to get their own numbers. - Embedding dimension (384, all-minilm) asserted deterministically. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01FtpJvZfg4nvLvtzgJTDWpB
3.6 KiB
3.6 KiB
spring-ai
Runnable companion code for the Spring AI articles on ankurm.com. One directory per module; each module is one commit and carries its own README, tests and captured output.
| Module | What it is | Article |
|---|---|---|
getting-started/ |
One ChatClient bean, three endpoints (plain call, templated system prompt, streaming), and a test proving spring.ai.model.chat switches providers with zero code change. Spring Boot 4.1.1, Spring AI 2.0.1, Java 25. |
Spring AI 2.0 in 10 Minutes: ChatClient on Spring Boot 4.1 |
rag/ |
Ingest PDFs, chunk, retrieve from pgvector, rerank, answer, check the answer. Spring Boot 4.1.1, Spring AI 2.0.1, Java 25. | Production-grade RAG with Spring AI and the complete example |
mcp-server/ |
An order-lookup service exposed as MCP tools, a resource, and a prompt with @McpTool/@McpResource/@McpPrompt, served over Streamable HTTP (Spring AI 2.0's default MCP server transport). Spring Boot 4.1.1, Spring AI 2.0.1, Java 25. |
Build an MCP Server with Spring AI 2.0 |
mcp-client/ |
ChatClient calling tools from two real external MCP servers (filesystem, git) over stdio via defaultToolCallbacks(ToolCallbackProvider...), contrasted with a local @Tool method, with every call logged through one Micrometer ObservationHandler. Spring Boot 4.1.1, Spring AI 2.0.1, Java 25. |
Spring AI MCP Client: Calling External MCP Servers from ChatClient |
mcp-secure/ |
The mcp-server article's order-lookup tools behind a real OAuth2 resource server: JWT validation, one scope per tool via @PreAuthorize, unauthenticated tool discovery rejected outright, and every call audit-logged through MDC -- denials included. Spring Boot 4.1.1, Spring AI 2.0.1, Spring Security 7.1.1, Java 25. |
Securing an MCP Server with Spring Security 7 |
tool-calling/ |
@Tool methods, ToolCallingAdvisor (the advisor-layer replacement for Spring AI 1.x's per-model tool loop), returnDirect, ToolContext, and ToolSearchToolCallingAdvisor for progressive disclosure across a 230-tool synthetic library -- every test driven by a hand-written ScriptedChatModel, no live model anywhere. Spring Boot 4.1.1, Spring AI 2.0.1, Java 25. |
Tool Calling in Spring AI 2.0 |
structured-output/ |
ChatClient.entity() mapping LLM responses to Java records, lists and maps; StructuredOutputValidationAdvisor retrying non-conforming JSON with a real enum-constrained schema, including a captured run that exhausts every retry without throwing. Spring Boot 4.1.1, Spring AI 2.0.1, Java 25. |
Structured Output in Spring AI 2.0 |
ollama-local/ |
Chat and embeddings against a real local qwen2.5:0.5b/all-minilm, no API key, driven by a Testcontainers-managed Ollama container started from a baked image; a confirmed model unload via keep_alive: 0 and /api/ps, not a scripted model anywhere. Spring Boot 4.1.1, Spring AI 2.0.1, Testcontainers 2.0.5, Java 25. |
Run LLMs Locally with Spring AI and Ollama |
Upgrading from Spring AI 1.x: migration guide.