Spring-AI入门与Spring-Boot接入笔记

O泡李华 5

Spring AI 入门笔记:模型接入、RAG、聊天记忆与工具调用

一、Spring AI 是什么

Spring AI 是 Spring 生态中的 AI 应用开发框架,提供模型调用、向量检索、工具调用等抽象,帮助应用连接 AI 模型、企业数据和业务接口。

它不是一个大模型,也不会因为加入依赖就自动拥有模型推理能力。应用仍然需要连接模型服务,例如云端模型 API,或者本地 Ollama 服务。

可以按下面的结构理解:

用户问题
   ↓
Spring Boot 应用
   ↓
Spring AI:组织消息、检索资料、调用工具等
   ↓
模型服务:执行推理、生成响应
   ↓
应用处理结果并返回

Spring AI 支持聊天、Embedding、部分图像和音频能力,以及向量存储、RAG、对话记忆、MCP 和可观测性等功能。具体能力取决于所用模块和模型提供方。Spring AI 官方介绍

二、Spring AI、Spring Boot 与大模型的关系

名称 主要作用
Spring Boot 应用启动、Web 接口、配置和依赖注入
Spring AI 对接模型,并组织 AI 调用流程
大模型 根据输入生成文本或其他响应
Ollama 在本地或指定服务器运行所支持的模型
向量数据库 保存向量及相关数据,支持相似度检索

Spring AI 通过统一 API 减少接入不同提供方的重复代码。不过,切换模型后仍要核对参数、上下文长度、工具调用和结构化输出支持,并重新评估效果。

三、先理解几个 AI 概念

1. Prompt:给模型的输入

Prompt 不只是用户输入的一句话,还可能包含角色要求、历史消息、检索资料、工具描述等内容。

例如:

角色要求:你是一位 Java 学习助手,使用中文,先解释概念,再给示例。
用户问题:Spring Boot 的依赖注入是什么?

提示词应表达任务、输入背景和输出要求,而不是依赖模糊指令。

2. 消息角色

角色 常见用途
System 应用预设的行为要求和任务背景
User 用户问题
Assistant 模型回复
Tool 工具执行结果,实际表示方式取决于提供方

System 消息不是业务权限系统。不能仅靠“禁止访问其他用户数据”的提示词实现数据隔离。

3. Token 与上下文窗口

Token 是模型处理文本等输入的计量单位,不等于一个汉字或一个英文单词。其划分取决于模型的分词方式。

上下文窗口限制模型一次能处理的上下文规模。系统提示、历史消息、检索材料、工具结果和输出预算都会消耗资源。历史越长,不代表回答一定越好。

4. Temperature

Temperature 是部分模型支持的采样参数。降低它通常使输出更集中,提高它通常增加多样性。

低 temperature 不保证答案正确,也不保证每次输出完全相同。参数范围和支持情况需要核对模型文档。

5. Embedding

Embedding 将文本等内容转换为向量,用于语义检索。例如,“退款要多久”和“退货后什么时候到账”文字不同,但可能在向量空间中较接近。

它主要用于匹配和检索,不是直接生成聊天答案。聊天模型与 Embedding 模型承担不同任务。

四、Spring AI 的核心组件

组件 用途
ChatModel 模型聊天调用的底层抽象
ChatClient 使用链式 API 构建和执行聊天请求
Prompt / Message 表示输入和消息
Advisor 在调用流程中组织记忆、检索等附加行为
ChatMemory 管理需要保留的对话消息
EmbeddingModel 将内容转换成向量
VectorStore 存储文档向量并执行相似度查询
ToolCallback / @Tool 定义应用允许模型请求使用的工具

下面这条调用链最适合入门:

String answer = chatClient.prompt()
        .user("用一个例子解释依赖注入")
        .call()
        .content();

prompt() 开始构建请求,user() 设置用户消息,call() 发起调用,content() 获取文本内容。需要用量、结束原因等元数据时,应获取更完整的响应对象。ChatClient 官方文档

五、接入前先匹配版本

官方当前文档说明,Spring AI 2.0.x 支持 Spring Boot 4.0.x 与 4.1.x。官方快速开始

本文采用:

项目项 本文设置
Java 17 或满足所选 Spring Boot 要求的更高版本
Spring Boot 选择兼容的 4.0.x / 4.1.x 正式版本
Spring AI 2.0.1
构建工具 Maven
模型运行服务 Ollama

已有 Spring Boot 3 项目,应核对 Spring AI 1.x 对应版本的兼容说明,不要直接将本文 BOM 复制进去。

还要区分版本文档:例如当前 Ollama 配置使用 spring.ai.ollama.chat.model,旧教程可能使用其他属性层次。框架 API、Starter 名称和配置属性变化时,优先以项目版本对应的文档为准。

六、Spring Boot 接入 Ollama 示例

这个示例用于理解一次基础聊天调用。使用本地模型前,需要确认机器内存、磁盘和推理性能适合所选模型。

1. 准备 Ollama 与模型

先安装并启动 Ollama,参考官方 Ollama 入口。选择一个适合本机、支持聊天的模型,然后在终端下载:

# 将“模型名称”替换成模型库中的实际标识
ollama pull 模型名称

# 查看已安装模型
ollama list

本文用环境变量 OLLAMA_CHAT_MODEL 指定实际模型名称,避免将不同机器的选择写死。

Ollama 常见本地地址为:

http://localhost:11434

Spring AI 依赖不会自动安装 Ollama,也不代表模型文件已经下载。Spring AI Ollama 接入文档

2. 创建 Spring Boot 项目

可以在 Spring Initializr 选择兼容的 Spring Boot 正式版本,添加 Spring Web 和 Ollama 相关依赖。

项目结构示例:

src/main/java/com/example/ai/
├── AiApplication.java
└── ChatController.java

src/main/resources/
└── application.yml

3. 管理 Spring AI 依赖版本

在已有 Spring Boot 项目的 pom.xml 中加入 BOM:

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

BOM 统一管理 Spring AI 模块版本,不会替你管理 Spring Boot 版本。已有 dependencyManagement 时应合并配置。

在 <dependencies> 中添加:

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

项目还需要 Spring Web 依赖,按所选 Spring Boot 版本由 Initializr 生成。正式发布的 Spring AI 依赖可从 Maven Central 获取。依赖管理说明

4. 配置 application.yml

server:
  port: 8080

spring:
  application:
    name: spring-ai-demo
  ai:
    model:
      chat: ollama
    ollama:
      base-url: http://localhost:11434
      chat:
        model: ${OLLAMA_CHAT_MODEL}
        temperature: 0.3

启动应用之前,将环境变量设为 ollama list 中实际存在的聊天模型名称。

Linux / macOS 的 Bash 示例:

export OLLAMA_CHAT_MODEL='实际模型名称'

Windows PowerShell 示例:

$env:OLLAMA_CHAT_MODEL = '实际模型名称'

这两种设置都只影响对应终端及之后启动的子进程。使用 IDEA 启动时,可以在运行配置的环境变量中设置。

应用如果运行在容器或其他机器上,localhost 指应用自身所在环境,需要改成应用可访问的 Ollama 地址。

5. 创建接口

创建 ChatController.java:

package com.example.ai;

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 ChatController {

    private final ChatClient chatClient;

    public ChatController(ChatClient.Builder builder) {
        this.chatClient = builder
                .defaultSystem("你是一位 Java 学习助手。使用中文,先解释概念,再给简短示例。")
                .build();
    }

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

在满足自动配置条件且只有合适的聊天模型配置时,Spring AI 会提供 ChatClient.Builder。本例仍需正常的 @SpringBootApplication 启动类,并将 Controller 放在其扫描范围内。

6. 验证接口

启动应用后,在 Bash 等终端中使用:

curl --get 'http://localhost:8080/ai/chat' \
  --data-urlencode 'message=用一个例子解释Spring的依赖注入'

上面的反斜线换行写法属于 Bash,不直接适用于 PowerShell。也可以使用 API 调试工具,设置 GET 参数 message。

预期调用链为:

HTTP 请求 → Controller → ChatClient → Ollama → 模型生成 → 返回文本

GET 适合这个最小演示;实际聊天接口可使用 POST 请求体,便于承载消息、会话标识等数据。输出内容由模型生成,不能期待固定答案。

七、流式输出:逐段返回生成内容

非流式调用通常等响应生成后再返回;流式调用允许应用逐段收到结果并发送给前端。

在上述 Controller 中可以追加:

@GetMapping(value = "/ai/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> stream(@RequestParam("message") String message) {
    return chatClient.prompt()
            .user(message)
            .stream()
            .content();
}

还需导入:

import org.springframework.http.MediaType;
import reactor.core.publisher.Flux;

此例使用 SSE 媒体类型,前端需要按事件流处理。分块内容不一定与一个汉字或一个 Token 一一对应。

网关、代理缓冲、超时和客户端取消都会影响流式体验,应一起验证。Flux 也不代表任意业务处理都可以忽略阻塞操作。ChatClient 流式 API

八、结构化输出:将结果映射成 Java 对象

如果应用需要字段而不是整段文本,可以定义一个结果类型:

public record TechnologySummary(String name, String purpose) {
}

在业务代码中请求映射:

TechnologySummary summary = chatClient.prompt()
        .user("介绍 Docker,name 填技术名称,purpose 填一句话用途。")
        .call()
        .entity(TechnologySummary.class);

结构化转换帮助组织输出,并不保证内容真实,也不保证所有提供方都以相同方式约束输出。应用要处理空值、转换失败,并对业务字段进行校验。

提供方原生 JSON Schema 支持与提示词加转换器是不同机制,应核对实际模型能力。结构化输出文档

九、聊天记忆:让多轮对话关联起来

前面的基础接口默认没有加入对话记忆。第二次请求不自动知道第一次用户问过什么。

例如:

第一轮:我正在学习 Spring Boot。
第二轮:它和 Spring MVC 有什么关系?

应用需要在第二轮提供必要的历史消息,模型才能理解“它”的上下文。

Spring AI 提供 ChatMemory 及相应 Advisor 来组织历史。通常需要:

  1. 选择记忆存储与窗口策略。
  2. 为每个对话关联 conversation ID。
  3. 在 ChatClient 调用中接入记忆 Advisor。
  4. 对会话所属用户进行服务端授权校验。

不要为所有用户复用一个固定 conversation ID,否则可能混入他人的消息。内存存储也不等于持久化,应用重启后可能丢失。

聊天记忆主要提供模型需要的上下文,不应当作完整审计记录;长对话要限制窗口或摘要,避免不断增加成本和噪声。Chat Memory 官方文档

十、RAG:让模型参考自己的知识库

RAG 是 Retrieval-Augmented Generation,即检索增强生成。它先从资料库找到相关内容,再让模型结合这些内容回答。

例如希望模型回答“公司退款规则是什么”,模型未必知道公司的最新制度;可以先检索制度文档,再将相关段落提供给模型。

1. 建库流程

读取资料
   ↓
清理内容、保留来源与权限元数据
   ↓
切分成文档片段
   ↓
Embedding 模型生成向量
   ↓
写入 VectorStore

2. 问答流程

flowchart LR
    U[用户问题] --> R[检索相关文档]
    V[向量存储及权限过滤] --> R
    R --> P[问题与检索内容组成上下文]
    P --> M[聊天模型]
    M --> A[答案与来源]

Spring AI 可以通过 VectorStore 和检索相关 Advisor 组织此流程,具体模块和依赖应按版本选择。RAG 官方文档

3. RAG 不等于训练模型

RAG 通常在请求时提供额外上下文,不修改模型参数。微调则涉及训练过程,两者解决的问题不同。

RAG 也不保证回答一定正确:资料可能过期,切分可能破坏上下文,检索可能选错段落,模型可能误解内容。

应关注来源、更新机制、权限过滤和检索评估。聊天模型可以与 Embedding 模型不同,但同一向量索引的建库和查询应使用匹配的 Embedding 模型与向量维度;换模型时通常需要重建索引。

找不到可靠资料时,应明确表达证据不足,而不是让模型自行补全制度或业务事实。

十一、工具调用:让模型请求使用业务能力

RAG 适合从资料中查知识,工具调用适合查询实时信息或执行受控业务动作。

例如用户问“订单 2001 目前是什么状态”,应用可以向模型提供一个订单查询工具。

工具调用的基本过程:

  1. 应用提供工具名称、说明和参数结构。
  2. 模型可能返回工具调用请求及参数。
  3. 应用验证请求,执行允许的工具。
  4. 工具结果返回模型,由模型组织回复。

**执行 Java 方法的是应用,不是模型直接获得数据库或 API 权限。**Spring AI 可以帮助处理调用循环。工具调用说明

@Tool 的基本写法示意:

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;

@Component
public class OrderTools {

    @Tool(description = "按订单编号查询演示订单状态,仅支持编号 2001")
    public String queryOrderStatus(Long orderId) {
        if (orderId == null || orderId != 2001L) {
            return "未找到演示订单";
        }
        return "订单 2001:已发货";
    }
}

上面返回的是固定演示数据,不代表真实数据库查询。将工具对象注入业务类后,可通过相应版本的 .tools(orderTools) API 提供给 ChatClient;模型必须支持工具调用才可使用。

仅将工具类注册成 Bean,不代表每次请求都自动拥有它。工具说明要清楚,执行时还需参数校验和用户授权;实际订单权限应根据服务端登录身份检查,不要相信模型生成的用户 ID。

写入型工具还需要幂等、审计和适当的确认机制,避免重复或越权执行。简单查询场景可先从只读工具练习。

十二、MCP 与 Agent 如何理解

MCP 是连接应用与工具、资源等能力的一种协议。Spring AI 支持相应客户端和服务端集成:可以消费外部 MCP 服务,也可以将 Spring 应用中的能力通过 MCP 暴露。

MCP 不是大模型,也不是 RAG 本身。它解决能力连接和交互方式的问题。

Agent 通常描述模型结合工具、状态和控制循环执行任务的应用模式。一次普通聊天调用不会自动成为能可靠完成复杂任务的 Agent;需要设计终止条件、工具范围、失败恢复和资源预算。

十三、实际项目需要补充什么

方面 需要关注
超时与限流 模型可能响应慢,需要整体时限和并发控制
重试 控制次数,避免重复工具动作与额外成本
可观测性 记录延迟、用量、失败类型,避免默认记录完整敏感输入
输出处理 校验字段,处理空响应、格式错误和内容不可靠的情况
数据隔离 会话、文档检索和业务工具都要关联真实权限
评估 用固定测试问题检查回答质量、来源准确性和工具行为
模型配置 模型名称、上下文长度和参数不能仅凭统一 API 推断

提示词和检索文档都可能包含误导模型的内容。业务授权与重要操作约束应由确定的应用逻辑执行。

十四、常见问题排查

问题 排查方向
找不到 ChatClient.Builder 检查 Starter、模型选择和自动配置条件
连接 Ollama 失败 检查服务是否启动、地址、端口及网络
提示模型不存在 用 ollama list 核对名称,先下载对应模型
配置没有生效 检查是否复制了其他版本的属性名称
每次对话都没有上下文 检查 ChatMemory、Advisor 和会话标识
模型不调用工具 检查模型支持、工具是否提供、描述与参数是否清楚
RAG 检索不到资料 检查建库、Embedding 一致性、过滤条件和阈值
输出无法映射成对象 检查模型输出、约束方式和目标类型,处理转换异常
流式响应直到最后才显示 检查客户端处理、代理缓冲和服务端流式链路
结果有事实错误 检查输入与证据,完善检索及评估,不只调整 temperature