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.

The Dominant Programmer
The Dominant Programmer
The Dominant Programmer
Complete Guide to Building a Spring AI Alibaba + Ollama Function Calling Project

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 dependencies

Maven 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.7

Key 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:run

API 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.)

Function Call Test Screenshot
Function Call Test Screenshot

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaSpring BootFunction CallingSpring AIOllama
The Dominant Programmer
Written by

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

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.