国产av一二三区|日本不卡动作网站|黄色天天久久影片|99草成人免费在线视频|AV三级片成人电影在线|成年人aV不卡免费播放|日韩无码成人一级片视频|人人看人人玩开心色AV|人妻系列在线观看|亚洲av无码一区二区三区在线播放

網(wǎng)易首頁(yè) > 網(wǎng)易號(hào) > 正文 申請(qǐng)入駐

炸裂!Spring AI 1.0 正式發(fā)布,讓 Java 再次偉大!

0
分享至

大家好,我是程序員魚(yú)皮。

炸裂,炸裂,炸裂!從第一次提交代碼到現(xiàn)在,經(jīng)過(guò) 2 年的沉淀,Spring AI 框架的第一個(gè)正式版本 1.0 終于發(fā)布了。

有了這玩意,開(kāi)發(fā) AI 應(yīng)用就是灑灑水的事,Java 開(kāi)發(fā)者們是不是又爽了,反正我是很興奮啊,讓 Java 再次偉大!

但可能很多同學(xué)還不知道 Spring AI 能干什么,憑什么這玩意就讓 Java 偉大了?

正好我最近剛帶編程導(dǎo)航的同學(xué)做完一套 AI 超級(jí)智能體實(shí)戰(zhàn)項(xiàng)目,毫不夸張地說(shuō),我已經(jīng)把 Spring AI 玩得 “手拿把掐” 了。

下面我來(lái)給大家快速分享一下 Spring AI 的核心能力和魔法。看完之后,我相信你會(huì)點(diǎn)贊收藏三連,并且說(shuō)一句:“偉的太大了”。

Spring AI 核心特性

1、大模型調(diào)用能力

大模型調(diào)用能力是 AI 應(yīng)用開(kāi)發(fā)的基礎(chǔ),允許應(yīng)用程序與各種 AI 大模型進(jìn)行交互,發(fā)送提示詞并獲取模型的響應(yīng)。Spring AI 提供了統(tǒng)一的接口來(lái)支持各種主流大模型,包括 OpenAI GPT 系列、Claude、通義千問(wèn)等。

Spring AI 通過(guò)配置 + 抽象接口簡(jiǎn)化了大模型的調(diào)用過(guò)程,我可以直接在配置中聲明多個(gè)大模型:

spring:
ai:
# 阿里大模型
dashscope:
chat:
options:
model:qwen-max
# 本地大模型
ollama:
base-url:http://localhost:11434
chat:
model:gemma3:1b
# 谷歌大模型
vertex:
ai:
gemini:
chat:
options:
model:gemini-1.5-pro-001

然后使用支持鏈?zhǔn)秸{(diào)用的 ChatClient 靈活地調(diào)用各種不同的大模型:

// 使用 Spring AI 調(diào)用大模型
@Bean
publicChatClientchatClient(ChatModel chatModel){
returnChatClient.builder(chatModel).build();
}
publicStringdoChat(String message){
ChatResponse response = chatClient
.prompt(message)
.call()
.chatResponse();
returnresponse.getResult().getOutput().getText();
}

只用一行代碼,就能支持 Stream 流式響應(yīng),實(shí)現(xiàn)打字機(jī)效果:

chatClient
.prompt(message)
.stream()

如果不使用 Spring AI,則需要為每個(gè)模型分別實(shí)現(xiàn) API 調(diào)用,要自己編寫(xiě)請(qǐng)求、解析響應(yīng),很麻煩!

// 不使用 Spring AI 調(diào)用大模型
publicStringchatWithOpenAI(String message){
// 配置 OpenAI API
OkHttpClient client =newOkHttpClient();
MediaType JSON = MediaType.get("application/json; charset=utf-8");
// 構(gòu)建請(qǐng)求體
JSONObject requestBody =newJSONObject();
requestBody.put("model","gpt-3.5-turbo");
JSONArray messages =newJSONArray();
JSONObject userMessage =newJSONObject();
userMessage.put("role","user");
userMessage.put("content", message);
messages.put(userMessage);
requestBody.put("messages", messages);
// 發(fā)送請(qǐng)求
RequestBody body = RequestBody.create(requestBody.toString(), JSON);
Request request =newRequest.Builder()
.url("https://api.openai.com/v1/chat/completions")
.header("Authorization","Bearer "+ OPENAI_API_KEY)
.post(body)
.build();
try(Response response = client.newCall(request).execute()) {
String responseBody = response.body().string();
JSONObject jsonResponse =newJSONObject(responseBody);
returnjsonResponse.getJSONArray("choices")
.getJSONObject(0)
.getJSONObject("message")
.getString("content");
}catch(Exception e) {
return"Error: "+ e.getMessage();
}
}

Spring AI 不僅提供了統(tǒng)一接口支持多種大模型,讓我們可以輕松切換模型而無(wú)需修改業(yè)務(wù)代碼。它還支持多模態(tài)大模型調(diào)用,使 AI 能夠同時(shí)處理文本、圖像、音頻等多種輸入類型。

我們只需要將圖片等資源添加到消息對(duì)象中,一起發(fā)送給 AI 就可以了,使用 Spring AI 幾行代碼就能實(shí)現(xiàn):

// 調(diào)用多模態(tài)模型
String response = ChatClient.create(chatModel).prompt()
.user(u -> u.text("描述這張圖片中的內(nèi)容")
.media(MimeTypeUtils.IMAGE_PNG,newClassPathResource("/yupi.png")))
.call()
.content();

如果不使用 Spring AI,多模態(tài)處理將變得復(fù)雜得多:

// 不使用 Spring AI 的多模態(tài)實(shí)現(xiàn)
publicStringanalyzeImage(String textPrompt, File imageFile){
// 讀取圖像文件并編碼為 Base64
String base64Image ="";
try{
byte[] fileContent = Files.readAllBytes(imageFile.toPath());
base64Image = Base64.getEncoder().encodeToString(fileContent);
}catch(IOException e) {
return"Error reading image file: "+ e.getMessage();
}
// 構(gòu)建請(qǐng)求體,不同模型的格式差異很大
JSONObject requestBody =newJSONObject();
requestBody.put("model","gpt-4-vision-preview");
JSONArray messages =newJSONArray();
JSONObject userMessage =newJSONObject();
userMessage.put("role","user");
// 構(gòu)建復(fù)雜的內(nèi)容數(shù)組
JSONArray contentArray =newJSONArray();
// 添加文本部分
JSONObject textContent =newJSONObject();
textContent.put("type","text");
textContent.put("text", textPrompt);
contentArray.put(textContent);
// 添加圖像部分
JSONObject imageContent =newJSONObject();
imageContent.put("type","image_url");
JSONObject imageUrl =newJSONObject();
imageUrl.put("url","data:image/png;base64,"+ base64Image);
imageContent.put("image_url", imageUrl);
contentArray.put(imageContent);
userMessage.put("content", contentArray);
messages.put(userMessage);
requestBody.put("messages", messages);
// 發(fā)送請(qǐng)求并解析響應(yīng)...
// 代碼略
}

此外,Spring AI 提供了強(qiáng)大的 Advisors 機(jī)制,有點(diǎn)類似面向切面編程,可以在模型調(diào)用前后添加額外的邏輯,增強(qiáng) AI 的能力。

舉個(gè)例子,使用 Spring AI 內(nèi)置的日志 Advisor,一行代碼就能在調(diào)用 AI 前后記錄日志:

// 使用 Advisors 增強(qiáng) ChatClient
publicStringdoChatWithAdvisors(String message, String chatId){
ChatResponse response = chatClient
.prompt()
.user(message)
// 添加日志 Advisor
.advisors(newLoggingAdvisor())
.call()
.chatResponse();
returnresponse.getResult().getOutput().getText();
}

Advisor 的應(yīng)用場(chǎng)景還有很多,比如調(diào)用 AI 前檢查提示詞是否安全、得到 AI 響應(yīng)后保存到數(shù)據(jù)庫(kù)中等等。

2、提示工程

提示工程(Prompt Engineering)是一門(mén)復(fù)雜的學(xué)問(wèn),指通過(guò)精心設(shè)計(jì)提示詞,讓 AI 更準(zhǔn)確地理解用戶意圖,生成更符合預(yù)期的回答,減少幻覺(jué)(生成虛假信息)的概率,同時(shí)優(yōu)化 AI 模型的性能表現(xiàn)并節(jié)省成本。

Spring AI 通過(guò) Prompt 和 PromptTemplate 類實(shí)現(xiàn)提示工程。

Prompt 類可以統(tǒng)一封裝多種不同類型的提示詞,便于發(fā)送給大模型:

// 用戶提示詞
Message userMessage =newUserMessage(userText);
// 系統(tǒng)提示詞
Message systemMessage =newSystemMessage(systemText);
Prompt prompt =newPrompt(List.of(userMessage, systemMessage));

利用 PromptTemplate 可以創(chuàng)建支持替換變量的提示詞模板,便于提示詞的維護(hù)和復(fù)用:

// 使用 Spring AI 的提示模板
PromptTemplate promptTemplate =newPromptTemplate("你好,我是{name},我擅長(zhǎng){skill}");
Prompt prompt = promptTemplate.create(Map.of(
"name","魚(yú)皮",
"skill","編程"
));
ChatResponse response = chatClient.call(prompt);

如果不使用 Spring AI,你就需要手動(dòng) / 或者利用工具類來(lái)拼接提示詞字符串,會(huì)更麻煩:

// 不使用 Spring AI 需要手動(dòng)字符串拼接
String name ="AI 戀愛(ài)顧問(wèn)";
String skill ="解決戀愛(ài)問(wèn)題";
String promptText ="你好,我是"+ name +",我擅長(zhǎng)"+ skill;
// 還需自行實(shí)現(xiàn)條件邏輯、變量轉(zhuǎn)義等
if(hasCondition) {
promptText +=",我注意到你可能遇到了"+ conditionType +"問(wèn)題";
}
// 調(diào)用 API 需自行封裝請(qǐng)求
Response response = apiClient.sendPrompt(promptText);

3、會(huì)話記憶

會(huì)話記憶(Chat Memory)使 AI 能夠保存多輪對(duì)話歷史,理解上下文,實(shí)現(xiàn)連貫對(duì)話體驗(yàn),防止 AI 斷片兒。

利用 Spring AI 的 Advisor 機(jī)制,一行代碼就能輕松開(kāi)啟對(duì)話記憶:

// 使用 Spring AI 的會(huì)話記憶
publicStringdoChatWithMemory(String message, String chatId){
ChatResponse response = chatClient
.prompt()
.user(message)
.advisors(
// 將對(duì)話記憶保存到內(nèi)存中
newMessageChatMemoryAdvisor(newInMemoryChatMemory())
)
.call()
.chatResponse();
returnresponse.getResult().getOutput().getText();
}

還可以設(shè)置會(huì)話 id 實(shí)現(xiàn)隔離、設(shè)置上下文大小限制等參數(shù):

// 使用 Spring AI 的會(huì)話記憶
publicStringdoChatWithMemory(String message, String chatId){
ChatResponse response = chatClient
.prompt()
.user(message)
.advisors(
// 將對(duì)話記憶保存到內(nèi)存中
newMessageChatMemoryAdvisor(newInMemoryChatMemory())
)
.advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY,10))
.call()
.chatResponse();
returnresponse.getResult().getOutput().getText();
}

Spring AI 會(huì)自動(dòng)處理上下文窗口大小限制,避免超出模型最大 token 限制。

如果不使用 Spring AI,需要手動(dòng)管理對(duì)話歷史,代碼量一下子就上來(lái)了:

// 不使用 Spring AI 的會(huì)話記憶實(shí)現(xiàn)
MapnewHashMap<>();
publicStringchat(String message, String userId){
// 獲取用戶歷史記錄
ListnewArrayList<>());
// 添加用戶新消息
Message userMessage =newMessage("user", message);
history.add(userMessage);
// 構(gòu)建完整歷史上下文
StringBuilder contextBuilder =newStringBuilder();
for(Message msg : history) {
contextBuilder.append(msg.getRole()).append(": ").append(msg.getContent()).append("\n");
}
// 調(diào)用 AI API
String response = callAiApi(contextBuilder.toString());
// 保存 AI 回復(fù)到歷史
Message aiMessage =newMessage("assistant", response);
history.add(aiMessage);
conversationHistory.put(userId, history);
returnresponse;
}

> conversationHistory =

history = conversationHistory.getOrDefault(userId,

Spring AI 的實(shí)現(xiàn)非常優(yōu)秀,將會(huì)話存儲(chǔ)和保存機(jī)制分離,我們可以自己定義 ChatMemory,將對(duì)話歷史保存到數(shù)據(jù)庫(kù)等持久存儲(chǔ)中。

4、RAG 檢索增強(qiáng)生成

RAG(Retrieval-Augmented Generation)是指利用外部知識(shí)來(lái)增強(qiáng) AI 生成結(jié)果的技術(shù)。通過(guò)從知識(shí)庫(kù)檢索相關(guān)信息并注入到提示詞中,讓 AI 能夠利用這些信息生成更準(zhǔn)確的回答。

比如我?guī)Т蠹易隽艘粋€(gè) AI 戀愛(ài)大師應(yīng)用,給 AI 準(zhǔn)備了一套專注于戀愛(ài)問(wèn)答的知識(shí)庫(kù)文檔:

利用 RAG 技術(shù),AI 就能從我自己定義的知識(shí)庫(kù)中獲取到特定領(lǐng)域的、最新的信息,不僅能減少大模型的幻覺(jué)(防止瞎編內(nèi)容),還能趁機(jī)推薦一波自己的課程,豈不美哉?

所以 AI 的回復(fù)也不能完全相信哦~

RAG 的完整工作流程包括文檔收集和切割、向量轉(zhuǎn)換和存儲(chǔ)、文檔過(guò)濾和檢索、查詢?cè)鰪?qiáng)和關(guān)聯(lián) 4 大步驟。

Spring AI 給 RAG 全流程的實(shí)現(xiàn)都提供了支持:

1)文檔讀取。直接利用 Spring AI 提供的文檔加載器,各種類型的文檔都能輕松讀?。?/p>

publicListloadDocuments(){
ListnewArrayList<>();
// 加載 Markdown 文檔
Resource resource = resourceLoader.getResource("classpath:documents/knowledge.md");
MarkdownDocumentReaderConfig config = MarkdownDocumentReaderConfig.builder()
.withHorizontalRuleCreateDocument(true)
.withIncludeCodeBlock(true)
.withAdditionalMetadata("source","knowledge-base")
.build();
MarkdownDocumentReader reader =newMarkdownDocumentReader(resource, config);
documents.addAll(reader.get());
returndocuments;
}

documents =

2)向量存儲(chǔ)。利用 Spring AI 提供的 VectorStore 輕松將文檔轉(zhuǎn)換為向量并保存到向量數(shù)據(jù)庫(kù)中:

// 創(chuàng)建簡(jiǎn)單向量存儲(chǔ)
SimpleVectorStore vectorStore = SimpleVectorStore.builder(embeddingModel)
.build();
// 加載文檔并存儲(chǔ)
List
vectorStore.add(documents);

documents = documentLoader.loadDocuments();

3)文檔過(guò)濾檢索 + 查詢?cè)鰪?qiáng)關(guān)聯(lián)。直接使用 QuestionAnswerAdvisor,一行代碼就可以讓 Spring AI 自動(dòng)從知識(shí)庫(kù)中檢索文檔,并將檢索到的文檔提供給 AI 來(lái)增強(qiáng)輸出結(jié)果。

ChatResponse response = chatClient.prompt()
.user(question)
.advisors(newQuestionAnswerAdvisor(vectorStore))
.call()
.chatResponse();

如果不使用 Spring AI,上述過(guò)程的實(shí)現(xiàn)可就太復(fù)雜了,要自己檢索文檔、構(gòu)建提示詞等等:

// 不使用 Spring AI 的 RAG 實(shí)現(xiàn)
publicStringgenerateAnswerWithKnowledge(String query){
// 1. 將查詢轉(zhuǎn)換為向量
float[] queryVector = embeddingService.embedText(query);
// 2. 在向量數(shù)據(jù)庫(kù)中搜索相似內(nèi)容
ListnewArrayList<>();
for(Document doc : vectorDatabase.getAllDocuments()) {
floatsimilarity = calculateCosineSimilarity(queryVector, doc.getVector());
if(similarity >0.5) {
relevantDocs.add(doc);
}
}
relevantDocs.sort((a, b) -> Float.compare(
calculateCosineSimilarity(queryVector, b.getVector()),
calculateCosineSimilarity(queryVector, a.getVector())
));
// 3. 截取前三個(gè)最相關(guān)文檔
relevantDocs = relevantDocs.subList(0, Math.min(3, relevantDocs.size()));
// 4. 構(gòu)建提示詞,包含檢索到的知識(shí)
StringBuilder prompt =newStringBuilder();
prompt.append("使用以下信息回答問(wèn)題:\n\n");
for(Document doc : relevantDocs) {
prompt.append("---\n").append(doc.getContent()).append("\n---\n\n");
}
prompt.append("問(wèn)題: ").append(query);
// 5. 調(diào)用 AI 生成回答
returnaiService.generateResponse(prompt.toString());
}

relevantDocs =

除了實(shí)現(xiàn)基礎(chǔ)的 RAG 能力外,Spring AI 還提供了更多高級(jí)能力來(lái)優(yōu)化 RAG 的效果。比如提供了完整的 ETL流程的支持,能夠快速抽取文檔、切分處理文檔、并加載到向量存儲(chǔ)中。

提供了多查詢擴(kuò)展器,可以為原始提示詞生成多個(gè)查詢變體,提高召回文檔的幾率:

MultiQueryExpander queryExpander = MultiQueryExpander.builder()
.chatClientBuilder(chatClientBuilder)
.numberOfQueries(3)
.build();
ListnewQuery("誰(shuí)是程序員魚(yú)皮?"));

queries = queryExpander.expand(

提供了查詢重寫(xiě)器,可以把原始提示詞變得更精確和專業(yè):

publicStringdoQueryRewrite(String prompt){
QueryTransformer queryTransformer = RewriteQueryTransformer.builder()
.chatClientBuilder(builder)
.build();
Query query =newQuery(prompt);
// 執(zhí)行查詢重寫(xiě)
Query transformedQuery = queryTransformer.transform(query);
// 輸出重寫(xiě)后的查詢
returntransformedQuery.text();
}

效果如圖:

還支持自定義文檔檢索器,能夠更靈活地定義查詢規(guī)則,比如按照文檔的元信息精確查詢、只查詢相似度最高的 N 條數(shù)據(jù)等:

DocumentRetriever retriever = VectorStoreDocumentRetriever.builder()
.vectorStore(vectorStore)
.similarityThreshold(0.73)
.topK(5)
.filterExpression(newFilterExpressionBuilder()
.eq("name","魚(yú)皮")
.build())
.build();

5、工具調(diào)用

工具調(diào)用(Tool Calling)允許 AI 借助外部工具完成自身無(wú)法直接完成的任務(wù),比如網(wǎng)絡(luò)搜索、文件操作、數(shù)據(jù)查詢等。它擴(kuò)展了 AI 的能力范圍,使 AI 能夠獲取實(shí)時(shí)信息、執(zhí)行實(shí)際操作。

工具調(diào)用實(shí)現(xiàn)的本質(zhì)是拼接提示詞,讓 AI 選擇要調(diào)用哪些工具,然后由程序調(diào)用工具并將返回結(jié)果交給 AI 進(jìn)行后續(xù)輸出。

利用 Spring AI,只需要通過(guò)注解就能快速定義工具:

// 使用 Spring AI 定義工具
publicclassWebSearchTool{
@Tool(description ="Search for information from Baidu Search Engine")
publicStringsearchWeb(
@ToolParam(description ="Search query keyword")String query){
// 網(wǎng)絡(luò)搜索實(shí)現(xiàn)
return"搜索結(jié)果: "+ query +" 的相關(guān)信息...";
}
}

然后一行代碼就能使用工具,Spring AI 會(huì)控制程序和大模型進(jìn)行交互并自動(dòng)調(diào)用工具,非常方便:

ChatResponse response = chatClient
.prompt()
.user(message)
.tools(newWebSearchTool())
.call()
.chatResponse();

如果不使用 Spring AI,可就太復(fù)雜了!

// 不使用 Spring AI 的工具調(diào)用實(shí)現(xiàn)
publicStringhandleUserRequest(String userMessage){
// 1. 構(gòu)建含工具定義的提示詞
String toolDefinition ="""
{
"tools": [
{
"name": "searchWeb",
"description": "Searchforinformation from Baidu Search Engine",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search query keyword"
}
},
"required": ["query"]
}
}
]
}
""";
// 2. 調(diào)用 AI 判斷是否需要工具
JsonObject aiResponse = callAiWithTools(userMessage, toolDefinition);
// 3. 解析 AI 響應(yīng)判斷是否需調(diào)用工具
if(aiResponse.has("tool_calls")) {
JsonArray toolCalls = aiResponse.getAsJsonArray("tool_calls");
// 4. 依次執(zhí)行每個(gè)工具
ListnewArrayList<>();
for(JsonElement toolCall : toolCalls) {
String toolName = toolCall.getAsJsonObject().get("name").getAsString();
JsonObject args = toolCall.getAsJsonObject().get("arguments").getAsJsonObject();
// 5. 根據(jù)工具名執(zhí)行對(duì)應(yīng)工具
if("searchWeb".equals(toolName)) {
String query = args.get("query").getAsString();
String result = searchWeb(query);// 實(shí)際執(zhí)行搜索
toolResults.add(result);
}
}
// 6. 將工具結(jié)果發(fā)回給 AI 生成最終回答
returncallAiWithToolResults(userMessage, toolCalls, toolResults);
}
returnaiResponse.get("content").getAsString();
}

toolResults =

此外,Spring AI 提供了工具上下文 ToolContext,可以讓程序給工具傳遞額外參數(shù),實(shí)現(xiàn)用戶身份認(rèn)證等功能。還支持直接返回模式(returnDirect),可以繞過(guò)大模型直接返回工具結(jié)果。

6、MCP 模型上下文協(xié)議

MCP(Model Context Protocol 模型上下文協(xié)議)是一種開(kāi)放標(biāo)準(zhǔn),目的是增強(qiáng) AI 與外部系統(tǒng)的交互能力。MCP 為 AI 提供了與外部工具、資源和服務(wù)交互的標(biāo)準(zhǔn)化方式,讓 AI 能夠訪問(wèn)最新數(shù)據(jù)、執(zhí)行復(fù)雜操作,并與現(xiàn)有系統(tǒng)集成。

可以將 MCP 想象成 AI 應(yīng)用的 USB 接口,就像 USB 為設(shè)備連接各種外設(shè)和配件提供了標(biāo)準(zhǔn)化方式一樣,MCP 為 AI 模型連接不同的數(shù)據(jù)源和工具提供了標(biāo)準(zhǔn)化的方法。從而輕松增強(qiáng) AI 的能力,有效降低開(kāi)發(fā)者的理解成本,并且打造出 MCP 服務(wù)生態(tài)。

利用 Spring AI,我們可以快速接入別人的 MCP 服務(wù),只需要定義 MCP 服務(wù)配置,然后直接通過(guò) Bean 注入 MCP 服務(wù)提供的工具即可:

// 使用 Spring AI 的 MCP 客戶端
// 1. 在配置文件中定義 MCP 服務(wù)
// mcp-servers.json
{
"mcpServers": {
"amap-maps": {
"command":"npx",
"args": ["-y","@amap/amap-maps-mcp-server"],
"env": {"AMAP_MAPS_API_KEY":"你的API密鑰"}
}
}
}
// 2. 在應(yīng)用程序中使用 MCP 服務(wù)
@Resource
privateToolCallbackProvider toolCallbackProvider;
publicStringdoChatWithMcp(String message){
ChatResponse response = chatClient
.prompt()
.user(message)
.tools(toolCallbackProvider)// MCP 服務(wù)提供的所有工具
.call()
.chatResponse();
returnresponse.getResult().getOutput().getText();
}

當(dāng)然,開(kāi)發(fā) MCP 服務(wù)也很簡(jiǎn)單。先利用注解定義工具,然后將工具注冊(cè)到 MCP 服務(wù)中:

// 定義工具
publicclassImageSearchTool{
@Tool(description ="search image from web")
publicStringsearchImage(@ToolParam(description ="Search query keyword")String query){
// 搜索圖片,返回結(jié)果
return"https://www.codefather.cn";
}
}
// 注冊(cè) MCP 服務(wù)
@Bean
publicToolCallbackProviderimageSearchTools(){
returnMethodToolCallbackProvider.builder()
.toolObjects(newImageSearchTool())
.build();
}

如果不使用 Spring AI,你就需要引入 MCP 官方的 SDK 進(jìn)行開(kāi)發(fā),或者自主實(shí)現(xiàn),太麻煩了!

// 不使用 Spring AI 的 MCP 實(shí)現(xiàn)
publicStringchatWithExternalTools(String userMessage){
// 1. 啟動(dòng)外部 MCP 服務(wù)進(jìn)程
Process mcpProcess = startMcpProcess("npx","-y","@amap/amap-maps-mcp-server");
// 2. 建立與 MCP 服務(wù)的通信通道
InputStream inputStream = mcpProcess.getInputStream();
OutputStream outputStream = mcpProcess.getOutputStream();
// 3. 發(fā)送初始化握手消息
JsonObject initMessage =newJsonObject();
initMessage.addProperty("jsonrpc","2.0");
initMessage.addProperty("method","initialize");
// ... 添加更多初始化參數(shù)
sendMessage(outputStream, initMessage);
// 4. 接收并解析服務(wù)提供的工具定義
JsonObject response = readResponse(inputStream);
JsonArray toolDefinitions = extractToolDefinitions(response);
// 5. 調(diào)用 AI 模型,將工具定義傳遞給模型
JsonObject aiResponse = callAiWithTools(userMessage, toolDefinitions);
// 6. 解析 AI 響應(yīng),如果需要調(diào)用工具則發(fā)送給 MCP 服務(wù)
if(aiResponse.has("tool_calls")) {
JsonArray toolCalls = aiResponse.getAsJsonArray("tool_calls");
ListnewArrayList<>();
for(JsonElement toolCall : toolCalls) {
// 7. 將工具調(diào)用請(qǐng)求發(fā)送給 MCP 服務(wù)
JsonObject toolRequest =newJsonObject();
toolRequest.addProperty("jsonrpc","2.0");
toolRequest.addProperty("method","executeFunction");
// ... 添加工具調(diào)用參數(shù)
sendMessage(outputStream, toolRequest);
// 8. 接收 MCP 服務(wù)的執(zhí)行結(jié)果
JsonObject toolResponse = readResponse(inputStream);
toolResults.add(toolResponse.toString());
}
// 9. 將工具結(jié)果發(fā)回給 AI 生成最終回答
returncallAiWithToolResults(userMessage, toolCalls, toolResults);
}
// 10. 最后關(guān)閉 MCP 服務(wù)
mcpProcess.destroy();
returnaiResponse.get("content").getAsString();
}

toolResults =

結(jié)尾

以上就是 Spring AI 的核心特性解析,相信大家也感受到使用 Spring AI 開(kāi)發(fā) AI 應(yīng)用有多爽了吧!

除了前面提到的之外,Spring AI 還提供了大模型評(píng)估測(cè)試能力,比如評(píng)估 AI 回答與用戶輸入和上下文的相關(guān)性;還提供了全面的可觀測(cè)性功能,幫助開(kāi)發(fā)者監(jiān)控 AI 應(yīng)用的運(yùn)行狀態(tài)。

不過(guò)目前這些特性還不夠成熟,Spring AI 也還有很長(zhǎng)一段路要走,后續(xù)應(yīng)該也會(huì)推出智能體工作流編排框架吧~

特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。

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.

相關(guān)推薦
熱點(diǎn)推薦
陳小群割肉離場(chǎng)!生態(tài)變了?其殺入電網(wǎng)股,股民:你不要過(guò)來(lái)啊

陳小群割肉離場(chǎng)!生態(tài)變了?其殺入電網(wǎng)股,股民:你不要過(guò)來(lái)啊

金石隨筆
2026-01-21 00:11:35
官媒三評(píng)西貝“100%沒(méi)預(yù)制菜”是謊言:賈國(guó)龍聽(tīng)勸了,要轉(zhuǎn)換思維

官媒三評(píng)西貝“100%沒(méi)預(yù)制菜”是謊言:賈國(guó)龍聽(tīng)勸了,要轉(zhuǎn)換思維

漢史趣聞
2026-01-20 20:20:40
三峽大壩運(yùn)營(yíng)二十余年的 “賬本” 對(duì)外披露,當(dāng)初高達(dá)2500億的投入,如今是否已經(jīng)收回?

三峽大壩運(yùn)營(yíng)二十余年的 “賬本” 對(duì)外披露,當(dāng)初高達(dá)2500億的投入,如今是否已經(jīng)收回?

史海孤雁
2026-01-15 21:41:23
高調(diào)炫富僅是冰山一角!李湘被封禁不到一天,曝出的猛料太炸裂

高調(diào)炫富僅是冰山一角!李湘被封禁不到一天,曝出的猛料太炸裂

老吳教育課堂
2026-01-21 00:34:12
伊朗或退出2026年世界杯,誰(shuí)能替代他們?

伊朗或退出2026年世界杯,誰(shuí)能替代他們?

星耀國(guó)際足壇
2026-01-20 18:12:43
U23國(guó)足5場(chǎng)0失球晉級(jí)!U23亞洲杯僅次沙特,決賽或復(fù)刻奇跡

U23國(guó)足5場(chǎng)0失球晉級(jí)!U23亞洲杯僅次沙特,決賽或復(fù)刻奇跡

奧拜爾
2026-01-21 01:29:58
【獨(dú)家】連線剛從伊朗回國(guó)的中國(guó)學(xué)者:過(guò)去十幾天,伊朗到底發(fā)生了什么?

【獨(dú)家】連線剛從伊朗回國(guó)的中國(guó)學(xué)者:過(guò)去十幾天,伊朗到底發(fā)生了什么?

環(huán)球網(wǎng)資訊
2026-01-20 07:03:07
中日打出真火了,中國(guó)48小時(shí)內(nèi)祭出兩大反制措施,高市惱羞成怒

中日打出真火了,中國(guó)48小時(shí)內(nèi)祭出兩大反制措施,高市惱羞成怒

生活的哲學(xué)
2026-01-19 18:34:26
A股:周二夜晚傳來(lái)1個(gè)核彈級(jí)利好!周三很可能會(huì)迎史詩(shī)級(jí)別大行情?

A股:周二夜晚傳來(lái)1個(gè)核彈級(jí)利好!周三很可能會(huì)迎史詩(shī)級(jí)別大行情?

股市皆大事
2026-01-20 19:45:50
2026年:一匹狼臨死前放下藏了7年的東西,讓兩億人淚崩

2026年:一匹狼臨死前放下藏了7年的東西,讓兩億人淚崩

茉莉聊聊天
2026-01-18 09:05:09
HWG!羅馬諾:阿森納小將恩瓦內(nèi)里租借加盟馬賽,租借費(fèi)+薪水約400萬(wàn)歐

HWG!羅馬諾:阿森納小將恩瓦內(nèi)里租借加盟馬賽,租借費(fèi)+薪水約400萬(wàn)歐

懂球帝
2026-01-20 21:42:13
如果在家突發(fā)心梗,黃金3分鐘自救法,快了解,關(guān)鍵時(shí)刻可自救

如果在家突發(fā)心梗,黃金3分鐘自救法,快了解,關(guān)鍵時(shí)刻可自救

健康之光
2026-01-06 13:15:35
納指跌幅擴(kuò)大至1.8% 標(biāo)普500指數(shù)跌1.6%

納指跌幅擴(kuò)大至1.8% 標(biāo)普500指數(shù)跌1.6%

財(cái)聯(lián)社
2026-01-21 02:25:11
才剛下課!阿隆索下家曝光!10億豪門(mén)送邀請(qǐng),聯(lián)手愛(ài)徒,英超變天

才剛下課!阿隆索下家曝光!10億豪門(mén)送邀請(qǐng),聯(lián)手愛(ài)徒,英超變天

阿泰希特
2026-01-20 11:00:21
毛主席只用一句話,就點(diǎn)破武則天無(wú)字碑:原來(lái)我們猜了千年都錯(cuò)了

毛主席只用一句話,就點(diǎn)破武則天無(wú)字碑:原來(lái)我們猜了千年都錯(cuò)了

鶴羽說(shuō)個(gè)事
2026-01-20 11:48:10
克羅斯談歐冠:拜仁的重點(diǎn)在于避免傷??;皇馬的狀態(tài)難以?shī)Z冠

克羅斯談歐冠:拜仁的重點(diǎn)在于避免傷?。换蜀R的狀態(tài)難以?shī)Z冠

懂球帝
2026-01-21 02:19:12
A股明天周三劇本已出!晚間突傳一重大消息,明天要來(lái)大動(dòng)作嗎?

A股明天周三劇本已出!晚間突傳一重大消息,明天要來(lái)大動(dòng)作嗎?

股市皆大事
2026-01-20 16:25:49
醫(yī)生發(fā)現(xiàn):早期腦梗不是頭暈,而是頻繁出現(xiàn)這5個(gè)異常,別忽視

醫(yī)生發(fā)現(xiàn):早期腦梗不是頭暈,而是頻繁出現(xiàn)這5個(gè)異常,別忽視

蜉蝣說(shuō)
2026-01-20 15:16:24
弘一法師:不要太操心你的孩子和在意的親人,每個(gè)人都有自己的命

弘一法師:不要太操心你的孩子和在意的親人,每個(gè)人都有自己的命

木言觀
2026-01-18 13:56:24
紅利曼防御體系崩了!

紅利曼防御體系崩了!

星火聊天下
2026-01-18 05:41:14
2026-01-21 03:03:00
程序員魚(yú)皮
程序員魚(yú)皮
一手科技資訊和編程干貨
1文章數(shù) 0關(guān)注度
往期回顧 全部

科技要聞

收藏|這可能是CES2026最清醒一份復(fù)盤(pán)

頭條要聞

丹麥?zhǔn)紫啵褐鳈?quán)不談判 準(zhǔn)備貿(mào)易戰(zhàn)

頭條要聞

丹麥?zhǔn)紫啵褐鳈?quán)不談判 準(zhǔn)備貿(mào)易戰(zhàn)

體育要聞

勇士遭暴擊!巴特勒重傷賽季報(bào)銷

娛樂(lè)要聞

網(wǎng)紅版閆學(xué)晶!600萬(wàn)粉博主阿爆翻車

財(cái)經(jīng)要聞

李迅雷:2026買(mǎi)房不如租房

汽車要聞

奇瑞張貴兵:墨甲不做秀技術(shù)的企業(yè) 只做痛點(diǎn)終結(jié)者

態(tài)度原創(chuàng)

游戲
教育
藝術(shù)
手機(jī)
時(shí)尚

《秘奧:秘宇?yuàn)W憶》評(píng)測(cè):因簡(jiǎn)潔而特別"/> 主站 商城 論壇 自運(yùn)營(yíng) 登錄 注冊(cè) 《秘奧:秘宇?yuàn)W憶》評(píng)測(cè):因簡(jiǎn)潔而特別 Marvin 2026-01-2...

教育要聞

學(xué)習(xí)不再靠死磕,是從初二開(kāi)始的

藝術(shù)要聞

陳丹青:困擾幾代人的中國(guó)寫(xiě)實(shí)油畫(huà)

手機(jī)要聞

iQOO 15 Ultra跑分出爐:451萬(wàn)行業(yè)最高記錄

冬季不臃腫穿搭指南來(lái)了,奔五奔六照著穿,拿捏溫暖與高級(jí)感

無(wú)障礙瀏覽 進(jìn)入關(guān)懷版