Spring AI 实战系列|第 1 篇 Spring AI 概述与快速上手(含环境搭建 + 核心概念)
~📊 本文约 6439 字,阅读时间约 22 分钟。~
本文面向具备 Spring Boot 基础的 Java 开发者,旨在系统梳理 Spring AI 的核心概念与工程实践。阅读前建议对 AI 基础术语有初步了解。
文章目录
- [Spring AI 实战系列|第 1 篇 Spring AI 概述与快速上手(含环境搭建 + 核心概念)](#Spring AI 实战系列|第 1 篇 Spring AI 概述与快速上手(含环境搭建 + 核心概念))
-
- 前言
- [1. Spring AI 到底是什么](#1. Spring AI 到底是什么)
-
- [1.1 诞生背景](#1.1 诞生背景)
- [1.2 核心定位](#1.2 核心定位)
- [1.3 与 LangChain4j 的对比](#1.3 与 LangChain4j 的对比)
- [2. Spring AI 解决了什么痛点](#2. Spring AI 解决了什么痛点)
-
- [2.1 供应商锁定](#2.1 供应商锁定)
- [2.2 Prompt 管理混乱](#2.2 Prompt 管理混乱)
- [2.3 企业级能力缺失](#2.3 企业级能力缺失)
- [3. 快速上手:第一个 Spring AI 项目](#3. 快速上手:第一个 Spring AI 项目)
-
- [3.1 环境准备](#3.1 环境准备)
- [3.2 创建项目](#3.2 创建项目)
- [3.3 添加依赖](#3.3 添加依赖)
- [3.4 配置 API Key](#3.4 配置 API Key)
- [3.5 编写第一个 Controller](#3.5 编写第一个 Controller)
- [3.6 启动并测试](#3.6 启动并测试)
- [3.7 流式输出](#3.7 流式输出)
- [4. 核心概念速览](#4. 核心概念速览)
-
- [4.1 Model(模型)](#4.1 Model(模型))
- [4.2 Prompt(提示词)](#4.2 Prompt(提示词))
-
- [Prompt 不是简单的字符串](#Prompt 不是简单的字符串)
- [Message 的三种角色](#Message 的三种角色)
- [PromptTemplate 动态模板](#PromptTemplate 动态模板)
- [4.3 Embedding(嵌入)](#4.3 Embedding(嵌入))
-
- [什么是 Embedding](#什么是 Embedding)
- [为什么需要 Embedding](#为什么需要 Embedding)
- 代码示例
- [4.4 Token](#4.4 Token)
-
- [Token 是什么](#Token 是什么)
- [为什么 Token 很重要](#为什么 Token 很重要)
- [Token 计数](#Token 计数)
- [4.5 四个概念的关系](#4.5 四个概念的关系)
- [5. 版本说明与选型建议](#5. 版本说明与选型建议)
-
- [5.1 当前版本状态](#5.1 当前版本状态)
- [5.2 本系列的选择](#5.2 本系列的选择)
- [5.3 Spring Boot 版本匹配](#5.3 Spring Boot 版本匹配)
- [6. 常见问题](#6. 常见问题)
- 参考资源
- 写在最后
前言
从事 Java 开发多年,笔者最初对 AI 领域持审慎态度。彼时 AI 技术栈以 Python 生态为主导,LangChain、LlamaIndex 等框架虽成熟,但切换技术栈对 Java 团队而言成本较高。
2024 年 Spring AI 正式发布后,这一局面得以改观。Java 开发者得以在熟悉的 Spring 生态中构建大模型应用,无需迁移至 Python 技术栈。
本文内容分为两部分:首先阐述 Spring AI 的核心价值与技术定位,随后通过完整的工程实践,指导读者从零搭建环境并实现首个 AI 对话接口。
1. Spring AI 到底是什么
1.1 诞生背景
2023 年 ChatGPT 引发的技术浪潮,推动了大模型能力向业务系统的集成需求。技术社区中,"如何接入 GPT-4"、"AI 智能客服实现方案"等议题成为讨论热点。
Python 生态率先响应,LangChain、LlamaIndex 等框架快速迭代,短期内形成了较为完善的工具链。相较之下,Java 生态的应对显得滞后:多数团队仍采用手写 HTTP 客户端调用 OpenAI API 的方式,代码耦合度高,模型提供商切换成本大。Prompt 管理、对话记忆等高级功能,往往需要自行在业务层实现。
Spring 团队于 2024 年推出 Spring AI,其定位明确:为 Java 开发者提供符合 Spring 设计哲学的 AI 应用开发框架。该框架并非简单的 HTTP 客户端封装,而是将 AI 能力深度融入 Spring 生态,支持依赖注入、自动配置、Starter 机制等核心特性。
1.2 核心定位
Spring AI 并非 LangChain 的 Java 移植版本,亦非特定 AI 厂商的 SDK 封装。它是面向 Spring 生态的专用 AI 框架,核心价值体现在三个维度:
可移植的抽象层
通过统一 API 对接 OpenAI、Anthropic、DeepSeek、Ollama、智谱等主流模型提供商。模型切换仅需调整配置,无需修改业务代码。此特性在多模型选型、成本控制及合规要求等场景中具有显著工程价值。
Spring 原生体验
框架遵循 Spring 设计哲学,提供自动配置、Starter 依赖、依赖注入等核心机制。开发者可直接使用 @Autowired、@ConfigurationProperties 等既有能力。若具备 Spring Boot 开发经验,学习曲线较为平缓。
企业级能力
涵盖 RAG(检索增强生成)、Tool Calling(工具调用)、对话记忆(ChatMemory)、可观测性(Observability)等生产环境必备特性。该框架面向工程实践设计,而非仅限于概念验证级别的演示。

1.3 与 LangChain4j 的对比
关于 Spring AI 与 LangChain4j 的选型问题,需结合具体场景分析:
| 维度 | Spring AI | LangChain4j |
|---|---|---|
| 生态集成 | ✅ 深度整合 Spring Boot | ⚠️ 可用但非原生 |
| 学习成本 | ✅ Spring 开发者几乎零门槛 | ⚠️ 需学习 Chain/Agi 等概念 |
| 编排灵活性 | ⚠️ Advisor 模式相对固定 | ✅ Chain 概念更丰富 |
| 模型支持 | ✅ 主流模型全覆盖 | ✅ 同样覆盖 |
| 社区活跃度 | 📈 快速增长中 | 📈 已有较大用户群 |
选型建议如下:
- 项目已基于 Spring Boot 生态 构建:优先选用 Spring AI,集成成本低,学习曲线平缓。
- 需要灵活的工作流编排能力(如复杂 Agent 场景):LangChain4j 的 Chain 模型更为丰富,可作为补充方案。
- 从 Python 技术栈迁移:Spring AI 的 API 设计更符合 Spring 开发者习惯,迁移成本相对较低。
两者在实际项目中可协同使用,例如以 Spring AI 处理主要对话交互,LangChain4j 承担特定编排需求。
2. Spring AI 解决了什么痛点
在深入代码实践之前,有必要先厘清 Spring AI 所解决的核心问题。以下痛点在工程实践中较为常见:
2.1 供应商锁定
初期采用 OpenAI 时,代码中往往充斥着 OpenAiApi 的直接调用。当企业因合规或成本因素要求切换至国产模型(如通义千问、DeepSeek)时,传统方式需要重写大量调用逻辑,涉及数十个文件的修改。
实际项目中,仅将模型调用从 OpenAI 迁移至自研模型,就曾耗费三周时间。原因在于各处的 URL 拼接、请求头处理、响应解析逻辑均不相同,修改工作量巨大。
Spring AI 通过提供统一抽象层解决此问题:开发者仅需与 ChatClient 交互,底层模型对接完全由配置决定。切换模型通常只需修改几行 YAML 配置。
2.2 Prompt 管理混乱
直接拼接字符串实现 Prompt 的方式,通常仅适用于初学者或简单场景。
实际生产环境中的 Prompt 往往具有较高复杂度:不同业务场景需要不同的提示词模板,需动态填充用户名、上下文等变量,且 Prompt 变更后可能需要回滚。在某些情况下,产品经理亦需参与调优过程。
手动实现上述逻辑不仅繁琐,且容易出错。Spring AI 提供的 PromptTemplate 支持占位符填充及外部文件管理,结合 Spring 的 ResourceLoader 可将 Prompt 模板置于 classpath 或外部路径,便于团队协作与版本控制。
2.3 企业级能力缺失
构建 Demo 场景较为简单,单个 HTTP 调用即可满足。但生产环境部署则面临诸多挑战:
- 如何使 AI 基于企业私有数据生成回答?需借助 RAG(检索增强生成)。
- 如何使 AI 调用业务系统 API 获取数据?需借助 Tool Calling。
- 如何维护用户对话上下文,避免 AI "失忆"?需借助 ChatMemory。
- 如何监控 AI 调用成本与响应质量?需借助 可观测性。
上述能力若自行实现,每个模块均需投入相当的开发资源。Spring AI 已将这些能力内建,可开箱即用。
具体代码实现马上在下一节动手写,先把问题理解到位就行。
3. 快速上手:第一个 Spring AI 项目
本节目标明确:在环境准备充分的前提下,于 15 分钟内完成首个 AI 对话接口的搭建与验证。
3.1 环境准备
开始之前,请确认以下环境已就绪:
| 项目 | 要求 | 如何确认 |
|---|---|---|
| JDK | 17 或更高 | 终端执行 java -version |
| 构建工具 | Maven 3.6+ 或 Gradle 7+ | mvn -v 或 gradle -v |
| IDE | IDEA(推荐) | 2023.2+ 版本 |
| API Key | OpenAI 兼容格式 | 下文详细介绍 |
JDK 版本说明 :Spring AI 1.0+ 要求 JDK 17 及以上,此为硬性要求。若当前环境仍为 JDK 8 或 11,建议先行升级。推荐选用 Adoptium (Eclipse Temurin) 或 Oracle JDK 17/21,安装完成后配置 JAVA_HOME 即可。
API Key 获取途径:
| 选择 | 优点 | 缺点 | 推荐度 |
|---|---|---|---|
| OpenAI 官方 | 模型最强,生态最全 | 需海外信用卡,国内访问需代理 | ⭐⭐ |
| DeepSeek | 国内直连,便宜,注册送额度 | 模型生态不如 OpenAI | ⭐⭐⭐⭐⭐ |
| 智谱 GLM | 国产合规,中文能力强 | API 格式略有差异 | ⭐⭐⭐ |
本文选用 DeepSeek 进行演示,主要基于以下考量:国内网络可直接访问、注册即赠送额度、API 格式与 OpenAI 完全兼容,且调用成本较低。注册地址为 platform.deepseek.com,注册完成后在「API Keys」页面创建 Key 并妥善保存。
3.2 创建项目
访问 Spring Initializr,按以下配置创建项目:
| 选项 | 值 | 说明 |
|---|---|---|
| Project | Maven | 也可选 Gradle |
| Language | Java | 17 |
| Spring Boot | 3.2.x 或更高 | Spring AI 要求 |
| Group | com.example | 按需修改 |
| Artifact | demo | 按需修改 |
在 Dependencies 中搜索并添加以下两项:
- Spring Web --- 提供 REST API 能力
- Spring AI OpenAI --- AI 核心依赖(DeepSeek 也走这个)
注意:Spring Initializr 中提供的 Spring AI 版本可能并非最新。若列表中未找到 Spring AI OpenAI,或版本较旧,无需担心,后续可通过手动修改
pom.xml调整版本。此为常见情况,并非操作失误。
配置完成后点击 Generate,下载压缩包并解压至本地目录。
3.3 添加依赖
打开项目根目录下的 pom.xml,需补充两部分内容:BOM(版本管理)与具体的 Starter 依赖。
第一步,添加 BOM ,在 <dependencyManagement> 节点内加入:
xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.1.7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
BOM(Bill of Materials)用于统一管理版本号。引入 BOM 后,后续添加 Spring AI 相关依赖时无需再指定版本,可有效避免版本冲突。
第二步,添加具体依赖 ,在 <dependencies> 节点内加入:
xml
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI OpenAI Starter -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
</dependencies>
使用 DeepSeek 同样采用此 Starter,原因在于 DeepSeek 的 API 格式与 OpenAI 兼容(均遵循 OpenAI Chat Completions API 规范),Spring AI 将其纳入同一套实现。开发者仅需通过
base-url与api-key区分具体服务提供商。
添加完成后,在 IDE 中刷新 Maven(IDEA 右下角将弹出提示,或点击 Maven 面板的刷新按钮),等待依赖下载完成。
Gradle 用户请使用以下配置(Controller 代码部分与 Maven 完全一致,无需改动):
gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.x'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter'
}
dependencyManagement {
imports {
mavenBom "org.springframework.ai:spring-ai-bom:1.1.7"
}
}
3.4 配置 API Key
在 src/main/resources/application.yml 中加入以下配置:
yaml
spring:
ai:
openai:
api-key: ${DEEPSEEK_API_KEY}
base-url: https://api.deepseek.com
chat:
options:
model: deepseek-chat
temperature: 0.7
各配置项说明如下:
| 配置项 | 值 | 说明 |
|---|---|---|
api-key |
${DEEPSEEK_API_KEY} |
从环境变量读取,不要硬编码 |
base-url |
https://api.deepseek.com |
DeepSeek 的 API 地址(用 OpenAI 则删掉这行) |
model |
deepseek-chat |
指定使用的模型 |
temperature |
0.7 |
控制回答随机性,0-1 之间 |
为何使用 ${DEEPSEEK_API_KEY} 而非直接写入 Key? 出于安全考量。API Key 属于敏感信息,不应提交至 Git 仓库。使用环境变量引用是业界通行的最佳实践。
设置环境变量的方法:
Windows(PowerShell):
powershell
$env:DEEPSEEK_API_KEY="sk-xxxxxxxx"
Mac / Linux:
bash
export DEEPSEEK_API_KEY=sk-xxxxxxxx
或在 IDEA 中配置:Run Configuration → Environment variables → 添加一行 DEEPSEEK_API_KEY=sk-xxxxxxxx。此方式在调试阶段最为便捷,无需每次手动在终端中设置。
若使用 OpenAI 官方 API,仅需删除(或注释)
base-url配置项,model改为gpt-4o或gpt-3.5-turbo,api-key替换为 OpenAI 的 Key 即可。其余代码无需任何调整。
3.5 编写第一个 Controller
环境就绪后,开始编写代码。在 src/main/java/com/example/demo/ 目录下新建 ChatController.java:
java
package com.example.demo;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/ai")
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
@GetMapping("/chat")
public String chat(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
代码逻辑逐行说明:
| 代码 | 作用 | 备注 |
|---|---|---|
ChatClient.Builder chatClientBuilder |
构造器注入 | Spring AI 自动提供,无需手动创建 |
.build() |
构建 Client 实例 | 可以在构造时预设默认参数 |
.prompt() |
开始构建请求 | 返回 PromptSpec,支持链式调用 |
.user(message) |
设置用户消息 | 也可以用 .system() 设置系统消息 |
.call() |
发起同步调用 | 阻塞等待 AI 返回完整结果 |
.content() |
提取文本内容 | 返回 String 类型的回复 |

整个 Controller 结构简洁,无需额外的配置类、手写 HTTP 调用或 JSON 解析,这正是 Spring AI 的设计哲学------将复杂度封装于框架内部,向开发者暴露简洁的 API。
3.6 启动并测试
代码编写完成后,启动项目。以下两种方式任选其一:
方式一,直接运行 DemoApplication 的 main 方法(IDEA 中右键选择 Run)
方式二,命令行启动
bash
mvn spring-boot:run
出现以下日志即表示启动成功:
Started DemoApplication in 2.5 seconds
随后打开浏览器(或 Postman / curl),访问:
http://localhost:8080/ai/chat?message=你好,请用一句话介绍Spring AI
正常情况下,将收到类似如下的回复:
Spring AI 是 Spring 官方推出的 AI 应用开发框架,让 Java 开发者可以用熟悉的 Spring 生态方式集成和调用大语言模型。
首次调用通常需要 3-5 秒(包含连接建立与模型加载),后续调用响应速度会显著提升,一般在 1-2 秒内返回结果。
若出现报错,请按以下顺序排查:
| 排查项 | 症状 | 解决方法 |
|---|---|---|
| API Key | 日志出现 401 Unauthorized |
检查环境变量是否正确设置 |
| 网络连通 | Connection timeout / refused |
公司内网可能需要配代理,先用 curl 测 api.deepseek.com |
| base-url | 调用了 OpenAI 但 key 是 DeepSeek 的 | 用 DeepSeek 必须配 base-url,默认值指向 OpenAI |
快速验证网络连通性的方法:
bash
curl https://api.deepseek.com/v1/models -H "Authorization: Bearer $DEEPSEEK_API_KEY"
返回 JSON 模型列表即表明 Key 与网络均正常。
3.7 流式输出
上述示例采用同步调用(.call()),AI 需生成完整文本后一次性返回。若回复内容较长(如生成数百字文章),用户需等待空白页面数秒,体验不佳。
更优方案为流式输出:AI 每生成若干字符即实时推送至前端,实现打字机效果。Spring AI 仅需调整两行代码:
java
import org.springframework.http.MediaType;
import reactor.core.publisher.Flux;
@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chatStream(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.stream()
.content();
}
改动点仅有两处:
| 改动 | 原来 | 现在 | 说明 |
|---|---|---|---|
| 调用方式 | .call() |
.stream() |
从同步改为流式 |
| 返回类型 | String |
Flux<String> |
返回响应式流 |
前端使用浏览器原生 EventSource API 即可接收:
javascript
const eventSource = new EventSource('/ai/chat/stream?message=你好');
eventSource.onmessage = (event) => {
document.getElementById('output').textContent += event.data;
};

测试流式接口可使用 curl 的 -N 参数(禁用缓冲,实时输出):
bash
curl -N "http://localhost:8080/ai/chat/stream?message=讲一个程序员笑话"
可观察到文字逐字呈现,而非等待许久后一次性显示。在长文本生成场景下,两者的体验差异尤为显著。
流式输出的底层实现基于 Project Reactor 的
Flux,即 Spring WebFlux 的响应式基础。若对响应式编程尚不熟悉,目前只需理解.stream()返回的是一个"字符串流"即可。后续文章将深入讲解响应式编程在 Spring AI 中的具体应用。
4. 核心概念速览
项目已顺利运行。在深入更多功能之前,建议先厘清以下几个核心概念。Model、Prompt、Embedding、Token 等术语将在后续每一篇文章中反复出现,此刻投入 10 分钟理解其含义,将显著提升后续学习效率。
4.1 Model(模型)
什么是模型
简单理解,模型可视为一个"黑盒":输入文本,输出回复;输入图像,输出识别结果;输入音频,输出转录文本。
其内部结构极其复杂,涉及数十亿参数、Transformer 架构、注意力机制等。但作为使用者,无需关注这些内部实现,重点在于Spring AI 支持哪些模型类型,以及如何调用。
Spring AI 支持的三类模型
| 类型 | 代表模型 | 用途 | 使用频率 |
|---|---|---|---|
| Chat Model | GPT-4o、Claude、DeepSeek-V3 | 文本对话、代码生成、问答 | ⭐⭐⭐⭐⭐ 最常用 |
| Embedding Model | text-embedding-3-small、bge-large | 文本向量化,语义搜索的基础 | ⭐⭐⭐⭐ RAG 必用 |
| Image Model | DALL-E 3、Stable Diffusion | 文生图、图像编辑 | ⭐⭐ 按需使用 |
Chat Model 是本系列的核心。无论是聊天机器人、代码助手还是文档问答,底层均由 Chat Model 驱动。后续第 2 篇将专门讲解 ChatClient 的完整用法。
Embedding Model 当前或许尚未用到,但它是 RAG(第 5 篇)的核心组件。其本质是将文本转换为数值向量(一串数字),语义相近的文本对应的向量距离也较近。
Image Model 用于图像生成,属于锦上添花的能力,本系列不作重点展开。
代码示例
三类模型在代码中的调用方式类似,均通过对应的 Client 接口完成:
java
// Chat Model --- 最常用
ChatClient chatClient = ChatClient.builder(chatModel).build();
String reply = chatClient.prompt().user("你好").call().content();
// Embedding Model --- RAG 时使用
EmbeddingModel embeddingModel = ...; // Spring 自动注入
List<Double> embedding = embeddingModel.embed("这段文字的向量表示");
// 返回一个 1536 维的向量(取决于具体模型)
// Image Model --- 生图时使用
ImageModel imageModel = ...;
ImageResponse response = imageModel.call(new ImagePrompt("一只穿西装的猫"));
注意到,无论何种模型,调用模式均遵循注入 Client → 构建请求 → 调用 → 获取结果的流程。这正是 Spring AI 统一抽象层的价值所在:掌握一种,其余触类旁通。
切换模型提供商?仅需修改配置,代码无需改动。这也是上一节所述"供应商锁定"问题的解决方案。

4.2 Prompt(提示词)
Prompt 不是简单的字符串
初学者常将 Prompt 直接拼接为字符串:
java
String prompt = "请用 Java 写一个排序算法";
这种方式虽可运行,但过于粗糙。实际项目中的 Prompt 是一个结构化对象,包含多条 Message,每条 Message 承担不同的角色与职责。
Message 的三种角色
| 角色 | 谁发的 | 作用 | 典型用法 |
|---|---|---|---|
| System Message | 开发者(你) | 设定 AI 的行为准则、角色背景 | "你是 Java 专家""回答不超过 100 字" |
| User Message | 最终用户 | 用户的问题或输入 | "怎么写快速排序?""翻译这段代码" |
| Assistant Message | AI 自己 | AI 的历史回复 | 多轮对话时传入,让 AI "记住"上下文 |
java
Prompt prompt = new Prompt(List.of(
new SystemMessage("你是一位幽默的 Java 技术专家,回答不超过 100 字"),
new UserMessage("什么是 Spring AI?")
));
System Message 尤为重要。同样的 User Message,配合不同的 System Message,AI 的回复风格可能截然不同。类比于任务下达:指定"以严谨工程师身份"回答与"以轻松讲师身份"回答,产出差异显著。
PromptTemplate 动态模板
实际项目中,Prompt 往往包含动态内容。例如构建翻译接口时,源语言与目标语言由用户传参决定,此时需使用 PromptTemplate:
java
PromptTemplate template = new PromptTemplate("""
请将以下{text}从{sourceLang}翻译成{targetLang}。
要求:保留原文格式,专业术语用括号标注原文。
""");
Prompt prompt = template.create(Map.of(
"text", "Hello World",
"sourceLang", "英文",
"targetLang", "中文"
));
{text}、{sourceLang} 等占位符将被 Map 中的值替换。相较于字符串拼接,此方式更为安全,可避免格式错乱与注入风险。
更进一步,结合 Spring 的 ResourceLoader,可将 Prompt 模板置于外部文件(如 classpath:/prompts/translate.st)管理:
java
@Resource
private Resource translatePromptResource;
// 从文件加载模板
PromptTemplate template = new PromptTemplate(translatePromptResource);
此举的优势在于:Prompt 修改无需重新编译部署,产品经理亦可参与调优(只需具备文本文件编辑能力),版本变更亦有记录可查。这正是上一节"Prompt 管理混乱"问题的解决方案。
4.3 Embedding(嵌入)
什么是 Embedding
Embedding(嵌入)是 NLP 领域的一个核心技术,作用是把文本转换成向量(一组浮点数)。
为何要将文本转为数字?因为计算机无法直接理解"猫"与"狗"的语义差异,但擅长计算向量间的距离。Embedding 模型的核心特性在于:语义相近的文本,其向量距离亦近;语义差异大的文本,向量距离亦远。
举个例子:
- "猫" 和 "kitten" 的向量距离 → 很近(意思相近)
- "猫" 和 "编程" 的向量距离 → 较远(有些关联)
- "猫" 和 "汽车" 的向量距离 → 很远(毫不相关)
这种特性使机器能够"理解"文本的语义相似性,而非依赖简单的关键词匹配。
为什么需要 Embedding
Embedding 是 RAG(检索增强生成,第 5 篇详述)的核心步骤。完整流程如下:
- 把你的私有文档切成小段(chunk)
- 每段用 Embedding 模型转成向量
- 向量存入向量数据库(如 Milvus、PgVector)
- 用户提问时,把问题也转成向量
- 在向量数据库中找与问题向量最相似的文档片段
- 把这些片段注入 Prompt,交给 AI 生成最终回答
步骤 2 与步骤 4 均由 Embedding 完成。若无此环节,AI 只能基于训练数据回答,无法利用私有知识库。
代码示例
java
@Autowired
private EmbeddingModel embeddingModel;
public void embedDemo() {
// 把一句话转成向量
List<Double> embedding = embeddingModel.embed("Spring AI 很强大");
// 输出:[0.0023, -0.0156, 0.0231, ..., 0.0087]
// 这是一个 1536 维的向量(取决于具体模型)
System.out.println("向量维度: " + embedding.size());
}
不同 Embedding 模型返回的向量维度各异:
| 模型 | 维度 | 特点 |
|---|---|---|
| text-embedding-3-small | 1536 | 速度快,成本低,大多数场景够用 |
| text-embedding-3-large | 3072 | 精度更高,对语义细微差别更敏感 |
| bge-large-zh | 1024 | 国产模型,中文优化 |
选型建议:起步阶段选用 small 即可,若效果不足再升级至 large。
4.4 Token
Token 是什么
Token 是模型处理文本的基本单位。注意,Token ≠ 字 ≠ 词。它是模型训练时通过分词算法(tokenizer)定义的最小单元。
一些直观的参考数据:
- 英文 "hello world" → 大约 2 个 Token
- 中文 "你好世界" → 大约 4-8 个 Token(取决于分词策略)
- 一段 100 字的中文描述 → 大约 150-250 个 Token
可前往 OpenAI Tokenizer 页面自行验证,输入任意文本查看其 Token 切分结果。该工具对成本估算颇具参考价值。
为什么 Token 很重要
以下三个维度直接影响应用设计与成本:
成本维度
大模型按 Token 计费。输入 Token(Prompt)与输出 Token(Completion)均计入费用。Prompt 越长、AI 回复越长,成本越高。典型生产环境中,每月 Token 费用可能从数千至数万美元不等,取决于调用规模。
上下文窗口维度
模型单次可处理的 Token 数存在上限,称为"上下文窗口"(Context Window)。超出上限的部分将被截断,AI 无法"看到"。
| 模型 | 上下文窗口 | 说明 |
|---|---|---|
| GPT-4o | 128K | 约 10 万汉字 |
| DeepSeek-V3 | 128K | 与 GPT-4o 相当 |
| Claude 3.5 Sonnet | 200K | 目前最大之一 |
若文档过长无法容纳,需进行切分(chunking),这也是 RAG 中的关键环节。
性能维度
Token 数量越多,模型推理时间越长,响应延迟越高。因此控制 Prompt 长度不仅是成本考量,亦是性能优化的重要手段。
Token 计数
Spring AI 提供了 Token 计数工具,调用后可获取实际 Token 用量:
java
@Autowired
private ChatClient chatClient;
public void countTokens() {
Prompt prompt = new Prompt("请介绍一下 Spring AI 的核心概念");
ChatResponse response = chatClient.prompt(prompt).call().chatResponse();
int promptTokens = response.getMetadata().getUsage().getPromptTokens();
int completionTokens = response.getMetadata().getUsage().getCompletionTokens();
int totalTokens = response.getMetadata().getUsage().getTotalTokens();
System.out.println("输入 Token: " + promptTokens);
System.out.println("输出 Token: " + completionTokens);
System.out.println("总计 Token: " + totalTokens);
}
不同模型的 Token 计算方式可能存在差异(分词算法不同),实际计费以各模型提供商返回的数据为准。Spring AI 仅负责透传该信息。
4.5 四个概念的关系
上面四个概念并非孤立存在,它们在典型 AI 应用中协同工作:
简单对话场景:
用户输入 → 组装 Prompt(System + User Message)→ Chat Model 处理 → AI 回复
↓
按 Token 计费
基于私有数据的智能问答(RAG 场景):
用户提问 → Embedding Model → 问题向量
↓
向量数据库检索相似文档片段
↓
文档片段 + 用户问题 → 注入 Prompt → Chat Model → 基于事实的准确回答

最后以表格总结四个概念的定位:
| 概念 | 类比 | 一句话 | 后续在哪篇展开 |
|---|---|---|---|
| Model | 大脑 | 负责理解和生成内容 | 第 2 篇(ChatModel 深入) |
| Prompt | 指令 | 告诉大脑该怎么回答 | 第 2 篇(Prompt 进阶) |
| Embedding | 翻译官 | 把文字变成机器能计算的数字 | 第 4 篇(Embedding 详解) |
| Token | 计价单位 | 决定了成本、性能和上限 | 贯穿全系列 |
5. 版本说明与选型建议
5.1 当前版本状态
截至 2026 年,Spring AI 的版本线如下:
| 版本 | 类型 | 基于 | 状态 | 适用场景 |
|---|---|---|---|---|
| 1.1.7 | 稳定版 | Spring Boot 3.x | ✅ 最新,推荐 | 生产环境首选 |
| 1.0.x | GA 版 | Spring Boot 3.x | ✅ 维护中 | 已有稳定项目 |
| 2.0.0-M7 | 里程碑 | Spring Boot 4.0 | 🔧 预览 | 关注动态,暂不上生产 |
可前往 Spring AI GitHub Releases 查看最新的版本信息与 Changelog。
5.2 本系列的选择
本系列所有文章基于 Spring AI 1.1.x 编写,部分基础示例兼容 1.0.x。涉及 2.0 新特性的部分,将特别标注版本要求。
若当前使用 1.0.x,大部分代码可直接运行;少数新 API(如某些 Advisor 的配置方式)可能需要微调,届时将予以注明。
5.3 Spring Boot 版本匹配
Spring AI 与 Spring Boot 版本需严格匹配,不可随意组合:
| Spring AI | Spring Boot | 说明 |
|---|---|---|
| 1.1.x | 3.2.x ~ 3.4.x | ✅ 推荐 |
| 1.0.x | 3.2.x ~ 3.3.x | ✅ 稳定 |
| 2.0.0-Mx | 4.0.x | ⚠️ 早期预览 |
若项目仍在使用 Spring Boot 2.x,需先升级至 3.x 方可使用 Spring AI。Spring Boot 2.x 已于 2024 年停止维护,升级宜早不宜迟。
6. 常见问题
Q1:Spring Initializr 里找不到 Spring AI 怎么办?
正常现象,Spring AI 尚未进入 Initializr 的官方 Starter 列表。手动在 pom.xml 中添加依赖即可,不影响任何功能。本文 3.3 节已对此进行详细演示。
Q2:用 OpenAI 官方 API 怎么配置?
删除 application.yml 中的 base-url 行(默认指向 OpenAI),model 改为 gpt-4o 或 gpt-3.5-turbo,api-key 替换为 OpenAI 的 Key。其余代码完全无需改动。
Q3:temperature 参数的含义是什么?
用于控制 AI 回复的「随机性」或「创造性」。取值范围 0-2:
| 值域 | 效果 | 适用场景 |
|---|---|---|
| 0.0 ~ 0.3 | 保守、确定、事实性强 | 代码生成、数据提取、格式化 |
| 0.4 ~ 0.8 | 平衡 | 日常对话、通用问答 ← 推荐起点 |
| 0.9 ~ 2.0 | 放飞、创意性强 | 写诗、头脑风暴、创意写作 |
日常开发建议以 0.7 左右为起点。若发现 AI 回答过于发散,可适当调低;若过于死板,则可适当调高。
Q4:一直报 Connection timeout 怎么排查?
按以下三层顺序检查:
- 本地网络 →
ping api.deepseek.com看能不能通 - 公司防火墙 → 可能需要配 HTTP 代理或白名单
- DNS 问题 → 试试直接用 IP(不推荐长期)
最快的方式是用 curl 直接测试:
bash
curl https://api.deepseek.com/v1/models -H "Authorization: Bearer $DEEPSEEK_API_KEY"
能返回 JSON 模型列表即说明网络无异常。
Q5:Embedding 和 Chat Model 必须用同一个提供商吗?
不必。Spring AI 的配置完全独立。Chat 可用 DeepSeek(成本较低),Embedding 可用 OpenAI 的 text-embedding-3-small(效果较优)。混合使用在实际项目中颇为常见。
Q6:System Message 真的有那么重要吗?
非常重要,甚至可以说 System Message 是决定 AI 回复质量的关键因素之一。同样的 User Message:"什么是 Spring AI?",配合不同的 System Message:
- "你是严谨的技术文档作者" → 得到正式的定义和架构说明
- "你是幽默的程序员博主" → 得到口语化的比喻和个人经验分享
- "你是小学老师" → 得到通俗易懂的类比和例子
投入时间优化 System Message,远比盲目增加 Prompt 长度更为有效。
Q7:Spring AI 返回的 Token 计数准不准?
该数据来自模型提供商的 API 响应,通常较为准确。但需注意,不同模型的分词算法不同,同样一段中文文本,DeepSeek 可能计数为 120 Token,GPT-4o 可能为 150 Token。计费以各自提供商的数据为准。
参考资源
官方资源:
- Spring AI 官方文档 --- 最权威的技术参考
- Spring AI GitHub 仓库 --- 源码、Issue、Release Notes
- Spring Initializr --- 快速创建 Spring Boot 项目
模型相关:
- OpenAI API 文档 --- Chat Completion API 协议规范
- DeepSeek 开放平台 --- 国产大模型,API 兼容 OpenAI
- OpenAI Tokenizer --- 在线查看文本的 Token 切分结果
生态对比:
- LangChain4j 官方文档 --- Java 生态另一个 AI 框架
基础知识:
- Spring Boot 文档
- Project Reactor 文档 --- Flux/Mono 响应式编程
写在最后
本文作为系列开篇,目标明确:阐明 Spring AI 的定位与核心价值,并指导读者从零搭建环境、实现首个 AI 对话项目。
回顾本文内容:
- 理解了 Spring AI 的定位和核心价值
- 从零搭建了一个完整的 Spring Boot + Spring AI 项目
- 写出了同步和流式两个对话接口
- 搞懂了 Model、Prompt、Embedding、Token 四个核心概念
下一篇(第 2 篇)将深入讲解 ChatClient 的完整用法,涵盖多模型切换、Prompt 模板进阶、聊天记忆、输出解析等实战技巧。此乃日常开发中最常用的部分。
若读者希望提前深入了解,可前往 Spring AI 官方文档 查阅。但建议跟随本系列系统学习,可少走弯路。
系列目录:
-
第一篇-SpringAI概述与快速上手 ✅(本文)
如果这篇文章对你有帮助,欢迎点赞、收藏与关注,系列持续更新中。