
Spring AI 1.0,一个全面的 Java 人工智能工程解决方案,在人工智能领域快速发展的影响下,经过重要的开发周期后现已可用。该版本包括许多对 AI 工程师至关重要的新特性。以下是一些最突出的特性的快速概述。在本文中,我们将逐步介绍这些概念。
可移植的服务抽象,使开发人员能够轻松、熟悉、一致且符合习惯地访问各种聊天模型、转录模型、嵌入模型、图像模型等。
与更广泛的 Spring 生态系统的丰富集成,包括 Micrometer.io、Spring Boot、Spring MVC 和 GraalVM 等项目。
支持 AI 工程的日常模式,包括检索增强生成(RAG)和工具调用,这些工具调用可以告知 AI 模型了解其环境中的工具。
支持 MCP,允许 Spring AI 用于构建和集成 MCP 服务。
和往常一样,当在Spring Initializr上生成应用程序时,你可以获得这些功能。
Spring AI 是你进行 AI 工程的一站式解决方案。
Java 和 Spring 正处于抓住这波 AI 浪潮的黄金位置。许多公司都在 Spring Boot 上运行他们的应用程序,这使得将 AI 轻松地融入他们现有的业务变得轻而易举。你基本上可以将业务逻辑和数据直接链接到这些 AI 模型上,而无需付出太多努力。
Spring AI 为各种 AI 模型和技术提供支持。图像模型可以根据文本提示生成图像。转录模型可以将音频转换为文本。嵌入模型可以将任意数据转换为向量,这是一种针对语义相似性搜索进行了优化的数据类型。聊天模型应该很熟悉!您肯定在某个地方与它们进行过简短的对话。聊天模型似乎是 AI 领域最受关注的部分。你可以让它们帮助你纠正文档或写一首诗(但别让它们讲笑话)。它们非常有用,但也存在一些问题。
让我们来看看这些问题以及它们在 Spring AI 中的解决方案。聊天模型思想开放且容易分心。你需要给它们一个系统提示来控制它们的整体形状和结构。AI 模型没有记忆。帮助它们将给定用户的一条消息与另一条消息关联起来取决于你,你可以通过赋予它们记忆来实现这一点。AI 模型生活在孤立的小沙箱中,但如果你让它们访问工具,它们可以做一些非常了不起的事情,这些工具是它们认为必要时可以调用的函数。Spring AI 支持工具调用,你可以向 AI 模型介绍其环境中的工具,然后模型可以请求你调用这些工具。这种多轮交互都是透明处理的。
AI 模型很聪明,但它们并非无所不知!它们既不知道你的专有数据库中有什么,也不想知道!因此,你需要通过填充提示来通知它们的响应,基本上就是使用字符串连接操作符在请求中放置文本,模型在查看被问到的问题之前会考虑这些文本(如果你愿意,可以称之为背景信息)。
你可以填充大量数据,但不是无限量的。你如何决定应该发送什么和不应该发送什么?使用向量存储来选择相关数据并将其发送出去。这种技术被称为检索增强生成(Retrieval Augmented Generation,RAG)。
AI 聊天模型喜欢,嗯,聊天!有时它们会如此自信地进行操作,以至于可以编造内容,所以你需要使用评估,使用一个模型来验证另一个模型的输出,以确认合理的结果。
当然,没有哪个 AI 应用程序是孤立存在的。如今,现代 AI 系统和服务在与其他系统和服务集成时效果最佳。MCP 可以将你的 AI 应用程序与其他基于 MCP 的服务连接起来,无论它们是用哪种语言编写的。你可以在代理式工作流中组装和组合 MCP 服务,以实现更大的目标。
而且,你可以在熟悉的惯用法和抽象概念的基础上完成这一切,这是任何 Spring Boot 开发人员所期望的:方便的启动依赖项,基本上 Spring Initializr 上可用的所有内容。Spring AI 提供了方便的 Spring Boot 自动配置,为你提供你已经熟悉和期望的约定优于配置的设置。Spring AI 还支持 Spring Boot 的 Actuator 和 Micrometer 项目来实现可观测性。它也与 GraalVM 和虚拟线程配合良好,使你能够构建快速高效的可扩展 AI 应用程序。
遇见狗狗
为了展示实际操作中一些酷炫的可能性,我们将构建一个示例应用程序。我总是很难为这类事情确定一个合适的领域。让我们选择一个贴近生活的:我们将构建一个名为 Pooch Palace 的虚构的狗狗领养机构。它就像一个收容所,你可以在线找到并领养狗狗!就像大多数收容所一样,人们会想要和某人交谈,并询问他们关于狗狗的情况。我们将构建一个助手服务来实现这一功能。
我们的 SQL 数据库里有很多狗狗的信息,当应用程序启动时它们会被安装。我们的目标是构建一个助手,帮助人们找到他们梦寐以求的狗狗,Prancer,它被描述得相当滑稽:“恶魔般的、神经质的、讨厌男人的、讨厌动物的、讨厌孩子的狗狗,看起来像小精灵”。这只狗狗太棒了。你可能听说过它。几年前,它的主人想为它找个新家,发布的广告非常搞笑,然后它迅速走红!这是原始的广告帖子,在Buzzfeed新闻、《今日美国》和《纽约时报》上都有报道。
我们将构建一个简单的 HTTP 端点,将使用 Spring AI 与大语言模型(LLM)进行集成。在这种情况下,我们将使用 Open AI,尽管你可以选择任何你喜欢的工具,包括 Ollama、Amazon Bedrock、Google Gemini、HuggingFace 等等——所有这些都可以通过 Spring AI 进行支持——让 AI 模型帮助我们找到我们梦寐以求的狗狗,它通过分析我们的问题,并在查看收容所(以及我们的数据库)里的狗狗后,决定哪只可能是最适合我们的。
构建
使用Spring Initializr,让我们生成一个新项目。我将使用最新版本的 Spring Boot。选择 Open AI(1.0 或更高版本)。我将使用一个向量存储库。在这种情况下,它是一个基于 PostgreSQL 的向量存储库,称为PgVector。我们还要添加 Spring Boot Actuator
模块以实现可观测性。添加 Web 支持。添加对基于 SQL 的类似 ORM 数据映射的支持,使用 Spring Data JDBC。你还应该选择 Docker Compose
。我也使用了 Apache Maven。我将在本文中使用 Java 24,但你应该使用最新的合理版本。如果你读到这篇文章时 Java 25 已发布,那么就使用 Java 25!我也使用了GraalVM
原生镜像。所以,请确保添加 GraalVM 及其依赖项。
这里有很多不同的选项,包括 Weaviate、Qdrant、ChromaDB、Elastic、Oracle、SQLServer、MySQL、Redis、MongoDB 等。实际上,Spring AI 甚至提供了一个 SimpleVectorStore
类,一个向量存储实现,你都可以使用。然而,我不会在生产环境中使用这个实现,因为它只是内存中的,并不擅长保留数据。但它是一个起点。
我们需要支持上述 RAG 模式,因此在 pom.xml
中添加以下依赖项:
你使用 GraalVM 了吗?没有?好吧,你应该使用!如果你在 macOS 或 Linux 或 Windows Subsystem for Linux 上,你应该使用令人惊叹的SDKMAN.io项目来管理你的基于 JVM 的基础设施。安装完 SDKMAN.io 后,安装 GraalVM 就像这样简单:
请注意,我使用的是截至本文撰写时的最新版本的 Java。不过,你按需选择就好!永远记得使用最新版本的运行时和相关技术。就像我已故的父亲常说的那样,“一寸易,一尺难”。如果你不使用英制单位,有人可能会将其翻译为“一厘米易,一米难”。如果你按部就班地做事,它们就不会累积成难以克服的技术债。
点击“生成”,解压生成的.zip 文件,然后在你最喜欢的 IDE 中打开 pom.xml
。
我们添加了 Docker Compose 支持,因此你会在文件夹中看到一个 compose.yml
文件。打开它,并确保更改端口导出行,如下所示:
将其更改为:
这样,当你启动 PostgreSQL Docker 镜像时,你可以从外部客户端连接到它。这在开发中很有用,因为你可以查看正在执行的操作。
配置
首先,Spring AI 是一个多模态 AI 系统,允许你使用许多不同的模型。在这种情况下,我们将主要与 ChatModel
、OpenAI 进行交互。使用数十种不同的受支持模型是完全可能切合理的,如 Amazon Bedrock、Google Gemini、Azure OpenAI,甚至是本地模型,如那些通过 Docker 的 Model Runner 和 Ollama 启用的模型。如果你处于隐私敏感领域,如银行或欧洲的大部分地区,运行你的模型是必不可少的。你也有多种选择!如果明确的支持方案不适合你,可以使用 OpenAI API,并将你购买的基本 URL 替换为的新模型,其中许多模型都实现了 OpenAI API。
要连接到模型,我们需要指定一个 OpenAI 密钥。在 application.properties
中添加以下内容:
如果你没有 OpenAI API 密钥,你可以从OpenAI开发者控制台获得一个。
Spring Boot 支持在启动时运行 Docker 镜像。它将自动运行文件夹根目录中的 compose.yml
文件。不幸的是,PostgreSQL 不是无服务器的,所以我们只希望 Spring Boot 在它还没有运行时启动镜像。在 application.properties
中添加如下指令:
Spring Boot 在启动时会自动连接到 Docker 镜像。但这只是用于开发。稍后,我们将构建一个 GraalVM 原生镜像,它是代码的生产版本。现在让我们指定一些 spring.datasource.*
属性,以便应用程序可以连接到运行在 Docker 守护进程中的本地 SQL 数据库。
现在你不需要这个,但最终你会想要将你的应用程序连接到一个 SQL 数据库。现在你知道怎么做了。另外请注意,在生产环境中,不能硬编码配置。设置环境变量,例如, SPRING_DATASOURCE_USERNAME
。
当 Spring Boot 启动时,它会启动 SQL 数据库。我们也希望它能够将一些数据安装到这个数据库中,所以我们有两个文件: data.sql
和 schema.sql
。如果我们要求,Spring Boot 将自动运行 schema.sql
,然后运行 data.sql
。
现在我们准备好了!
给我看看代码!
代码是最简单的部分。我们将构建一个简单的 HTTP 控制器,它将接受询问——实际上是——对收容所进行采访,了解收容所里的狗狗。
任何新的 Spring Boot 项目都会自动生成类似上述类的代码。在这个应用程序中,生成的类名为AssistantApplication.java
。
我们需要数据访问功能来将我们的应用程序连接到底层的 SQL 数据库,所以让我们现在就处理这个问题。在主类下面添加以下内容:
这是我们的数据访问层。现在,让我们继续实际的控制器。在其他所有内容下面添加以下控制器。
我们已经有了一些关键的东西。在构造函数中,我们注入了 ChatClient.Builder
,并使用该构建器配置默认的系统提示。在 inquire()
方法中,我们接受传入的请求,然后将这些请求从客户端作为 String
转发到底层模型。
试试看。我使用的是方便的 HTTPie
命令行工具。
它应该回应确认它理解你刚刚说的话。但它确实理解了吗?
这次,它应该回应说,它已经忘记你了。(或许只有我是这样。我似乎对人们有这种影响!)
无论如何,修复这个问题的方法是配置一个 advisor,这是一个 Spring AI 的概念,允许你对发往模型的请求进行预处理和后处理。让我们配置一个 PromptChatMemoryAdvisor
类的实例,它将跟踪发送到模型的所有内容,然后将其重新传输到后续请求。我们将使用 URL 中传递的用户路径变量作为区分每个记录的键。毕竟,我们不希望某个随机人得到你的聊天记录!我们将使用内存中的实现,但你同样也可以轻松使用基于 JDBC 的实现。
让我们创建一个并发映射来存储多租户请求。所以,将这个添加到类中。
让我们配置 advisor,然后将其传递到调用站点的 ChatClient
中。这是更新后的方法。
重新启动程序,然后再次尝试上述两个请求。它应该能记住你!
但是,它仍然不知道关于狗狗的事情!通过发出更具体的请求来证明这一点。
记住,我们想要找到 Prancer,这只“恶魔般的、神经质的、讨厌男人的、讨厌动物的、讨厌孩子的狗狗,看起来像一个哥布林”。
我们需要从 SQL 数据库中集成数据,并将其与请求一起发送,但不是全部数据。没有必要。相反,让我们使用向量存储来找到我们查询的最相关的数据。回想一下,我们之前使用的是 Spring AI 在 Spring AI 设计的表中实现的向量类型。让我们首先在 PostgreSQL 中设置一个表。
现在将构造函数修改成下面这样:
现在,当应用程序启动时,我们将从 SQL 数据库中读取所有数据并将其写入 VectorStore
。然后,我们配置一个新的 advisor,它将知道在将结果嵌入到模型的最终分析请求之前,查询VectorStore
以获取相关结果。
重新启动程序,然后再次尝试最后的 http
调用。
它起作用了!
现在,注释掉上面初始化 VectorStore
的代码,因为不需要初始化向量存储两次!
我们取得了很好的进展,但我们远未完成!我们可能已经找到了 Prancer,但现在怎么办?任何热血的人都会抓住机会收养这只狗狗!我知道我会。让我们修改程序,使我们的模型能够访问工具,以帮助我们安排一个可能接走或收养 Prancer 的时间。将以下类添加到代码页的底部。
该实现返回三天后的日期并打印出消息。修改构造函数,让它知道这个新工具:注入 DogAdoptionScheduler
,然后将其传递到 ChatClient.Builder
中定义的 defaultTools()
方法。重新启动程序。
它应该返回有一只名叫 Prancer 的神经质狗狗。现在,让它帮助我们领养这只狗狗。
你应该看到它起作用了。(不错,对吧?)
现在我们已经将我们的模型和业务逻辑与 AI 模型集成了。我们可以在这里停止了!毕竟,还有什么呢?嗯,相当多。我想通过引入模型上下文协议(Model Context Protocol,MCP)将这里的工具调用支持再向前推进几步。
Anthropic 在 2024 年 11 月推出了 MCP。这是一个用于模型(在这种情况下,通过 Claude 桌面应用程序的 Claude)与世界范围内的工具进行互操作的协议。Spring AI 团队抓住了这个机会,并构建了一个 Java 实现,最终成为了 MCP 网站上的官方 Java SDK。然后 Spring AI 团队在此基础上重新构建了它们的集成。我们看看它的实际效果。我们首先将调度器提取成一个单独的 MCP 服务(称为调度器),然后连接我们的助手。
使用Spring Initializr,将它命名为 scheduler
,选择 Web
和 MCP Server
,然后点击"生成"。在 IDE 中打开项目。
从上面剪切并粘贴 DogAdoptionScheduler
类,并将其粘贴到新创建的scheduler
代码库的代码页面的底部。确保服务不会在与 assistant
相同的端口上启动;将以下内容添加到 application.properties
中:
我们还需要注册一个 ToolCallbackProvider
,它告诉 Spring AI 将哪些 bean 导出为 MCP 服务导出。以下是我们新scheduler
应用程序的全部代码:
启动这个服务。然后回到`assistant` 那里。删除代码中对 DogAdoptionScheduler
的引用——构造函数、它的定义、 defaultTools
上的配置等。在主类中定义一个新的 McpSyncClient
类型的 bean:
将该引用注入到构造函数中,然后将其更改为:
启动程序并询问关于神经质的狗狗以及你可能会在什么时间领养狗狗。你应该可以看到这次,这一次,该工具是在 scheduler
模块中调用的。
生产级别的 AI
代码已经完成了;现在,是时候将我们的注意力转向生产环境了。
安全性
使用 Spring Security 来锁定这个 Web 应用程序是很简单的。你可以使用经过身份验证的 Principal.getName()
作为对话 ID。但是,关于存储在 SQL 数据库中的数据,比如对话呢?你有几个选择。大多数 SQL 数据库都有透明的数据加密。当你读取或写入值时,它会安全地存储在磁盘上。这不需要对代码进行任何更改。
可伸缩性
我们希望这段代码是可伸缩的。记住,每次你向 LLM(或许多 SQL 数据库)发出 HTTP 请求时,你都会阻塞 IO,这似乎是对一个完美线程的浪费!线程不应该只是闲置和等待。Java 21 为我们提供了虚拟线程,它可以显著提高充分绑定 IO 的服务的可伸缩性。这就是为什么我们要在 application.properties 文件中设置spring.threads.virtual.enabled=true
的原因。
GraalVM 原生镜像
GraalVM CE 是一个 Ahead-of-Time (AOT)编译器,它生成特定于架构和操作系统的原声二进制文件。如果你将其设置为你的 SDK,你可以轻松地将这个 Spring AI 应用程序转换为原生映像:
在大多数机器上,这需要一分钟左右的时间,但一旦完成,你就可以轻松运行二进制文件。
这个程序的启动时间比在 JVM 上运行的时间短得多。它在我的机器上不到十分之一秒就启动了。该应用程序占用的内存只占它在 JVM 上占用的内存的一小部分。你可能会说,这一切都很好,但我需要让它在我的云平台上运行(当然是 CloudFoundry 或 Kubernetes),这意味着要把它变成 Docker 镜像。简单!
往后站。这可能需要一分钟。执行完毕后,你会看到生成的 Docker 镜像的名称被打印出来了。你可以运行它,记住要覆盖它在你的主机上引用的主机和端口。
喔!
我们在 macOS 上运行,令人惊讶的是,当在模拟 Linux 的虚拟机中运行时,这个应用程序运行得甚至比——而且从一开始就——在 macOS 上直接运行还要快!不可思议。
可观测性
这个应用程序非常好,我打赌它很快就会像 Prancer 一样成为头条新闻。当这种情况发生
可观察性
这个应用程序是如此的好,我打赌它很快就会像 Prancer 一样成为头条新闻。当这种情况发生时,建议你密切关注系统资源,更重要的是关注 token 数量。对 LLM 的所有请求都有成本,如果不是美元和美分,至少是一种复杂性。幸运的是,Spring AI 支持你。向模型发起几个请求,然后打开由Micrometer: http://localhost:8080/actuator/metrics
提供支持的 Spring Boot Actuator 指标端点,你会看到一些与 token 使用相关的指标。好了!你可以使用千分尺将这些指标转发到时间序列数据库中,以获得一块玻璃,即仪表板。
结论/总结
AI 极大地改变了我们构建软件的方式,为我们提供了新的机会,使我们的应用更具交互性、更易用、更强大,并且越来越具有智能性。但请放心,Java 和 Spring 的开发人员要振作起来:你们不需要转向 Python 就能参与这场革命。
就其核心而言,AI 集成通常归结为与 HTTP 端点通信,这是 Java 和 Spring 一直擅长的事情。集成是我们的强项。除此之外,Java 和 Spring 是构建生产级软件的成熟平台。使用 Spring,你可以获得强大的可观测性、安全性支持,以及通过 GraalVM 实现的闪电般的性能和虚拟线程的可伸缩性,这些都是你在真实负载下运行真实系统所需的一切。
大多数企业已经在 JVM 上运行他们的关键业务逻辑。。支撑世界的软件已经是用 Java 和 Spring 编写的了。而有了 Spring AI,不仅仅是添加 AI,,而是将生产就绪的 AI 添加到持久构建的系统中。
资源
查看Spring Initializr。你可以在 Spring Boot 3.5 上构建项目,而在 2025 年晚些时候,你还可以在 Spring Boot 4 和 Spring Framework 7 上构建项目!
原文链接:
评论