1.什么是spring AI
Spring AI?是 Spring 官方推出的一個基于 Spring 生態的?AI 應用開發框架,旨在簡化將人工智能(如大語言模型、生成式 AI)集成到 Java 應用中的過程。它提供了統一的 API 和工具,讓開發者能更輕松地調用 AI 模型
2.項目集成Spring ai
本篇文章需使用JDK17 以上的版本 ,spring boot 版本為3.2.5 ,且在通義百煉申請了大模型的api-key請大家務必與我的版本一致
引入spring AI Alibaba的maven坐標
<!--Spring Ai alibaba--> <dependency><groupId>com.alibaba.cloud.ai</groupId><artifactId>spring-ai-alibaba-starter</artifactId><version>1.0.0-M6.1</version> </dependency>
application.yml
api-key需要使用自己的我這里是錯誤的api-key演示
spring:ai:dashscope:api-key: "sk-5sadd21dsanbd1321ndsakda"chat:options:model: qwen-plus
3.項目測試
編寫一個類,當spring boot項目啟動時自動會執行一次run方法
package com.example.demo.demos;import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;import jakarta.annotation.Resource;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;/*** 使用springAi框架調用ai*//*** 實現 CommandLineRunner接口的話在,每次項目啟動時就會執行一次他的run方法*/@Component
public class SpringAiInvoke implements CommandLineRunner {@Resourceprivate ChatModel dashscopeChatModel;@Overridepublic void run(String... args) throws Exception {// 調用模型 Prompt是模型輸入AssistantMessage message = dashscopeChatModel.call(new Prompt("你是誰")).getResult().getOutput();System.out.println(message.getText()); // 輸出結果 文本響應}
}
4.構建初始化大模型類
初始化大模型,主要是初始化ChatClient 接口的實現類,給ChatClient 配置一些默認的配置
例如提示詞,對話記憶,及Advisor(顧問,類似于AOP)
為什么有了chatModel還需要chatClient?
CatModel 相較于 ChatClient 更為底層,Catmodel所使用的Api是直接對大模型進行調用,
例如:
處理模型本身的參數(如溫度值?
temperature
、最大 token 數?maxTokens
)。返回原始響應數據(如?
ChatResponse
?包含消息、元數據)。
而ChatClien主要是與業務交互提供了更高級的抽象方法
例如:
提供更高層次的抽象,隱藏復雜性(如?
Prompt
?對象構建、響應解析)。集成 Spring 生態特性(如自動重試、監控)。
標準化輸入輸出(如直接返回?
String
?而非?ChatResponse
)
但是本質上ChatClient也是在調用CatModel,只不過提供了更多便捷的方法
總結:
ChatClient
?本質上是對?ChatModel
?的封裝,提供更高層次的便捷方法,而初始化?ChatClient
?時通常需要傳入?ChatModel
。這種設計看似冗余,但背后有明確的架構意圖和實際價值。
演示:
當前是初始化了大模型和配置
package com.example.demo.app;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.stereotype.Component;@Component
public class AiApp {ChatClient chatClient;// 構造函數 初始化大模型時會注入對象 (根據使用的名稱注入,例如阿里的就注入dashscopeChatClient)public AiApp(ChatModel dashscopeChatModel) {//創建一個基于內存的會話歷史記錄ChatMemory memory = new InMemoryChatMemory();chatClient= ChatClient.builder(dashscopeChatModel) //傳入大模型對象.defaultSystem("你當前的角色是i桂航小助手,解決學生在學校的各種疑問") //設置系統提示詞 例如當前aiapp是一個學校客服系統,角色是i桂航小助手.defaultAdvisors(new MessageChatMemoryAdvisor(memory)//設置一個advisor (顧問) 當前設置的是處理對話上下文的advisor//也設置多個advsior 和自定義的advisor).build();}}
5.ChatClien實現對話
給AiApp類中添加新的對話方法
//Chatclien對話public String dochat(String message,String sessionId){ChatResponse chatResponse = chatClient.prompt().user(message)//傳入用戶輸入信息.advisors(advisorSpec -> advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, sessionId)//對話的會話id 用于查看是否是當前上下文.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 3) //檢索上下文的長度 如果長度過長所消耗的Token數量會過大).call().chatResponse();log.info("chatResponse: {}", chatResponse.getResult().getOutput().getText());//輸出模型返回的結果return chatResponse.getResult().getOutput().getText();}
測試調用對話
@SpringBootTest
class DemoApplicationTests {@AutowiredAiApp app;@Testvoid contextLoads() {app.dochat("你好,請記住我的朋友叫Java", "1");app.dochat("你是誰? 回復不超過10個字","1");app.dochat("我的朋友叫什么?還有幫忙回憶一下回復不超過幾個字?","1");}}
輸出的結果為
說明實現了對話,且具有了對話記憶功能
6.結構化輸出(將大模型輸出轉為JAVA對象)
引入maven
<!--springAi結構化輸出--> <dependency><groupId>com.github.victools</groupId><artifactId>jsonschema-generator</artifactId><version>4.38.0</version> </dependency>
在AiApp類中編寫一個用于返回,一個Java對象的聊天 方法
其中創建了一個Tmplate類 與一個 聊天方法
//JDK14提供的語法 用于創建一個對象public record Template(String title, List<String> mesages){}public Template dochatTemplate(String message, String sessionId){Template template = chatClient.prompt("現在你需要根據用戶的需求給出建議標題為: 給{xxx}的建議,內容列出列表").user(message).advisors(advisorSpec -> advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, sessionId).param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 3)).call().entity(Template.class);//輸出成為一個Java對象log.info("結果:{}", template);return template;}
測試 :
@Testvoid dochatTemplate() {AiApp.Template template = app.dochatTemplate("你好,我叫小明,在學校我有些困惑,請給我3條建議", "1");}
輸出結果
大模型給出的返回值變成了Taplate對象 ,建議也變成了List集合