欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入解析Spring?AI框架如何在Java應(yīng)用中實(shí)現(xiàn)智能化交互的關(guān)鍵

 更新時(shí)間:2024年11月14日 11:54:02   作者:努力的小雨  
本文詳細(xì)介紹了SpringAI框架在Java應(yīng)用中的應(yīng)用,包括實(shí)體類映射、函數(shù)回調(diào)等核心功能的實(shí)現(xiàn),通過(guò)源碼分析,幫助開(kāi)發(fā)者更好地理解和使用這些高級(jí)特性,提升業(yè)務(wù)效率,感興趣的朋友跟隨小編一起看看吧

今天我們的Spring AI源碼分析主題即將結(jié)束。我已經(jīng)對(duì)自己感興趣的基本內(nèi)容進(jìn)行了全面的審視,并將這些分析分享給大家。如果你對(duì)這個(gè)主題感興趣,可以閱讀以下幾篇文章。每篇文章都層層遞進(jìn),深入探討相關(guān)內(nèi)容??紤]到長(zhǎng)文可能讓大家感到疲憊,我采用了逐步推進(jìn)的方式,確保每一篇都簡(jiǎn)明易懂,便于理解。希望能為你們提供有價(jià)值的參考!

Spring AI的基本用法:http://www.dbjr.com.cn/program/330616f4f.htm

Spring.3版本自動(dòng)裝配機(jī)制的演變與實(shí)踐:http://www.dbjr.com.cn/program/325161cdp.htm

Spring AI的阻塞式請(qǐng)求與響應(yīng)機(jī)制的核心邏輯:http://www.dbjr.com.cn/program/3306809ji.htm

Spring AI的流式回答源碼分析:http://www.dbjr.com.cn/program/3306816zk.htm

今天我們的主題將聚焦于最后一步:如何將AI技術(shù)有效應(yīng)用于Java程序中。眾所周知,Java是一種面向?qū)ο蟮木幊陶Z(yǔ)言,因此不論我們調(diào)用什么AI接口,從業(yè)務(wù)的角度來(lái)看,它本質(zhì)上只是一個(gè)接口,而AI則充當(dāng)了一個(gè)第三方對(duì)接平臺(tái)。然而,值得注意的是,AI的聊天回復(fù)往往不適用于對(duì)象,因?yàn)檫@些回復(fù)無(wú)法直接返回格式化的JSON數(shù)據(jù)。這一問(wèn)題導(dǎo)致Spring無(wú)法將其轉(zhuǎn)化為實(shí)體類,從而無(wú)法真正融入業(yè)務(wù)流程。

今天,我們將探討Spring AI框架是如何有效解決這一挑戰(zhàn)的。通過(guò)深入分析框架的設(shè)計(jì)和實(shí)現(xiàn),我們希望為大家展示如何將AI能力順利整合到Java應(yīng)用中,推動(dòng)業(yè)務(wù)的進(jìn)一步發(fā)展。

除此之外,function call 函數(shù)回調(diào)也是AI技術(shù)的一個(gè)重要特性。那么,Spring AI是如何應(yīng)對(duì)這一挑戰(zhàn)的呢?今天,我們將深入探討這個(gè)問(wèn)題,解析Spring AI框架如何有效處理函數(shù)回調(diào),從而增強(qiáng)AI與Java程序之間的交互能力。

實(shí)體化類

實(shí)體類在Java程序中扮演著不可或缺的角色,無(wú)論是進(jìn)行內(nèi)部操作,還是將數(shù)據(jù)返回給前端的RESTful接口,實(shí)體類都是業(yè)務(wù)中信息傳遞的核心。在Spring AI框架中,我們可以有效地控制AI的回答,以確保其能夠正確映射到實(shí)體類。接下來(lái),我們將探討Spring AI是如何實(shí)現(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 方法作為返回類型。這一變化意味著我們需要重點(diǎn)關(guān)注 entity 的實(shí)現(xiàn)及其在整個(gè)流程中的作用。接下來(lái),讓我們通過(guò)代碼示例來(lái)深入分析這一關(guā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);
}

這里使用了一個(gè)名為 BeanOutputConverter 的轉(zhuǎn)換器。接下來(lái),我們來(lái)詳細(xì)查看一下 doSingleWithBeanOutputConverter 方法的具體實(shí)現(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 方法主要負(fù)責(zé)與第三方 API 的交互過(guò)程。由于我們?cè)谥暗闹v解中已經(jīng)對(duì)聊天調(diào)用API方法的實(shí)現(xiàn)進(jìn)行了詳細(xì)分析,因此這次我們就不再深入探討其具體內(nèi)容,而是集中于方法的核心功能和應(yīng)用場(chǎng)景。

實(shí)體類提示詞限制

在這里,我們來(lái)查看一下 boc.getFormat() 方法。這個(gè)方法返回一段提示詞,而這些提示詞會(huì)根據(jù)不同的類型而有所區(qū)別。為了更好地理解,我們可以具體分析一下單個(gè) Bean 實(shí)體類所對(duì)應(yīng)的提示詞格式。

具體如下:

 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);
    }

這其實(shí)非常簡(jiǎn)單。通過(guò)使用提示詞來(lái)明確限制 AI 返回的格式,可以最大程度地確保其輸出符合我們的要求。這種方式使得 Spring 能夠有效地進(jìn)行解析,而 jsonSchema 則僅僅是我們傳遞的實(shí)體類的各種信息。

封裝實(shí)體類

boc.convert 方法負(fù)責(zé)將數(shù)據(jù)封裝成實(shí)體類的過(guò)程。具體來(lái)說(shuō),它會(huì)接收原始數(shù)據(jù),并通過(guò)內(nèi)部邏輯進(jìn)行轉(zhuǎn)換,以生成符合我們定義的實(shí)體類結(jié)構(gòu)。

從表面上看,我們可以清晰地看出該過(guò)程涉及到 JSON 序列化,它將數(shù)據(jù)封裝成我們所期望的對(duì)象格式。然而,需要注意的是,雖然 AI 的提示詞旨在盡量限制其回復(fù)內(nèi)容,以使其盡可能符合我們的要求,但由于各種因素的影響,我們無(wú)法保證其返回的格式會(huì)完全按照預(yù)設(shè)進(jìn)行。

因此,為了確保程序的穩(wěn)健性和可靠性,在此過(guò)程中引入了異常捕獲機(jī)制。這一機(jī)制能夠有效地處理潛在的格式不一致或錯(cuò)誤,從而確保應(yīng)用在面對(duì)不符合預(yù)期的數(shù)據(jù)時(shí),能夠平穩(wěn)運(yùn)行而不至于崩潰。

函數(shù)回調(diào)

AI目前能夠發(fā)揮一定作用,主要得益于模型的函數(shù)調(diào)用功能。如果僅僅依靠訓(xùn)練模型進(jìn)行聊天回答,其實(shí)際價(jià)值是相對(duì)有限的,因?yàn)檫@種方式的成本非常高,很多企業(yè)難以承受。然而,隨著函數(shù)回調(diào)功能的引入,AI可以實(shí)時(shí)訪問(wèn)和利用各種數(shù)據(jù),包括實(shí)時(shí)數(shù)據(jù)和業(yè)務(wù)數(shù)據(jù),使其能夠根據(jù)提供的信息進(jìn)行更為精準(zhǔn)和有效的回答,從而具備了實(shí)質(zhì)性的業(yè)務(wù)能力。

接下來(lái),我們來(lái)看看Spring AI是如何實(shí)現(xiàn)這一點(diǎn)的。

基本用法

了解了之前的 Spring AI 用法文章后,你大概已經(jīng)掌握了如何創(chuàng)建一個(gè) Function 函數(shù)。接下來(lái),我們將直接深入探討如何將這個(gè)函數(shù)添加到我們的項(xiàng)目中。

@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;
}

在我們的項(xiàng)目中,functions 函數(shù)允許添加多種功能,不僅僅局限于單一工具的調(diào)用。例如,在可視化智能體的應(yīng)用中,如千帆 AppBuilder,我們可以觀察到思考輪數(shù)的運(yùn)用,這其中涉及了多個(gè)工具的調(diào)用。這種方式為我們的智能體提供了更豐富的功能和靈活性。

接下來(lái),我們將進(jìn)行一次函數(shù)的調(diào)用,以實(shí)際展示其效果。

在這里,我們使用了一個(gè)固定的 30 度作為示例值,但你可以在函數(shù)方法內(nèi)部通過(guò)接口調(diào)用其他第三方服務(wù)來(lái)獲取實(shí)時(shí)數(shù)據(jù)。因此,通過(guò)集成外部數(shù)據(jù)源,你可以實(shí)現(xiàn)更為智能和適應(yīng)性強(qiáng)的功能。

源碼分析

還記得我們之前討論過(guò)的內(nèi)容嗎?在回答的最后,我們會(huì)進(jìn)行一次判斷,以確定當(dāng)前的輸出是否為函數(shù)調(diào)用。這一過(guò)程是確保系統(tǒng)能夠準(zhǔn)確識(shí)別和執(zhí)行函數(shù)的重要環(huán)節(jié)。接下來(lái),我們將展示相關(guān)的源碼,以便更深入地理解這一機(jī)制的具體實(shí)現(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()));
}

我也在這里設(shè)置了一個(gè)斷點(diǎn),以便大家可以清楚地看到這一過(guò)程。這一斷點(diǎn)幫助我們確認(rèn),返回的結(jié)果完全是由 AI 生成的。在這個(gè)基礎(chǔ)上,我們會(huì)進(jìn)行進(jìn)一步的判斷,以決定是否需要調(diào)用函數(shù)工具。

接下來(lái),我們將進(jìn)入函數(shù)調(diào)用的過(guò)程。這一步驟至關(guān)重要,因?yàn)楹瘮?shù)的返回值將被再次提供給 AI,作為后續(xù)回答的參考。我們來(lái)看看具體是如何進(jìn)行函數(shù)調(diào)用的。雖然我已經(jīng)找到了相關(guān)的源碼,但為了讓大家更容易理解這個(gè)過(guò)程,我將提供一張可視化的圖片。這張圖片將清晰地展示函數(shù)調(diào)用的流程,以及返回值是如何被整合進(jìn) AI 的回答中的。

發(fā)送這些參數(shù)的原因在于,在發(fā)起請(qǐng)求時(shí)已經(jīng)設(shè)置了相關(guān)限制。以下是我截取下來(lái)的請(qǐng)求參數(shù):

tools=[FunctionTool[type=FUNCTION, function=Function[description=獲取指定地點(diǎn)的天氣情況, 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接口都提供了一個(gè)名為 tools 的參數(shù),用于傳遞我們需要的參數(shù)。以O(shè)penAI為例:

調(diào)用函數(shù)接口

由于我們的函數(shù)實(shí)現(xiàn)了 @FunctionalInterface 接口,因此 call 這一行實(shí)際上會(huì)調(diào)用我們定義的 apply 接口。鑒于我們的參數(shù)是一個(gè)實(shí)體記錄,系統(tǒng)會(huì)對(duì)其進(jìn)行 JSON 轉(zhuǎn)化和封裝,隨后再進(jìn)行調(diào)用。具體過(guò)程如下所示:

 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);
    }

因此,即使所有操作都已結(jié)束,如果在下次 AI 判斷中仍然需要調(diào)用工具,系統(tǒng)將繼續(xù)進(jìn)行循環(huán),直到所有問(wèn)題都得到完整的回答為止。這種設(shè)計(jì)確保了整個(gè)過(guò)程的連貫性和完整性。

總結(jié)

在這次探討中,我們深入挖掘了Spring AI框架如何與Java程序完美結(jié)合,提升業(yè)務(wù)能力。隨著AI技術(shù)的不斷發(fā)展,其在Java應(yīng)用中的整合成為了提升開(kāi)發(fā)效率和用戶體驗(yàn)的關(guān)鍵。我們不僅分析了實(shí)體類的映射與控制,還探討了函數(shù)回調(diào)的強(qiáng)大功能,展示了如何通過(guò)Spring AI有效處理這些復(fù)雜交互。

希望這些分析能夠激發(fā)你對(duì)AI應(yīng)用的靈感,并促使你在自己的項(xiàng)目中大膽嘗試,將AI技術(shù)融入到業(yè)務(wù)流程中。期待未來(lái)能看到大家的創(chuàng)意實(shí)現(xiàn)和應(yīng)用!

完結(jié)撒花!關(guān)于Spring AI的一系列源碼分析到此結(jié)束,以后如果還有感興趣的出發(fā)點(diǎn),我也會(huì)繼續(xù)為大家?guī)?lái)分析!

到此這篇關(guān)于深入解析Spring AI框架如何在Java應(yīng)用中實(shí)現(xiàn)智能化交互的關(guān)鍵的文章就介紹到這了,更多相關(guān)springAI智能化交互內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot入門之集成Druid的方法示例

    SpringBoot入門之集成Druid的方法示例

    這篇文章主要介紹了SpringBoot入門之集成Druid的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • 基于java SSM springboot實(shí)現(xiàn)抗疫物質(zhì)信息管理系統(tǒng)

    基于java SSM springboot實(shí)現(xiàn)抗疫物質(zhì)信息管理系統(tǒng)

    這篇文章主要介紹了基于JAVA SSM springboot實(shí)現(xiàn)的抗疫物質(zhì)信息管理系統(tǒng),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • Java中實(shí)例初始化和靜態(tài)初始化的過(guò)程詳解

    Java中實(shí)例初始化和靜態(tài)初始化的過(guò)程詳解

    Java代碼初始化塊是Java語(yǔ)言中的一個(gè)非常重要的概念。初始化塊負(fù)責(zé)在創(chuàng)建對(duì)象時(shí)進(jìn)行一些必要的操作,例如設(shè)置對(duì)象的初始狀態(tài)、初始化成員變量等。初始化塊被分為實(shí)例初始化塊和靜態(tài)初始化塊兩種類型。本文詳細(xì)介紹了初始化的過(guò)程,需要的朋友可以參考下
    2023-05-05
  • Mybatis-Plus開(kāi)發(fā)提速器mybatis-plus-generator-ui詳解

    Mybatis-Plus開(kāi)發(fā)提速器mybatis-plus-generator-ui詳解

    這篇文章主要介紹了Mybatis-Plus開(kāi)發(fā)提速器mybatis-plus-generator-ui,本文簡(jiǎn)要介紹一款基于Mybatis-Plus的代碼自助生成器,文章通過(guò)實(shí)例集成的方式來(lái)詳細(xì)講解mybatis-plus-generator-ui,從相關(guān)概念到實(shí)際集成案例,以及具體的擴(kuò)展開(kāi)發(fā)介紹,需要的朋友可以參考下
    2022-11-11
  • SpringBoot整合Freemarker的基本步驟

    SpringBoot整合Freemarker的基本步驟

    這篇文章主要介紹了SpringBoot整合Freemarker的基本步驟,添加依賴及添加相關(guān)配置的實(shí)例代碼詳解,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • Java Web 簡(jiǎn)單的分頁(yè)顯示實(shí)例代碼

    Java Web 簡(jiǎn)單的分頁(yè)顯示實(shí)例代碼

    這篇文章主要介紹了Java Web 簡(jiǎn)單的分頁(yè)顯示實(shí)例代碼的相關(guān)資料,本文通過(guò),計(jì)算總的頁(yè)數(shù)和查詢指定頁(yè)數(shù)據(jù)兩個(gè)方法實(shí)現(xiàn)分頁(yè)效果,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • Java中死鎖的原理實(shí)戰(zhàn)分析

    Java中死鎖的原理實(shí)戰(zhàn)分析

    這篇文章主要介紹了Java中死鎖的原理,結(jié)合具體案例形式分析了java死鎖形成的相關(guān)原理,需要的朋友可以參考下
    2019-08-08
  • IDEA 阿里JAVA規(guī)范插件的具體使用

    IDEA 阿里JAVA規(guī)范插件的具體使用

    這篇文章主要介紹了IDEA 阿里JAVA規(guī)范插件的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • java?ReentrantLock并發(fā)鎖使用詳解

    java?ReentrantLock并發(fā)鎖使用詳解

    這篇文章主要為大家介紹了java?ReentrantLock并發(fā)鎖使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Java?Optional的判空操作詳解

    Java?Optional的判空操作詳解

    JAVA在1.8版本推出Optional,官方文檔將其描述為可能包含或不包含非空值的容器對(duì)象,目前Optional用于避免程序出現(xiàn)異常NullPointerException,感興趣的可以了解一下
    2022-09-09

最新評(píng)論