Spring AI Chat 简单示例

官方文档地址: https://docs.spring.io/spring-ai/reference/index.html

Spring AI 可以方便 Java 开发者在代码中集成 AI 的功能,通过 Spring 提供的抽象,可以方便的切换不同的AI提供商,Spring AI 是对 AI 的使用,并不涉及 AI 的训练。

特别注意: Spring AI 目前还很不稳定,官方文档还有大量错误,API 也会变动导致不兼容,当前文章示例使用的 0.8.1 版本。

创建初始项目

可以通过 https://start.spring.io/ 创建一个包含 Spring AI 的初始项目:
在这里插入图片描述

上图所示,我们添加最常见的 OpenAI 依赖,Spring AI 主要添加了下面的 BOM:

<dependency>
	<groupId>org.springframework.ai</groupId>
	<artifactId>spring-ai-bom</artifactId>
	<version>0.8.1</version>
	<type>pom</type>
	<scope>import</scope>
</dependency>

还有我们选择的 OpenAI:

<dependency>
	<groupId>org.springframework.ai</groupId>
	<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>

示例代码

为了更清楚的了解 Spring AI,本文使用更底层的代码来演示 Spring AI 的功能。

由于可能无法直接访问 OpenAI,在Java中进行调用时,可以通过下面的方式设置代理:

System.setProperty("https.proxyHost", "localhost");
System.setProperty("https.proxyPort", "7890");

除了上面方式外,如果你部署过 ChatGPT-Next-Web ,还可以通过间接的方式调用 OpenAI,可以使用类似下面形式的URL和TOKEN:

  • URL:https://你的域名/api/openai/
  • TOKEN: nk-你的CODE

我们可以通过下面的方式创建 OpenAiApi:

var openAiApi = new OpenAiApi("token");
//为了避免泄漏token,还可以配置环境变量后使用下面方式
//注意使用IDEA时,配置环境变量后需要完全关闭IDEA重启才能生效
var openAiApi = new OpenAiApi(System.getenv("OPENAI_API_KEY"));

如果使用 ChatGPT-Next-Web 代理的接口,可以使用带有 baseUrl 构造参数的方法。

var openAiApi = new OpenAiApi("https://你的域名/api/openai/", "nk-你的CODE");
//为了避免泄漏token,还可以配置环境变量后使用下面方式
//注意使用IDEA时,配置环境变量后需要完全关闭IDEA重启才能生效
var openAiApi = new OpenAiApi(
		System.getenv("OPENAI_BASE_URL"), 
		System.getenv("OPENAI_API_KEY"));

上面代码使用了具体的 OpenAiApi,这一层是具体的实现,一般通过 starter 的配置来动态创建,接下来是更通用的 ChatClient 接口(这里特地指定了类型,没有使用 var):

ChatClient chatClient = new OpenAiChatClient(openAiApi, OpenAiChatOptions.builder()
		.withModel("gpt-3.5-turbo")
		.withTemperature(0.4F)
		.withMaxTokens(200)
		.withFunctionCallbacks(List.of(
				FunctionCallbackWrapper.builder(new MockWeatherService())
				.withName("CurrentWeather")
				.withDescription("Get the weather in location").build()
		))
		.build());

在上面的客户端中指定了 openAiApi,指定了模型名和其他参数,还特地增加了一个函数回调,增加了一个函数 CurrentWeather,通过这个函数提供的实现 MockWeatherService 可以让 ChatGPT 拥有获取实时温度的功能,这里只是演示,所以没有对接真实的 API,直接返回的随机数:

public static class MockWeatherService
	implements Function<MockWeatherService.Request, MockWeatherService.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(Math.random() * 40, Unit.C);
	}
}

ChatClient 最简单的接口是 default String call(String message) 方法,输入提示词返回结果,我们这里为了演示函数功能,使用复杂的接口方法 ChatResponse call(Prompt prompt)

ChatResponse response = chatClient.call(
	new Prompt("北京、石家庄的天气怎么样,适合穿什么衣服?温度保留1位小数。", 
	OpenAiChatOptions.builder().withFunction("CurrentWeather").build()));

System.out.println(response.getResult().getOutput().getContent());

目前使用的 Function 功能只有 OpenAI 支持,这里只能使用 OpenAiChatOptions 指定要使用什么函数,这里要注意,前面定义的时候是在注册函数,在提示词中需要指定要使用的函数,如果不指定函数就不会生效。上面示例执行的结果如下:

北京目前气温为28.8°C,石家庄目前气温为11.8°C。
根据当前天气情况,建议穿着清凉舒适的夏季衣服在北京,而在石家庄则建议穿着春秋过渡季节的衣服。

目前的 Spring AI 还不适合用于生产,接口变化比较大,而且提供者无关的抽象还不够完善,官方文档中示例代码落后,有很多都无法执行。希望 Spring AI 越来越强大,成为 Java 开发中的 LangChain 和 LlamaIndex。

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

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

相关文章

Android 地图SDK 绘制点 删除 指定

问题 Android 地图SDK 删除指定绘制点 详细问题 笔者进行Android 项目开发&#xff0c;对于已标记的绘制点&#xff0c;提供撤回按钮&#xff0c;即删除绘制点&#xff0c;如何实现。 解决方案 新增绘制点 private List<Marker> markerList new ArrayList<>…

没有公式,不要代码,让你理解 RCNN:目标检测中的区域卷积神经网络

⭐️ 导言 在计算机视觉领域&#xff0c;目标检测是一项关键任务&#xff0c;它涉及识别图像中感兴趣的物体&#xff0c;并定位它们的位置。而RCNN&#xff08;Region-based Convolutional Neural Network&#xff09;是一种经典的目标检测算法&#xff0c;它以区域为基础进行…

BMP280 arduino调试

终于成功了。 #include <SPI.h> //定义数据类型 #define s32_t long signed int #define u32_t long unsigned int #define u16_t unsigned short #define s16_t signed short // 定义从设备选择引脚 const int chipSelectPin 10; //定义BMP280寄存器/// unsigned int …

R语言:如何基于地球外辐射(Ra)和相对日照(n/N)计算太阳辐射Rs?

正在编写相关软著&#xff0c;借此机会了解R语言的基本语法和一些处理流程&#xff0c;所以解释稍微繁琐。 Note&#xff1a; 使用的R语言版本是 R version 4.3.2 (2023-10-31 ucrt) 使用的RStudio编辑器版本是&#xff1a; 01 基于随机森林的插值填补缺失值 这是目前处理…

电子供应链的未来:电子元器件采购商城的洞察

电子供应链的未来将受到数字化技术、智能化制造和全球化贸易等趋势的深刻影响。在这一背景下&#xff0c;电子元器件采购商城将发挥越来越重要的作用&#xff0c;并提供以下洞察&#xff1a; 数字化转型&#xff1a; 电子元器件采购商城将更加注重数字化转型&#xff0c;通过引…

【计算机系统结构】重叠方式

&#x1f4dd;本文介绍 本文主要内容位计算机系统结构的重叠方式 &#x1f44b;作者简介&#xff1a;一个正在积极探索的本科生 &#x1f4f1;联系方式&#xff1a;943641266(QQ) &#x1f6aa;Github地址&#xff1a;https://github.com/sankexilianhua &#x1f511;Gitee地址…

不可变集合

2. 3. 如果键值对超过10个的话 优化之后 要生成不可变的集合直接使用copyof就可以

Python XML处理实战指南:从基础到高级技巧

Python XML处理实战指南&#xff1a;从基础到高级技巧 介绍XML基础XML的定义和特点XML结构组成命名空间&#xff08;Namespaces&#xff09;小结 Python中处理XML的库ElementTreeminidomlxml 使用ElementTree解析XML读取XML文件遍历XML元素查找特定元素修改XML文件 使用lxml处理…

除了「au revoir」,「再见」还能怎么说?柯桥成人学外语来银泰附近

1. Je dois y alle#15857575376r I have to go there Y there&#xff0c;意思是“我要走了”。 例如&#xff0c;”Moi, je dois y aller.” 对不起&#xff0c;我该走了。 如果你和同伴都要离开&#xff0c;那就可以说"On y va"&#xff0c;它相当于英语里…

C#集合和数据结构,随笔记录

C#集合和数据结构 System.Collections命名空间包含接口和类&#xff0c;这些接口和类定义各种对象&#xff08;如列表/链表、位数组、哈希表、队列和堆栈&#xff09;的集合 System.Collections.Generic命名空间&#xff1a; 所有集合都直接或间接基于ICollection接口 列表类集…

Redis数据结构对象(一)

对象 概述 Redis并没有直接使用简单动态字符串(SDS)、双端链表、字典、压缩列表、整数集合等这些数据结构来实现键值对数据库&#xff0c;而是基于这些数据结构创建了一个对象系统&#xff0c;这个系统包含字符串对象、列表对象、 哈希对象、集合对象和有序集合对象这五种类型…

Cesium 获取 3dtileset的包围盒各顶点坐标

Cesium 获取 3dtileset的包围盒各顶点坐标 /*** 获取 3dtileset的包围盒各顶点坐标, z 方向取高度最低的位置* param {*} tileset* param {*} options* returns* ref https://blog.csdn.net/STANDBYF/article/details/135012273* ref https://community.cesium.com/t/accurate-…

基于SpringBoot+Vue的IT博客管理系统

目录 一、绪论1.1 开发背景1.2 系统开发平台1.2.1 Java语言的简介1.2.2 MySQL的简介1.2.3 IntelliJ IDEA的简介 二、需求分析2.1 系统简介2.1.1 系统类型2.1.2 系统用法2.1.3 系统特点 2.2 需求分析2.2.1 系统设计任务2.2.2 系统设计目标2.2.3 系统设计步骤 三、系统设计3.1 用…

视频素材库大全高清素材必备网站,总有一个值得收藏!

喜欢制作短视频的朋友们&#xff0c;你们是否时常苦于寻找合适的视频素材库大全高清素材必备网站&#xff1f;今天&#xff0c;我为大家整理了五个超棒的短视频素材下载网站&#xff0c;希望能够为你们的视频创作提供更多灵感和选择&#xff01; 1.蛙学网&#xff1a; 蛙学网不…

qt可以信号触发信号(信号与槽)信号串联

使用场景&#xff1a;一大堆lineEdit要更新数据上面10几个QLineEdit,z&#xff0c;只要任意改一个数据我都要把所有数据封装成一个包 connect(ui.radar_name_, &QLineEdit::textChanged, ui.antenna_height, &QLineEdit::textChanged); connect(ui.antenna_height, &a…

裸机编程的几种模式、架构与缺陷。

大多数嵌入式的初学者都是从单片机裸机编程开始的&#xff0c;对于初学者来说&#xff0c;裸机编程更加直观、简单&#xff0c;代码所见及所得&#xff0c;调试也非常方便&#xff0c;区别于使用操作系统需要先了解大量的操作系统基础知识&#xff0c;调度的基本常识&#xff0…

【JavaEE Spring 项目】消息队列的设计

消息队列的设计 一、消息队列的背景知识二、需求分析核心概念⼀个⽣产者, ⼀个消费者N 个⽣产者, N 个消费者Broker Server 中的相关概念核⼼ API交换机类型 (Exchange Type)持久化⽹络通信消息应答 三、 模块划分四、 项⽬创建五、创建核心类创建 Exchange创建 MSGQUeue创建 B…

C语言数据结构基础笔记——树、二叉树简介

1.树 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次关系的集合。 把它叫做树是因 为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 &#xff08;图片来源于网络&#xff09;…

计算机考研|王道四本书够吗?

如果你是跨考生&#xff0c;王道的四本书只能覆盖你需要的80% 如果你是计算机专业的考生&#xff0c;王道四本书可以覆盖你需要的90% 我已经说的很明显了&#xff0c;王道的内容覆盖不了408考研的全部大纲&#xff0c;有的知识点虽然在王道书上提到了&#xff0c;但是因为不是…

拿捏指针(二)

个人主页&#xff1a;秋邱博客 所属栏目&#xff1a;C语言 &#xff08;感谢您的光临&#xff0c;您的光临蓬荜生辉&#xff09; 目录 前言 数组与指针 数组名的理解 指针数组与数组指针 指针数组 数组指针 数组传参 一维数组传参的本质 二维数组传参的本质 二维数组…