Spring AI 1.0.0 M6 釋出

釋出 | Mark Pollack | 2025 年 2 月 14 日 | ...

我們很高興宣佈釋出 Spring AI 1.0.0 里程碑 6。為了慶祝此釋出,我們建立了一個特別的AI 生成音樂播放列表,以增強您的部落格閱讀和編碼體驗!

與往常一樣,此版本包含多項新功能和錯誤修復。我們繼續從設計的角度審閱了程式碼庫。雖然我們試圖透過在一個釋出週期內棄用方法和類來使過渡順利,但我們知道存在一些破壞性變更,也可能存在一些我們不知道的變更,所以請大家諒解。有關詳細資訊,請參閱本文底部的破壞性變更部分。

新功能

🎵 工具時間到!

函式呼叫的整體設計和功能集有了顯著改進,現在採用了更普遍的術語“工具呼叫”。非常感謝 Thomas Vitale 推動了這些改進。

現在有幾種定義工具的方式

  • 使用 @Tool@ToolParam 註解的宣告式方法工具
  • 使用 MethodToolCallback 的程式設計式方法工具
  • 使用 FunctionToolCallback 的基於函式的工具
  • 從 Spring beans 動態解析工具

以下是使用 @Tool 註解建立獲取當前日期和時間的工具的示例。

import java.time.LocalDateTime;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.context.i18n.LocaleContextHolder;

class DateTimeTools {

    @Tool(description = "Get the current date and time in the user's timezone")
    String getCurrentDateTime() {
        return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();
    }
}

// Using the tool with ChatClient
String response = ChatClient.create(chatModel)
        .prompt("What day is tomorrow?")
        .tools(new DateTimeTools())
        .call()
        .content();

當模型需要知道當前日期和時間時,它會自動請求呼叫該工具。ChatClient 在內部處理工具執行並將結果返回給模型,然後模型使用此資訊生成最終響應。JSON Schema 是使用類和工具註解自動生成的。

關於棄用,org.springframework.ai.model.function 包中的所有內容都已被棄用,新的介面和類可在 org.springframework.ai.tool 包中找到。

相關 API 已更新

  • FunctionCallingOptions 更名為 ToolCallingChatOptions
  • ChatClient.builder().defaultFunctions() 更名為 ChatClient.builder().defaultTools()
  • ChatClient.functions() 更名為 ChatClient.tools()

請參閱工具遷移指南瞭解更多資訊。

工具呼叫功能還有其他多項改進,請查閱工具參考文件瞭解更多資訊。

🎵 MCP,就這麼簡單 (1, 2, 3)

與其說是“十月驚喜”,不如說是去年的“十一月驚喜”:Model Context Protocol 釋出了,並受到了 AI 社群的廣泛好評。

簡而言之,Model Context Protocol (MCP) 提供了一種統一的方式,將 AI 模型連線到不同的資料來源和工具,使整合變得無縫且一致。它幫助您在大語言模型 (LLMs) 的基礎上構建代理和複雜的工作流。由於 LLMs 經常需要與資料和工具整合,MCP 提供了

  • 不斷增長的預構建整合列表,您的 LLM 可以直接接入
  • 在不同 LLM 提供商和供應商之間切換的靈活性
  • 工具發現和執行的標準化介面

spring-ai-mcp 實驗專案於去年 11 月啟動,並一直在發展。Spring AI 團隊已與 David Soria Parra 以及 Anthropic 的其他成員合作,將該實驗專案納入官方的 MCP Java SDK。MCP Java SDK 具有以下核心功能

  • 同步和非同步 MCP 客戶端/伺服器實現
  • 協議版本相容性協商
  • 帶有變更通知的工具發現和執行
  • 使用 URI 模板進行資源管理
  • 根列表管理和通知
  • Prompt 處理和管理
  • AI 模型互動的取樣支援

還有多種傳輸選項

  • 基於 Stdio 的傳輸用於基於程序的通訊
  • 基於 Java HttpClient 的 SSE 客戶端傳輸
  • 基於 Servlet 的 SSE 伺服器傳輸
  • Spring 特定的傳輸,用於響應式 HTTP 流的 WebFlux SSE 傳輸和用於基於 Servlet 的 HTTP 流的 WebMVC SSE 傳輸

請查閱 MCP Java SDK 文件,瞭解有關 SDK 入門的更多資訊,並訪問 MCP Java SDK GitHub 倉庫以提交問題並參與討論。

核心元件已移至 Anthropic Java SDK,與 Spring AI 的整合為開發人員提供了更輕鬆的體驗,可以利用 Spring Boot 自動配置建立客戶端和伺服器實現。

這裡有一個小的客戶端示例,展示瞭如何在簡單的聊天機器人應用程式中使用 Brave Search API

@SpringBootApplication
public class Application {
    @Bean
    public CommandLineRunner predefinedQuestions(
            ChatClient.Builder chatClientBuilder, 
            ToolCallbackProvider tools,
            ConfigurableApplicationContext context) {
        return args -> {
            var chatClient = chatClientBuilder
                    .defaultTools(tools)
                    .build();

            String question = "Does Spring AI support the Model Context Protocol?";
            System.out.println("ASSISTANT: " + 
                chatClient.prompt(question).call().content());
        };
    }
}

配置很簡單

spring.ai.mcp.client.stdio.enabled=true
spring.ai.mcp.client.stdio.servers-configuration=classpath:/mcp-servers-config.json

伺服器配置是

{
  "mcpServers": {
    "brave-search": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-brave-search"
      ],
      "env": {
      }
    }
  }
}

在您的依賴配置中,匯入 Spring AI Bom 並新增 Spring Boot 客戶端啟動器,此處顯示的是 Maven 配置。

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
</dependency>

MCP 是一個很大的主題。參考文件包含更多資訊,並且有多個示例

向量儲存增強

VectorStore API 已得到改進,儘管伴隨了一些破壞性變更。
VectorStore 介面的 delete 方法已簡化為 void 操作,移除了之前的 Optional返回型別。開發者現在應該使用異常處理來管理刪除失敗,而不是檢查返回值。請參閱參考文件瞭解更多資訊。

基於過濾器的刪除

現在您可以根據元資料條件而不是僅僅根據文件 ID 刪除文件。

以下是一個示例

// Create and add documents to the store
Document bgDocument = new Document("content", 
    Map.of("country", "BG", "year", 2020));
Document nlDocument = new Document("content", 
    Map.of("country", "NL", "year", 2021));
vectorStore.add(List.of(bgDocument, nlDocument));

// Delete documents using string filter expression
vectorStore.delete("country == 'BG'");

// Or use the Expression-based API
Filter.Expression expr = // ... your filter expression
vectorStore.delete(expr);

此功能已在所有向量儲存提供商中實現,包括 Chroma、Elasticsearch、PostgreSQL、Weaviate、Redis、Milvus 等。

原生客戶端訪問

新的 getNativeClient() API 允許開發人員在需要時訪問底層的原生客戶端實現

WeaviateVectorStore vectorStore = // get vector store
Optional<WeaviateClient> nativeClient = vectorStore.getNativeClient();
if (nativeClient.isPresent()) {
    WeaviateClient client = nativeClient.get();
    // Use native client capabilities
}

簡單向量儲存改進

SimpleVectorStore 實現現在支援使用 Spring Expression Language (SpEL) 進行元資料過濾

Postgres 向量儲存改進

PostgreSQL 向量儲存實現已得到改進,可以更靈活地處理不同的 ID 列型別。它現在支援以下型別,而不是強制 UUID 作為唯一的 Primary Key 型別:

  • UUID
  • TEXT
  • INTEGER
  • SERIAL
  • BIGSERIAL

這使得與現有資料庫 schema 和不同的 ID 管理策略的整合更加容易。

已移除已棄用的 Amazon Bedrock Chat 模型

這些模型現已替換為 Amazon Bedrock Converse API,後者更靈活,並支援使用相同的 API 呼叫不同的模型。

🎵 一切都關於這些代理...

每個人都在談論代理。我們近期不會構建代理框架,因為 Anthropic 的部落格文章 “構建高效代理” 引起了團隊的強烈共鳴。

摘自部落格文章

在過去的一年裡,我們與數十個在各行業構建大語言模型 (LLM) 代理的團隊合作。最成功的實現並非使用了複雜的框架或專用庫。相反,它們是使用簡單、可組合的模式構建的。

代理系統的兩個主要類別是工作流和代理

  • 工作流:透過預定義的程式碼路徑協調 LLMs 和工具的系統
  • 代理:LLMs 動態指導其自身流程和工具使用,並保持對其如何完成任務的控制的系統

Spring AI 已經提供了“構建塊:增強型 LLM”——這是一個透過檢索、工具和記憶體等增強功能得到加強的 LLM。利用這個構建塊,部落格文章描述了幾種構建高效代理的工作流

  1. 鏈式工作流 – 將任務分解為順序步驟,其中每個 LLM 呼叫處理上一步的輸出,確保結構化的進展。
  2. 評估器-最佳化器 – 使用評估器 LLM 評估另一個 LLM 的輸出,透過提供反饋和最佳化響應來提高質量。
  3. 編排器-工作者 – 一箇中央編排器 LLM 將任務委託給專門的工作者 LLMs,從而實現模組化和可擴充套件的任務執行。
  4. 並行化工作流 – 將任務分解為可以並行執行的獨立子任務,提高效率並聚合多個視角。
  5. 路由工作流 – 對輸入進行分類,並將其定向到合適的 LLM 模型或處理路徑,以最佳化準確性和效率。

有關這些模式的詳細實現,請參閱 Spring AI 的 使用 Spring AI 構建高效代理(第一部分) 和配套的示例

以下是第一個模式的示例

Spring AI 中的鏈式工作流

在本示例中,我們將建立一個鏈式工作流,透過以下步驟處理商業報告:

  1. 提取數值指標
  2. 標準化其格式
  3. 對其進行排序
  4. 以整潔的表格格式呈現它們

以下是使用 Spring AI 實現此模式的方法

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    // Sample business report with various metrics in natural language
    String report = """
            Q3 Performance Summary:
            Our customer satisfaction score rose to 92 points this quarter.
            Revenue grew by 45% compared to last year.
            Market share is now at 23% in our primary market.
            Customer churn decreased to 5% from 8%.
            New user acquisition cost is $43 per user.
            Product adoption rate increased to 78%.
            Employee satisfaction is at 87 points.
            Operating margin improved to 34%.
            """;

    @Bean
    public CommandLineRunner commandLineRunner(ChatClient.Builder chatClientBuilder) {
        return args -> {
            new ChainWorkflow(chatClientBuilder.build()).chain(report);
        };
    }
}

/**
 * Implements a prompt chaining workflow that breaks down complex tasks into a sequence
 * of simpler LLM calls, where each step's output feeds into the next step.
 */
public class ChainWorkflow {
    /**
     * System prompts that define each transformation step in the chain.
     * Each prompt acts as a gate that validates and transforms the output
     * before proceeding to the next step.
     */
    private static final String[] CHAIN_PROMPTS = {
        // Step 1: Extract numerical values
        """
        Extract only the numerical values and their associated metrics from the text.
        Format each as 'value: metric' on a new line.
        Example format:
        92: customer satisfaction
        45%: revenue growth""",
        
        // Step 2: Standardize to percentages
        """
        Convert all numerical values to percentages where possible.
        If not a percentage or points, convert to decimal (e.g., 92 points -> 92%).
        Keep one number per line.
        Example format:
        92%: customer satisfaction
        45%: revenue growth""",
        
        // Step 3: Sort in descending order
        """
        Sort all lines in descending order by numerical value.
        Keep the format 'value: metric' on each line.
        Example:
        92%: customer satisfaction
        87%: employee satisfaction""",
        
        // Step 4: Format as markdown
        """
        Format the sorted data as a markdown table with columns:
        | Metric | Value |
        |:--|--:|
        | Customer Satisfaction | 92% |"""
    };

    private final ChatClient chatClient;

    public ChainWorkflow(ChatClient chatClient) {
        this.chatClient = chatClient;
    }

    public String chain(String userInput) {
        String response = userInput;
        
        for (String prompt : CHAIN_PROMPTS) {
            response = chatClient.prompt(
                String.format("{%s}\n{%s}", prompt, response)
            ).call().content();
        }
        
        return response;
    }
}

關鍵的資料流是每一步的輸出都成為下一步的輸入。對於我們的示例報告,資料流如下:

  • 步驟 1 提取諸如“92:客戶滿意度”、“45%:收入增長”等指標
  • 步驟 2 標準化為百分比格式:“92%:客戶滿意度”
  • 步驟 3 按降序對值進行排序
  • 步驟 4 建立格式化的 Markdown 表格

完整的原始碼以及其他代理模式的實現可在 spring-ai-examples 倉庫和 使用 Spring AI 構建高效代理(第一部分) 中找到。

貢獻者

許多貢獻者進行了廣泛的重構、錯誤修復和文件增強。如果您的 PR 尚未被處理,請耐心等待,我們會盡快處理。感謝以下貢獻者:

破壞性變更

本次釋出包含幾項破壞性變更,這是我們持續改進 API 設計的結果。主要變更包括

  • 將函式相關的包和類重新命名為工具相關的對應項(例如,org.springframework.ai.model.function 更改為 org.springframework.ai.tool
  • VectorStore API 的更新
  • 模型客戶端配置屬性的變更

有關破壞性變更的完整列表和詳細的升級說明,請參閱參考文件中的升級說明

獲取 Spring 資訊

訂閱 Spring 資訊,保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助力您加速進步。

瞭解更多

獲取支援

Tanzu Spring 在一個簡單的訂閱中提供對 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視全部