Complete Guide to Building a Spring AI Alibaba + Ollama Function Calling Project
This tutorial walks through creating a Spring Boot application that integrates the Spring AI Alibaba framework with a local Ollama model to enable function calling, covering environment setup, Maven dependencies, configuration, core code, testing, best practices, and common troubleshooting steps.
Project Overview
SpringBoot is used with the Spring AI framework to integrate a local Ollama large‑model service and implement full Function Calling capabilities.
Framework Relationship
Spring AI Alibaba – development framework providing @Tool and @ToolParam annotations.
Spring AI – underlying official AI framework.
Ollama – local LLM service that replaces Alibaba Cloud DashScope.
Technology Stack
Spring Boot 3.2.5
Spring AI Alibaba 1.0.0-M6.1
Spring AI 1.0.0-M6
JDK 17+
Ollama (latest) with model qwen2.5
Core Functions
Time and date query
Weather information query
Arithmetic calculation (add, subtract, multiply, divide)
Temperature conversion (Celsius ↔ Fahrenheit)
Environment Preparation
JDK Installation
Requires JDK 17 or higher.
Ollama Installation
Download from https://ollama.com/, start service with ollama serve, pull model with ollama pull qwen2.5, verify with ollama list and a curl request.
Project Setup
Project Structure
spring-ai-alibaba-ollama-functioncall/
├── src/main/java/com/badao/ai/
│ ├── SpringAiDemoApplication.java # main class
│ ├── config/
│ │ └── ChatClientConfig.java # ChatClient bean
│ ├── controller/
│ │ └── ChatController.java # REST endpoints
│ └── function/
│ └── ToolService.java # tool implementations
├── src/main/resources/
│ ├── application.yml # configuration
│ └── static/function-call-test.html # test page
└── pom.xml # Maven dependenciesMaven Dependencies
Key dependencies: spring-boot-starter-web – provides HTTP service. spring-ai-ollama-spring-boot-starter – connects to Ollama. spring-ai-alibaba-core – supplies Spring AI Alibaba extensions.
Using spring-ai-alibaba-starter would pull DashScope and require an API key, so the core module is preferred for local Ollama.
Configuration (application.yml)
server:
port: 885
logging:
level:
com.badao: debug
org.springframework.ai: debug
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
options:
model: qwen2.5
temperature: 0.7Key properties are spring.ai.ollama.base-url (required) and spring.ai.ollama.chat.options.model (required).
Core Code Implementation
Application Entry
package com.badao.ai;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringAiDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringAiDemoApplication.class, args);
}
}Tool Service (Function Calling)
package com.badao.ai.function;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
@Service
public class ToolService {
@Tool(description = "获取当前日期,格式为yyyy-MM-dd")
public String getCurrentDate() {
return LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
}
@Tool(description = "获取当前时间,格式为HH:mm:ss")
public String getCurrentTime() {
return LocalTime.now().format(DateTimeFormatter.ISO_LOCAL_TIME);
}
@Tool(description = "根据城市名称获取天气信息")
public String getWeather(@ToolParam(description = "城市名称,例如:北京、上海、广州") String city) {
Map<String, String> weatherData = new HashMap<>();
weatherData.put("北京", "晴天,温度25°C,湿度30%");
weatherData.put("上海", "多云,温度22°C,湿度60%");
weatherData.put("广州", "阴天,温度28°C,湿度75%");
weatherData.put("深圳", "晴天,温度30°C,湿度50%");
return weatherData.getOrDefault(city, "抱歉,暂无" + city + "的天气信息");
}
@Tool(description = "计算器功能,支持加减乘除运算")
public String calculate(@ToolParam(description = "第一个数字") double num1,
@ToolParam(description = "运算符:+、-、*、/") String operator,
@ToolParam(description = "第二个数字") double num2) {
double result;
switch (operator) {
case "+":
result = num1 + num2;
break;
case "-":
result = num1 - num2;
break;
case "*":
result = num1 * num2;
break;
case "/":
if (num2 == 0) return "错误:除数不能为零";
result = num1 / num2;
break;
default:
return "错误:不支持的运算符,请使用 +、-、*、/";
}
return num1 + " " + operator + " " + num2 + " = " + result;
}
@Tool(description = "将摄氏度转换为华氏度")
public String celsiusToFahrenheit(@ToolParam(description = "摄氏度温度值") double celsius) {
double fahrenheit = (celsius * 9 / 5) + 32;
return celsius + "°C = " + String.format("%.2f", fahrenheit) + "°F";
}
}Annotation Details
Core Insight: The @Tool and @ToolParam annotations come from org.springframework.ai.tool.annotation in the Spring AI core package; Spring AI Alibaba extends them, so they are available in the Alibaba project.
Good description example for @Tool:
@Tool(description = "获取当前时间,格式为HH:mm:ss,当用户询问时间、几点时使用此工具")ChatClient Configuration
package com.badao.ai.config;
import com.badao.ai.function.ToolService;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ChatClientConfig {
@Bean
public ChatClient chatClientWithTools(ChatClient.Builder builder, ToolService toolService) {
return builder
.defaultSystem("你是一个智能助手,可以使用提供的工具来帮助用户解决问题。")
.build();
}
}The ChatClient.Builder is auto‑configured by spring-ai-ollama-spring-boot-starter. The system prompt guides the model to invoke tools.
Controller
package com.badao.ai.controller;
import com.badao.ai.function.ToolService;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
public class ChatController {
private final ChatClient chatClient;
private final ToolService toolService;
public ChatController(ChatClient.Builder builder, ToolService toolService) {
this.chatClient = builder.build();
this.toolService = toolService;
}
/** GET endpoint */
@GetMapping("/ai/function-call")
public String functionCall(@RequestParam(value = "message", defaultValue = "现在几点了?") String message) {
return chatClient.prompt()
.user(message)
.tools(toolService)
.call()
.content();
}
/** POST endpoint */
@PostMapping("/ai/function-call/chat")
public Map<String, String> functionCallChat(@RequestBody Map<String, String> request) {
String message = request.get("message");
String response = chatClient.prompt()
.user(message)
.tools(toolService)
.call()
.content();
return Map.of(
"message", message,
"response", response,
"model", "ollama-qwen2.5",
"type", "function-call");
}
}Function Calling Workflow
用户发起请求:"北京天气怎么样?"
↓
ChatClient 发送消息给 Ollama 模型
↓
AI 分析:需要查询天气 → 决定调用 getWeather("北京")
↓
ChatClient 自动执行 ToolService.getWeather("北京")
↓
工具返回:"晴天,温度25°C,湿度30%"
↓
结果返回给 AI 模型
↓
AI 生成最终回答:"北京现在是晴天,温度25°C,湿度30%。"
↓
返回给用户Testing and Verification
Build and Run
# Compile
mvn clean compile
# Start
mvn spring-boot:runAPI Tests
GET
http://localhost:885/ai/function-call?message=现在几点了?→ expected "现在是 15:30:25。"
GET date query → expected "今天是 2026-06-01。"
GET weather query → expected "北京现在是晴天,温度25°C,湿度30%。"
GET calculation → expected "123 * 456 = 56088.0"
POST temperature conversion → returns JSON with "100.0°C = 212.00°F"
Web Test Page
A static HTML page function-call-test.html under src/main/resources/static provides a UI for quick tests. Access it at http://localhost:885/function-call-test.html. (Screenshot shown below.)
Common Issues and Solutions
Java version mismatch : Maven may use JDK 8/11; Spring Boot 3.x requires JDK 17+. Set JAVA_HOME to JDK 17 and recompile.
@Tool annotation not found : Use Spring AI 1.0.0-M6+ and include spring-ai-alibaba-core.
Multiple ChatModel beans : Remove spring-ai-alibaba-starter (which pulls DashScope) and keep only the core module.
DashScope API key missing : Same as above; the core module avoids DashScope.
OllamaOptions builder method change : M5 uses withModel(); M6 uses model().
Ollama service not started : Run ollama serve and pull the model.
Tool not invoked : Provide clear @Tool(description that tells the model when to use it.
Conclusion
The project demonstrates how to combine the Spring AI Alibaba framework with a local Ollama LLM to achieve full function‑calling capabilities, offering a completely offline solution with no API costs, data‑privacy guarantees, and support for multiple open‑source models.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
The Dominant Programmer
Resources and tutorials for programmers' advanced learning journey. Advanced tracks in Java, Python, and C#. Blog: https://blog.csdn.net/badao_liumang_qizhi
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
