深入解析Spring AI框架:在Java应用中实现智能化交互的关键

众所周知,Java是一种面向对象的编程语言,因此不论我们调用什么AI接口,从业务的角度来看,它本质上只是一个接口,而AI则充当了一个第三方对接平台。然而,值得注意的是,AI的聊天回复往往不适用于对象,因为这些回复无法直接返回格式化的JSON数据。这一问题导致Spring无法将其转化为实体类,从而无法真正融入业务流程。

今天,我们将探讨Spring AI框架是如何有效解决这一挑战的。通过深入分析框架的设计和实现,我们希望为大家展示如何将AI能力顺利整合到Java应用中,推动业务的进一步发展。

除此之外,function call 函数回调也是AI技术的一个重要特性。那么,Spring AI是如何应对这一挑战的呢?今天,我们将深入探讨这个问题,解析Spring AI框架如何有效处理函数回调,从而增强AI与Java程序之间的交互能力。

实体化类

实体类在Java程序中扮演着不可或缺的角色,无论是进行内部操作,还是将数据返回给前端的RESTful接口,实体类都是业务中信息传递的核心。在Spring AI框架中,我们可以有效地控制AI的回答,以确保其能够正确映射到实体类。接下来,我们将探讨Spring AI是如何实现这一功能的,基本用法如下:

@GetMapping("/ai-Entity")
ActorFilms generationByEntity() {ActorFilms actorFilms = chatClient.prompt().user("Generate the filmography for a random actor.").call().entity(ActorFilms.class);return actorFilms;
}

源码分析

在这里,我们不再直接调用 content 方法,而是选择使用 entity 方法作为返回类型。这一变化意味着我们需要重点关注 entity 的实现及其在整个流程中的作用。接下来,让我们通过代码示例来深入分析这一关键部分:

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 方法的具体实现。

        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 的交互过程。由于我们在之前的讲解中已经对聊天调用API方法的实现进行了详细分析,因此这次我们就不再深入探讨其具体内容,而是集中于方法的核心功能和应用场景。

实体类提示词限制

在这里,我们来查看一下 boc.getFormat() 方法。这个方法返回一段提示词,而这些提示词会根据不同的类型而有所区别。为了更好地理解,我们可以具体分析一下单个 Bean 实体类所对应的提示词格式。

image

具体如下:

    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 方法负责将数据封装成实体类的过程。具体来说,它会接收原始数据,并通过内部逻辑进行转换,以生成符合我们定义的实体类结构。

image

从表面上看,我们可以清晰地看出该过程涉及到 JSON 序列化,它将数据封装成我们所期望的对象格式。然而,需要注意的是,虽然 AI 的提示词旨在尽量限制其回复内容,以使其尽可能符合我们的要求,但由于各种因素的影响,我们无法保证其返回的格式会完全按照预设进行。

因此,为了确保程序的稳健性和可靠性,在此过程中引入了异常捕获机制。这一机制能够有效地处理潜在的格式不一致或错误,从而确保应用在面对不符合预期的数据时,能够平稳运行而不至于崩溃。

函数回调

AI目前能够发挥一定作用,主要得益于模型的函数调用功能。如果仅仅依靠训练模型进行聊天回答,其实际价值是相对有限的,因为这种方式的成本非常高,很多企业难以承受。然而,随着函数回调功能的引入,AI可以实时访问和利用各种数据,包括实时数据和业务数据,使其能够根据提供的信息进行更为精准和有效的回答,从而具备了实质性的业务能力。

接下来,我们来看看Spring AI是如何实现这一点的。

基本用法

了解了之前的 Spring AI 用法文章后,你大概已经掌握了如何创建一个 Function 函数。接下来,我们将直接深入探讨如何将这个函数添加到我们的项目中。

@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 函数允许添加多种功能,不仅仅局限于单一工具的调用。例如,在可视化智能体的应用中,如千帆 AppBuilder,我们可以观察到思考轮数的运用,这其中涉及了多个工具的调用。这种方式为我们的智能体提供了更丰富的功能和灵活性。

接下来,我们将进行一次函数的调用,以实际展示其效果。

image

在这里,我们使用了一个固定的 30 度作为示例值,但你可以在函数方法内部通过接口调用其他第三方服务来获取实时数据。因此,通过集成外部数据源,你可以实现更为智能和适应性强的功能。

源码分析

还记得我们之前讨论过的内容吗?在回答的最后,我们会进行一次判断,以确定当前的输出是否为函数调用。这一过程是确保系统能够准确识别和执行函数的重要环节。接下来,我们将展示相关的源码,以便更深入地理解这一机制的具体实现:

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 生成的。在这个基础上,我们会进行进一步的判断,以决定是否需要调用函数工具。

image

接下来,我们将进入函数调用的过程。这一步骤至关重要,因为函数的返回值将被再次提供给 AI,作为后续回答的参考。我们来看看具体是如何进行函数调用的。虽然我已经找到了相关的源码,但为了让大家更容易理解这个过程,我将提供一张可视化的图片。这张图片将清晰地展示函数调用的流程,以及返回值是如何被整合进 AI 的回答中的。

image

发送这些参数的原因在于,在发起请求时已经设置了相关限制。以下是我截取下来的请求参数:

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 的参数,用于传递我们需要的参数。以OpenAI为例:

image

调用函数接口

由于我们的函数实现了 @FunctionalInterface 接口,因此 call 这一行实际上会调用我们定义的 apply 接口。鉴于我们的参数是一个实体记录,系统会对其进行 JSON 转化和封装,随后再进行调用。具体过程如下所示:

    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 判断中仍然需要调用工具,系统将继续进行循环,直到所有问题都得到完整的回答为止。这种设计确保了整个过程的连贯性和完整性。

总结

在这次探讨中,我们深入挖掘了Spring AI框架如何与Java程序完美结合,提升业务能力。随着AI技术的不断发展,其在Java应用中的整合成为了提升开发效率和用户体验的关键。我们不仅分析了实体类的映射与控制,还探讨了函数回调的强大功能,展示了如何通过Spring AI有效处理这些复杂交互。

希望这些分析能够激发你对AI应用的灵感,并促使你在自己的项目中大胆尝试,将AI技术融入到业务流程中。期待未来能看到大家的创意实现和应用!

文章转载自:努力的小雨

原文链接:https://www.cnblogs.com/guoxiaoyu/p/18441709

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/62077.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

idea 自动导包,并且禁止自动导 *(java.io.*)

自动导包配置 进入 idea 设置&#xff0c;可以按下图所示寻找位置&#xff0c;也可以直接输入 auto import 快速定位到配置。 Add unambiguous imports on the fly&#xff1a;自动帮我们优化导入的包Optimize imports on the fly&#xff1a;自动去掉一些没有用到的包 禁止导…

基于C++实现的(控制台)双人俄罗斯方块小游戏

基于win32控制台应用程序的双人俄罗斯方块小游戏 1. 课题概述 1.1 课题目标和主要内容 使用visual studio 2015在win32控制台应用程序下用多线程实现双人同时进行俄罗斯方块的桌面游戏。最终将要完成的效果如图1.1所示&#xff0c;左右共两片工作区&#xff0c;也是游戏的主…

Python subprocess.run 使用注意事项,避免出现list index out of range

在执行iOS UI 自动化专项测试的时候&#xff0c;在运行第一遍的时候遇到了这样的错误&#xff1a; 2024-12-04 20:22:27 ERROR conftest pytest_runtest_makereport 106 Test test_open_stream.py::TestOpenStream::test_xxx_open_stream[iPhoneX-xxx-1-250] failed with err…

力扣1401. 圆和矩形是否有重叠

用矢量计算&#xff1a; class Solution { public:bool checkOverlap(int radius, int xCenter, int yCenter, int x1, int y1, int x2, int y2) {//矩形中心float Tx(float)(x1x2)/2;float Ty(float)(y1y2)/2;//强行进行对称操作&#xff0c;只考虑第一象限if(xCenter<Tx)…

信号和槽思维脑图+相关练习

将登录框中的取消按钮使用信号和槽的机制&#xff0c;关闭界面。 将登录按钮使用信号和槽连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否为"123456",如果账号密码匹配成功&#xff0c;当前界面关…

第一部分:基础知识 2. SQL基础 --[MySQL轻松入门教程]

第一部分:基础知识 2. SQL基础 --[MySQL轻松入门教程] SQL(Structured Query Language)是一种用于管理和处理关系型数据库的标准语言。它被广泛应用于各种数据库系统,如MySQL, PostgreSQL, Oracle, SQL Server等。下面是一些SQL的基础知识和常用操作示例。 1.SQL简介 SQ…

《Clustering Propagation for Universal Medical Image Segmentation》CVPR2024

摘要 这篇论文介绍了S2VNet&#xff0c;这是一个用于医学图像分割的通用框架&#xff0c;它通过切片到体积的传播&#xff08;Slice-to-Volume propagation&#xff09;来统一自动&#xff08;AMIS&#xff09;和交互式&#xff08;IMIS&#xff09;医学图像分割任务。S2VNet利…

源码可运行-PHP注册登录源码,PHP实现登陆后才能访问页面

最近有一个项目需要实现会员注册和页面登陆后才能访问&#xff0c;所以简单的HTML是无法实现的&#xff0c;就必须通过PHP、html和Mysql来实现&#xff0c;先给大家看一下登录和注册页的效果图。&#xff08;注册完成后会自动跳转到登录窗口&#xff0c;即使A用户登陆后分享了网…

性能测试常见面试问题和答案

一、有没有做过性能测试&#xff0c;具体怎么做的 性能测试是有做过的&#xff0c;不过我们那个项目的性能做得不多&#xff0c;公司要求也不严格。一般SE 给我们相关的性能需求&#xff0c;首先我们需要对性能需求进行场景分析与设计&#xff0c;这里&#xff0c;其实主要就是…

二百七十八、ClickHouse——将本月第一天所在的那一周视为第一周,无论它是从周几开始的,查询某个日期是本月第几周

一、目的 ClickHouse指标表中有个字段week_of_month&#xff0c;含义是这条数据属于本月第几周。 而且将本月第一天所在的那一周视为第一周&#xff0c;无论它是从周几开始的。比如2024-12-01是周日&#xff0c;即12月第一周。而2024-12-02是周一&#xff0c;即12月第二周 二…

【OCR】——端到端文字识别GOT-OCR2.0不香嘛?

代码&#xff1a;https://github.com/Ucas-HaoranWei/GOT-OCR2.0?tabreadme-ov-file 在线demo&#xff1a;https://huggingface.co/spaces/stepfun-ai/GOT_official_online_demo 0.前言 最早做ocr的时候&#xff0c;就在想如何能做一个端到端的模型&#xff0c;就不用先检测再…

AndroidStudio-常见界面控件

一、Button package com.example.review01import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button import android.widget.TextViewclass Review01Activity : AppCompatActivity() {override fun onCreate(savedInstanceStat…

网络安全中的 SOC 是什么?

当今世界&#xff0c;网络威胁日益增多&#xff0c;确保网络安全已成为各种规模企业的首要任务。网络安全讨论中经常出现的一个术语是 SOC&#xff0c;即安全运营中心的缩写。但网络安全中的 SOC 是什么呢&#xff1f; SOC在防御网络威胁、管理安全事件和全天候监控系统方面发…

智选球员:运用动态规划提升棒球队的签约效益

目录 一、签约棒球自由球员 二、分析和理解 &#xff08;一&#xff09;问题背景回顾 &#xff08;二&#xff09;目标确定 &#xff08;三&#xff09;约束条件分析 &#xff08;四&#xff09;明确输出要求 三、动态规划&#xff08;Dynamic Programming&#xff09;解…

Lua面向对象实现

Lua中的面向对象是通过表&#xff08;table&#xff09;来模拟类实现的&#xff0c;通过setmetatable(table,metatable)方法&#xff0c;将一个表设置为当前表的元表&#xff0c;之后在调用当前表没有的方法或者键时&#xff0c;会再查询元表中的方法和键&#xff0c;以此来实现…

航空美食新升级,光明肉业携手东航食品打造经典辣肉面新篇章

在航空餐饮日益注重品质与创新的大环境下&#xff0c;各大航空公司纷纷在美食领域下功夫&#xff0c;力求为乘客提供更加多元化、高品质的餐饮体验。近日&#xff0c;东航那碗面再次成为行业焦点&#xff0c;其经典辣肉面在光明肉业的助力下实现了“创新”升级&#xff0c;为乘…

在.NET 6中使用Serilog收集日志

此示例的完整详细信息&#xff1a;https://download.csdn.net/download/hefeng_aspnet/89998498 Serilog 是一个日志库&#xff0c;它提供对文件、控制台和其他几个地方的记录。它易于配置&#xff0c;并且具有干净且易于使用的界面。 Serilog具有无与伦比的输出目的地选择&…

STM32 HAL库开发学习5. 系统滴答定时器

STM32 HAL库开发学习5. 系统滴答定时器 一、滴答定时器概述1. 概述2. 时钟源3. 寄存器&#xff08;1&#xff09;控制与状态寄存器 STK_CTRL&#xff08;2&#xff09;重载寄存器 STK_LOAD&#xff08;3&#xff09;当前值寄存器 STK_VAL 二、HAL库滴答定时器初始化三、SysTick…

智慧零售时代传统供应链的痛点与数字化变革:定制开发 AI 智能名片 S2B2C 商城系统的应用与影响

摘要&#xff1a;本文深入探讨了智慧零售时代传统供应链所面临的痛点&#xff0c;分析了在该时代背景下打通线上线下渠道以及整合资源的关键需求。阐述了传统零售供应链若线上线下渠道独立、数据不流通将导致的库存管理与物流效率问题&#xff0c;并强调其必须进行数字化变革以…

国家信息中心单志广:智慧城市转型中的数据要素价值释放

今日&#xff0c;由中国电信集团主办的2024数字科技生态大会数据要素合作论坛在广州市举办。国家发改委国家信息中心信息化和产业发展部主任单志广在论坛发展主旨演讲&#xff1a;智慧城市转型中的数据要素价值释放&#xff0c;主要包括发展新形势、数据新要素、数据新产权、数…