原创

Spring Boot 使用 Spring AI 实战指南:从聊天调用到 RAG 落地

Spring AI 不是“给 Spring Boot 接个大模型 SDK”这么简单,它本质上是一个 面向 AI 工程的应用框架。它把 Spring 一贯强调的可移植性、模块化、自动装配和面向对象抽象带到了 AI 场景里,核心目标是把 企业数据、业务 API 和 AI 模型 连接起来,而不是只做一次简单的文本生成。到 2026 年 3 月,Spring AI 官方项目页显示稳定线为 1.0.x,Spring AI 1.0 已在 2025 年 5 月 GA,1.1 已在 2025 年 11 月 GA;官方文档当前明确支持 Spring Boot 3.4.x 和 3.5.x,并且 1.0.0 之后的构件已发布到 Maven Central。(Home)

Spring Boot 为什么适合用 Spring AI

如果你直接集成某个模型厂商的 SDK,通常会很快遇到几个问题:模型供应商切换成本高、Prompt 组织分散、结构化输出解析重复、聊天上下文管理混乱、向量库接入零散、RAG 链路缺少统一抽象。Spring AI 的价值就在于它在这些问题上提供了一层 统一 API:聊天模型、Embedding 模型、向量库、工具调用、结构化输出、聊天记忆、Advisor 拦截扩展,都可以放进 Spring Boot 的自动配置体系里。官方文档也明确把这些能力列为 Spring AI 的核心特性。(Home)

先明确版本边界

当前推荐的理解方式

如果你现在新建项目,建议按 Spring Boot 3.4.x / 3.5.x + Spring AI 1.0.x 或 1.1.x 的思路来写。官方 Getting Started 页面明确写了 Spring AI 支持 Spring Boot 3.4.x 和 3.5.x。(Home)

1.0 之后要注意的变化

Spring AI 1.0 GA 之后,官方建议通过 BOM 管理版本,并直接从 Maven Central 获取依赖。与此同时,自动配置和 starter 模块的 artifact 命名在 1.0 阶段发生过明显调整,向量库文档里也特别提示过这一点。(Home)

1.1 的新增方向

Spring AI 1.1 GA 的官方发布说明里,重点提到了 MCP(Model Context Protocol)集成、更多模型能力和更广的模型提供方支持。也就是说,如果你的目标已经不只是“调一下模型”,而是要让模型安全地接入工具、外部系统和上下文,Spring AI 1.1 会比早期版本更完整。(Home)

Spring Boot 中使用 Spring AI 的核心方式

在 Spring Boot 项目里,Spring AI 最常见的使用路径可以概括成四层:

  1. Model 层:接聊天模型、Embedding 模型、图像模型、语音模型。
  2. Client 层:通过 ChatClient 组织 Prompt、消息、参数和返回结果。
  3. 增强层:通过 Advisor、Chat Memory、Tool Calling 给调用链增加上下文和能力。
  4. 知识层:通过 VectorStore 和 RAG,把企业文档、数据库或业务知识接入模型。(Home)

真正做项目时,最常见的是下面三类落地场景:

  • AI 问答接口
  • 结构化数据抽取接口
  • 基于企业知识库的 RAG 问答接口

一个最小可运行的接入思路

下面先用 OpenAI 模型做示例。之所以选它,不是因为 Spring AI 只能接 OpenAI,而是因为它最容易说明 Spring AI 的统一编程模型。官方项目页明确说明,Spring AI 支持多个主流模型提供方,不局限于 OpenAI。(Home)

1. 引入依赖

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

<dependencies>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-model-openai</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

这里的重点不是具体厂商,而是两个原则: 一是 用 BOM 统一版本;二是 按能力引入 starter,比如聊天模型、向量库、Embedding 模型分别引入对应 starter。Spring AI 官方文档和 1.0 GA 发布说明都明确采用这种方式。(Home)

2. 配置 application.yml

spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      chat:
        options:
          model: gpt-4o-mini
          temperature: 0.2

官方 OpenAI Chat 文档中,公共连接前缀是 spring.ai.openai,聊天模型专属前缀是 spring.ai.openai.chatspring.ai.openai.chat.options.model 用来指定模型,默认示例里也列出了 gpt-4o-mini 等模型名。文档同时说明了:如果同时配置了公共属性和 chat 专属属性,chat 专属配置优先。(Home)

3. 写一个最简单的 Controller

package com.example.demo.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AiController {

    private final ChatClient chatClient;

    public AiController(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }

    @GetMapping("/ai/chat")
    public String chat(@RequestParam String message) {
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }
}

这段代码的核心在于:你不直接 new 某个模型 SDK 客户端,而是注入 Spring Boot 自动配置好的 ChatClient.Builder。官方 ChatClient 文档明确说明,Spring AI 会自动创建一个可注入的 ChatClient.Builder,最简单的调用链就是 .prompt().user(...).call().content()。(Home)

ChatClient 才是日常开发的主入口

很多人第一次接触 Spring AI,会以为重点是 OpenAiChatModel 之类的底层模型对象。实际上,业务开发最常用的入口通常是 ChatClient。Spring AI 1.0 GA 发布说明也专门强调,ChatClient 是核心且易用的主接口。(Home)

为什么优先用 ChatClient

因为它把几个高频动作统一了:

  • 组织 system / user / assistant 消息
  • 指定模型参数
  • 接入 Advisor
  • 处理结构化返回
  • 对接流式输出和工具调用

也就是说,模型是底层能力,ChatClient 才是上层编排入口。(Home)

一个更像生产代码的写法

package com.example.demo.service;

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

@Service
public class ArticleSummaryService {

    private final ChatClient chatClient;

    public ArticleSummaryService(ChatClient.Builder builder) {
        this.chatClient = builder
                .defaultSystem("你是一个严谨的技术助手,只输出准确、简洁、结构化的中文。")
                .build();
    }

    public String summarize(String content) {
        return chatClient.prompt()
                .user(u -> u.text("""
                        请总结下面内容,要求:
                        1. 提炼 3 个核心观点
                        2. 给出一句适合技术负责人阅读的结论
                        
                        内容:
                        {content}
                        """).param("content", content))
                .call()
                .content();
    }
}

这类写法适合把 Prompt 模板、默认 System Prompt 和业务逻辑放在服务层,而不是散落在 Controller 里。Spring AI 文档中对 Prompt 的描述也很明确:它本质上是消息集合,支持占位符替换、运行时注入和参数化构造。(Home)

Spring AI 最值得用的几个能力

1. 结构化输出

AI 返回纯文本很容易,但真正落地时,后端更需要的是 可被程序直接消费的数据结构。Spring AI 官方专门提供了 Structured Output Converter,用来把大模型输出映射成 JSON、XML 或 Java 类型;其中 BeanOutputConverter 会根据 Java 类生成 JSON Schema,再把输出转换成目标对象。(Home)

示例:把模型输出直接转成 Java 对象

package com.example.demo.dto;

public record MeetingConclusion(
        String summary,
        String riskLevel,
        String actionItem
) {
}
package com.example.demo.service;

import com.example.demo.dto.MeetingConclusion;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.converter.BeanOutputConverter;
import org.springframework.stereotype.Service;

@Service
public class MeetingAnalysisService {

    private final ChatClient chatClient;

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

    public MeetingConclusion analyze(String transcript) {
        BeanOutputConverter<MeetingConclusion> converter =
                new BeanOutputConverter<>(MeetingConclusion.class);

        String content = chatClient.prompt()
                .system("你是会议纪要分析助手。")
                .user(u -> u.text("""
                        请从下面会议内容中提取结果,并严格按照指定格式输出:
                        
                        {format}
                        
                        会议内容:
                        {transcript}
                        """)
                        .param("format", converter.getFormat())
                        .param("transcript", transcript))
                .call()
                .content();

        return converter.convert(content);
    }
}

这个能力的价值不在“少写几行 JSON 解析代码”,而在于它把 Prompt 约束、格式说明、结果解析 统一进 Spring 的转换体系里,后端服务可以更稳定地消费模型输出。(Home)

2. Chat Memory

大模型本身是无状态的。Spring AI 官方 Chat Memory 文档明确指出,LLM 默认不会保留前文状态,因此 Spring AI 提供了 ChatMemory 抽象,用来跨多轮对话保存和检索上下文。默认自动配置通常会使用内存型仓库和 MessageWindowChatMemory,默认窗口大小是 20 条消息。(Home)

什么时候该用 Chat Memory

适合下面这类场景:

  • 一个用户连续追问同一主题
  • 客服机器人要记住前几轮上下文
  • 需求澄清型 Copilot 要保持短会话一致性

什么时候不该把它当历史库

官方文档特别强调了 Chat Memory 和 Chat History 不是一回事。Chat Memory 是给模型维持当前上下文用的,不适合拿来做全量会话归档;如果要保存完整历史记录,应该交给数据库和 Spring Data 这一类存储层来做。(Home)

3. Tool Calling

Spring AI 支持工具调用,官方文档把它定义为一组统一抽象,让模型可以请求执行本地工具或服务。当前文档里也明确给出了 ToolCallback 这一套 API,并且迁移指南说明旧的 FunctionCallback 已被新的 ToolCallback 体系替代。(Home)

这意味着你可以把现有 Java 方法、业务服务甚至外部能力,暴露成模型可调用的工具,而不是让模型“凭空编答案”。

一个典型理解

比如你做一个报表助手:

  • 模型负责理解用户意图
  • 工具负责真正查数据库
  • 最后再由模型把查到的真实结果组织成自然语言

这类模式的价值在于:事实由系统提供,表达由模型负责。这比让模型自己瞎猜数据库结果可靠得多。(Home)

4. Advisor

Advisor 是 Spring AI 很容易被忽略、但实际很重要的能力。官方文档明确说明,Advisor API 用来在 AI 调用链中拦截、修改和增强请求与响应,适合封装可复用的生成式 AI 模式。(Home)

它适合解决什么问题

比如下面这些都适合放进 Advisor:

  • 每次调用前自动注入租户信息
  • 自动附加统一系统提示词
  • 调用前追加检索到的知识片段
  • 统一记录 token、耗时和审计日志
  • 对输出做后处理或敏感词过滤

在传统 Spring 里你会想到拦截器、过滤器、AOP;在 Spring AI 里,Advisor 可以理解为更贴近 AI 调用链的增强机制。(Home)

5. Vector Store 与 RAG

如果你的目标是“让模型回答企业内部知识”,那真正关键的不是聊天模型本身,而是 Embedding + 向量库 + 检索增强生成(RAG)。Spring AI 官方向量数据库文档明确说明,向量库的基本过程是:先把文档写入向量库,再在用户提问时做相似度检索,把相关文档作为上下文发给模型。(Home)

为什么 Spring Boot 项目里特别适合做 RAG

因为企业知识通常已经在这些地方:

  • MySQL / PostgreSQL
  • 文件系统
  • 对象存储
  • 内部接口
  • 现有 Spring Boot 微服务

Spring AI 做的不是发明一套新 Web 框架,而是让你把这些现有数据源更顺畅地接到模型侧。(Home)

用 PGvector 做一个 RAG 示例

PGvector 是 PostgreSQL 的向量扩展,Spring AI 官方有单独的 PGvector VectorStore 文档。它支持把文档 Embedding 存到 PostgreSQL 中,再做相似搜索。官方文档还给出了 starter 名称,以及向量表的典型结构。(Home)

1. 依赖

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

<dependencies>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-model-openai</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-vector-store-pgvector</artifactId>
    </dependency>

    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
</dependencies>

spring-ai-starter-vector-store-pgvector 是官方文档明确给出的 starter 名称。(Home)

2. 数据库准备

官方文档展示的默认表示例里,向量表通常叫 vector_store,包含主键、内容、元数据和 embedding 向量字段。下面给出一份完整建表 SQL,结构与官方示例保持一致,并补充了扩展创建语句。需要注意,维度要与你实际使用的 Embedding 模型一致。官方 PGvector 页面示例使用的是 1536 维,并明确提示如果模型维度不同要替换。(Home)

CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE TABLE IF NOT EXISTS vector_store (
    id uuid DEFAULT uuid_generate_v4() PRIMARY KEY,
    content text,
    metadata json,
    embedding vector(1536)
);

CREATE INDEX IF NOT EXISTS vector_store_embedding_hnsw_idx
ON vector_store USING HNSW (embedding vector_cosine_ops);

3. 配置文件

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/ai_demo
    username: postgres
    password: postgres

  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      embedding:
        options:
          model: text-embedding-3-small

    vectorstore:
      pgvector:
        initialize-schema: false
        index-type: HNSW
        distance-type: COSINE_DISTANCE
        dimensions: 1536
        max-document-batch-size: 10000

这里有两个关键点。 第一,PGvector 文档明确写了,新版本里 schema 初始化不再默认开启,要显式设置 initialize-schema 或在构造时选择启用;这与早期版本默认自动初始化不同,是一个典型版本差异。第二,向量维度必须与 Embedding 模型输出维度一致,否则写入和检索都会出问题。(Home)

4. 写入知识库

package com.example.demo.service;

import jakarta.annotation.PostConstruct;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service
public class KnowledgeInitService {

    private final VectorStore vectorStore;

    public KnowledgeInitService(VectorStore vectorStore) {
        this.vectorStore = vectorStore;
    }

    @PostConstruct
    public void init() {
        List<Document> documents = List.of(
                new Document(
                        "Spring Boot 是一个用于快速构建独立运行 Spring 应用的开发框架。",
                        Map.of("source", "spring-boot.txt", "category", "spring")
                ),
                new Document(
                        "Spring AI 提供 ChatClient、EmbeddingModel、VectorStore、Tool Calling 等统一抽象。",
                        Map.of("source", "spring-ai.txt", "category", "spring-ai")
                )
        );

        vectorStore.add(documents);
    }
}

Spring AI 官方文档对向量库的通用使用方式说得很直接:通常会先把数据加载成 Document,然后调用 VectorStoreadd 方法写入。(Home)

5. 基于知识库问答

package com.example.demo.service;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;

@Service
public class RagService {

    private final ChatClient chatClient;
    private final VectorStore vectorStore;

    public RagService(ChatClient.Builder builder, VectorStore vectorStore) {
        this.chatClient = builder.build();
        this.vectorStore = vectorStore;
    }

    public String ask(String question) {
        return chatClient.prompt()
                .advisors(new QuestionAnswerAdvisor(vectorStore))
                .user(question)
                .call()
                .content();
    }
}

这个示例的关键不是 QuestionAnswerAdvisor 这个类名本身,而是它代表的思路:先检索,再把检索结果注入 Prompt,最后再由模型回答。Spring AI 当前 API 文档中明确说明,相关 Advisor 会从 Vector Store 中检索上下文并加入用户问题文本。(Home)

实际项目里该怎么设计

场景一:只做文本生成

如果你的需求只是:

  • 文章润色
  • 邮件生成
  • 摘要总结
  • 翻译改写

那只要:

  • spring-ai-starter-model-xxx
  • ChatClient
  • 少量 Prompt 模板

就够了。不要一上来就做 RAG、Memory、Tool Calling。简单问题简单解。(Home)

场景二:做企业知识问答

如果你的需求是:

  • 问公司制度
  • 问接口文档
  • 问产品说明
  • 问历史工单经验

那重点不是堆 Prompt,而是:

  • 文档清洗
  • 分块策略
  • Embedding 模型选择
  • 向量库索引参数
  • 检索召回质量
  • Prompt 注入方式

这已经是一个标准 RAG 项目。Spring AI 提供统一抽象,但知识库效果好不好,主要还是取决于你怎么做数据工程。官方文档也把文档加载、向量库和 RAG 单独拆成了专门主题。(Home)

场景三:做业务执行型 AI 助手

如果你的需求是:

  • 帮用户查订单
  • 帮用户创建工单
  • 帮用户生成报表
  • 帮销售读取 CRM 数据

那重点是:

  • Tool Calling
  • 权限控制
  • 参数校验
  • 审计日志
  • 幂等处理
  • 外部系统调用失败兜底

这类系统的关键不是模型“聪明”,而是工具调用链要可靠。Spring AI 提供的是统一工具抽象,不会替你省掉业务系统本身的安全和治理工作。(Home)

使用 Spring AI 时最容易踩的坑

1. 把 Spring AI 当成“某个模型厂商 SDK 的皮肤”

这是最常见误解。Spring AI 的价值不只是发请求,而是统一模型调用、上下文管理、知识检索、工具集成和输出转换。如果你只是想做一次裸调用,直接 SDK 也能做;只有当应用进入工程化阶段,Spring AI 的优势才会真正体现出来。(Home)

2. 把 Chat Memory 当聊天记录表

官方文档明确区分了 memory 和 history。Memory 是给模型维持“当前上下文”的,不是给你做全量会话归档的。全历史记录应该落数据库。(Home)

3. 向量维度和模型不匹配

PGvector 的列维度、配置里的 dimensions、你实际选用的 Embedding 模型输出维度,三者必须一致。官方 PGvector 文档和 Embedding 文档都明确强调了这一点。(Home)

4. 升级后沿用旧 starter 名称和旧初始化行为

Spring AI 1.0 前后存在 starter 命名和自动配置变化;PGvector 的 schema 自动初始化默认值也发生过 breaking change。升级时不看升级说明,项目很容易启动失败或行为异常。(Home)

5. 迷信 Prompt,忽视后端治理

在生产系统里,AI 应用的质量通常由这些环节共同决定:

  • Prompt
  • 数据质量
  • 检索质量
  • 工具可用性
  • 输出校验
  • 可观测性

Spring AI 官方能力里已经把工具调用、结构化输出、向量库、Observability 都纳入整体体系,这本身就说明:AI 应用不是“写几句 Prompt”这么简单。(Home)

一个更实用的学习路线

如果你准备在 Spring Boot 项目里正式使用 Spring AI,建议按这个顺序学:

第一步:先掌握最小聊天调用

目标是熟悉:

  • starter 依赖
  • 配置项
  • ChatClient
  • Prompt 构造

第二步:再做结构化输出

目标是让模型输出能直接进入你的服务逻辑,而不是停留在“给用户看一段文本”。

第三步:再做 Chat Memory 或 Advisor

目标是把多轮上下文和统一增强逻辑沉淀下来。

第四步:最后做 RAG 和 Tool Calling

因为这两个部分最容易把 Demo 做成、却最容易把生产系统做坏。前者依赖数据工程,后者依赖业务治理。(Home)

总结

在 Spring Boot 里使用 Spring AI,正确的理解不是“怎么接 OpenAI”,而是“怎么把 AI 能力纳入现有 Spring 工程体系”。它最重要的价值有三点: 第一,提供统一抽象,降低模型和向量库切换成本;第二,把 ChatClient、Memory、Advisor、Tool Calling、Structured Output 这些工程化能力收敛到同一套编程模型;第三,让企业已有的数据、服务和 Spring Boot 基础设施更自然地接入 AI 应用。(Home)

如果只是做一个 Demo,Spring AI 会让你写得更顺手;如果要做真正上线的 AI 应用,Spring AI 的意义才会真正放大,因为它解决的不是“能不能调用模型”,而是 Spring Boot 项目如何以可维护、可扩展、可治理的方式接入 AI。(Home)

正文到此结束
评论插件初始化中...
Loading...