【Spring AI 实战】从零开始调用大模型接口,构建 Java AI 应用

Spring AI 实战:从零开始调用大模型接口,构建 Java AI 应用

一、为什么需要 Spring AI?

随着大语言模型(LLM)在企业应用中的普及,Java 开发者开始面临一个新问题:如何将大模型能力集成到现有的 Spring Boot 系统中?

传统方式通常是使用 RestTemplate、WebClient 或 HTTP 客户端,手动构造请求 JSON、设置 API Key、处理响应结果和异常。虽然这种方式可以实现模型调用,但当系统需要切换模型供应商、增加流式输出、接入知识库或实现多轮对话时,代码维护成本会逐渐增加。

Spring AI 正是为解决这些问题而设计的 AI 应用开发框架。它借鉴 Spring 生态的设计理念,为不同大模型提供统一的调用抽象,并支持提示词管理、结构化输出、对话记忆、RAG 检索增强生成和工具调用等能力。

官方文档:https://docs.spring.io/spring-ai/reference/

本文将从最基础的接口调用开始,逐步实现一个可运行的 Spring Boot 大模型服务。

二、Spring AI 的核心架构

Spring AI 并不是一个新的大模型,而是 Java 应用与大模型服务之间的适配层。

典型调用链路如下:

text 复制代码
用户请求
   |
   v
Spring Boot Controller
   |
   v
业务 Service
   |
   v
Spring AI ChatClient
   |
   v
ChatModel 模型适配层
   |
   v
HTTP API 请求
   |
   v
大模型服务
   |
   v
模型响应 -> 解析 -> 返回业务系统

Spring AI 的几个核心组件如下:

组件 主要作用
ChatClient 提供简洁、流畅的大模型调用 API
ChatModel 抽象底层聊天模型的调用能力
Prompt 封装系统指令、用户输入和模型调用选项
ChatResponse 承载模型响应及相关元数据
Advisors 扩展对话记忆、RAG 等通用 AI 处理流程

其中,日常业务开发优先使用 ChatClient;当需要更底层的模型控制或处理完整响应元数据时,可以使用 ChatModel。

Spring AI 的模型抽象使应用能够在支持的模型实现之间切换,减少业务代码对特定供应商 API 的直接依赖。

三、创建 Spring Boot 项目

3.1 环境准备

本文示例使用以下技术栈:

  • JDK 17 或更高版本。
  • Maven 3.8+。
  • Spring Boot 3.5.x。
  • Spring AI 1.0.x。
  • 一个兼容 OpenAI Chat Completions API 的大模型服务。

为了便于在现有 Spring Boot 项目中集成,本文采用 Spring AI 1.0.x 版本体系。实际项目应选择与 Spring Boot 版本兼容的 Spring AI 版本,并使用对应版本的官方文档。

3.2 添加 Maven 依赖

在 pom.xml 中添加以下依赖:

xml 复制代码
<properties>
    <java.version>17</java.version>
    <spring-ai.version>1.0.9</spring-ai.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>${spring-ai.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring AI OpenAI 兼容模型适配器 -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-model-openai</artifactId>
    </dependency>
</dependencies>

这里使用 OpenAI 兼容模型适配器,并不意味着只能连接 OpenAI 官方服务。只要目标服务实现了兼容的接口协议,就可以根据服务商提供的地址、密钥和模型名称进行配置。

如果使用其他 Spring AI 版本,请以对应版本的依赖坐标和配置属性为准。

四、配置大模型 API

大模型接口通常需要三个核心参数:

  1. base-url:模型服务的 API 地址。
  2. api-key:用于身份认证的访问密钥。
  3. model:需要调用的模型名称。

在 src/main/resources/application.yml 中添加配置:

yaml 复制代码
server:
  port: 8080

spring:
  ai:
    openai:
      base-url: ${LLM_BASE_URL}
      api-key: ${LLM_API_KEY}
      chat:
        options:
          model: ${LLM_MODEL}
          temperature: 0.3

这里通过环境变量注入参数,而不是将真实密钥直接写入源代码。

例如,在本地开发环境中设置:

bash 复制代码
# 以下地址、密钥和模型名仅为配置示例
export LLM_BASE_URL="https://your-llm-provider.example"
export LLM_API_KEY="your-api-key"
export LLM_MODEL="your-model-name"

注意:

  • LLM_BASE_URL 应填写供应商要求的 API 基础地址,不要未经确认就自行拼接 /v1。
  • LLM_MODEL 必须使用服务商实际支持的模型标识。
  • temperature 用于控制生成随机性,具体支持范围以模型服务为准。

Spring AI 会根据配置自动创建相应的模型组件,并提供可注入的 ChatClient.Builder。

五、第一种方式:使用 ChatClient 调用大模型

这是最常见、也最适合业务开发的调用方式。

5.1 创建业务服务

创建 AiService.java:

java 复制代码
package com.example.demo.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;

@Service
public class AiService {

    private final ChatClient chatClient;

    public AiService(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }

    public String chat(String message) {
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }
}

这段代码完成了最核心的大模型调用逻辑。

逐步分析:

第一步:构建 ChatClient

java 复制代码
this.chatClient = builder.build();

通过 Spring 自动配置提供的 ChatClient.Builder 创建客户端,无须手动管理底层 HTTP 请求和 JSON 解析。

第二步:设置用户输入

java 复制代码
.user(message)

将业务系统收到的问题作为用户消息传给模型。

第三步:发起同步调用

java 复制代码
.call()

选择同步响应模式。实际模型调用会在读取响应内容等终结操作执行时触发。

第四步:获取文本结果

java 复制代码
.content();

提取模型生成的文本,方便控制器或其他业务逻辑使用。

5.2 创建 REST 接口

创建 AiController.java:

java 复制代码
package com.example.demo.controller;

import com.example.demo.service.AiService;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RestController
@RequestMapping("/api/ai")
public class AiController {

    private final AiService aiService;

    public AiController(AiService aiService) {
        this.aiService = aiService;
    }

    @PostMapping("/chat")
    public Map<String, String> chat(
            @RequestBody Map<String, String> request) {

        String message = request.get("message");

        if (message == null || message.isBlank()) {
            throw new IllegalArgumentException("message 不能为空");
        }

        String answer = aiService.chat(message);

        return Map.of("answer", answer);
    }
}

现在,Java 应用已经具备一个可以调用大模型的 HTTP 接口。

5.3 启动与测试

启动 Spring Boot 项目后,使用以下命令测试:

bash 复制代码
curl -X POST "http://localhost:8080/api/ai/chat" \
  -H "Content-Type: application/json" \
  -d '{"message":"请解释什么是大语言模型"}'

请求 JSON:

json 复制代码
{
  "message": "请解释什么是大语言模型"
}

返回结果示例:

json 复制代码
{
  "answer": "大语言模型是一类基于大规模文本数据训练的人工智能模型,能够理解和生成自然语言,并执行问答、总结、分类等任务。"
}

以上返回内容仅为格式示例,实际回答由所配置的模型生成。

至此,一个基础的大模型调用服务就搭建完成了。

六、第二种方式:使用 ChatModel 直接调用

除了 ChatClient,还可以直接使用 ChatModel。

java 复制代码
package com.example.demo.service;

import org.springframework.ai.chat.model.ChatModel;
import org.springframework.stereotype.Service;

@Service
public class DirectChatService {

    private final ChatModel chatModel;

    public DirectChatService(ChatModel chatModel) {
        this.chatModel = chatModel;
    }

    public String chat(String message) {
        return chatModel.call(message);
    }
}

这种方式更加直接,适合简单的模型调用场景。

两种方式的区别:

对比维度 ChatClient ChatModel
API 风格 流畅式调用 模型抽象接口
系统指令和用户消息组合 方便 可通过 Prompt 实现
Advisor 扩展 支持 通常需自行组织调用流程
获取文本回答 .call().content() call(message)
推荐用途 常规业务开发 底层模型调用和精细控制

需要注意:如果应用需要在同一个请求中组合系统指令、用户输入、对话记忆以及检索上下文,优先使用 ChatClient 通常更方便。

七、进阶一:通过 System Prompt 约束模型行为

在实际业务中,仅仅将用户问题发送给模型往往不够。我们通常还需要限定模型的身份、输出风格和回答边界。

例如,构建一个面向工业场景的技术助手:

java 复制代码
public String industrialAssistant(String question) {
    return chatClient.prompt()
            .system("""
                你是一名工业技术助手。
                回答应专业、准确、结构清晰。
                对于缺少数据支撑的结论,应明确说明不确定性。
                不得将未经验证的推测描述为确定事实。
                """)
            .user(question)
            .call()
            .content();
}

这里的 system() 用于提供系统级指令,user() 用于传递本次业务问题。

例如,用户询问"如何分析设备振动异常",模型会根据系统指令组织回答,而不是仅依据问题自由发挥。

但要注意:Prompt 只能引导模型行为,并不能保证模型永远正确。对于生产控制、设备保护和安全操作等场景,关键结论仍需要结合实时数据、企业规程及专业人员审核。

八、进阶二:使用模板参数构建动态提示词

实际应用中,提示词往往需要包含动态变量,例如设备名称、测量值和报警等级。

可以通过模板参数组织输入:

java 复制代码
public String diagnose(String device, String value) {
    return chatClient.prompt()
            .user(u -> u
                    .text("""
                        请分析以下设备数据:

                        设备名称:{device}
                        当前测量值:{value}

                        请给出可能原因、需要核查的数据和后续建议。
                        """)
                    .param("device", device)
                    .param("value", value))
            .call()
            .content();
}

这种写法比直接拼接长字符串更加清晰,也更容易复用提示词模板。

不过,提示词参数并不等于安全校验。用户输入仍需进行长度限制、权限检查和必要的数据清洗。

九、进阶三:实现流式输出

同步调用需要等待模型生成结果后再返回完整文本。如果模型回答较长,用户可能需要等待较久。

流式输出可以让前端逐步接收生成内容。

Spring AI 的 ChatClient 支持通过 stream() 获取响应流。结合 Spring WebFlux,可以将结果以 Server-Sent Events(SSE)形式返回前端。

在项目中添加响应式 Web 依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

创建流式接口:

java 复制代码
package com.example.demo.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/api/ai")
public class AiStreamController {

    private final ChatClient chatClient;

    public AiStreamController(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }

    @GetMapping(
        value = "/stream",
        produces = MediaType.TEXT_EVENT_STREAM_VALUE
    )
    public Flux<String> stream(
            @RequestParam String message) {

        return chatClient.prompt()
                .user(message)
                .stream()
                .content();
    }
}

测试请求:

bash 复制代码
curl -N \
  "http://localhost:8080/api/ai/stream?message=介绍Spring%20AI"

客户端可以逐步接收模型生成的文本,而不必等到完整回答生成后才开始展示。

注意:流式接口需要模型服务支持流式响应。若使用 Spring MVC 与 WebFlux 混合依赖,应明确项目采用的 Web 技术栈,避免配置冲突。生产环境还需要考虑客户端断开、请求超时、取消订阅及异常事件的处理。

十、企业应用中需要注意的问题

完成接口调用只是第一步。真正上线时,还需要关注以下问题。

10.1 API Key 安全

不要把 API Key 提交到 Git 仓库,也不要通过前端代码直接暴露密钥。应使用环境变量、密钥管理服务或部署平台的 Secret 机制。

10.2 超时与重试

模型接口可能受到网络波动、服务限流和推理耗时影响。需要根据模型服务能力配置合理的连接超时、读取超时及重试策略。

对于限流、网络错误等可恢复异常,可以进行有限次数的退避重试;对于参数错误、认证失败等问题,应优先修复配置,而不是反复请求。

10.3 日志与监控

建议记录请求耗时、模型标识、调用状态、Token 用量和错误类型。生产环境应对敏感数据进行脱敏,避免将密钥、个人信息或企业机密写入普通日志。

10.4 并发与成本控制

大模型调用通常具有较高的网络延迟和推理成本。应根据业务规模设置并发限制、请求队列、调用配额及必要的缓存机制,避免突发请求造成服务过载。

10.5 结果可靠性

大模型回答不应直接等同于业务事实。对于设备联锁、工艺参数调整、质量判定等关键场景,应结合规则引擎、实时数据、权限体系和人工确认机制,确保输出能够被验证和追溯。

十一、总结

Spring AI 为 Java 开发者提供了统一的大模型集成方式。通过 ChatClient,开发者可以使用简洁的链式 API 完成模型调用;通过 ChatModel,可以更直接地访问底层聊天模型能力;结合系统提示词、动态模板和流式响应,还可以逐步构建更加完整的 AI 应用。

对于已经使用 Spring Boot 的企业系统,推荐采用以下演进路线:

  1. 基础调用: 使用 ChatClient 实现问答接口。
  2. 业务约束: 添加系统提示词和模板参数。
  3. 交互优化: 根据需要支持流式输出。
  4. 知识增强: 通过 Advisors 和向量检索构建 RAG。
  5. 能力扩展: 接入工具调用、业务 API 和智能体工作流。
  6. 生产部署: 补齐权限、监控、超时、限流和安全审计。

大模型的价值不仅在于能够回答问题,更在于将语言理解、知识检索和业务系统能力整合到现有应用中。Spring AI 提供了连接这两类能力的一条实用技术路径。

相关推荐
漫步的猪1 小时前
# 告别混乱与付费墙!Linkit:完全免费、本地优先的开源 AI 智能书签与收藏夹管理神器
人工智能·ai·开源·react·免费·书签·收藏夹
深圳市益普科技有限公司1 小时前
半导体良率管理YMS:良率与设备参数的相关性,先拉哪几组数据
人工智能·python·算法
“AI国潮设计-小江”2 小时前
【AIGC实战】Python+SDXL打造“潮汕英歌舞IP”万能立牌插件,批量生成“发财元宝蛋糕”视觉营销方案(附源码)
开发语言·人工智能·python·prompt·aigc
Song_RsHt2 小时前
Redis 与微服务,什么场景下无可替代
java·redis·后端·学习·微服务
xsd202411182 小时前
Hy Image3.5:一张提示词,怎么撑起一整套品牌广告
人工智能
sbjdhjd2 小时前
AI产业周度动态:从“更强模型”走向“可执行、可治理、可计价”的系统竞争 (2026年10月19日—10月25日)
人工智能·笔记·ai·开源·gemini·信息差·claude code
学长毕设2 小时前
基于SpringBoot的建筑材料管理系统-附源码
java·spring boot·后端
程序员cxuan2 小时前
掀桌子了!Kimi K3.1 Pro 这效果也太离谱了。
人工智能·后端·程序员
摸爬滚打的小李2 小时前
关于 Arthas
java·后端