深入解析Spring?AI框架如何在Java應用中實現(xiàn)智能化交互的關鍵
今天我們的Spring AI源碼分析主題即將結束。我已經(jīng)對自己感興趣的基本內(nèi)容進行了全面的審視,并將這些分析分享給大家。如果你對這個主題感興趣,可以閱讀以下幾篇文章。每篇文章都層層遞進,深入探討相關內(nèi)容。考慮到長文可能讓大家感到疲憊,我采用了逐步推進的方式,確保每一篇都簡明易懂,便于理解。希望能為你們提供有價值的參考!
Spring AI的基本用法:http://www.dbjr.com.cn/program/330616f4f.htm
Spring.3版本自動裝配機制的演變與實踐:http://www.dbjr.com.cn/program/325161cdp.htm
Spring AI的阻塞式請求與響應機制的核心邏輯:http://www.dbjr.com.cn/program/3306809ji.htm
Spring AI的流式回答源碼分析:http://www.dbjr.com.cn/program/3306816zk.htm
今天我們的主題將聚焦于最后一步:如何將AI技術有效應用于Java程序中。眾所周知,Java是一種面向對象的編程語言,因此不論我們調(diào)用什么AI接口,從業(yè)務的角度來看,它本質(zhì)上只是一個接口,而AI則充當了一個第三方對接平臺。然而,值得注意的是,AI的聊天回復往往不適用于對象,因為這些回復無法直接返回格式化的JSON數(shù)據(jù)。這一問題導致Spring無法將其轉化為實體類,從而無法真正融入業(yè)務流程。
今天,我們將探討Spring AI框架是如何有效解決這一挑戰(zhàn)的。通過深入分析框架的設計和實現(xiàn),我們希望為大家展示如何將AI能力順利整合到Java應用中,推動業(yè)務的進一步發(fā)展。
除此之外,function call 函數(shù)回調(diào)也是AI技術的一個重要特性。那么,Spring AI是如何應對這一挑戰(zhàn)的呢?今天,我們將深入探討這個問題,解析Spring AI框架如何有效處理函數(shù)回調(diào),從而增強AI與Java程序之間的交互能力。
實體化類
實體類在Java程序中扮演著不可或缺的角色,無論是進行內(nèi)部操作,還是將數(shù)據(jù)返回給前端的RESTful接口,實體類都是業(yè)務中信息傳遞的核心。在Spring AI框架中,我們可以有效地控制AI的回答,以確保其能夠正確映射到實體類。接下來,我們將探討Spring AI是如何實現(xiàn)這一功能的,基本用法如下:
@GetMapping("/ai-Entity") ActorFilms generationByEntity() { ActorFilms actorFilms = chatClient.prompt() .user("Generate the filmography for a random actor.") .call() .entity(ActorFilms.class); return actorFilms; }
源碼分析
在這里,我們不再直接調(diào)用 content
方法,而是選擇使用 entity
方法作為返回類型。這一變化意味著我們需要重點關注 entity
的實現(xiàn)及其在整個流程中的作用。接下來,讓我們通過代碼示例來深入分析這一關鍵部分:
public <T> T entity(Class<T> type) { Assert.notNull(type, "the class must be non-null"); var boc = new BeanOutputConverter<T>(type); return doSingleWithBeanOutputConverter(boc); }
這里使用了一個名為 BeanOutputConverter
的轉換器。接下來,我們來詳細查看一下 doSingleWithBeanOutputConverter
方法的具體實現(xiàn)。
private <T> T doSingleWithBeanOutputConverter(StructuredOutputConverter<T> boc) { var chatResponse = doGetObservableChatResponse(this.request, boc.getFormat()); var stringResponse = chatResponse.getResult().getOutput().getContent(); return boc.convert(stringResponse); }
在這里,我們要討論的 doGetObservableChatResponse
方法主要負責與第三方 API 的交互過程。由于我們在之前的講解中已經(jīng)對聊天調(diào)用API方法的實現(xiàn)進行了詳細分析,因此這次我們就不再深入探討其具體內(nèi)容,而是集中于方法的核心功能和應用場景。
實體類提示詞限制
在這里,我們來查看一下 boc.getFormat()
方法。這個方法返回一段提示詞,而這些提示詞會根據(jù)不同的類型而有所區(qū)別。為了更好地理解,我們可以具體分析一下單個 Bean 實體類所對應的提示詞格式。
具體如下:
public String getFormat() { String template = """ Your response should be in JSON format. Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation. Do not include markdown code blocks in your response. Remove the ```json markdown from the output. Here is the JSON Schema instance your output must adhere to: ```%s``` """; return String.format(template, this.jsonSchema); }
這其實非常簡單。通過使用提示詞來明確限制 AI 返回的格式,可以最大程度地確保其輸出符合我們的要求。這種方式使得 Spring 能夠有效地進行解析,而 jsonSchema 則僅僅是我們傳遞的實體類的各種信息。
封裝實體類
boc.convert
方法負責將數(shù)據(jù)封裝成實體類的過程。具體來說,它會接收原始數(shù)據(jù),并通過內(nèi)部邏輯進行轉換,以生成符合我們定義的實體類結構。
從表面上看,我們可以清晰地看出該過程涉及到 JSON 序列化,它將數(shù)據(jù)封裝成我們所期望的對象格式。然而,需要注意的是,雖然 AI 的提示詞旨在盡量限制其回復內(nèi)容,以使其盡可能符合我們的要求,但由于各種因素的影響,我們無法保證其返回的格式會完全按照預設進行。
因此,為了確保程序的穩(wěn)健性和可靠性,在此過程中引入了異常捕獲機制。這一機制能夠有效地處理潛在的格式不一致或錯誤,從而確保應用在面對不符合預期的數(shù)據(jù)時,能夠平穩(wěn)運行而不至于崩潰。
函數(shù)回調(diào)
AI目前能夠發(fā)揮一定作用,主要得益于模型的函數(shù)調(diào)用功能。如果僅僅依靠訓練模型進行聊天回答,其實際價值是相對有限的,因為這種方式的成本非常高,很多企業(yè)難以承受。然而,隨著函數(shù)回調(diào)功能的引入,AI可以實時訪問和利用各種數(shù)據(jù),包括實時數(shù)據(jù)和業(yè)務數(shù)據(jù),使其能夠根據(jù)提供的信息進行更為精準和有效的回答,從而具備了實質(zhì)性的業(yè)務能力。
接下來,我們來看看Spring AI是如何實現(xiàn)這一點的。
基本用法
了解了之前的 Spring AI 用法文章后,你大概已經(jīng)掌握了如何創(chuàng)建一個 Function 函數(shù)。接下來,我們將直接深入探討如何將這個函數(shù)添加到我們的項目中。
@PostMapping("/ai-function") ChatDataPO functionGenerationByText(@RequestParam("userInput") String userInput) { String content = this.myChatClientWithSystem.prompt() .user(userInput) .functions("CurrentWeather") .call() .content(); log.info("content: {}", content); ChatDataPO chatDataPO = ChatDataPO.builder().code("text").data(ChildData.builder().text(content).build()).build();; return chatDataPO; }
在我們的項目中,functions 函數(shù)允許添加多種功能,不僅僅局限于單一工具的調(diào)用。例如,在可視化智能體的應用中,如千帆 AppBuilder,我們可以觀察到思考輪數(shù)的運用,這其中涉及了多個工具的調(diào)用。這種方式為我們的智能體提供了更豐富的功能和靈活性。
接下來,我們將進行一次函數(shù)的調(diào)用,以實際展示其效果。
在這里,我們使用了一個固定的 30 度作為示例值,但你可以在函數(shù)方法內(nèi)部通過接口調(diào)用其他第三方服務來獲取實時數(shù)據(jù)。因此,通過集成外部數(shù)據(jù)源,你可以實現(xiàn)更為智能和適應性強的功能。
源碼分析
還記得我們之前討論過的內(nèi)容嗎?在回答的最后,我們會進行一次判斷,以確定當前的輸出是否為函數(shù)調(diào)用。這一過程是確保系統(tǒng)能夠準確識別和執(zhí)行函數(shù)的重要環(huán)節(jié)。接下來,我們將展示相關的源碼,以便更深入地理解這一機制的具體實現(xiàn):
if (isToolCall(chatResponse, Set.of(ChatCompletionFinishReason.TOOL_CALLS.name(), ChatCompletionFinishReason.STOP.name()))) { var toolCallConversation = handleToolCalls(prompt, chatResponse); // Recursively call the call method with the tool call message // conversation that contains the call responses. return this.call(new Prompt(toolCallConversation, prompt.getOptions())); }
我也在這里設置了一個斷點,以便大家可以清楚地看到這一過程。這一斷點幫助我們確認,返回的結果完全是由 AI 生成的。在這個基礎上,我們會進行進一步的判斷,以決定是否需要調(diào)用函數(shù)工具。
接下來,我們將進入函數(shù)調(diào)用的過程。這一步驟至關重要,因為函數(shù)的返回值將被再次提供給 AI,作為后續(xù)回答的參考。我們來看看具體是如何進行函數(shù)調(diào)用的。雖然我已經(jīng)找到了相關的源碼,但為了讓大家更容易理解這個過程,我將提供一張可視化的圖片。這張圖片將清晰地展示函數(shù)調(diào)用的流程,以及返回值是如何被整合進 AI 的回答中的。
發(fā)送這些參數(shù)的原因在于,在發(fā)起請求時已經(jīng)設置了相關限制。以下是我截取下來的請求參數(shù):
tools=[FunctionTool[type=FUNCTION, function=Function[description=獲取指定地點的天氣情況, name=CurrentWeather, parameters={$schema=https://json-schema.org/draft/2020-12/schema, type=object, properties={location={type=string}, unit={type=string, enum=[C, F]}}}]]]
目前幾乎所有第三方AI接口都提供了一個名為 tools
的參數(shù),用于傳遞我們需要的參數(shù)。以OpenAI為例:
調(diào)用函數(shù)接口
由于我們的函數(shù)實現(xiàn)了 @FunctionalInterface
接口,因此 call
這一行實際上會調(diào)用我們定義的 apply
接口。鑒于我們的參數(shù)是一個實體記錄,系統(tǒng)會對其進行 JSON 轉化和封裝,隨后再進行調(diào)用。具體過程如下所示:
public String call(String functionArguments) { // Convert the tool calls JSON arguments into a Java function request object. I request = fromJson(functionArguments, inputType); // extend conversation with function response. return this.andThen(this.responseConverter).apply(request); }
因此,即使所有操作都已結束,如果在下次 AI 判斷中仍然需要調(diào)用工具,系統(tǒng)將繼續(xù)進行循環(huán),直到所有問題都得到完整的回答為止。這種設計確保了整個過程的連貫性和完整性。
總結
在這次探討中,我們深入挖掘了Spring AI框架如何與Java程序完美結合,提升業(yè)務能力。隨著AI技術的不斷發(fā)展,其在Java應用中的整合成為了提升開發(fā)效率和用戶體驗的關鍵。我們不僅分析了實體類的映射與控制,還探討了函數(shù)回調(diào)的強大功能,展示了如何通過Spring AI有效處理這些復雜交互。
希望這些分析能夠激發(fā)你對AI應用的靈感,并促使你在自己的項目中大膽嘗試,將AI技術融入到業(yè)務流程中。期待未來能看到大家的創(chuàng)意實現(xiàn)和應用!
完結撒花!關于Spring AI的一系列源碼分析到此結束,以后如果還有感興趣的出發(fā)點,我也會繼續(xù)為大家?guī)矸治觯?/p>
到此這篇關于深入解析Spring AI框架如何在Java應用中實現(xiàn)智能化交互的關鍵的文章就介紹到這了,更多相關springAI智能化交互內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
基于java SSM springboot實現(xiàn)抗疫物質(zhì)信息管理系統(tǒng)
這篇文章主要介紹了基于JAVA SSM springboot實現(xiàn)的抗疫物質(zhì)信息管理系統(tǒng),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08Mybatis-Plus開發(fā)提速器mybatis-plus-generator-ui詳解
這篇文章主要介紹了Mybatis-Plus開發(fā)提速器mybatis-plus-generator-ui,本文簡要介紹一款基于Mybatis-Plus的代碼自助生成器,文章通過實例集成的方式來詳細講解mybatis-plus-generator-ui,從相關概念到實際集成案例,以及具體的擴展開發(fā)介紹,需要的朋友可以參考下2022-11-11