Spring AI实战之一:快速体验(OpenAI)

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

关于Spring AI

  • Spring Boot、Spring Cloud、Spring Data,作为一名Java程序员,相信您对这些概览早已耳熟能详,或者天天在用,在Spring体系中,它们都被称为project,而本系列的核心Spring AI,也是个project,和 Spring Boot、Spring Cloud属于同一级别的存在,其定位是面向人工智能的应用框架
    在这里插入图片描述

  • Spring AI有以下特点:

  1. 在AI的聊天、文生图、嵌入模型等方面提供API级别的支持
  2. 与模型之间支持同步式和流式交互(还记得ChatGPT返回内容时,是逐字生成的吗,这就是流式交互的效果)
  3. 多种模型支持

关于《SpringAI实战》系列

  • 这是欣宸作为一名Java程序员在LLM应用领域的原创,目标是与广大Java爱好者共同学习和进步,以编码实战的方式逐渐熟悉如何将AI应用在工程中,去实现业务功能

环境信息

  • 首先是JDK版本,整个实战系列使用了JDK17,您也可以考虑使用更高版本
  • maven版本是3.8.6
  • SpringBoot版本是3.2.4
  • Spring AI版本是0.8.1,这是目前最新的稳定版
    在这里插入图片描述
  • 另外就是开发环境,我的本地电脑上并未安装java、maven这些开发工具,而是通过GitHub提供的codespace功能,直接在浏览器上用web版的vscode实现了开发和运行的全部过程,自己的电脑只要有浏览器就行,无所谓windows还是mac,安卓平板一样能用

本篇概览

  • 作为《SpringAI实战》系列的开篇,本文打算以最快的速度写一个demo并且运行成功,通过这种方法对LLM有个初步的认识
  • 这个demo的功能是使用SpringAI提供的openai的starter,来实现对OpenAI接口的调用,得益于Spring框架的良好设计,使整个开发过程也非常简单
  • 如果您对OpenAI有所了解,就应该质疑本篇实战的内容:OpenAI的服务就是http接口调用,所以本篇实战不就是调用了http接口吗?这也太水了吧
  • 您说的没错,本质上就是写代码进行http调用,但具体的实现方式并不是写http请求和响应的代码,而是使用了SpringAI中和OpenAI相关的API和配置,在《SpringAI实战》系列的后续中,还会使用SpringAI去调用更多的大模型服务,它们并非全部都像OpenAI那样提供http接口,有的甚至是本地部署,这时候,SpringAI的优势就体现出来了:以一致的统一的风格使用各类LLM的能力

准备工作

  • 实际上,要想使用OpenAI的服务还是有一定难度的,例如账号里要有钱,对应的API Key才能使用,否则收到的响应就是失败信息
  • 如果只是学习用途,也能在网上发现一些免费使用ChatGPT的方法,本篇用的是这个项目提供的免费服务:https://gitcode.com/chatanywhere/GPT_API_free,真心感谢项目作者为我们的学习提供的宝贵帮助
  • 上述项目可以为你提供访问OpenAI的地址和API Key,前提是你要有个GitHub账号,具体操作如下
    在这里插入图片描述

源码下载

  • 准备工作完成,接下来开始编码,如果您不想写代码,也可以从GitHub下载代码直接运行,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
名称链接备注
项目主页https://github.com/zq2599/blog_demos该项目在GitHub上的主页
git仓库地址(https)https://github.com/zq2599/blog_demos.git该项目源码的仓库地址,https协议
git仓库地址(ssh)git@github.com:zq2599/blog_demos.git该项目源码的仓库地址,ssh协议
  • 这个git项目中有多个文件夹,本篇的源码在leader-tutorials文件夹下,如下图红色箭头所示:
    在这里插入图片描述
  • tutorials目录下有多个项目,整个《SpringAI实战》系列的源码在springai-tutorials,这是个maven工程,里面有多个子工程,今天的实战就是子工程hello-openai

编码:《SpringAI实战》系列的父工程

  • 首先是创建一个maven工程,这是《SpringAI实战》系列的父工程,作用是方便对所有实战源码的管理,另外对依赖库的版本管理也可以在这里统一处理,pom.xml内容如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <modules>
        <module>hello-openai</module>
    </modules>

    <parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.2.4</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

    <groupId>com.bolingcavalry</groupId>
    <artifactId>springai-tutorials</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>springai-tutorials</name>
	<description>Simple AI Application demos</description>
    <packaging>pom</packaging>
	<properties>
		<java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
	</properties>

    <dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.ai</groupId>
				<artifactId>spring-ai-bom</artifactId>
				<version>0.8.1</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<releases>
				<enabled>false</enabled>
			</releases>
		</repository>
	</repositories>
</project>
  • 这个父工程只有这么一个pom.xml文件

编码:快速体验SpringAI的子工程hello-openai

  • 接下来的内容就是今天的核心:使用SpringAI来调用
  • 在父工程里面创建名为hello-openai的子工程,pom.xml如下,这里面最重要的就是spring-ai-openai-spring-boot-starter这个包的依赖,它给我们带来了
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springai-tutorials</artifactId>
        <groupId>com.bolingcavalry</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>hello-openai</artifactId>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

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

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

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

    <build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>
  • 通过命令看一下这个starter的依赖情况,看起来spring-ai-core是关键(后面会有专门的文章讲述),其他的都是工具性质的依赖
[INFO] |  \- org.springframework.ai:spring-ai-openai:jar:0.8.1:compile
[INFO] |     +- org.springframework.ai:spring-ai-core:jar:0.8.1:compile
[INFO] |     |  +- io.swagger.core.v3:swagger-annotations:jar:2.2.20:compile
[INFO] |     |  +- com.github.victools:jsonschema-module-swagger-2:jar:4.33.1:compile
[INFO] |     |  +- org.springframework.cloud:spring-cloud-function-context:jar:4.1.0:compile
[INFO] |     |  |  +- net.jodah:typetools:jar:0.6.2:compile
[INFO] |     |  |  \- org.springframework.cloud:spring-cloud-function-core:jar:4.1.0:compile
[INFO] |     |  +- org.antlr:stringtemplate:jar:4.0.2:compile
[INFO] |     |  |  \- org.antlr:antlr-runtime:jar:3.3:compile
[INFO] |     |  +- org.antlr:antlr4-runtime:jar:4.13.1:compile
[INFO] |     |  +- io.projectreactor:reactor-core:jar:3.6.4:compile
[INFO] |     |  |  \- org.reactivestreams:reactive-streams:jar:1.0.4:compile
[INFO] |     |  +- org.springframework:spring-messaging:jar:6.1.5:compile
[INFO] |     |  \- com.knuddels:jtokkit:jar:1.0.0:compile
[INFO] |     +- org.springframework.ai:spring-ai-retry:jar:0.8.1:compile
[INFO] |     |  +- org.springframework.retry:spring-retry:jar:2.0.5:compile
[INFO] |     |  \- org.springframework:spring-webflux:jar:6.1.5:compile
[INFO] |     +- io.rest-assured:json-path:jar:5.3.2:compile
[INFO] |     |  +- org.apache.groovy:groovy-json:jar:4.0.20:compile
[INFO] |     |  +- org.apache.groovy:groovy:jar:4.0.20:compile
[INFO] |     |  \- io.rest-assured:rest-assured-common:jar:5.3.2:compile
[INFO] |     |     \- org.apache.commons:commons-lang3:jar:3.13.0:compile
[INFO] |     +- com.github.victools:jsonschema-generator:jar:4.31.1:compile
[INFO] |     |  \- com.fasterxml:classmate:jar:1.6.0:compile
[INFO] |     +- com.github.victools:jsonschema-module-jackson:jar:4.31.1:compile
[INFO] |     \- org.springframework:spring-context-support:jar:6.1.5:compile
  • 配置文件spring-ai-core,这是hello-openai工程的配置文件,内容如下,您在运行的时候,一定要将sk-xxxxxx改为您自己的API Key:
# 调用OpenAI接口时表明身份的API Key,前面的章节有提到如何生成一个免费的
spring.ai.openai.api-key=sk-xxxxxx
# 调用OpenAI接口时的基础地址,如果用的是chatanywhere的API Key,这里就要用chatanywhere提供的地址,
# 如果用的是OpenAI的原生API Key,就不用配置这个参数
spring.ai.openai.base-url=https://api.chatanywhere.tech
# 用到的模型
spring.ai.openai.chat.options.model=gpt-3.5-turbo
# temperature越小,回答的内容越严谨,temperature越大,回答的内容越有创造性
spring.ai.openai.chat.options.temperature=0.7
  • 一共有两个java文件,第一个是普通的application类,负责启动服务
package com.bolingcavalry.helloopenai;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}
  • 另一个是controller类,收到请求后调用OpenAI的接口,将聊天内容发过去,并将OpenAI响应的内容返回,这也是本文的核心内容,completion方法负责接受post请求,并将请求通过chatClinet发送到OpenAI,而call的返回值就是OpenAI的返回内容
package com.bolingcavalry.helloopenai.controller;

import org.springframework.ai.chat.ChatClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;


import java.util.Map;

@RestController
public class SimpleAiController {
	// 负责处理OpenAI的bean,所需参数来自properties文件
	private final ChatClient chatClient;

	public SimpleAiController(ChatClient chatClient) {
		this.chatClient = chatClient;
	}

	@PostMapping("/ai/simple")
	public Map<String, String> completion(@RequestBody Map<String,String> map) {
		return Map.of("generation", chatClient.call(map.get("message")));
	}
}
  • 至此,编码完成,把服务运行起来试试吧

运行验证

  • 启动服务后,执行以下命令即可发送请求调用服务的/ai/simple接口,我这边问了一个三国有关的问题
curl --request POST \
  --url http://127.0.0.1:8080/ai/simple \
  --header 'content-type: application/json' \
  --data '{
    "message":"你是精通中国历史的专家,请回答:三国时期,魏延的子午谷奇谋是否可行?能在潼关把魏国的援兵堵住吗?如果魏国援兵走武关进入,整个计划是否还有意义?"
}'
  • 稍等数秒,控制台就会显示返回内容,这就是OpenAI服务返回的内容了
{"generation":"作为专家,我可以告诉你,魏延的子午谷奇谋在理论上是可行的。子午谷是一个地势险要的地方,如果能够在那里设下埋伏,堵住魏国的援兵是有可能的。但是,这需要充分的准备和合理的部署,同时也需要对魏国援兵的行动有准确的情报。\n\n如果魏国援兵走武关进入,整个计划的意义可能会有所减弱。因为子午谷的奇谋是建立在堵住潼关的前提下,如果援兵绕道武关进入,那么计划的效果可能会受到影响。在这种情况下,需要及时调整计划,采取其他措施来应对敌人的行动。\n\n总的来说,魏延的子午谷奇谋在三国时期是一个具有一定可行性的战术计划,但是在实际执行过程中需要根据敌军的行动及时调整和变通。"}
  • 至此,本篇实战已经完成,第一次使用SpringAI,似乎…没啥感觉,无非是几个配置,一个client bean,整个过程和接入数据库、消息服务一样简单,但是这样也挺好,可以让咱们的注意力集中到对LLM的使用上
  • 接下来的章节,会有更多实战陪大家,一起投入大精彩纷呈的大模型时代,感谢Spring,这一次咱们不掉队

你不孤单,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

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

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

相关文章

本地搭建springboot服务并实现公网远程调试本地接口

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

重发被恶意举报的主食冻干测评,速看可能再被删!PR、希喂和SC真实对比PK!

要给猫咪提供高品质主食&#xff0c;主食冻干是不二之选。主食冻干不仅含肉量高、吸收消化率高&#xff0c;还有着丰富的、普通猫粮无法提供的各类营养素&#xff0c;满足猫咪微量元素的需求。可以说是营养与生骨肉喂养媲美&#xff0c;又能完美避开生骨肉细菌超标带来的一系列…

KaiwuDB 解析器之语义解析

KaiwuDB 解析器介绍 解析器是数据库系统的重要组成部分之一&#xff0c;主要的功能是将客户端输入的 SQL 语句分解为语法单元&#xff0c;然后将这些语法单元转化成数据库内部可识别的数据结构&#xff0c;最终生成数据库可以执行的计划。 KaiwuDB 的一条 SQL 执行的整个生命…

go导入包时提示no required module provides package解决方法

原因&#xff0c;这个包在你的本机没有安装 如redis包的提示为 could not import github.com/gomodule/redigo/redis (no required module provides package "github.com/gomodule/redigo/redis")解决方法&#xff1a; go get github.com/gomodule/redigo/redis

PHP+MySQL组合开发 自定义商城系统源码 带完整的安装代码包以及安装部署教程

随着电子商务的蓬勃发展&#xff0c;越来越多的企业和个人希望拥有自己的在线商城系统。小编给大家分享一款基于PHP和MySQL技术栈&#xff0c;开发的一套自定义商城系统源码。该系统旨在帮助用户快速搭建稳定、高效的电子商务平台&#xff0c;并提供灵活的自定义功能&#xff0…

日本站群服务器的优点以及适合该服务器的业务类型?

日本站群服务器的优点以及适合该服务器的业务类型? 日本站群服务器是指位于日本地区的多个网站共享同一台服务器的架构。这种服务器架构有着诸多优点&#xff0c;使其成为许多企业和网站管理员的首选。以下是日本站群服务器的优点以及适合该服务器的业务类型的分析&#xff1…

链表经典面试题02--链表的带环问题

目录 引言 环形链表 题目描述: 思路分析: 代码展示: 面试中遇到的问题: 环形链表Ⅱ 题目描述: 思路分析: 代码展示: 面试中遇到的问题: 方法二: 随机链表的复制 题目描述: 思路分析: 代码展示: 小结 引言 这个专题专门讲解链表的带环问题,并且对面试有关链表带环…

开源文档管理系统Paperless-ngx如何在Linux系统运行并发布至公网

文章目录 1. 部署Paperless-ngx2. 本地访问Paperless-ngx3. Linux安装Cpolar4. 配置公网地址5. 远程访问6. 固定Cpolar公网地址7. 固定地址访问 Paperless-ngx是一个开源的文档管理系统&#xff0c;可以将物理文档转换成可搜索的在线档案&#xff0c;从而减少纸张的使用。它内置…

使用HashMap实现,对一个字符集进行哈夫曼编码

最终达到的效果: 调用一个类 class HuffmanCodin{.....} 使用类中的静态方法&#xff0c;获取哈夫曼编码&#xff1a; 事前准备——哈夫曼树的节点定义 class Node implements Comparable<Node> {int weight;//权重Node left;Node right;char ch;//关键字&#xff0c…

asp.net论坛指南系统

说明文档 运行前附加数据库.mdf&#xff08;或sql生成数据库&#xff09; 主要技术&#xff1a; 基于asp.net架构和sql server数据库 登陆可查看 浏览记录 TA的发布 TA的回复 TA的收藏 TA的点赞 管理员登陆可以查看举报管理 编辑管理 认证审核 帖子置顶申请审核 运行环境…

如何利用IPIDEA代理IP优化数据采集效率?

一、 前言二、 IPIDEA介绍三、体验步骤四、实战训练五、结语 一、 前言 在全球化与信息化交织的当代社会&#xff0c;数据已成为驱动商业智慧与技术革新的核心引擎。网络&#xff0c;作为信息汇聚与交流的枢纽&#xff0c;不仅是人们获取知识的窗口&#xff0c;更是商业活动与技…

FX110书籍推荐:如何快速成为一名专业股票投资人?

股票投资领域有一本神作《股票交易入门》&#xff0c;它是股票从业人员的入门必备书籍。 关于股票入门的书籍很多&#xff0c;但这本书涉及的知识面最全、实用性最强。从这本书里&#xff0c;我们可以领略到股票交易世界的跌宕起伏而又波澜壮阔的魅力。本书作者 本书的作者是美…

Navicat导入sql报错[Err] 1046 - No database selected

Navicat导入sql报错[Err] 1046 - No database selected ​ 今天系统重装了&#xff0c;就很完蛋。所有东西都重新下载安装。向Navicat导入sql的时候导入失败&#xff1a; 报错[Err] 1046 - No database selected。我很疑惑地又导了几次。当然又全都失败. 错误造成原因&#x…

项目风采展示【车酷-雷克萨斯2】

1&#xff1a;支持桌面展示 2&#xff1a;支持桌面时钟 3&#xff1a;支持桌面陀螺仪

怎么将文字做成二维码?文本活码在线的生成技巧

文本类型的活码该如何来制作呢&#xff1f;通过二维码来展示文字信息是现在很常用的一种方式&#xff0c;包括物品、建筑、人员等方面的信息&#xff0c;都可以用生成二维码后让其他人通过扫码了解自己需要的信息。那么文本活码的制作需要几步操作呢&#xff1f;下面就教大家使…

mysql等保测评2.0命令-三级

版本 Win默认安装位置 C:\Program Files\MySQL\MySQL Server 8.0\bin 版本&#xff1a;select version() from dual; 身份鉴别 a应对登录的用户进行身份标识和鉴别&#xff0c;身份标识具有唯一性&#xff0c;身份鉴别信息具有复杂度要求并定期更换&#xff1b; 1、SELEC…

OpenGL入门第二步:颜色、纹理设置(解析)

OpenGL入门第一步:创建窗口、重写虚函数-CSDN博客 1、设置颜色 添加QColor变量,如果需要颜色随时间变化,那就再添加一个定时器QElapsedTimer以及重写虚函数timerEvent。 initializeGL()函数设置片段着色器中颜色变量 如果需要设置时间别忘了开启计时器 timerEvent函数里写…

UE和three.js的区别

UE&#xff08;Unreal Engine&#xff09;和three.js都是用于创建3D图形的软件平台&#xff0c;但它们在功能、目标和应用场景方面存在一些差异。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 功能 UE 是一款功能全面的3D游戏引擎&…

03-单片机商业项目编程,从零搭建低功耗系统设计

一、本文内容 上一节《02-单片机商业项目编程&#xff0c;从零搭建低功耗系统设计-CSDN博客》引出了伪时间片的概念&#xff0c;这也是再低功耗系统设计中必须使用的程序设计逻辑&#xff0c;本文着重来讲解如何利用伪时间片来设计伪多任务&#xff0c;以及伪时间片多任务内核设…

力扣刷题第1天:消失的数字

大家好啊&#xff0c;从今天开始将会和大家一起刷题&#xff0c;从今天开始小生也会开辟新的专栏。&#x1f61c;&#x1f61c;&#x1f61c; 目录 第一部分&#xff1a;题目描述 第二部分&#xff1a;题目分析 第三部分&#xff1a;解决方法 3.1 思路一&#xff1a;先排序…