场景
SpringBoot+LangChain4j+Ollama实现本地大模型语言LLM的搭建、集成和示例流程:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/160340066
在上面的基础上,学习LangChain4j 工具调用(Function Calling)
一、工具调用(Function Calling)是什么?
工具调用允许大语言模型(LLM)在生成回复时,主动请求调用外部函数(工具)来获取实时数据或执行操作。
例如,用户问"北京天气怎么样?",模型会返回一个调用天气工具的函数请求,
由你的代码执行并返回结果,模型再基于结果生成最终回答。
核心价值:
扩展模型能力:
获取实时信息、操作数据库、调用第三方 API
提高准确性:
避免模型"幻觉",基于真实数据回答
实现自动化:
让 AI 能真正"做事"
二、环境准备与模型选择
2.1 必须条件
模型必须支持 Function Calling。Ollama 中支持工具调用的模型:
qwen2:7b(推荐,中文好)
llama3.1:8b
mistral:7b-v0.3
LangChain4j 版本:建议使用 1.0.0-beta4 或更高版本(API 更稳定)
Spring Boot 3.x + JDK 17
2.2 Ollama配置国内镜像源
前面通过魔搭社区下载的 GGUF 模型(如 modelscope.cn/Qwen/Qwen2.5-7B-Instruct-GGUF:latest)
通常不支持工具调用。请使用 Ollama 官方仓库中的模型名。
为此需要先配置Ollama的国内镜像源
到此目录下
创建 %USERPROFILE%\.ollama\config.json
比如
C:\Users\admin\.ollama
修改内容:
{
"registry": {
"mirrors": {
"registry.ollama.ai": "https://registry.ollama.ai"
}
}
}
这里是配置的阿里镜像源,也可配置其他镜像源。
重启ollama
2.3 下载支持工具的模型
ollama pull qwen2:7b

注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
实现
三、Spring Boot 项目依赖与yml修改
pom修改:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
</parent>
<groupId>com.example</groupId>
<artifactId>spring-langchain4j-ollama-tool</artifactId>
<version>1.0</version>
<properties>
<java.version>17</java.version>
<langchain4j.version>1.0.0-beta4</langchain4j.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>${langchain4j.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- 核心:用于启用 @AiService 声明式 AI 服务 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
</dependency>
<!-- 具体模型:用于集成本地 Ollama 服务 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama-spring-boot-starter</artifactId>
</dependency>
<!-- LangChain4j 的流式返回类型 Flux<String> 需要额外的模块支持。需要添加依赖。 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-reactor</artifactId>
<version>${langchain4j.version}</version>
</dependency>
</dependencies>
yml修改:
langchain4j:
ollama:
chat-model:
base-url: http://localhost:11434
model-name: qwen2:7b
temperature: 0.7
timeout: PT120S # 总超时时间 120 秒
connect-timeout: PT10S # 连接超时 10 秒
read-timeout: PT120S # 读取超时 120 秒
log-requests: true
log-responses: true
四、定义工具(@Tool 注解)
4.1 天气查询工具示例
package com.badao.ai.tool;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class WeatherTool {
@Tool("获取指定城市当前的天气状况")
public String getWeather(@P("城市名称,例如:Beijing") String city) {
if ("Beijing".equalsIgnoreCase(city)) {
return "北京现在是晴天,温度 25°C。";
}
return "无法获取 " + city + " 的天气信息。";
}
@Tool("获取当前时间")
public String getCurrentDateTime(@P("你希望了解当前日期和时间") String placeholder) {
return "当前时间是:" + LocalDateTime.now().toString();
}
}
4.2 智能客服工具示例(订单、物流、优惠券)
package com.badao.ai.tool;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class CustomerServiceTools {
// 模拟订单数据库
private static final Map<String, String> ORDER_STATUS_DB = new HashMap<>();
private static final Map<String, String> ORDER_LOGISTICS_DB = new HashMap<>();
private static final Map<String, String> COUPON_DB = new HashMap<>();
static {
ORDER_STATUS_DB.put("123456", "已发货");
ORDER_STATUS_DB.put("789012", "待支付");
ORDER_STATUS_DB.put("345678", "已完成");
ORDER_LOGISTICS_DB.put("123456", "申通快递:777888999,已揽件");
ORDER_LOGISTICS_DB.put("345678", "顺丰快递:SF123456789,已签收");
COUPON_DB.put("user_1", "满100减10元优惠券一张");
COUPON_DB.put("user_2", "无门槛5元优惠券一张");
}
@Tool("查询订单状态。根据订单号获取当前状态(已发货、待支付、已完成等)")
public String getOrderStatus(@P("订单号,例如 123456") String orderId) {
String status = ORDER_STATUS_DB.getOrDefault(orderId, "未找到该订单");
return "订单 " + orderId + " 当前状态:" + status;
}
@Tool("查询订单物流信息。根据订单号获取物流公司、单号及最新轨迹")
public String getLogistics(@P("订单号,例如 123456") String orderId) {
String logistics = ORDER_LOGISTICS_DB.getOrDefault(orderId, "暂无物流信息,可能订单尚未发货");
return "订单 " + orderId + " 物流信息:" + logistics;
}
@Tool("查询用户可用的优惠券。根据用户ID返回优惠券信息")
public String getCoupon(@P("用户ID,例如 user_1") String userId) {
String coupon = COUPON_DB.getOrDefault(userId, "您当前没有可用的优惠券");
return "用户 " + userId + " 的优惠券:" + coupon;
}
}
五、创建 AI 服务接口与 Bean
5.1 定义 Assistant 接口
智能天气:
package com.badao.ai.config;
import dev.langchain4j.service.SystemMessage;
public interface Assistant {
@SystemMessage("你是一个有帮助的AI助手。你可以使用工具来回答用户关于天气和时间的问题。")
String chat(String userMessage);
}
智能客服:
package com.badao.ai.config;
import dev.langchain4j.service.SystemMessage;
public interface CustomerServiceAssistant {
@SystemMessage("""
你是一个智能客服助手,可以回答用户关于订单状态、物流信息、优惠券等问题。
请使用提供的工具来获取准确信息。
如果用户询问订单状态,请调用 getOrderStatus 工具。
如果用户询问物流信息,请调用 getLogistics 工具。
如果用户询问优惠券,请调用 getCoupon 工具。
回答要简洁、友好,使用中文。
""")
String chat(String userMessage);
}
5.2 手动构建 AiServices Bean(推荐,避免自动扫描冲突)
package com.badao.ai.config;
import com.badao.ai.tool.CustomerServiceTools;
import com.badao.ai.tool.WeatherTool;
import dev.langchain4j.memory.chat.ChatMemoryProvider;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.service.AiServices;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiConfig {
@Bean
public ChatMemoryProvider chatMemoryProvider() {
// 为每个 memoryId 分配一个独立的 ChatMemory,保留最近 10 条消息
return memoryId -> MessageWindowChatMemory.withMaxMessages(10);
}
@Bean(name = "assistant")
public Assistant assistant(ChatModel chatModel, WeatherTool weatherService) {
return AiServices.builder(Assistant.class)
.chatModel(chatModel)
.tools(weatherService)
.build();
}
@Bean(name = "customAssistant")
public CustomerServiceAssistant customerServiceAssistant(ChatModel chatModel, CustomerServiceTools customerServiceTools) {
return AiServices.builder(CustomerServiceAssistant.class)
.chatModel(chatModel)
.tools(customerServiceTools)
.build();
}
}
注意:tools() 方法接收的是工具实例,而不是 Class。且 @SystemMessage 注解在接口方法上会被自动识别。
六、Controller 与测试
测试天气:
package com.badao.ai.controller;
import com.badao.ai.config.Assistant;
import org.springframework.web.bind.annotation.*;
@RestController
public class ChatController {
private final Assistant aiAssistant;
// 构造函数注入
public ChatController(Assistant aiAssistant) {
this.aiAssistant = aiAssistant;
}
@GetMapping("/ai/assistant")
public String askAssistant(@RequestParam String message) {
return aiAssistant.chat(message);
}
}
测试智能客服:
package com.badao.ai.controller;
import com.badao.ai.config.CustomerServiceAssistant;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/customer")
public class CustomerServiceController {
private final CustomerServiceAssistant assistant;
public CustomerServiceController(CustomerServiceAssistant assistant) {
this.assistant = assistant;
}
@GetMapping("/chat")
public String chat(@RequestParam("message") String message) {
return assistant.chat(message);
}
}
七、测试结果
测试智能天气:
curl "http://localhost:885/ai/chat?message=北京天气怎么样?"

测试智能客服:
curl "http://localhost:885/ai/chat?message=我的订单123456现在什么状态?
八、常见问题
(1)模型不支持 tools
错误信息:
400 Bad Request: {"error":"... does not support tools"}
原因:使用的模型不支持 Function Calling。
解决:改用 qwen2:7b、llama3.1:8b 等官方模型。
(2)Bean 名称冲突
错误信息:
ConflictingBeanDefinitionException: Annotation-specified bean name 'assistant' conflicts with existing
原因:同时使用了 @AiService 注解和手动 @Bean 创建。
解决:二选一。推荐手动创建,并在接口上移除 @AiService。
(3)Cannot resolve method 'systemMessage' in 'AiServices'
原因:手动构建时没有 systemMessage() 方法。
解决:使用接口方法上的 @SystemMessage 注解,或使用 systemMessageProvider()。
九、总结
模型选择:优先使用 Ollama 官方支持 Function Calling 的模型(如 qwen2:7b)。
工具定义:每个 @Tool 方法都要有清晰的描述,参数用 @P 注解。
依赖管理:使用 BOM 统一版本,避免混用 beta 和 rc 版本。
Bean 注册:手动创建 AiServices Bean 比注解更可控,避免扫描冲突。
系统提示词:放在接口方法的 @SystemMessage 中,保持声明式风格。
超时设置:本地模型推理较慢,务必调高 read-timeout。
测试验证:先用 curl 直接调用 Ollama API 确认模型支持工具,再集成到 Spring。
