【Spring AI】聊天API-OpenAI-Function Call

文章目录

  • Function Calling
    • 工作原理
    • 快速上手
      • 将函数注册为 Bean
        • 纯 Java 函数实现(Plain Java Functions)
        • FunctionCallback Wrapper
      • Specifying functions in Chat Options
      • Register/Call Functions with Prompt Options
    • 附录:
      • Spring AI 函数调用流程
      • OpenAI API 函数调用流程

Function Calling

您可以向 OpenAiChatClient 注册自定义 Java 函数,并让 OpenAI 模型输出包含参数的 JSON 对象,智能地选择调用一个或多个已注册函数。这允许您将LLM功能与外部工具和 API 连接起来。OpenAI 模型经过训练,可以检测何时应调用函数,并使用符合函数协议的 JSON 进行响应。
OpenAI API 不直接调用函数;相反,模型会生成符合函数协议的 JSON,您可以使用该 JSON 在代码中调用函数并将结果返回给模型以完成对话。
Spring AI 提供了灵活且用户友好的注册和调用自定义函数的方式。通常,自定义函数需要提供函数name、description和函数调用signature(作为 JSON 架构),以便让模型知道函数需要哪些参数。description有助于模型了解何时调用函数。
作为开发人员,您需要实现一个函数,该函数接收从 AI 模型返回的函数调用参数,并将函数的结果再返回给模型。您的函数也可以反过来调用其他第三方服务来提供结果。
Spring AI 使这变得简单,只需定义一个返回java.util.Function的@Bean定义,在调用ChatClient的时候,设置这个 Bean 的名字到ChatClient的参数中。
当下,Spring 使用适配器包装您的 POJO(函数),该代理支持与 AI 模型进行交互,从而避免编写繁琐的代码。底层基础结构的基础是 FunctionCallback.java 接口和配套的 FunctionCallbackWrapper.java实用程序类,以简化 Java 回调函数的实现和注册。

工作原理


假设我们希望 AI 模型处理它没有的信息进行响应,例如让大模型提供某个位置的实时温度。
我们可以为 AI 模型提供有关我们自己函数的元数据,它可以结合您的提示词和这些元数据来判断是否调用用户定义的函数检索该信息。
例如,如果在处理提示词期间,AI 模型确定它需要给定地域的实时温度,它将启动一个请求/响应交互的服务器端。AI 模型调用客户端。AI 模型以 JSON 格式提供方法调用详细信息给客户端,客户端负责执行该函数并将函数返回的数据返回给 AI模型。
模型与客户端的交互在下面的 Spring AI 函数调用流程图 中进行了说明。
Spring AI 大大简化了支持函数调用所需的代码。它为您代理函数调用对话。您只需将函数定义为@Bean,然后在提示词参数(options)中提供函数的 Bean 名称即可。您还可以在提示词中引用多个函数 Bean 名称。


快速上手

让我们创建一个聊天机器人,通过调用我们自己的函数来回答问题。为了支持聊天机器人的响应,我们将注册自己的函数,该函数获取一个位置并返回该位置的当前天气。
当模型对提示词的返回信息中有需要回答问题如"What’s the weather like in Boston?",AI模型将调用客户端,提供位置值作为要传递给函数的参数。此类似 RPC 的数据以 JSON 形式传递。
我们的函数可以基于一些 SaaS 的天气服务 API 实现,将天气响应返回给模型以完成对话。在此示例中,我们将使用一个名为“ MockWeatherService ” 的类进行硬编码来简单实现,该实现对不同位置的温度进行硬编码。
天气服务 API MockWeatherService.java 如下所示:

public class MockWeatherService implements Function<Request, Response> {

	public enum Unit { C, F }
	public record Request(String location, Unit unit) {}
	public record Response(double temp, Unit unit) {}

	public Response apply(Request request) {
		return new Response(30.0, Unit.C);
	}
}

将函数注册为 Bean

OpenAI 章节中自动装配 机制,可以让您通过多种方式在 Spring 上下文中将自定义函数注册为 bean。
我们需要对POJO的参数做友好的描述。

纯 Java 函数实现(Plain Java Functions)

在这种方法中,您可以在应用程序上下文中定义@Beans,就像定义任何其他 Spring 托管对象一样。
在内部,Spring AI ChatClient 将创建一个 FunctionCallbackWrapper 包装类实例,该实例添加通过 AI 模型调用它的逻辑。@Bean的名称将转换成一个ChatOption 。

@Configuration
static class Config {

	@Bean
	@Description("Get the weather in location") // function description
	public Function<MockWeatherService.Request, MockWeatherService.Response> weatherFunction1() {
		return new MockWeatherService();
	}
	...
}

@Description注释是可选的,它提供了函数描述(2),可帮助模型了解何时调用函数。这是一个重要的属性,可帮助 AI 模型确定要调用的客户端函数。
提供函数描述的另一个注解是 @JacksonDescription , 这个注解可以作用在MockWeatherService.Request 上面:

@Configuration
static class Config {

	@Bean
	public Function<Request, Response> currentWeather3() { // (1) bean name as function name.
		return new MockWeatherService();
	}
	...
}

@JsonClassDescription("Get the weather in location") // (2) function description
public record Request(String location, Unit unit) {}

最佳做法是对请求对象使用注解进行描述,以便该函数的生成 JSON 架构时候尽可能具有描述性,帮助 AI 模型可以正确选择要调用的函数。
FunctionCallbackWithPlainFunctionBeanIT.java 演示了这种方法。

FunctionCallback Wrapper

注册函数的另一种方法是创建 FunctionCallbackWrapper 包装器,如下所示:

@Configuration
static class Config {

	@Bean
	public FunctionCallback weatherFunctionInfo() {

		return new FunctionCallbackWrapper<>("CurrentWeather", // (1) function name
				"Get the weather in location", // (2) function description
				(response) -> "" + response.temp() + response.unit(), // (3) Response Converter
				new MockWeatherService()); // function code
	}
	...
}

它包装第 3 方函数MockWeatherService并将其注册为 OpenAiChatClient 的 CurrentWeather 函数 。它还提供了函数描述 (2)参数 和可选的响应转换器 (3)参数(用于将响应转换为模型预期的文本)。

默认情况下,响应转换器是对 Response 对象执行 JSON 序列化操作。

FunctionCallbackWrapper 基于 MockWeatherService.Request 类解析函数调用签名。

Specifying functions in Chat Options

要让模型知道并调用您的 CurrentWeather 函数,您需要在提示词中启用它:

OpenAiChatClient chatClient = ...

UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?");

ChatResponse response = chatClient.call(new Prompt(List.of(userMessage),
		OpenAiChatOptions.builder().withFunction("CurrentWeather").build())); // (1) Enable the function

logger.info("Response: {}", response);

上面的用户问题将触发 3 次CurrentWeather函数调用(每个城市一个),最终响应如下:

Here is the current weather for the requested cities:
- San Francisco, CA: 30.0°C
- Tokyo, Japan: 10.0°C
- Paris, France: 15.0°C

FunctionCallbackWrapperIT.java 测试演示了这种方法。

Register/Call Functions with Prompt Options

除了自动配置之外,您还可以在提示词中动态注册回调函数:

OpenAiChatClient chatClient = ...

UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?");

var promptOptions = OpenAiChatOptions.builder()
	.withFunctionCallbacks(List.of(new FunctionCallbackWrapper<>(
		"CurrentWeather", // name
		"Get the weather in location", // function description
		new MockWeatherService()))) // function code
	.build();

ChatResponse response = chatClient.call(new Prompt(List.of(userMessage), promptOptions));

默认情况下,会启用提示词内注册的函数。

这种方法允许用户动态输入想要调用的函数。
FunctionCallbackInPromptIT.java 集成测试提供了一个完整的示例,说明如何向 OpenAiChatClient 注册函数并在提示词中使用它。


附录:


Spring AI 函数调用流程

下图说明了 OpenAiChatClient 函数调用的流程:
在这里插入图片描述

OpenAI API 函数调用流程

下图说明了 OpenAI API Function Calling 的流程:
在这里插入图片描述

OpenAiApiToolFunctionCallIT.java 提供了使用 OpenAI API 函数调用的完整示例。它基于 OpenAI Function Calling 教程。


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL使用Sequence创建唯一主键

目录 第一章、快速了解Sequence1.1&#xff09;是什么&#xff1f;为什么使用1.2&#xff09;Sequence和自增主键的区别 第二章、在MySQL中使用Sequence2.1&#xff09;创建mysql_sequence表2.1.1&#xff09;创建表2.1.2&#xff09;插入数据 2.2&#xff09;创建函数2.2.1&am…

Kubernetes学习-核心概念篇(三) 核心概念和专业术语

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Kubernetes渐进式学习-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 1. 前言 在前面两篇文章我们简单介绍了什么是K8S&#xff0c;以及K8S的…

Vue面试经验

Vue部分 Vue编译时声明周期的执行顺序 Vue中父子组件渲染顺序&#xff08;同步引入子组件&#xff1a;import Son from ‘/components/son’ &#xff09; 父子组件编译时的生命周期执行顺序 这里修改data数据时也修改了dom&#xff0c;如过知识通过按钮对数据进行操作&…

MySQL8.0 msi版本安装教程

MySQL8.0 msi 版本安装教程 1> 官网下载安装包 2> 安装MySQL 2.1双击打开下载的安装包&#xff0c;进入到下面这个页面&#xff0c;选择 Custom 选项&#xff0c;之后&#xff0c;点击next 说明&#xff1a; 2.2 选择所需产品&#xff0c;更改安装位置(当然也可以默认安…

springCahe框架

基于springboot项目 介绍:Spring Cache 是一个框架&#xff0c;实现了基于注解的缓存功能&#xff0c;只需要简单地加一个注解&#xff0c;就能实现缓存功能。 Spring Cache 提供了一层抽象&#xff0c;底层可以切换不同的缓存实现&#xff0c;例如&#xff1a; EHCache Caff…

Java-字符集-Unicode字符集

1 需求 Unicode 字符集UTF-8、UTF-16、UTF-32字符编码 2 接口 3 示例 4 参考资料

新媒体运营-----短视频运营-----PR视频剪辑----软件基础

新媒体运营-----短视频运营-----PR视频剪辑-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/138079659 文章目录 1.1 PR软件重置与初始化设置1.2 新建项目及序列设置1.3 PR工作区的管理方法1.4 导入4K超高清视频并与ME配合工作1…

【C语言】编译与链接

1.翻译环境与运行环境 在ANSI C的任何一种实现中&#xff0c;存在两个不同的环境。 1.翻译环境&#xff0c;在这个环境中源代码被转换为可执行的机器指令&#xff08;二进制指令&#xff09; 2.执行环境&#xff0c;它用于实际执行代码 2.翻译环境 那么翻译环境是怎么将源代码…

Linux(文件系统和日志分析)

目录 1.inode & block​编辑 1.1 inode的内容 1.3 inode的号码 1.4 inode的大小 1.5 inode的特殊作用 1.6 模拟inode号被占满 2. 链接文件 3.文件恢复 3.1 修复EXT类型的文件 3.1.1 EXT类型文件恢复步骤 3.2 修复XFS类型的文件 1.inode & block 1.1 in…

算法应用实例:最大子列和问题

给定N个整数的序列{A1,A2,……AN}&#xff0c;求函数的最大值。 分析&#xff1a;求该序列中最大的连续子列和&#xff0c;若函数最后为负数&#xff0c;返回0作为程序结束。 1.算法1 /*命名为MaxSubseqSum1&#xff0c;A[]:输入整数序列&#xff0c;N&#xff1a;整数序列里面…

7-29 删除字符串中的子串

题目链接&#xff1a;7-29 删除字符串中的子串 一. 题目 1. 题目 2. 输入输出样例 3. 限制 二、代码&#xff08;python&#xff09; 1. 代码实现 str1 input().split(\n)[0] str2 input().split(\n)[0] while str2 in str1:str1 str1.replace(str2, "") // 删…

第4篇:创建Nios II工程之Hello_World<三>

Q&#xff1a;接着我们再来完成Nios II软件工程设计部分。 A&#xff1a;从Quartus Tools选择Nios II Software Build Tools for Eclipse&#xff0c;打开Nios II SBT软件&#xff0c;Workspace指定到hello_world工程的software文件夹路径&#xff1b;再从File-->New-->…

使用STM32CubeMX对STM32F4的CAN1/2/3配置及接收中断开启

目录 1. CAN配置1.1引脚&#xff08;STM32F413VGT6-LQFP100&#xff09;1.2 时钟1.3 RCC配置1.4 CAN1配置1.5 CAN2配置1.6 CAN3配置1.7 输出设置 2. CAN代码2.1 CAN初始化2.2 CAN滤波器设置2.3 CAN使能2.4 激活中断2.5 CAN发送函数2.6 CAN回调函数2.7 main之后的代码 1. CAN配置…

数据分析:生存分析原理和应用实例

介绍 生存分析的目的是分析某个时间点的“生存概率”是多少。基于这样的研究目的,需要提供生存数据,它是一种由不同的开始时间和结束时间组成的事件-时间的数据,比如在癌症研究领域,研究手术到死亡的过程、治疗到疾病进展等等。 在开展生存分析前,需要了解什么是删失(c…

二维码门楼牌管理应用平台建设:隐患统计与智能管理

文章目录 前言一、二维码门楼牌管理应用平台概述二、隐患统计功能的重要性三、隐患统计的实现方式四、隐患统计的实践应用五、面临的挑战与未来发展 前言 随着城市管理的不断升级&#xff0c;二维码门楼牌管理应用平台已成为现代城市管理的重要工具。该平台通过集成先进的信息…

WCH RISC CH32V303RCT6 单片机的SDI Printf 虚拟串口功能 类似SEGGER RTT打印功能 简单分析

参考&#xff1a; 有关于 SDI printf 更多的信息和资料吗&#xff1f; 关于 CH32 系列 MCU SDI 虚拟串口功能的使用 【CH32X035 评估板测评】 教你使用 SDI 接口重定向 printf SDI (Serial Data Interface) 是沁恒微电子 RISC-V 内核的私有外设接口,CH32 RISC-V 系列目前提供了…

PDCA循环:持续精进的工具

文章目录 一、什么是PDCA二、PDCA的应用场景三、PDCA在信息系统项目管理中的应用 一、什么是PDCA PDCA循环是由美国质量管理专家沃特阿曼德休哈特&#xff08;Walter A. Shewhart&#xff09;在20世纪30年代提出的&#xff0c;最初用于制造业的质量管理。休哈特博士在构想PDCA…

二极管钳位型三电平SVPWM(羊角波)闭环系统simulink建模与仿真

整理了二极管钳位型三电平SVPWM&#xff08;羊角波&#xff09;闭环系统simulink建模与仿真模型&#xff0c;附赠参考资料。 在二极管钳位型三电平SVPWM中&#xff0c;通过控制逆变器的开关器件&#xff08;IGBT&#xff09;的导通和关断&#xff0c;将输入的直流电压转换为三…

知网怎么查重 知网查重的详细步骤

知网查重八个步骤&#xff1a;1. 访问官网&#xff0c;注册账号。2. 上传待查文档。3. 选择查重规则。4. 选择相似来源库。5. 提交查重任务。6. 等待查重结果。7. 获取查重报告。8. 下载查重报告。 知网查重的详细步骤 第一步&#xff1a;进入知网查重系统 打开浏览器&#x…

怎样将便签软件搬家?便签迁移攻略

便签软件已成为我们日常生活中不可或缺的记录工具。无论是重要的工作内容&#xff0c;还是琐碎的生活事务&#xff0c;我们都会在便签中一一记下。然而&#xff0c;当我们需要更换电脑或其他设备时&#xff0c;如何将这些珍贵的便签内容迁移到新设备上&#xff0c;成为了许多人…
最新文章