网易首页 > 网易号 > 正文 申请入驻

Spring AI 1.0 提供简单的 AI 系统和服务

0
分享至

作者 | Josh Long

译者 | 刘雅梦

策划 | 丁晓昀

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 BootActuator模块以实现可观测性。添加 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中添加以下依赖项:


     

 org.springframework.ai groupId>     

 spring-ai-advisors-vector-store artifactId> dependency> 



你使用 GraalVM 了吗?没有?好吧,你应该使用!如果你在 macOS 或 Linux 或 Windows Subsystem for Linux 上,你应该使用令人惊叹的 SDKMAN.io 项目来管理你的基于 JVM 的基础设施。安装完 SDKMAN.io 后,安装 GraalVM 就像这样简单:

$ sdk install java 24-graalce

请注意,我使用的是截至本文撰写时的最新版本的 Java。不过,你按需选择就好!永远记得使用最新版本的运行时和相关技术。就像我已故的父亲常说的那样,“一寸易,一尺难”。如果你不使用英制单位,有人可能会将其翻译为“一厘米易,一米难”。如果你按部就班地做事,它们就不会累积成难以克服的技术债。

点击“生成”,解压生成的.zip 文件,然后在你最喜欢的 IDE 中打开pom.xml

我们添加了 Docker Compose 支持,因此你会在文件夹中看到一个compose.yml文件。打开它,并确保更改端口导出行,如下所示:

ports: 
    - '5432'

将其更改为:

ports:
    - '5432:5432'

这样,当你启动 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中添加以下内容:

spring.ai.openai.api-key=

如果你没有 OpenAI API 密钥,你可以从 OpenAI 开发者控制台 获得一个。

Spring Boot 支持在启动时运行 Docker 镜像。它将自动运行文件夹根目录中的compose.yml文件。不幸的是,PostgreSQL 不是无服务器的,所以我们只希望 Spring Boot 在它还没有运行时启动镜像。在application.properties中添加如下指令:

spring.docker.compose.lifecycle-management=start_only

Spring Boot 在启动时会自动连接到 Docker 镜像。但这只是用于开发。稍后,我们将构建一个 GraalVM 原生镜像,它是代码的生产版本。现在让我们指定一些spring.datasource.*属性,以便应用程序可以连接到运行在 Docker 守护进程中的本地 SQL 数据库。

spring.datasource.password=secret
spring.datasource.username=myuser
spring.datasource.url=jdbc:postgresql://localhost/mydatabase

现在你不需要这个,但最终你会想要将你的应用程序连接到一个 SQL 数据库。现在你知道怎么做了。另外请注意,在生产环境中,不能硬编码配置。设置环境变量,例如,SPRING_DATASOURCE_USERNAME

当 Spring Boot 启动时,它会启动 SQL 数据库。我们也希望它能够将一些数据安装到这个数据库中,所以我们有两个文件:data.sqlschema.sql。如果我们要求,Spring Boot 将自动运行schema.sql,然后运行data.sql

spring.sql.init.mode=always

现在我们准备好了!

给我看看代码!

代码是最简单的部分。我们将构建一个简单的 HTTP 控制器,它将接受询问——实际上是——对收容所进行采访,了解收容所里的狗狗。

package com.example.assistant;
import io.modelcontextprotocol.client.McpClient;
import io.modelcontextprotocol.client.McpSyncClient;
import io.modelcontextprotocol.client.transport.HttpClientSseClientTransport;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemoryRepository;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.document.Document;
import org.springframework.ai.mcp.SyncMcpToolCallbackProvider;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.annotation.Id;
import org.springframework.data.repository.ListCrudRepository;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@SpringBootApplication
public class AssistantApplication {
    public static void main(String[] args) {
        SpringApplication.run(AssistantApplication.class, args);
    }
}

任何新的 Spring Boot 项目都会自动生成类似上述类的代码。在这个应用程序中,生成的类名为AssistantApplication.java

我们需要数据访问功能来将我们的应用程序连接到底层的 SQL 数据库,所以让我们现在就处理这个问题。在主类下面添加以下内容:

interface DogRepository extends ListCrudRepository

 { } record Dog(@Id int id, String name, String owner, String description) { } 

这是我们的数据访问层。现在,让我们继续实际的控制器。在其他所有内容下面添加以下控制器。

@Controller
@ResponseBody
class AssistantController {
    private final ChatClient ai;
    AssistantController(ChatClient.Builder ai,
                        McpSyncClient mcpSyncClient,
                        DogRepository repository, VectorStore vectorStore
    ) {
        var system = """
                You are an AI powered assistant to help people adopt a dog from the adoption
                agency named Pooch Palace with locations in Antwerp, Seoul, Tokyo, Singapore, Paris,
                Mumbai, New Delhi, Barcelona, San Francisco, and London. Information about the dogs 
                available will be presented below. If there is no information, then return a polite response 
                suggesting we don't have any dogs available.
                """;
        this.ai = ai
                .defaultSystem(system)
                .build();
    }
    @GetMapping("/{user}/assistant")
    String inquire (@PathVariable String user, @RequestParam String question) {
        return this.ai
                .prompt()
                .user(question)
                .call()
                .content();
    }
}

我们已经有了一些关键的东西。在构造函数中,我们注入了ChatClient.Builder,并使用该构建器配置默认的系统提示。在inquire()方法中,我们接受传入的请求,然后将这些请求从客户端作为String转发到底层模型。

试试看。我使用的是方便的HTTPie命令行工具。

$ http :8080/jlong/assistant question=="my name is Josh"

它应该回应确认它理解你刚刚说的话。但它确实理解了吗?

$ http :8080/jlong/assistant question=="what's my name?"

这次,它应该回应说,它已经忘记你了。(或许只有我是这样。我似乎对人们有这种影响!)

无论如何,修复这个问题的方法是配置一个 advisor,这是一个 Spring AI 的概念,允许你对发往模型的请求进行预处理和后处理。让我们配置一个PromptChatMemoryAdvisor类的实例,它将跟踪发送到模型的所有内容,然后将其重新传输到后续请求。我们将使用 URL 中传递的用户路径变量作为区分每个记录的键。毕竟,我们不希望某个随机人得到你的聊天记录!我们将使用内存中的实现,但你同样也可以轻松使用基于 JDBC 的实现。

让我们创建一个并发映射来存储多租户请求。所以,将这个添加到类中。

//...    
    private final Map

 memory = new ConcurrentHashMap<>();     //... 

让我们配置 advisor,然后将其传递到调用站点的ChatClient中。这是更新后的方法。

@GetMapping("/{user}/assistant")
String assistant(@PathVariable String user, @RequestParam String question) {
    var inMemoryChatMemoryRepository = new InMemoryChatMemoryRepository();
    var chatMemory = MessageWindowChatMemory
            .builder()
            .chatMemoryRepository(inMemoryChatMemoryRepository)
            .build();
    var advisor = PromptChatMemoryAdvisor
            .builder(chatMemory)
            .build();
    var advisorForUser = this.memory.computeIfAbsent(user, k -> advisor);
    return this.ai
            .prompt()
            .user(question)
            .advisors(advisorForUser)
            .call()
            .content();
}

重新启动程序,然后再次尝试上述两个请求。它应该能记住你!

但是,它仍然不知道关于狗狗的事情!通过发出更具体的请求来证明这一点。

$ http :8080/jlong/assistant question==" do you have any neurotic dogs?"

记住,我们想要找到 Prancer,这只“恶魔般的、神经质的、讨厌男人的、讨厌动物的、讨厌孩子的狗狗,看起来像一个哥布林”。

我们需要从 SQL 数据库中集成数据,并将其与请求一起发送,但不是全部数据。没有必要。相反,让我们使用向量存储来找到我们查询的最相关的数据。回想一下,我们之前使用的是 Spring AI 在 Spring AI 设计的表中实现的向量类型。让我们首先在 PostgreSQL 中设置一个表。

 spring.ai.vectorstore.pgvector.initialize-schema=true

现在将构造函数修改成下面这样:

AssistantController(ChatClient.Builder ai,
                        DogRepository repository, VectorStore vectorStore
    ) {
        // be prepared to comment out from here...
        repository.findAll().forEach(dog -> {
            var dogument = new Document("id: %s, name: %s, description: %s".formatted(dog.id(), dog.name(), dog.description()));
            vectorStore.add(List.of(dogument));
        });
        // to here
        // ..as before... 
        this.ai = ai
            // as before
            .defaultAdvisors(new QuestionAnswerAdvisor(vectorStore))
            // as before ...
            .build();
    }

现在,当应用程序启动时,我们将从 SQL 数据库中读取所有数据并将其写入VectorStore。然后,我们配置一个新的 advisor,它将知道在将结果嵌入到模型的最终分析请求之前,查询VectorStore以获取相关结果。

重新启动程序,然后再次尝试最后的http调用。

它起作用了!

现在,注释掉上面初始化VectorStore的代码,因为不需要初始化向量存储两次!

我们取得了很好的进展,但我们远未完成!我们可能已经找到了 Prancer,但现在怎么办?任何热血的人都会抓住机会收养这只狗狗!我知道我会。让我们修改程序,使我们的模型能够访问工具,以帮助我们安排一个可能接走或收养 Prancer 的时间。将以下类添加到代码页的底部。

@Component
class DogAdoptionScheduler {
    @Tool(description = "schedule an appointment to pickup or "+ 
                        "adopt a dog from a Pooch Palace location")
    String scheduleAdoption(
            @ToolParam(description = "the id of the dog") int dogId,
            @ToolParam(description = "the name of the dog") String dogName) {
        System.out.println("scheduleAdoption: " + dogId + " " + dogName + "".);
        return Instant
                .now()
                .plus(3, ChronoUnit.DAYS)
                .toString();
    }
}

该实现返回三天后的日期并打印出消息。修改构造函数,让它知道这个新工具:注入DogAdoptionScheduler,然后将其传递到ChatClient.Builder中定义的defaultTools()方法。重新启动程序。

 $ http :8080/jlong/assistant question==" do you have any neurotic dogs?"

它应该返回有一只名叫 Prancer 的神经质狗狗。现在,让它帮助我们领养这只狗狗。

$ http :8080/jlong/assistant question== "fantastic. When can I schedule an  appointment to pick up or adopt Prancer from the San Francisco Pooch Palace location?"

你应该看到它起作用了。(不错,对吧?)

现在我们已经将我们的模型和业务逻辑与 AI 模型集成了。我们可以在这里停止了!毕竟,还有什么呢?嗯,相当多。我想通过引入模型上下文协议(Model Context Protocol,MCP)将这里的工具调用支持再向前推进几步。

Anthropic 在 2024 年 11 月推出了 MCP。这是一个用于模型(在这种情况下,通过 Claude 桌面应用程序的 Claude)与世界范围内的工具进行互操作的协议。Spring AI 团队抓住了这个机会,并构建了一个 Java 实现,最终成为了 MCP 网站上的官方 Java SDK。然后 Spring AI 团队在此基础上重新构建了它们的集成。我们看看它的实际效果。我们首先将调度器提取成一个单独的 MCP 服务(称为调度器),然后连接我们的助手。

使用 Spring Initializr,将它命名为scheduler,选择WebMCP Server,然后点击"生成"。在 IDE 中打开项目。

从上面剪切并粘贴DogAdoptionScheduler类,并将其粘贴到新创建的scheduler代码库的代码页面的底部。确保服务不会在与assistant相同的端口上启动;将以下内容添加到application.properties中:

server.port=8081

我们还需要注册一个ToolCallbackProvider,它告诉 Spring AI 将哪些 bean 导出为 MCP 服务导出。以下是我们新scheduler应用程序的全部代码:

package com.example.scheduler;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
@SpringBootApplication
public class SchedulerApplication {
    public static void main(String[] args) {
        SpringApplication.run(SchedulerApplication.class, args);
    }
    @Bean
    MethodToolCallbackProvider methodToolCallbackProvider(DogAdoptionScheduler scheduler) {
        return MethodToolCallbackProvider
                .builder()
                .toolObjects(scheduler)
                .build();
    }
}
@Component
class DogAdoptionScheduler {
    @Tool(description = "schedule an appointment to pickup or"+
                        " adopt a dog from a Pooch Palace location")
    String scheduleAdoption(@ToolParam(description = "the id of the dog") int dogId,
                            @ToolParam(description = "the name of the dog") String dogName) {
        System.out.println("scheduleAdoption: " + dogId + " " + dogName + "".);
        return Instant
                .now()
                .plus(3, ChronoUnit.DAYS)
                .toString();
    }
}

启动这个服务。然后回到`assistant` 那里。删除代码中对DogAdoptionScheduler的引用——构造函数、它的定义、defaultTools上的配置等。在主类中定义一个新的McpSyncClient类型的 bean:

@Bean
    McpSyncClient mcpSyncClient() {
        var mcp = McpClient
                    .sync(HttpClientSseClientTransport
                            .builder("http://localhost:8081")
                            .build())
                    .build();
        mcp.initialize();
        return mcp;
    }

将该引用注入到构造函数中,然后将其更改为:

 AssistantController(ChatClient.Builder ai, 
                        McpSyncClient mcpSyncClient, 
                        DogRepository repository, 
                        VectorStore vectorStore
    ) {
        // like before... 
        this.ai = ai
                // ...
                .defaultToolCallbacks(new SyncMcpToolCallbackProvider(mcpSyncClient))
                .build();
    }

启动程序并询问关于神经质的狗狗以及你可能会在什么时间领养狗狗。你应该可以看到这次,这一次,该工具是在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 应用程序转换为原生映像:

$ ./mvnw -DskipTests -Pnative native:compile

在大多数机器上,这需要一分钟左右的时间,但一旦完成,你就可以轻松运行二进制文件。

$ ./target/assistant

这个程序的启动时间比在 JVM 上运行的时间短得多。它在我的机器上不到十分之一秒就启动了。该应用程序占用的内存只占它在 JVM 上占用的内存的一小部分。你可能会说,这一切都很好,但我需要让它在我的云平台上运行(当然是 CloudFoundry 或 Kubernetes),这意味着要把它变成 Docker 镜像。简单!

$ ./mvnw -DskipTests -Pnative spring-boot:build-image

往后站。这可能需要一分钟。执行完毕后,你会看到生成的 Docker 镜像的名称被打印出来了。你可以运行它,记住要覆盖它在你的主机上引用的主机和端口。

$ docker run -e SPRING_DATASOURCE_URL=jdbc:postgresql://docker.host.internal/mydatabase 
\ docker.io/library/assistant:0.0.1-SNAPSHOT

喔!

我们在 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 AI 1.0 博客链接

  • Josh 的 YouTube 频道

  • 查看 Spring Initializr。你可以在 Spring Boot 3.5 上构建项目,而在 2025 年晚些时候,你还可以在 Spring Boot 4 和 Spring Framework 7 上构建项目!

https://www.infoq.com/articles/spring-ai-1-0/

声明:本文由 InfoQ 翻译,未经许可禁止转载。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
几种毒蔬菜流通市面,建议:买菜切记避开这3样!

几种毒蔬菜流通市面,建议:买菜切记避开这3样!

健康科普365
2026-01-28 11:00:45
南京天润城,一共有451栋楼,房价从2380涨到19000,当前价格分化

南京天润城,一共有451栋楼,房价从2380涨到19000,当前价格分化

靓仔情感
2026-01-30 16:47:13
48岁瘫痪卧床、父亲离世,重获新生全靠汪嘉伟,郑亮现状如何?

48岁瘫痪卧床、父亲离世,重获新生全靠汪嘉伟,郑亮现状如何?

以茶带书
2026-01-30 20:14:45
消失75年的美潜艇现身我国南海,美方直言:所有国家都不准打捞

消失75年的美潜艇现身我国南海,美方直言:所有国家都不准打捞

寄史言志
2026-01-30 23:53:09
上海队战胜深圳!卢伟夸赞一人,不是张镇麟和王哲林,也不是外援

上海队战胜深圳!卢伟夸赞一人,不是张镇麟和王哲林,也不是外援

格斗联盟王大锤
2026-01-31 07:27:06
万万没想到,把自己给举报了

万万没想到,把自己给举报了

我是历史其实挺有趣
2026-01-30 09:12:34
闲鱼不愧是全国最大的黑市,网民:只有你想不到,没有你买不到

闲鱼不愧是全国最大的黑市,网民:只有你想不到,没有你买不到

小熊侃史
2026-01-16 07:40:07
公司:“二次合同不能终止,第二次岂不成了无固定”?法院:理解错误!| 劳动法库

公司:“二次合同不能终止,第二次岂不成了无固定”?法院:理解错误!| 劳动法库

劳动法库
2026-01-31 08:34:05
中央巡视组将再亮剑!这5类问题是重点,老百姓福音来了!

中央巡视组将再亮剑!这5类问题是重点,老百姓福音来了!

细说职场
2026-01-30 17:21:07
自作孽!44岁少帅,自从玩“战略放弃”后,再没赢球,如今5连败

自作孽!44岁少帅,自从玩“战略放弃”后,再没赢球,如今5连败

金山话体育
2026-01-31 06:28:15
白骨案前夫是自卫反击战老兵!独自带大儿子不再婚 28年为她正名

白骨案前夫是自卫反击战老兵!独自带大儿子不再婚 28年为她正名

好贤观史记
2026-01-30 17:01:36
看完《小城大事》再看《生命树》,我想说:没有对比就没有伤害!

看完《小城大事》再看《生命树》,我想说:没有对比就没有伤害!

老吴教育课堂
2026-01-31 01:48:11
儿子病逝,儿媳带孙子去了北方,15年后孙子突然回来,我泪如雨下

儿子病逝,儿媳带孙子去了北方,15年后孙子突然回来,我泪如雨下

媛来这样
2025-11-19 08:50:14
大爆冷!联盟第一轰然倒下!亚历山大30+8+6,雷霆的总冠军悬了

大爆冷!联盟第一轰然倒下!亚历山大30+8+6,雷霆的总冠军悬了

篮球扫地僧
2026-01-30 23:17:15
刘强东亿万身家背后,妹妹是一生的痛,长相靓还能干,却没享到福

刘强东亿万身家背后,妹妹是一生的痛,长相靓还能干,却没享到福

子芫伴你成长
2026-01-31 08:20:03
单场10+10,再中3记三分!火箭底薪后卫重回首发,300万年薪真香

单场10+10,再中3记三分!火箭底薪后卫重回首发,300万年薪真香

篮球看比赛
2026-01-30 13:45:28
1-0,法甲争冠热门避免2连败,反超巴黎圣日耳曼队升至榜首

1-0,法甲争冠热门避免2连败,反超巴黎圣日耳曼队升至榜首

侧身凌空斩
2026-01-31 05:46:46
兹维列夫怒斥阿卡抽筋使用医疗暂停,阿卡赛前呕吐引人担忧

兹维列夫怒斥阿卡抽筋使用医疗暂停,阿卡赛前呕吐引人担忧

网球之家
2026-01-30 22:46:01
同学聚会,老婆被起哄和初恋拥吻,我笑着鼓掌:你脏了,我不要了

同学聚会,老婆被起哄和初恋拥吻,我笑着鼓掌:你脏了,我不要了

夜阑故事集
2026-01-25 13:10:03
飞天茅台单瓶破1800元

飞天茅台单瓶破1800元

第一财经资讯
2026-01-30 22:27:19
2026-01-31 09:19:00
InfoQ incentive-icons
InfoQ
有内容的技术社区媒体
12005文章数 51727关注度
往期回顾 全部

科技要闻

意念控制机器人不是科幻 1-2年就落地

头条要闻

特朗普听到"中英破冰"秒垮脸 失心疯的全过程被拍下

头条要闻

特朗普听到"中英破冰"秒垮脸 失心疯的全过程被拍下

体育要闻

“假赌黑”的子弹,还要再飞一会儿吗?

娱乐要闻

警方通报金晨交通事故,否认网传骗保

财经要闻

白银,暴跌!黄金,40年最大跌幅!

汽车要闻

合资品牌首搭800V/5C快充 东风日产NX8将于3、4月上市

态度原创

游戏
数码
手机
旅游
本地

魔兽在搞什么邪门CP?高冷银月城法爷,爱上虚空小狼狗

数码要闻

美国洛杉矶拟禁止一次性打印机墨盒,厂商商业模式或受冲击

手机要闻

三星Galaxy S26/S26+手机配置偷跑,这就帮你划重点

旅游要闻

未开发山域不是免费景区,别让探险变遇险!

本地新闻

云游中国|拨开云雾,巫山每帧都是航拍大片

无障碍浏览 进入关怀版