SpringAI系列|第1篇:SpringAI概述与快速上手

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 -vgradle -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-urlapi-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-4ogpt-3.5-turboapi-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 启动并测试

代码编写完成后,启动项目。以下两种方式任选其一:

方式一,直接运行 DemoApplicationmain 方法(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 ReactorFlux,即 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 篇详述)的核心步骤。完整流程如下:

  1. 把你的私有文档切成小段(chunk)
  2. 每段用 Embedding 模型转成向量
  3. 向量存入向量数据库(如 Milvus、PgVector)
  4. 用户提问时,把问题也转成向量
  5. 在向量数据库中找与问题向量最相似的文档片段
  6. 把这些片段注入 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-4ogpt-3.5-turboapi-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 怎么排查?

按以下三层顺序检查:

  1. 本地网络ping api.deepseek.com 看能不能通
  2. 公司防火墙 → 可能需要配 HTTP 代理或白名单
  3. 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 的定位与核心价值,并指导读者从零搭建环境、实现首个 AI 对话项目。

回顾本文内容:

  • 理解了 Spring AI 的定位和核心价值
  • 从零搭建了一个完整的 Spring Boot + Spring AI 项目
  • 写出了同步和流式两个对话接口
  • 搞懂了 Model、Prompt、Embedding、Token 四个核心概念

下一篇(第 2 篇)将深入讲解 ChatClient 的完整用法,涵盖多模型切换、Prompt 模板进阶、聊天记忆、输出解析等实战技巧。此乃日常开发中最常用的部分。

若读者希望提前深入了解,可前往 Spring AI 官方文档 查阅。但建议跟随本系列系统学习,可少走弯路。


系列目录:


如果这篇文章对你有帮助,欢迎点赞、收藏与关注,系列持续更新中。

相关推荐
美狐美颜sdk1 小时前
自研还是第三方?直播APP开发中视频美颜SDK如何选择?
人工智能
aqi001 小时前
15天学会AI应用开发(十四)搭建LangChain的开发环境
人工智能·python·大模型·ai编程·ai应用
科技发布1 小时前
传统流量损耗严重,拓氪科技 AIGEO 怎样缩短转化链路?
人工智能·科技
中国搜索直付通1 小时前
避开直付通选型暗礁:二级商户的合规生存与背景甄别
java·大数据·开发语言·人工智能·游戏
Mr.朱鹏1 小时前
科技早报(第2026-07-17.md期):变现加速监管升温
人工智能·科技
想会飞的蒲公英1 小时前
词袋模型与 CountVectorizer:文本也可以做特征表
人工智能·python·机器学习
LadenKiller2 小时前
近期量化工具推荐,问题位置比功能清单更重要
人工智能·python
大郭鹏宇2 小时前
下篇:LangChain Agent 智能体从入门到实战(二)—— 记忆管理、中间件与最佳实践
网络·数据库·人工智能