Spring AI伊始:核心概念一次讲清

9 阅读16分钟

1. 什么是SpringAI

Spring AI 是 Spring 官方为 Java 开发者提供的“大模型工程框架”。它的目标是让你 像写普通 Spring 服务一样,写可维护、可治理的 AI 应用。它借鉴了 Python 生态中的 LangChain、LlamaIndex 等项目的设计思想,但用 Spring 风格重新抽象了一套 Java 开发者熟悉的 API 和组件体系

2. Spring AI 提供了什么特性

多模型统一调用

Spring AI 提供统一的 Model API,可以对接多个 AI 提供商:

  • OpenAI
  • Anthropic(Claude)
  • Google Gemini
  • DeepSeek
  • 本地模型(Ollama、LLM Studio)

你只需要换配置,就能切换模型,不用重写业务代码。

向量存储与语义检索

Spring AI 内置了统一的向量存储接口,可以对接:

  • Milvus
  • Pinecone
  • Redis
  • Elasticsearch
  • PostgreSQL / MySQL 向量扩展

你可以把文档、数据库内容转成向量,实现“语义搜索”。这也是构建企业知识库问答系统的核心能力。

工具调用与函数执行

Spring AI 支持 Tool / Function Calling:

  • AI 可以调用你的 Java 方法
  • 查询数据库
  • 调用第三方 API
  • 执行业务逻辑

例如:“查询最新的天气”,让AI 调用service.getWeather()

文档提取与 RAG

Spring AI 提供完整的 RAG(Retrieval-Augmented Generation)流程支持:

  • 文档加载(PDF、Word、HTML、数据库)
  • 文本切分
  • Embedding
  • 向量检索
  • 与大模型组合生成回答

让 AI 基于你的企业数据回答,而不是凭空幻想。可以避免 AI 胡编。

结构化输出与模型评估

Spring AI 支持:

  • 将模型输出直接映射为 Java POJO
  • JSON Schema 约束输出格式
  • AI 输出质量评估(减少幻觉)

解决“模型输出不稳定,业务代码难以处理”的痛点。

Spring Boot 原生集成

Spring AI 深度融入 Spring Boot:

  • Starter 自动配置
  • ChatClient API
  • Advisors(拦截器链式增强)
  • 配置中心、日志、监控全兼容

3. AI核心概念

在开始使用 Spring AI 之前,不妨先花点时间了解一下 AI 应用开发中的一些基本概念,这会帮助我们更好地理解 Spring AI 的设计,也能让后面的使用更加顺畅。

模型(Model)

在 Spring AI 中,Model 指的是具备“输入 → 处理 → 输出”能力的 AI 模型。本质上,它是一种经过海量数据训练的算法,能够理解输入信息并生成对应的结果。模型的输出形式并不局限于文本,还可以是图片、音频,甚至是向量数据。

为了统一不同模型的使用方式,Spring AI 按照输入 / 输出形式对模型能力进行了抽象,目前主要支持以下几类场景:

  • 文本 → 文本:对话、内容生成、总结、翻译
  • 文本 → 图片:图像生成
  • 语音 → 文本:语音识别
  • 文本 → 语音:语音合成
  • 文本 → 向量(Embedding):语义表示,用于搜索和检索

其中,Embedding 模型非常特殊,它不直接“生成内容”,而是把文本转换为一组数字向量,用来表示语义相似度,是 RAG、语义搜索、推荐系统的基础。也有专门的存储这些数字向量的数据库,我们常称为向量数据库。

提示词(Prompts)

在 Spring AI 中,Prompt 是驱动大模型行为的“输入载体”。它并不只是我们在聊天对话框里面的一行文字,而是一组结构化、带上下文语义的指令集合。我们可以把模型当成一个能力极强,但需要明确指引的员工。那 Prompt 就是你给它下达的工作说明书。

Prompt 远不只是一个字符串

很多人刚接触大模型时,会把 Prompt 理解为:

帮我写一段 Java 代码

但在真实的模型 API 中,Prompt 往往由多段文本组成,并且每一段都有角色含义。以ChatGPT / OpenAI 对话为例,一个完整的 Prompt 通常包含这几个常见的角色:

  • System(系统角色)

用来规定模型的行为边界和整体风格,给模型设定一个角色(例如:你是一个 Java 架构师)

  • User(用户角色)

用户给IA的具体的业务问题或请求

  • Assistant(AI角色)

最强打工人,根据历史回答 / 上下文, 负责输出结果

  • 可选的 Tool / Function

调用外部的扩展工具或者功能

Prompt设计也是一门学问

与 SQL 这种结构化、确定性查询语言不同,大模型更像是在和人“对话”。你不是在“查询数据”,而是在沟通意图。也正因为这种差异,逐渐形成了一个新的概念:Prompt Engineering(提示词工程)

它研究的不是语法是否正确,而是如下的一些问题:

  • 如何设定上下文
  • 如何拆解复杂问题
  • 如何引导模型一步步思考
  • 如何减少幻觉、提高输出质量

研究发现,**一个好的 Prompt,往往比换一个更大的模型更重要。**甚至有研究表明,一些看似“反直觉”的提示语(例如:“深吸一口气,一步一步地做。”)都会显著提升模型的推理质量。

可复用、可维护的 Prompt(Prompt Templates)

在真实系统中,Prompt 绝不会是写死的一段字符串。

它通常需要:

  • 复用
  • 参数化
  • 动态填充用户输入
  • 统一管理和维护

因此,Spring AI 引入了 Prompt Template(提示词模板) 的概念。

例如,一个简单的模板:

Tell me a {adjective} joke about {content}.

在运行时,你只需要提供变量:

adjective = "funny"
content = "Java"

最终生成的 Prompt 再交给模型。

Spring AI 中的 Prompt 模板机制

Prompt Template 在 Spring AI 中,类似于 Spring MVC 里的 View。

  • 模板:定义 Prompt 的结构
  • Model(通常是 Map<String, Object>):提供填充数据
  • 渲染结果:最终发送给模型的 Prompt 内容

这使 Prompt 的管理方式,做到工程化,而不是散落在代码里的字符串拼接。

Prompt的数据结构正在不断演进

最早的 Prompt 只是一个字符串。而现在,Prompt 往往包含:

  • 多条消息(Message)
  • 每条消息有不同角色(System / User / Assistant / Tool)
  • 不同模型对 Prompt 结构有不同要求

Spring AI 屏蔽了这些底层差异,让你可以用统一的方式构建 Prompt,而不必关心具体模型 API 的细节。

向量表示(Embeddings)

Embedding 是将文本、图片或视频等内容,转换为一组数字向量的过程。这些数字并不是随机生成的,而是经过模型训练后,用来刻画内容所包含的语义信息,也就是“它表达了什么含义”。

你可以把 Embedding 理解为:为一段内容生成一张“语义指纹”。
语义相近的内容,其指纹也会非常相似;而语义差异较大的内容,对应的指纹在向量空间中的距离也会更远。

正是这种特性,使得 Embedding 成为语义搜索、RAG、推荐系统等 AI 应用的基础能力。

向量与维度

在 Embedding 过程中,模型会把内容转换成一个由浮点数组成的数组,这个数组就叫 向量(Vector)

例如:[0.012, -0.98, 1.23, ...]

这个数组的长度,被称为向量的维度(Dimensionality)

  • 维度越高,表达语义的能力通常越强
  • 但维度越高,存储和计算成本也越高

在实际开发中,我们并不需要理解具体数学原理,只需记住:相似的内容,会生成“距离更近”的向量。

Embedding与RAG

RAG(Retrieval Augmented Generation,检索增强生成) 模式中:

  1. 文档先被转换成 Embedding
  2. 存入向量数据库
  3. 用户提问后,也被转换成 Embedding
  4. 通过向量相似度,找出最相关的文档
  5. 再把这些文档交给大模型生成答案

简单来说就是:Embedding 负责“找资料”,模型负责“组织语言”。

令牌(Tokens)

Token 是大模型处理文本时的最小计算单位,而不是一个单词或者说一个文字。 在给模型输入时: 文本会被拆分成一系列 Tokens ,模型输出时: Tokens 再被组合成人类可读的文字 。在英文场景 1 个 Token ≈ 0.75 个单词 中文场景下,一个汉字通常≈一个 Token,当然这取决于具体使用的模型。

Tokens = 钱

现在收费的模型一般都是按token来计费。模型计费规则通常是: 输入 Token 数 + 输出 Token 数 = 总消耗 Token。

你每问一个问题都会消耗你的Token 预算,所以如果你囊中羞涩 可以考虑好好进行Prompt 设计控制返回内容的长度。当然我相信在座的都是富豪。

Token限制与上下文窗口(Context Window)

除了费用,模型还受到 Token上限的限制。这个限制被称为上下文窗口。

简单来说就是:在一次与模型聊天的对话中,模型最多只能处理这么多 Tokens。

超过这个上限的文本:

  • 会被直接截断
  • 或根本无法被模型处理

以下是我在cursor官网截取的一张图,可以参考一下

大文本怎么办

既然上下文窗口是有限的,那么当遇到超出模型限制的大文本时,能不能直接一次性丢给模型?
答案是:不可能。

正确的处理方式应该是:

  • 拆分文档,将大文本切分为可控的小块
  • 分段处理,逐段交给模型进行分析或抽取
  • 逐步汇总,对阶段性结果进行合并与归纳
  • 控制上下文长度,确保每次请求都在模型可接受范围内

而恰好的是Spring AI 已经为这些场景提供了成熟且优雅的解决方案,帮助我们在工程实践中自然地应对上下文窗口的限制。

结构化输出

在传统的大模型调用中,模型的返回结果几乎永远是一个String。

即使你在 Prompt 里明确要求:“请以 JSON 格式返回”

你拿到的结果也只是:

String result = "...";

它可能长得像 JSON,但在程序看来,它仍然只是一段普通字符串,而不是一个真正的数据结构。

让模型返回 JSON并不可靠

很多初学者会觉得,只要在 Prompt 里写清楚:“请严格按照 JSON 格式输出”问题就解决了。

但现实是可能会出现如下的一些情况(AI有时真是让人摸不着头脑):

  • 模型可能多输出一句解释
  • JSON 字段顺序变化
  • 少一个引号、多一个逗号
  • ......

出现这样的结果,都会导致我们得不到预期结果或者直接解析失败。也正因为如此,我们才需要想办法让模型尽量按我们需要的格式输出,再把字符串想办法解析成结构化的数据。

结构化输出转换(Structured Output Converter)

为了解决上述的问题,Spring AI 引入了 结构化输出(Structured Output Converter)

它的核心目标只有一个:让模型输出,能够稳定地映射为 Java 中可用的数据结构(POJO)。

Structured Output 的基本思路

结构化输出并不是模型突然变得 100% 听话,而是通过工程手段降低不确定性,包括:

  • 为模型提供明确的结构化输出指引
  • 在 Prompt 中约束字段、类型和格式
  • 必要时通过多轮交互修正结果
  • 最终将输出安全地转换为 Java 对象

总结就是:Structured Output 的本质,是用工程化手段,把 AI 的不确定输出,转化为业务系统可依赖的确定数据结构。

如何让 AI 模型掌握它“从未训练过”的信息?

通用大模型,训练数据是一次性离线完成的,并且存在明确的知识截止时间, 模型无法得知训练集之后发生的事件 。而且开发大模型的公司也无法拿到个人或者企业的一些私有数据,用来训练模型。通用大模型它是一个静态的知识体。

在实际开发中,对于模型不知道的新知识,做法是在运行时向模型提供外部信息。目前主流有三种技术途径

微调模型(Fine-tuning)

通过继续训练模型,改变其内部参数权重,使其“记住”新的知识或行为模式。

优点

  • 输出风格和领域知识更稳定
  • 不需要在每次请求中重复传输数据

缺点

  • 对算力和数据要求极高
  • 训练成本昂贵、周期长
  • 对 GPT 这类超大模型而言,通常不可行或受限
  • 不适合频繁变化的数据

提示词填充(Prompt Stuffing / RAG)

在模型推理时,将外部知识直接塞进 prompt 中,让模型“临时看到”这些信息。但是由于模型存在 token 上限,不能说简单粗暴地把所有数据全部丢给AI。于是演化出了:检索增强生成技术RAG(Retrieval Augmented Generation)

RAG 的典型流程

  1. 用户开始提问
  2. 从数据库 / 向量库中检索相关文档
  3. 将检索结果拼接进 prompt
  4. 模型基于“问题 + 上下文”生成答案

优点

  • 不需要训练模型
  • 数据实时可更新
  • 非常适合企业知识库、文档问答

缺点

  • Prompt 设计复杂
  • 受 token 限制
  • 上下文质量直接影响回答质量

Spring AI 对 RAG 场景提供了完整的工程抽象,显著降低了 Prompt Stuffing 的实现成本。

外部工具调用 (Tool Calling)

让模型在生成过程中,主动调用外部系统的 API 来获取最新或权威数据。

例如:

  • 查询数据库
  • 调用业务系统
  • 获取实时数据
  • 执行业务规则

模型本身不存储数据,而是学会:什么时候该调用哪个工具

优点

  • 数据始终是最新的
  • 适合强业务、强一致性场景
  • 与现有系统天然融合

缺点

  • 需要定义工具协议
  • 需要处理调用失败、超时等工程问题

检索增强生成(Retrieval Augmented Generation)

在使用 AI 模型进行问答时,一个常见问题是:模型怎么知道答案?
模型它只能靠训练时学到的知识回答,无法利用你手头的文档、手册或者企业内部资料。RAG就是为解决这个问题而设计的技术——先检索,再生成答案。

RAG 的核心流程

RAG 可以拆分成两个主要环节:构建知识库回答问题

构建知识库(ETL Pipeline)

首先,我们需要把非结构化文档(比如 PDF、Word、网页、代码等)变成 AI 能理解的格式,这里用到了 ETL 管道:

  • 提取(Extract):读取文档内容。
  • 转换(Transform):对文档进行拆分:
    • 保持语义完整:不要把段落、表格或者代码拆开。
    • 控制每片内容大小:每片都应该是小于 AI 模型 token 上限的一小部分。
  • 加载(Load):将处理后的内容存入 向量数据库。

向量数据库的作用是:快速找到和问题相关的内容,它会把文本转成向量(数字化表示),便于检索相似信息。

回答问题(检索 + 生成)

当用户提问时,RAG 的流程是:

  1. 检索:根据问题,从向量数据库找到最相关的文档片段。
  2. 生成:把用户问题和检索到的片段一起,放入 AI 模型,生成回答。
  3. 输出:模型基于检索到的信息,给出更准确、更可靠的答案。

所以 RAG 的核心就是“先找相关信息,再生成回答”,相比直接问 AI,准确率大大提升。

在Spring AI 框架,RAG 的实现主要有两部分:

  • ETL Pipeline:负责把文档提取、转换、存储到向量数据库,保证数据格式适合 AI 模型检索。
  • ChatClient - RAG:利用 QuestionAnswerAdvisor 将 RAG 功能集成到应用里,实现自动回答问题。

外部工具调用(Tool Calling)

大型语言模型(LLM)在训练完成后通常是固定的,知识会逐渐过时,而且它们无法直接访问或修改外部数据。为了解决这个问题,出现了 Tool Calling(工具调用)机制,实现了让 LLM 接入外部系统。

Tool Calling 的作用

Tool Calling 允许你将自己的服务注册为“工具”,把 LLM 连接到外部系统的 API。
这些系统可以为 LLM 提供:

  • 实时数据(解决知识滞后问题)
  • 数据处理能力(模型可以让工具帮它完成一些操作)

Spring AI 中的支持

Spring AI 简化了工具调用的实现:

  • 你只需要在方法上加上 @Tool 注解,就可以将其作为工具提供给模型。
  • 在 prompt 中提供工具选项,模型就能使用这些工具。
  • 一个 prompt 可以同时定义和引用多个工具。

Spring AI 会处理整个工具调用对话的细节,开发者无需手动管理调用逻辑。

Tool Calling 的执行流程

首先我们通过@Tool注解,将服务注册到Spring AI。Spring AI 在处理对话时,会把这个工具信息传给模型(作为 prompt 的一部分),告诉模型“有这个工具可用,以及怎么调用它”。当模型决定要调用工具时,它会返回工具名称和参数,Spring AI 接收到后去执行你注册的服务方法。

  1. 注册工具
    • 在聊天请求中包含工具定义:
      • 名称(name)
      • 描述(description)
      • 输入参数的 schema
  2. 模型调用工具
    • 模型根据需要返回:
      • 工具名称
      • 输入参数(遵循定义的 schema)
  3. 应用执行工具
    • 应用根据工具名称找到对应方法,并使用参数执行
  4. 返回结果
    • 工具执行结果被应用处理后,返回给模型
  5. 生成最终回答
    • 模型将工具调用结果作为上下文,生成最终回答

4.参考

docs.spring.io/spring-ai/r…

以上就是本篇博客的全部内容。至于更深入的实践案例和技巧,就留到下回“分解”吧!祝大家新年快乐,代码少报错,项目顺利上线!