作為 Java 領域的資深從業人員,對 Java 在 AI 領域的一些進度一直是有一些關注的。但是基於一些語言本身的限制,Java 在 AI 方面幾乎沒有希望成為主流語言。
但是這不是說 Java 就不能介入這個領域了,作為主要的服務端語言,為 B/C 端提供 AI 的轉發是其比較主要的使用場景之一。
而這一期關注的 SpringAI,就是其主要發展對象。該框架在其剛發布的時候就有所關注,但是整體效果並不好,不適合生產能力。
隨著這2年的發展,整體上還是有了很大的發展,是否值得我們開始輸入學習了呢?
版本 | 發佈時間 | 核心變更 |
---|---|---|
0.8.1 | 2024年3月 | 首個公開版本,基礎AI模型集成 |
1.0.0-M1 | 2024年5月 | ChatClient API、結構化輸出、對話記憶 |
1.0.0-M2 | 2024年8月 | 擴展提供商支持、工具調用 |
1.0.0-M6 | 2025年2月 | @Tool註解、MCP協議集成 |
1.0.0-M7 | 2025年4月 | 獨立RAG模組、模組化架構 |
1.0.0-RC1 | 2025年5月13日 | API鎖定、產品準備 |
1.0.0 GA | 2025年5月20日 | 首個生產版本 |
1.0.3 | 2025年10月 | GraalVM原生鏡像支持 |
1.1.0-M3 | 2025年10月15日 | MCP SDK升級、多文檔支持 |
整體來說,SpringAI 是在不斷發展的,其本身定位我認為也很準確,不介入AI邏輯運算,只是一個外層的服務層。
通過 Java 在服務端強大的能力,來提供一個 AI 服務端應用,為其他的微服務提供 AI 能力。
┌─────────────────────────────────────────────────────────┐
│ 應用層 (Application) │
│ ChatClient API | Prompt Templates | Structured Output │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 集成層 (Integration) │
│ Spring Boot 自動配置 | 依賴注入 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 核心層 (Core) │
│ 模型抽象 | 嵌入 | 向量存儲 | 記憶 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 擴展層 (Extension) │
│ RAG | Agent | MCP | 工具調用 | 可觀察性 │
└─────────────────────────────────────────────────────────┘
API 接口是 SpringAI 生產化最核心的環節,其最終的效果是封裝 AI 調用細節,只需要簡單的操作就可以完成不同渠道的 AI 調用。(符合 Spring 一貫的定位
)。
如果對接過海外供應商的朋友,應該知道 Claude / Google Gemini / OpenAI
3者的接口規範是不同的。還包括BigModel(智譜)等也會在 OpenAI 的規範上有一些變化。
這也就意味著多種規範和寫法。 Spring AI 的統一 ChatClient、EmbeddingClient 等接口,屏蔽底層差異,通過配置切換模型,無需修改業務代碼。
現階段已經支持了 OpenAI、Anthropic、Google Gemini、AWS Bedrock、阿里通義千問、DeepSeek、智譜 AI、Ollama 等 20+ 模型提供商。
常規代碼寫法:
return chatClient.prompt() .system("你是一個專業的文本摘要助手,能夠提取關鍵信息並生成簡潔的摘要。") .user("請為以下文本生成摘要:\n" + text) .options(OpenAiChatOptions.builder() .withTemperature(0.3) .withMaxTokens(300) .build()) .call() .content();
基於簡單的幾句話,就可以完成一個供應商的調用,而不用關注具體的細節。
提出問題:
統一的 API 雖然好,但是其實不同的供應商細節挺多的,最常見的就是上下文的量和 Max Token 等都不一樣,效果也不一樣。
所以想一鍵切換模型/供應商,那就得明白如何對配置進行微調,保證最佳得輸出效果。
相關高級功能:
- Prompt 工程與模板化 : 可以為 System/User/Assistant/Tool 多角色定義不同得提示詞,可以規範化提示詞,通過模板變數渲染
SystemPromptTemplate sysTpl = new SystemPromptTemplate("以{role}風格回答"); Message sysMsg = sysTpl.createMessage(Map.of("role", "技術專家")); UserMessage userMsg = new UserMessage("解釋Spring Boot自動裝配"); Prompt prompt = new Prompt(List.of(sysMsg, userMsg)); String result = chatClient.prompt(prompt).call().content();
- 流式響應與異步處理 : 基於 Reactor 響應式編程,支持長文本溝通,支持同步、流式(SSE/Flux)、異步三種調用模式
- 這裡說白了就是
Reactor
的相關功能,比如代碼也是像下面這樣- 好處就是 Spring AI 的流式處理會很簡單,
除了通過註解使用到的高級功能,其他的基本上不用配置
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<ChatResponse> stream(@RequestParam String msg) { return chatClient.prompt().user(msg).stream().chatResponse(); }
這裡主要說的就是向量化及向量庫了,SpringAI 支持內建向量存儲抽象,支持 PGVector、Milvus、Pinecone、Redis、Chroma 等 20+ 向量資料庫。還支持 SpringData 模組對向量進行持久化的處理。
這也就一般我們說的知識庫,也是我看來非常重要,在各大應用裡面都能看到的核心組件。
在這個環節裡,又涉及到: 向量存儲 / 向量化 / 相似度檢索 / 提示詞工程 等很多小部分。
Spring 就是簡化了這個環節,通過極少的代碼(VectorStore),就能實現相關的功能:
@Service
public class RagService {
@Autowired
private VectorStore vectorStore;
@Autowired
private ChatClient chatClient;
public String query(String question) {
List<Document> docs = vectorStore.similaritySearch(question);
String context = docs.stream().map(Document::getContent).collect(Collectors.joining("\n"));
return chatClient.prompt().user("基於以下內容回答:\n" + context + "\n問題:" + question).call().content();
}
}
相比自己通過 API 進行調用的時候,自己去維護上下文和記憶。或者通過一個Token將記憶托管的 AI 服務商。
Spring AI 支持通過內建 ChatMemory 接口,從而支持多輪對話歷史存儲,還支持資料庫級別的存儲,各種策略的處理等。
對話記憶是一個服務的基礎,業務活動一旦產生,肯定不是一個回合就結束了。
@Autowired
private ChatMemory chatMemory;
@Autowired
private ChatClient chatClient;
public String chat(String sessionId, String msg) {
List<Message> history = chatMemory.get(sessionId);
history.add(new UserMessage(msg));
String reply = chatClient.prompt(new Prompt(history)).call().content();
chatMemory.add(sessionId, new AssistantMessage(reply));
return reply;
}
public class InMemoryChatMemory implements ChatMemory {
Map<String, List<Message>> conversationHistory = new ConcurrentHashMap<>();
}
支持文本、圖像、音頻等多種輸入輸出。重要性不言而喻吧。只支持圖片的對話,業務面要小得多。
連 GPT 等主流梯隊都早早的支持了多模態,沒這個環節可太慘了。
UserMessage msg = new UserMessage("描述這張圖片",
new Media(MimeTypeUtils.IMAGE_PNG, new ClassPathResource("photo.png")));
String description = chatClient.prompt(new Prompt(msg)).call().content();
工作流屬於去年年底,今年年初就爆火的功能,通過多個角色,讓一個任務的複雜度和準確性都大大提高。
至於好不好用還待評測,但是功能上其實已經很容易上手了。
// Agent A: 能調用天氣 + 資料庫兩個工具
@Bean(name = "opsAgent")
public Agent opsAgent(ChatClient.Builder builder, WeatherTool weatherTool, DatabaseTool databaseTool) {
ChatClient client = builder
.defaultSystem("你是智能助手,可調用工具完成任務")
.build();
return Agent.builder()
.chatClient(client)
.tools(List.of(weatherTool, databaseTool))
.systemPrompt("你是智能助手,可調用工具完成任務")
.build();
}
// Agent B: 只讀天氣查詢,不做資料庫保存
@Bean(name = "readonlyWeatherAgent")
public Agent readonlyWeatherAgent(ChatClient.Builder builder, WeatherTool weatherTool) {
ChatClient client = builder
.defaultSystem("你是天氣顧問,只提供天氣信息,不做任何持久化")
.build();
return Agent.builder()
.chatClient(client)
.tools(List.of(weatherTool))
.systemPrompt("你是天氣顧問,只提供天氣信息,不做任何持久化")
.build();
}
函數調用和工具集成
去年 MCP 就出來了,出來的時候那是非常火熱的,後面 Spring AI 的 MCP 能力我也嘗試過,初衷是通過 Spring AI 搭建一個 MCP 項目,跟一下去年那股 MCP 風。
但是效果其實中規中矩,最後也沒什麼好用的場景做出來(主要是 Python 寫一個太簡單了,真不想上 Spring)
更多:
- 結構化輸出映射 : 將 LLM 輸出直接映射為 Java 對象(POJO、枚舉、List 等
chatClient.prompt().user("我的世界").call().entity(MovieReview.class);
- 註解式開發與 AOP 集成 : 通過 @AiPrompt 等註解聲明式調用 AI
家裡事有點多,時間有限暫時啟動還有一些問題,這裡就不放了,可以先關注哦
總的來說,投入生產沒有太大的問題了,肯定無法通過它來部署模型什麼的,但是用來作為對外的第一層接口還是沒有什麼問題了。
一般業務場景裡面的東西該有就都有了。
如果沒太多的定制功能,用 SpringAI 來完成項目效率應該會很高,配合 AI 寫代碼,簡直不要太簡單。