Spring AI 2.0

文章目录

  • Spring AI 2.0简介
  • 阿里云百炼大模型平台接入
  • 新建 HelloWorld 项目
  • Ollama简介以及安装和使用
  • Spring AI项目调用本地Ollama模型
    • 进阶玩法:5个让DeepSeek更好用的技巧
      • 1. 绑定到局域网
      • 2. 搭配 Continue 插件写代码
      • 3. 用 AnythingLLM 做知识库问答
      • 4. 模型量化节省显存
      • 5. 换个好看的界面
  • stream()方法Flux流式响应输出
  • Advisors —— 拦截器模式增强AI能力
  • 对话与提示词工程(Prompt)
    • 一、核心概念总览
    • 二、核心知识点详解
      • 1. 消息类型(Message Type)
      • 2. 提示词工程基础原则
      • 3. 提示词模板(PromptTemplate)
      • 4. ChatClient 流畅 API
    • 三,具体应用实例
      • 1,PromptTemplate提示词模版
      • 2,使用 ChatClient 的流式 API 可以最快速地组装提示词
      • 3,系统提示词工程 —— defaultSystem
  • 结构化输出
    • 一、结构化输出核心概念
      • 1.1 为什么需要结构化输出
      • 1.2 Spring AI 2.0 结构化输出核心特性
    • 二、核心实现方式
      • 2.1 两种主要方案
      • 2.2 原生结构化输出
      • 2.3 实例 1:基础 POJO 结构化输出
      • 2.4 实例 2:集合类型结构化输出
    • 三,底层实现原理
  • 会话记忆(Chat Memory)
  • 工具调用(Function Calling / Tools)
    • 一、什么是工具调用
    • 二、核心工作原理
    • 三、快速入门实例:让 AI 学会“看时间”
    • 四、进阶实践:让 AI 执行操作
    • 五,工具调用底层实现原理
  • 嵌入模型(Embedding Model)与向量数据库(Vector Databases)
  • RAG(检索增强生成)
  • MCP(模型上下文协议)
  • 多模态支持

Spring AI 1.0

Spring AI 2.0简介

Spring AI 2.0 开发Java Agent智能体 - Spring AI 2.0简介

Spring AI 的核心设计思想是什么?它解决了 Java 开发者接入大模型时的哪些痛点?

阿里云百炼大模型平台接入

Spring AI 2.0 开发Java Agent智能体 - 阿里云百炼大模型平台接入

新建 HelloWorld 项目

Spring AI 2.0 开发Java Agent智能体 - 新建 HelloWorld 项目

Ollama简介以及安装和使用

Spring AI 2.0 开发Java Agent智能体 - Ollama简介以及安装和使用

Spring AI项目调用本地Ollama模型

Spring AI 2.0 开发Java Agent智能体 - Spring AI项目调用本地Ollama模型

Ollama 安装部署

进阶玩法:5个让DeepSeek更好用的技巧

1. 绑定到局域网

把Ollama的 OLLAMA_HOST 环境变量设为 0.0.0.0,局域网内其他设备都能调用。我家里台式机跑模型,笔记本和手机都能用。

2. 搭配 Continue 插件写代码

VS Code / JetBrains 安装 Continue 插件,配置指向本地Ollama。写代码时选中一段,Ctrl+L 直接让DeepSeek帮你解释或重构。

详细的Continue + DeepSeek配置教程,我之前写了一篇完整指南:DeepSeek本地部署全攻略

3. 用 AnythingLLM 做知识库问答

把PDF文档、技术手册丢进 AnythingLLM,底层用DeepSeek做推理,相当于给DeepSeek装了个"外挂知识库"。

Windows安装ollama和AnythingLLM及部署DeepSeek模型1

4. 模型量化节省显存

ollama create + Modelfile自定义量化参数,能让7B模型在6GB显存上跑起来。

DeepSeek-R1-Distill-Llama-8B实操手册:Ollama自定义Modelfile构建与量化部署技巧

5. 换个好看的界面

终端对话太硬核了。推荐装 Open WebUI,界面和ChatGPT一样好用:

dockerrun-d-p3000:8080\-vopen-webui:/app/backend/data\--nameopen-webui--restartalways\ghcr.io/open-webui/open-webui:main

然后打开浏览器访问 http://localhost:3000,一个完整的类ChatGPT界面就有了——对话历史、Markdown渲染、代码高亮全都有。

stream()方法Flux流式响应输出

Spring AI 2.0 开发Java Agent智能体 - stream()方法Flux流式响应输出

  1. 非流式输出 call:等待大模型把回答结果全部生成后输出给用户;
  2. 流式输出stream:逐个字符输出,一方面符合大模型生成方式的本质,另一方面当模型推理效率不是很高时,流式输出比起全部生成后再输出大大提高用户体验。
@GetMapping(value="/chat/stream",produces="text/html;charset=UTF-8")publicFlux<String>chatStream(@RequestParam(value="msg")Stringmessage){returnchatClient.prompt().user(message).stream().content();}

Advisors —— 拦截器模式增强AI能力

Spring AI 2.0 开发Java Agent智能体 - Advisors —— 拦截器模式增强AI能力

对话与提示词工程(Prompt)

一、核心概念总览

Spring AI 2.0 提供了统一、易用的对话与提示词工程 API,核心组件包括:

组件作用关键特性
Message封装对话内容支持SYSTEM、USER、ASSISTANT、TOOL四种类型Spring
Prompt模型输入容器包含消息列表和模型配置选项
PromptTemplate提示词模板引擎支持变量替换、外部文件加载、自定义分隔符Spring
ChatClient对话 API 入口流畅链式调用,简化提示词构建与响应处理Spring
ChatModel底层模型接口统一抽象不同大模型(OpenAI、Anthropic、Ollama等)Spring

二、核心知识点详解

1. 消息类型(Message Type)

Spring AI 定义了四种标准消息类型,用于构建结构化对话:

  • SYSTEM:设定 AI 角色、行为准则和能力边界(如 “你是一位 Java 开发专家,只回答编程相关问题”)
  • USER:用户输入的问题或指令
  • ASSISTANT:AI 的历史回复(用于多轮对话上下文)
  • TOOL:工具调用的结果(如函数执行返回值)

2. 提示词工程基础原则

有效提示词应包含三要素:

  • 角色设定:明确 AI 身份和能力范围
  • 上下文信息:提供必要背景知识
  • 清晰指令:明确任务目标和输出格式

提示词优化技巧:

  • 使用分隔符(如 ```、—)区分不同内容块
  • 设定输出格式(如 JSON、Markdown)
  • 控制模型参数(temperature:0~1,越低越确定;maxTokens:最大输出长度)

3. 提示词模板(PromptTemplate)

解决硬编码提示词的复用性和维护性问题,支持:

  • 变量替换(使用 {} 占位符
  • 外部文件加载(从 resources 读取模板)
  • 自定义渲染器(如修改分隔符为 <> )
  • 系统提示词模板(SystemPromptTemplate)专门用于角色设定

4. ChatClient 流畅 API

Spring AI 2.0 推荐使用 ChatClient 进行对话开发,特点:

  • 链式调用,代码简洁
  • 内置提示词构建器
  • 支持流式响应(Flux)
  • 统一处理不同模型的响应格式Spring

三,具体应用实例

1,PromptTemplate提示词模版

我们如果不用提示词模版,很多时候写代码是这样的:

// 不用模板:手写相同的逻辑,重复且难以维护@GetMapping("/chat/java")publicStringjava(){returnchatClient.prompt().user("介绍下Java").call().content();}@GetMapping("/chat/python")publicStringpython(){returnchatClient.prompt().user("介绍下Python").call().content();}

我们现在用提示词模版简化系统设计:

/** * 使用模板:一套代码应对所有场景 * @param topic * @return */@RequestMapping(value="/ask",produces="text/html;charset=utf-8")publicFlux<String>ask(Stringtopic){PromptTemplatetemplate=newPromptTemplate("介绍下{topic}");Promptprompt=template.create(Map.of("topic",topic));returnchatClient.prompt(prompt).stream().content();}

测试,浏览器输入: http://localhost:8080/ask?topic=java

2,使用 ChatClient 的流式 API 可以最快速地组装提示词

我们看下代码:

/** * 使用 `ChatClient` 的流式 API 可以最快速地组装提示词 * @param topic * @return */@RequestMapping(value="/ask2",produces="text/html;charset=utf-8")publicFlux<String>ask2(Stringtopic){returnchatClient.prompt().system("你是一个专业的书评助手")// 设置系统提示.user(u->u.text("请给我三本关于{topic}的书籍").param("topic",topic)).stream().content();}

测试,浏览器输入: http://localhost:8080/ask2?topic=python

3,系统提示词工程 —— defaultSystem

通过defaultSystem构建"专家角色",将其作为 AI 的"行动纲领",确保所有对话都有统一的行为准则。

我们先在AiConfiguration配置类里加一个ChatClient实例:

/** * 创建一个 ChatClient 对象,用于处理聊天请求。 * * @param model OpenAiChatModel 对象,用于处理聊天请求。 * @return ChatClient 对象,用于处理聊天请求。 */@BeanpublicChatClientchatClient3(OpenAiChatModelmodel){// System Prompt 工程:清晰定义 AI 的角色、任务、约束和输出格式StringsystemPrompt=""" 你是一个资深的 Java 技术顾问。 禁止回答任何非技术类问题,例如天气或娱乐八卦。 代码示例必须符合 Java 17+ 规范。 回答需要符合以下格式:首先一句话概括问题的核心,然后提供代码示例,最后补充注意事项。 如果自己不确定,可以说"关于这个问题,我目前没有确切的信息",禁止编造内容。 """;returnChatClient.builder(model)// 创建 ChatClient 对象,并设置模型为 model.defaultSystem(systemPrompt).defaultAdvisors(newSimpleLoggerAdvisor())// 添加一个 SimpleLoggerAdvisor,记录请求日志.build();// 构建 ChatClient 对象}

接下来,MyAiChatController里加下chatClient3实例,以及定义一个新接口方法:

@AutowiredprivateChatClientchatClient3;
/** * @param question * @return */@RequestMapping(value="/ask3",produces="text/html;charset=utf-8")publicFlux<String>ask3(Stringquestion){returnchatClient3.prompt()// 创建一个 Prompt 对象,用于构建聊天请求。.user(question)// 设置用户输入的文本。.stream()// 调用 ChatClient 对象的 call() 方法,发送聊天请求给大模型 并获取响应。.content();// 获取响应的文本内容。}

我们来测试下,浏览器输入: http://localhost:8080/ask3?question=写一个java起泡法排序算法

结构化输出

一、结构化输出核心概念

Spring AI 2.0 的结构化输出是将大语言模型 (LLM) 的自然语言响应转换为可预测、类型安全的 Java 对象(如 POJO、Record、Map、List 等)的机制,避免手动解析文本的复杂性和不稳定性。

1.1 为什么需要结构化输出

自然文本输出结构化输出
格式不固定,解析困难格式严格,直接映射为 Java 对象
无类型安全,易出错强类型校验,编译期检查
下游系统集成复杂可直接传递给其他应用程序函数
维护成本高减少解析逻辑,提升系统稳定性

1.2 Spring AI 2.0 结构化输出核心特性

  1. 自动 JSON Schema 生成:基于 Java 类自动生成 JSON Schema,确保模型输出符合预期格式
  2. 多种转换器支持:BeanOutputConverter、MapOutputConverter、ListOutputConverter 等
  3. 原生结构化输出:支持模型内置的 JSON 模式(如 OpenAI 的 JSON mode),提高输出可靠性
  4. 链式调用简化:通过 .entity() 方法直接将响应转换为目标类型,代码更简洁
  5. 集合类型支持:轻松处理 List、Set 等集合类型的结构化输出

二、核心实现方式

2.1 两种主要方案

方案说明适用场景
自动转换使用.entity()方法,Spring AI 自动处理转换大多数通用场景,代码简洁高效
显式转换器手动创建BeanOutputConverter等,精细控制转换过程复杂场景,需要自定义 JSON Schema或验证规则

2.2 原生结构化输出

Spring AI 2.0 支持模型原生的结构化输出能力,通过
AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT启用,自动处理以下流程Spring:

  1. 生成 JSON Schema
  2. . 配置模型使用 JSON 模式
  3. 验证输出格式
  4. 反序列化为 Java 对象

2.3 实例 1:基础 POJO 结构化输出

定义目标 Java 类(Record)

// 使用 Java 16+ 的 Record 特性,编译器会自动生成构造器、equals/hashCode等方法publicrecordTopicBooks(Stringtopic,// 主题List<String>books// 书籍列表){}

创建服务类实现结构化输出

/** * @param topic * @return */@RequestMapping(value="/ask4",produces="text/html;charset=utf-8")publicStringask4(Stringtopic){TopicBookstopicBooks=chatClient.prompt().system("你是一个专业的书评助手")// 设置系统提示.user(u->u.text("请给我三本关于{topic}的书籍").param("topic",topic)).call().entity(TopicBooks.class);System.out.println(topicBooks);return"OK";}

浏览器请求: http://localhost:8080/ask4?topic=java

后台输出:

TopicBooks[topic=Java,books=[Head First Java, Effective Java, Java ConcurrencyinPractice]]

2.4 实例 2:集合类型结构化输出

定义定义书评类

// 使用 Java 16+ 的 Record 特性,编译器会自动生成构造器、equals/hashCode等方法publicrecordBookReview(StringreviewerName,// 书评人intrating,// 评分(1-5)Stringcomment// 评论内容){}

生成多条书评

/** * @return */@RequestMapping(value="/ask5")publicStringask5(){List<BookReview>bookReviews=chatClient.prompt().user(u->u.text("请给{bookName}书籍三条评价信息").param("bookName","Head First Java")).call().entity(newParameterizedTypeReference<List<BookReview>>(){});System.out.println(bookReviews);return"OK";}

浏览器请求: http://localhost:8080/ask5
后台输出:

[BookReview[reviewerName=AliceChen,rating=5,comment=以生动有趣的漫画和互动练习讲解Java基础,非常适合初学者建立编程思维,但部分代码示例需结合新版JDK调整。],BookReview[reviewerName=DavidSmith,rating=4,comment=项目驱动的学习方式让人印象深 刻,通过构建实际应用巩固了面向对象概念,建议补充多线程和Lambda表达式的现代实践。],BookReview[reviewerName=MariaGarcia,rating=4,comment=幽默的叙事风格降低了学习门 槛,但章节进度跳跃较大,需要配合官方文档查漏补缺,整体仍是入门首选。]]

三,底层实现原理

大型语言模型生成结构化输出的能力,对于依赖于可靠解析输出值的下游应用至关重要。开发人员希望快速地将人工智能模型的输出转换为数据类型,例如JSON、XML或Java类,以便传递给其他应用程序的函数和方法。

Spring AIStructured Output Converters有助于将大语言模型的输出转换为结构化格式。如下图所示,这种方法围绕大语言模型文本补全端点运行:


使用通用补全API从大型语言模型(LLM)生成结构化输出,需要对输入和输出进行细致处理。在调用LLM前后,结构化输出转换器发挥着至关重要的作用,以确保实现所需的输出结构。

在大语言模型调用之前,转换器会将格式说明附加到提示中,为模型生成所需输出结构提供明确指导。这些说明充当蓝图,引导模型的响应符合指定的格式。

下图展示了使用结构化输出 API 时的数据流。

会话记忆(Chat Memory)

Spring AI 2.0 开发Java Agent智能体 - 会话记忆(Chat Memory)

Spring AI 2.0 对聊天记忆(Chat Memory)进行了多项改进,请说明其消息驱逐策略发生了怎样的变化?以及如何避免了工具调用过程中的重复记忆问题?

工具调用(Function Calling / Tools)

Spring AI 2.0 中 ChatClient API 有哪些重要变化?ToolCallingAdvisor 的自动注册机制是如何工作的?

一、什么是工具调用

工具调用(Tool Calling,又称 Function Calling)是 Spring AI 2.0 的核心能力之一,它让 LLM 能够调用你在 Java 后端中定义的函数,从而打通了 AI 与外部系统的连接。简单来说,就是让大模型不仅能“聊天”,还能真正“做事”——比如查询数据库、调用 API、执行业务逻辑等。

在 Spring AI 2.0 中,工具调用已与 Java 方法签名全面打通,只需用@Tool注解标记一个 Java 方法,AI 就能像调用本地函数一样调用它。

在没有工具调用的情况下,AI 模型只能基于其训练数据回答问题,无法获取实时信息或执行操作。例如,当你问“现在几点了?”时,模型会回答:“我无法获取实时信息,请告诉我当前日期。”而有了工具调用,模型可以自动调用你提供的getCurrentDateTime()方法,精准地返回当前时间。

我们可以先测试下,浏览器输入: http://localhost:8080/ai?question=现在是几点了?

二、核心工作原理

工具调用的核心流程可以概括为四个步骤:

  1. 定义工具:在 Java 代码中定义一个方法,并用@Tool(description = "xxx")注解标明其功能描述。
  2. 注册工具:将工具类实例注册到ChatClient中,Spring AI 会自动将其转换为 AI 模型可识别的JSON Schema。
  3. 模型决策:当 LLM 判断需要调用工具时,会在响应中生成 JSON 格式的调用指令(包含函数名和参数),而非直接输出最终答案。
  4. 执行与应答:Spring AI 将 JSON 指令转换为实际的方法调用,并将结果返回给模型,模型再基于这些“实时数据”生成最终的自然语言回答。

重要提醒:请务必注意,模型本身从不直接执行任何代码。它只是根据用户问题和定义的工具,以 JSON 格式“请求”你执行这个工具。真正的执行权 100% 掌握在你的 Java 应用中,这是一个关键的安全设计。

三、快速入门实例:让 AI 学会“看时间”

下面通过一个完整的代码示例,展示如何让 AI 获取当前日期和时间。本实例基于 Spring AI 2.0 推荐的@Tool注解方式。

importorg.springframework.ai.tool.annotation.Tool;importorg.springframework.context.i18n.LocaleContextHolder;importorg.springframework.stereotype.Component;importjava.time.LocalDateTime;importjava.time.format.DateTimeFormatter;@ComponentpublicclassDateTimeTools{@Tool(description="获取用户在指定时区的当前日期和时间,用于回答需要实时时间的问题")publicStringgetCurrentTime(){// 获取用户的时区偏好设置varzoneId=LocaleContextHolder.getTimeZone().toZoneId();varnow=LocalDateTime.now().atZone(zoneId);// 格式化为 yyyy-MM-dd HH:mm:ssreturnDateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(now);}}

对比说明:两种常见的工具定义方式:

  • @Tool 注解(推荐):代码最简洁,只需在方法上添加@Tool注解即可。这是 Spring AI 2.0 主推的新 API,也是本实例采用的方式。
  • FunctionCallback 方式(旧版):在 Spring AI 1.x 中需要实现复杂的Function接口,代码量较大。此 API 已被标记为过时(deprecated),建议在新项目中使用@Tool注解的方式。

MyAiChatController控制器里,在调用 ChatClient 时,通过 .tools() 方法将定义好的工具注册进去。

@AutowiredprivateDateTimeToolsdateTimeTools;@RequestMapping("/aitool")publicStringaitool(Stringquestion){returnchatClient.prompt()// 创建一个 Prompt 对象,用于构建聊天请求。.user(question)// 设置用户输入的文本。.tools(dateTimeTools)// 注册工具.call()// 调用 ChatClient 对象的 call() 方法,发送聊天请求给大模型并获 取响应。.content();// 获取响应的文本内容。}

我们再测试下,浏览器输入: http://localhost:8080/aitool?question=现在是几点了?


通过对比可以清晰地看出:注册工具后,AI 自动识别需求并调用了 getCurrentDateTime 方法,从而提供了精准的实时信息。

四、进阶实践:让 AI 执行操作

工具调用不仅能获取信息,还能让 AI 执行具体操作。以下示例展示了如何实现闹钟设置功能。

在工具类DateTimeTools中添加操作型工具

@Tool(description="设置闹钟,调用此工具可在指定时间触发提醒。时间参数必须是 ISO-8601 格 式,例如:2026-05-03 15:30:00")publicvoidsetAlarm(@ToolParam(description="闹钟的触发时间,标准格式:yyyyMM-dd HH:mm:ss")StringalarmTime){System.out.println("⏰ 闹钟已设置,将在 "+alarmTime+" 提醒用户。");// 此处可扩展实际逻辑:如存入数据库、发送推送通知等}

现在向 AI 提问:“帮我设置一个 1分钟后的闹钟。”


带工具注册的调用会自动触发如下流程:

  1. AI 模型首先调用getCurrentDateTime获取当前时间。
  2. 模型计算出 10 分钟后对应的时间点。
  3. 模型调用setAlarm工具,传入计算出的具体时间
  4. 控制台输出闹钟设置成功的提示。

这正是 Agent 模式的雏形:模型负责理解意图、拆解任务、规划步骤,你只需提供对应的工具方法,AI就能自动编排执行。

五,工具调用底层实现原理

Spring AI 通过一组灵活的抽象支持工具调用,使您能够以一致的方式定义、解析和执行工具。本节概述了 Spring AI 中工具调用的主要概念和组件。

  1. 当我们希望将某个工具提供给模型使用时,会将其定义包含在聊天请求中。每个工具定义包括名称、描述以及输入参数的模式。
  2. 当模型决定调用工具时,它会发送一条包含工具名称和按照定义的模式建模的输入参数的响应。
  3. 应用程序负责使用工具名称来识别并执行带有所提供输入参数的工具。
  4. 应用程序会处理工具调用的结果。
  5. 应用程序将工具调用结果发送回模型。
  6. 模型使用工具调用结果作为额外上下文,生成最终响应

工具是工具调用的构建模块,它们由ToolCallback接口进行建模。Spring AI 提供了内置支持,可从方法和函数中指定ToolCallback (s),但您也可以随时定义自己的ToolCallback实现,以支持更多用例。

ChatModel实现会透明地将工具调用请求分发到相应的ToolCallback实现,并将工具调用结果返回给模型,最终由模型生成最终响应。它们通过ToolCallingManager接口来完成这一过程,该接口负责管理工具执行的生命周期。

嵌入模型(Embedding Model)与向量数据库(Vector Databases)

Spring AI 2.0 开发Java Agent智能体 - 嵌入模型(Embedding Model)与向量数据库(Vector Databases)

Windows 下 Docker Desktop 安装教程及常用命令(2026 最新)

Spring AI 2.0 对向量存储(Vector Store)进行了哪些升级?新增了哪些向量存储后端?

RAG(检索增强生成)

Spring AI 2.0 开发Java Agent智能体 - RAG(检索增强生成)

分享一套锋哥原创的基于Spring AI 2.0的RAG企业内部知识库问答系统(AI大模型 SpringBoot4+Vue3+Ollama)

分享一套锋哥原创的基于Spring AI 2.0的RAG医疗健康知识智能问答系统(AI大模型 SpringBoot4+Vue3+Ollama)

分享一套锋哥原创的基于Spring AI 2.0的带AI智能客服的商城系统(支付宝沙箱模拟支付+SprnigBoot4+Vue3)

利用Cursor AI编程 两小时实现 基于Spring AI 2.0的带智能客服的商城系统(带在线支付功能)

MCP(模型上下文协议)

Spring AI 2.0 开发Java Agent智能体 - MCP(模型上下文协议)

多模态支持

Spring AI 2.0 开发Java Agent智能体 - 多模态支持