- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
今天我们的Spring AI源码分析主题即将结束。我已经对自己感兴趣的基本内容进行了全面的审视,并将这些分析分享给大家。如果你对这个主题感兴趣,可以阅读以下几篇文章。每篇文章都层层递进,深入探讨相关内容。考虑到长文可能让大家感到疲惫,我采用了逐步推进的方式,确保每一篇都简明易懂,便于理解。希望能为你们提供有价值的参考! 。
Spring AI的基本用法:https://www.cnblogs.com/guoxiaoyu/p/18284842 。
Spring.3版本自动装配机制的演变与实践:https://www.cnblogs.com/guoxiaoyu/p/18384642 。
SpringBoot.3中的aot.factories到底有什么用:https://www.cnblogs.com/guoxiaoyu/p/18434660 。
Spring AI的阻塞式请求与响应机制的核心逻辑:https://www.cnblogs.com/guoxiaoyu/p/18440488 。
Spring AI的流式回答源码分析:https://www.cnblogs.com/guoxiaoyu/p/18440684 。
今天我们的主题将聚焦于最后一步:如何将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 实体类所对应的提示词格式.
具体如下:
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 方法负责将数据封装成实体类的过程。具体来说,它会接收原始数据,并通过内部逻辑进行转换,以生成符合我们定义的实体类结构.
从表面上看,我们可以清晰地看出该过程涉及到 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,我们可以观察到思考轮数的运用,这其中涉及了多个工具的调用。这种方式为我们的智能体提供了更丰富的功能和灵活性.
接下来,我们将进行一次函数的调用,以实际展示其效果.
在这里,我们使用了一个固定的 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 生成的。在这个基础上,我们会进行进一步的判断,以决定是否需要调用函数工具.
接下来,我们将进入函数调用的过程。这一步骤至关重要,因为函数的返回值将被再次提供给 AI,作为后续回答的参考。我们来看看具体是如何进行函数调用的。虽然我已经找到了相关的源码,但为了让大家更容易理解这个过程,我将提供一张可视化的图片。这张图片将清晰地展示函数调用的流程,以及返回值是如何被整合进 AI 的回答中的.
发送这些参数的原因在于,在发起请求时已经设置了相关限制。以下是我截取下来的请求参数:
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为例:
由于我们的函数实现了 @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技术融入到业务流程中。期待未来能看到大家的创意实现和应用! 。
完结撒花!关于Spring AI的一系列源码分析到此结束,以后如果还有感兴趣的出发点,我也会继续为大家带来分析! 。
我是努力的小雨,一名 Java 服务端码农,潜心研究着 AI 技术的奥秘。我热爱技术交流与分享,对开源社区充满热情。同时也是一位腾讯云创作之星、阿里云专家博主、华为云云享专家、掘金优秀作者.
💡 我将不吝分享我在技术道路上的个人探索与经验,希望能为你的学习与成长带来一些启发与帮助.
🌟 欢迎关注努力的小雨!🌟 。
最后此篇关于深入解析SpringAI框架:在Java应用中实现智能化交互的关键的文章就讲到这里了,如果你想了解更多关于深入解析SpringAI框架:在Java应用中实现智能化交互的关键的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在 python 交互中,有没有办法在每次输入命令后自动从 python 文件执行方法? 例如:如果我有一个打印文件信息的方法,但我不想不断调用该方法,我怎样才能让它在 python 交互中的每个命令
当你使用Edge等浏览器或系统软件播放媒体时,Windows控制中心就会出现相应的媒体信息以及控制播放的功能,如图。 SMTC (SystemMedia
我在主菜单上使用标准的剪切,复制,粘贴操作。它们具有快捷键Ctrl-X,Ctrl-C和Ctrl-V。 当我打开模态表单时FindFilesForm.ShowModal,然后所有快捷方式都可以从表单中使
这是我想要实现的目标:打开一个 shell(korn 或 bash,没关系),从那个 shell,我想打开一个 ssh 连接(ssh user@host)。在某些时候,可能会提示我输入密码,或者可能会
我正在测试在C / C++程序中嵌入Python,但是我缺乏理解。 测试程序很简单: 初始化解释器; 从启动Timer的文件中执行python脚本(每0.1秒增加一个变量); 等待5秒(C++); 从
我正在尝试用java创建Excel文件。现在,我正在使用 Apache POI 库创建文件并将其保存到本地驱动器。有没有办法启动 Excel 并填充数据而不将其保存到硬盘驱动器? 最佳答案 考虑 Do
我有一个黑盒函数,它接受大约 10 个整数输入。该函数返回一个 pandas 数据框,我想捕获输出窗口(通过使用 bbwidget.children)并显示在布局中的其他地方。到目前为止,交互/交互似
我正在体验新的 QQuickWidget。我如何在 QQuickWidget 和 C++ 之间进行交互? C++ QQuickWidget *view = new QQuickWidget(); vi
我正在尝试设置一个使用 TWAIN 的 C# 应用程序 example from code project 除了我需要将 Form 转换为 IMessageFilter 和调用 IMessageFil
我想在使用 redis 的 python 中编写应用程序。我用谷歌搜索,但找不到我的问题的任何结果。通常,我这样做: import redis rs = redis.Redis('localhost'
最近做一个小项目,网页中嵌入google maps,输入经纬度坐标可以定位地图位置并加注标记,点击标记获取远端摄像头数据并在视频窗口实现播放。在实际操作过程中,由于经纬度数据和视频登录的用户名密码数
我需要在这里澄清一些事情: 我有一个网站,每次在浏览器中重新加载网站时都会更新两个变量的值。这个页面显然是一个 HTML 页面,但变量是由 javascript 函数更新的。此页面在我的服务器上运行。
我注意到,auto忽略双条件。这是一个简化的示例: Parameter A B : Prop. Parameter A_iff_B : A B. Theorem foo1: A -> B. Proo
使用 interactive使用多个小部件相当简单,例如: interactive(foo, w1=widget1, w2=widget2, ...) 但是,我想使用 VBox 和 HBox 的组合以
我们提供类似于 imagemagick 的浏览器页面 JavaScript,可帮助人们将图像转换为不同大小和格式。但是,它需要网页交互。 是否可以让人们自动进行这种交互——无需将图像发送到我们的服务器
大家好,我正在尝试制作一个具有大量动画和效果的交互式 UI。 但我不知道是否: 核心图形可以支持用户交互(触摸、拖动等) 核心图形支持对象旋转 核心图形可以以任何方式与 UIKit 和核心动画交互 谢
这是获取维基百科上一篇关于高盛的文章的介绍的链接。 http://en.wikipedia.org/w/api.php?action=query&prop=extracts&titles=Goldma
我正在尝试编写一个 AppleScript 来查询 iCal 并在任何日历中查找给定日期的所有事件。 我首先编写了一个简单的脚本,它对给定日历中的每个事件执行一些简单的操作: tell applica
我在我的 hudson 服务器上使用 jira 插件。将代码提交到 svn 时,我的提交注释包含在我的 jira 问题中,但有什么办法可以将注释归因于执行提交的实际人员,而不是让一个全局 jira 用
我正在播放一段视频来装饰我的用户界面。我隐藏了 AV 播放器控件,但用户仍然可以控制视频。例如,他们可以使用滑动手势快进或快退。 这让我特别惊讶,因为 AVPlayerView 上面有一个覆盖 Vie
我是一名优秀的程序员,十分优秀!