Spring?AI使用tool?Calling和MCP的示例詳解
深入探索 Spring AI
Spring AI版本1.0.0.M6
在人工智能與軟件開發(fā)深度融合的時(shí)代,Spring AI 作為一個(gè)強(qiáng)大的框架,持續(xù)為開發(fā)者提供著高效且便捷的工具,以實(shí)現(xiàn)與大語(yǔ)言模型(LLM)的無(wú)縫交互。Spring AI 的最新版本引入了一系列令人矚目的特性,其中 Function Calling 到 Tool Calling 的轉(zhuǎn)換以及模型上下文協(xié)議(MCP)的應(yīng)用,標(biāo)志著該框架在 AI 集成領(lǐng)域的又一次重大飛躍。
聊天接口示例
在今天的內(nèi)容之前我們回憶下如何使用SpringAI實(shí)現(xiàn)一個(gè)簡(jiǎn)單的聊天接口,使用千問(wèn)API實(shí)現(xiàn)聊天功能:
- 添加依賴
<dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-starter</artifactId> </dependency>
- 配置
spring: ai: ## Alibaba dashscope: api-key: ${DASH_SCOPE_API_KEY} chat: enable: true options: model: qwen-max
- 實(shí)現(xiàn)
@Bean public ChatClient chatClient(ChatClient.Builder chatClientBuilder) throws IOException { var chatClient = chatClientBuilder .defaultSystem("You are a helpful assistant.") .defaultAdvisors(new SimpleLoggerAdvisor()) // LOG .build(); return chatClient; } /** * 調(diào)用 * @param message * @return */ public String completion(String message) { return chatClient .prompt().user(message) .call().content(); }
當(dāng)進(jìn)行下面的提問(wèn)時(shí):
現(xiàn)在北京時(shí)間幾點(diǎn)了?
很遺憾,我無(wú)法直接獲取實(shí)時(shí)的北京時(shí)間。你可以查看設(shè)備上的時(shí)間或者通過(guò)網(wǎng)絡(luò)搜索來(lái)獲取準(zhǔn)確的北京時(shí)間。如果你使用的是電腦或手機(jī),通常在屏幕的一角會(huì)顯示當(dāng)前的時(shí)間。
Function Calling
在早期的 AI 交互中,F(xiàn)unction Calling 是一種常見的機(jī)制,允許模型在生成回復(fù)時(shí)調(diào)用外部函數(shù)以獲取額外信息。然而,這種方式在擴(kuò)展性和靈活性上存在一定的局限性。而 Spring AI 最新版本引入的 Tool Calling 則是對(duì) Function Calling 的進(jìn)一步演進(jìn)。Tool Calling 將函數(shù)調(diào)用抽象為工具調(diào)用,將工具視為可復(fù)用的資源,模型可以根據(jù)需求動(dòng)態(tài)調(diào)用這些工具,以完成更復(fù)雜的任務(wù)。在新版本中已經(jīng)被改為Tool Calling。
工具主要用于:
信息檢索
此類工具可用于從外部來(lái)源(例如數(shù)據(jù)庫(kù)、Web 服務(wù)、文件系統(tǒng)或 Web
搜索引擎)檢索信息。其目標(biāo)是增強(qiáng)模型的知識(shí),使其能夠回答原本無(wú)法回答的問(wèn)題。因此,它們可用于檢索增強(qiáng)生成 (RAG)
場(chǎng)景。例如,可以使用工具檢索給定位置的當(dāng)前天氣、檢索最新新聞文章或查詢數(shù)據(jù)庫(kù)中的特定記錄。
采取行動(dòng)
此類別中的工具可用于在軟件系統(tǒng)中采取行動(dòng),例如發(fā)送電子郵件、在數(shù)據(jù)庫(kù)中創(chuàng)建新記錄、提交表單或觸發(fā)工作流。其目標(biāo)是自動(dòng)化原本需要人工干預(yù)或明確編程的任務(wù)。例如,可以使用工具為與聊天機(jī)器人交互的客戶預(yù)訂航班、在網(wǎng)頁(yè)上填寫表單,或在代碼生成場(chǎng)景中基于自動(dòng)化測(cè)試 (TDD) 實(shí)現(xiàn) Java 類。
盡管我們通常將工具調(diào)用稱為模型功能,但實(shí)際上工具調(diào)用邏輯是由客戶端應(yīng)用程序提供的。模型只能請(qǐng)求工具調(diào)用并提供輸入?yún)?shù),而應(yīng)用程序負(fù)責(zé)根據(jù)輸入?yún)?shù)執(zhí)行工具調(diào)用并返回結(jié)果。
Spring AI 提供了便捷的 API 來(lái)定義工具、解析來(lái)自模型的工具調(diào)用請(qǐng)求以及執(zhí)行工具調(diào)用。
為了解決上面關(guān)于時(shí)間問(wèn)題的解決方案,我們可以定義一個(gè)工具,并嵌入到模型中…
public class TimeTools { private static final Logger logger = LoggerFactory.getLogger(TimeTools.class); @Tool(description = "Get the time of a specified city.") public String getCityTimeMethod(@ToolParam(description = "Time zone id, such as Asia/Shanghai") String timeZoneId) { logger.info("The current time zone is {}", timeZoneId); return String.format("The current time zone is %s and the current time is " + "%s", timeZoneId, ZoneUtils.getTimeByZoneId(timeZoneId)); } }
public ChatClient chatClient(ChatClient.Builder chatClientBuilder) throws IOException { // ... chatClientBuilder.defaultTools(timeTool); // ... }
Function Calling實(shí)現(xiàn)了大語(yǔ)言模型(LLM)與外部函數(shù)或工具進(jìn)行交互的能力。這一機(jī)制賦予了 AI 系統(tǒng)更強(qiáng)大的功能和靈活性,使其能夠處理更加復(fù)雜和動(dòng)態(tài)的任務(wù)。
注意不是所有模型都支持FunctionCalling
MCP
MCP(Model Context Protocol,模型上下文協(xié)議) 是的一種開放協(xié)議,旨在統(tǒng)一大語(yǔ)言模型(LLM)與外部數(shù)據(jù)源、工具和服務(wù)之間的交互標(biāo)準(zhǔn),推動(dòng) AI 應(yīng)用的標(biāo)準(zhǔn)化和去中心化發(fā)展。
MCP 提供了一種統(tǒng)一的接口,使得不同的工具和服務(wù)可以以標(biāo)準(zhǔn)化的方式與模型進(jìn)行交互。
核心功能
- 標(biāo)準(zhǔn)化交互
- MCP 提供了一套通用的通信協(xié)議、數(shù)據(jù)格式和規(guī)則,使 LLM 能夠以統(tǒng)一的方式與外部資源(如數(shù)據(jù)庫(kù)、API、文件系統(tǒng)等)進(jìn)行交互,無(wú)需為每個(gè)工具單獨(dú)開發(fā)適配接口。
- 增強(qiáng)模型能力
- 通過(guò) MCP,LLM 可以動(dòng)態(tài)調(diào)用外部工具或數(shù)據(jù)源,例如實(shí)時(shí)獲取天氣信息、查詢數(shù)據(jù)庫(kù)、調(diào)用第三方服務(wù)等,從而擴(kuò)展模型的功能邊界。
- 安全與合規(guī)
- MCP 內(nèi)置了安全機(jī)制,確保數(shù)據(jù)傳輸?shù)陌踩?,并支持?xì)粒度的權(quán)限控制,避免數(shù)據(jù)泄露和濫用。
- 降低開發(fā)成本
- 開發(fā)者無(wú)需重復(fù)造輪子,可直接基于 MCP 協(xié)議構(gòu)建 AI 應(yīng)用,顯著減少開發(fā)時(shí)間和成本。
在1.0.0-M6版本中引入了MCP,使得可以基于Spring AI實(shí)現(xiàn)各種擴(kuò)展
此時(shí)聊天應(yīng)用作MCP服務(wù)的調(diào)用者,也就是客戶端,需要調(diào)用外部的MCP服務(wù),首先對(duì)聊天服務(wù)改造:
- 添加必要的依賴:
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId> </dependency>
- 通過(guò)配置ChatClient完成集成:
@Bean public ChatClient chatClient(ToolCallbackProvider toolsProvider) throws IOException { var chatClient = chatClientBuilder // ... .defaultTools( toolsProvider.getToolCallbacks() ) //mcp // ... .build(); return chatClient; }
SpringAI中,MCP 客戶端支持兩種傳輸方式:STDIO 和 SSE。
標(biāo)準(zhǔn)啟動(dòng)器通過(guò)STDIO(進(jìn)程內(nèi))和/或SSE(遠(yuǎn)程)傳輸同時(shí)連接到一個(gè)或多個(gè) MCP 服務(wù)器。SSE 連接使用基于 HttpClient 的傳輸實(shí)現(xiàn)。每個(gè)與 MCP 服務(wù)器的連接都會(huì)創(chuàng)建一個(gè)新的 MCP 客戶端實(shí)例。
STDIO
其實(shí)就是通過(guò)本地命令進(jìn)行調(diào)用的實(shí)現(xiàn),需要注意的是,返回的數(shù)據(jù)結(jié)果必須遵循MCP規(guī)范,我們可以基于Spring開發(fā)一個(gè)可執(zhí)行的jar程序包,然后由客戶端調(diào)用。
- 添加依賴
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId> </dependency>
- 實(shí)現(xiàn)Tool并注冊(cè)
@Service public class TranslationService { @Tool(description = "將內(nèi)容翻譯成英文") public String translate(String content) { return "hello"; } } @Bean public ToolCallbackProvider weatherTools(TranslationService translationService) { return MethodToolCallbackProvider.builder().toolObjects(translationService).build(); }
- 添加配置,注意這里要關(guān)掉所有日志相關(guān)的輸出
spring: main: web-application-type: none banner-mode: off ai: mcp: server: name: translation-server version: 0.0.1 logging: level: root: off
- 打包,記得使用spring-boot-maven-plugin插件打包,下面的mcpServers引用的就是這里的jar
- 修改聊天應(yīng)用配置,并且重啟
spring: ai: mcp: client: type: SYNC stdio: servers-configuration: classpath:mcp-stdio-servers.json
mcp-stdio-servers.json
{ "mcpServers": { "weather": { "command": "java", "args": [ "-Dspring.ai.mcp.server.stdio=true", "-Dspring.main.web-application-type=none", "-Dlogging.pattern.console=", "-jar", "your_jar_path/mcp-stdio-server-1.0.1-SNAPSHOT.jar" ], "env": {} } } }
提問(wèn): 翻譯單詞運(yùn)勢(shì)
回答: 看起來(lái)在處理您的請(qǐng)求時(shí)發(fā)生了一些混淆。單詞"運(yùn)勢(shì)"的正確英文翻譯應(yīng)為 “fortune” 而非 “hello”。如果您需要關(guān)于星座運(yùn)勢(shì)的信息,請(qǐng)告訴我您的星座名稱。如果是其他類型的運(yùn)勢(shì),請(qǐng)?zhí)峁└嗟募?xì)節(jié)。
因?yàn)槲覜](méi)有實(shí)現(xiàn),全部返回的是hello,看樣子模型對(duì)我們的結(jié)果進(jìn)一步做了處理
SSE
這里提供一個(gè)簡(jiǎn)單的示例,主要實(shí)現(xiàn)星座運(yùn)勢(shì)獲取的Mcp,這是一個(gè)單獨(dú)的基于Spring開發(fā)的應(yīng)用,與上面的聊天應(yīng)用隔離:
- 引入相關(guān)依賴
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-mcp-server-webmvc-spring-boot-starter</artifactId> </dependency>
- 定義Tool實(shí)現(xiàn)
@Service public class HoroscopeService { private String url = "https://apis.tianapi.com/star/index?key=%s&astro=%s"; private String key = "xx"; private RestTemplate restTemplate = new RestTemplate(); private ObjectMapper objectMapper = new ObjectMapper(); @Tool(description = "Get constellation fortune by consName") public String getFortune(String consName) { Map map = restTemplate.getForObject(String.format(url, key, consName), Map.class); try { return objectMapper.writeValueAsString(map.get("result")); } catch (JsonProcessingException e) { e.printStackTrace(); return "獲取失?。?+ e.getMessage(); } } }
- 配置文件
spring: ai: mcp: server: name: webmvc-mcp-server version: 1.0.0 type: SYNC sse-message-endpoint: /mcp/messages server: port: 8081 servlet: encoding: charset: utf-8 enabled: true force: true
- 啟動(dòng)應(yīng)用,訪問(wèn):http://localhost:8081
- 修改聊天應(yīng)用配置,并且重啟
spring: ai: mcp: client: type: SYNC sse: connections: constellation: url: http://localhost:8081
提問(wèn): 白羊座的運(yùn)勢(shì)
回答: 今天白羊座的運(yùn)勢(shì)如下: - 綜合指數(shù):80% - 愛情指數(shù):70% - 工作指數(shù):55% - 財(cái)運(yùn)指數(shù):65% - 健康指數(shù):80% - 幸運(yùn)顏色:藍(lán)色 - 幸運(yùn)數(shù)字:5 - 貴人星座:射手座 今日概述:今天你可能會(huì)忍不住向另一半抱怨工作上遇到的問(wèn)題,但這樣也會(huì)給對(duì)方帶來(lái)困擾。在感情中,要注意不要過(guò)多地向?qū)Ψ桨l(fā)泄負(fù)面情緒,而應(yīng)該把溫暖和幸福帶給他們。
結(jié)束語(yǔ)
現(xiàn)階段的AI技術(shù),恰似一臺(tái)功能強(qiáng)大卻需精心調(diào)校的計(jì)算機(jī)系統(tǒng)。它并非“即插即用”的萬(wàn)能工具,而是需要開發(fā)者如同配置硬件般,根據(jù)特定業(yè)務(wù)場(chǎng)景的需求,按需增加“認(rèn)知模塊”與“計(jì)算資源”。這種靈活擴(kuò)展的能力,與模塊化計(jì)算平臺(tái)(MCP,Modular Computing Platform)的設(shè)計(jì)理念不謀而合——通過(guò)標(biāo)準(zhǔn)化接口與可組合架構(gòu),讓AI系統(tǒng)既能像積木般自由拼接算法能力,又能像云計(jì)算般彈性調(diào)度算力資源。開發(fā)者需像搭建樂(lè)高城堡般,將自然語(yǔ)言處理、視覺識(shí)別、決策推理等模塊按需組合,再通過(guò)數(shù)據(jù)管道與反饋機(jī)制持續(xù)優(yōu)化,最終讓AI在醫(yī)療診斷、智能制造、智慧城市等垂直領(lǐng)域中,展現(xiàn)出接近專家水平的場(chǎng)景化智能
到此這篇關(guān)于Spring AI使用tool Calling和MCP的示例詳解的文章就介紹到這了,更多相關(guān)spring ai tool calling和mcp內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring實(shí)現(xiàn)控制反轉(zhuǎn)和依賴注入的示例詳解
這篇文章主要為大家詳細(xì)介紹IoC(控制反轉(zhuǎn))和DI(依賴注入)的概念,以及如何在Spring框架中實(shí)現(xiàn)它們,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-08-08JAVA集成Freemarker生成靜態(tài)html過(guò)程解析
這篇文章主要介紹了JAVA集成Freemarker生成靜態(tài)html過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06Mybatis批量插入數(shù)據(jù)的兩種方式總結(jié)與對(duì)比
批量插入功能是我們?nèi)粘9ぷ髦斜容^常見的業(yè)務(wù)功能之一,下面這篇文章主要給大家介紹了關(guān)于Mybatis批量插入數(shù)據(jù)的兩種方式總結(jié)與對(duì)比的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01springboot接受前端請(qǐng)求的方法實(shí)現(xiàn)
本文主要介紹了springboot接受前端請(qǐng)求的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01詳解RabbitMQ延遲隊(duì)列的基本使用和優(yōu)化
這篇文章主要介紹了詳解RabbitMQ延遲隊(duì)列的基本使用和優(yōu)化,延遲隊(duì)列中的元素都是帶有時(shí)間屬性的。延遲隊(duì)列就是用來(lái)存放需要在指定時(shí)間被處理的元素的隊(duì)列,需要的朋友可以參考下2023-05-05關(guān)于spring版本與JDK版本不兼容的問(wèn)題及解決方法
這篇文章主要介紹了關(guān)于spring版本與JDK版本不兼容的問(wèn)題,本文給大家?guī)?lái)了解決方法,需要的朋友可以參考下2018-11-11java學(xué)生成績(jī)管理系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)
這篇文章主要介紹了java學(xué)生成績(jī)管理系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01springboot?整合?clickhouse的實(shí)現(xiàn)示例
本文主要介紹了springboot?整合?clickhouse的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02