Spring AI 1.0 提供簡單的 AI 系統和服務

作者 | 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中添加以下依賴項:

你使用 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 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 翻譯,未經許可禁止轉載。