源码及更详细的介绍说明参见Git上的README.md文档 https://github.com/asleepyfish/chatgpt
本文Demo(SpringBoot和Main方法Demo均包括)的Git地址:https://github.com/asleepyfish/chatgpt-demo
流式输出结合Vue前端的Demo的Git地址:https://github.com/asleepyfish/chatgpt-vue
后续使用方法和api版本更新均在Github的README.md文档更新,本博客暂停更新~
2023-05-28更新
制作了一个基于本文sdk包的对话网站,可前往http://chatgpt.alpacos.cn/体验。
[注]: 由于本人的服务器的带宽较低,首次加载页面可能会略有些慢,请耐心等待,详细使用说明请查看另一篇博客~ 👇
ChatGPT网页版(基于SpringBoot和Vue)
2023-07-17更新
所有的测试Demo均包括结合Spring框架的(类中)和方法使用(类中)Demo地址:https://github.com/asleepyfish/chatgpt-demo
- 1.1.5 增加查询账单功能(单位:美元),可以选择传入开始和结束日期查询(最多100天),或者不传入参,此时表示查询所有日期账单。
- 1.1.6 增加自定义功能,支持单个SpringBoot中添加多个实例,每个实例可以拥有个性化的参数;查询账单功能优化。
- 1.2.0 增加方法(查询订阅信息,包括订阅到期日和账号额度等信息,但是没有使用量情况,使用通过方法查询使用量),增加方法,整合了和方法,出参包括订阅到期日、额度、使用量、余量等信息。增加对内部cache的多种操作,包括获取,赋值等操作。
- 1.2.1 方法中出参取值逻辑修改,类支持build链式创建对象。
- 1.3.0 新增以下方法,每种方法均包含多种重载方法,具体使用请参考:https://github.com/asleepyfish/chatgpt-demo
- 、
- 、
- 、
- 、、、、
- 、、、、、、
- 1.3.1 支持自定义baseUrl,默认为 ,配置参数在类中,可通过配置。
- 1.3.2 修复自定义后无法访问bug,自定义必须以结尾。新增自定义属于自己的示例。
- 1.3.3 支持自定义,解决默认并发数无法指定问题,解决部分Proxy登录需要账号密码问题,详细介绍见2.12节。
- 1.3.4 修复指定后未切换bug,版本不建议使用。
- 1.3.5 支持SpringBoot3引用(SpringBoot3所需JDK最低是17),代码Demo见https://github.com/asleepyfish/chatgpt-demo,分支为dev-springboot3
- 1.3.6 新增以下功能
- ① 新增设置系统级别提示功能
- ② 新增计算输入prompt消耗token功能
- ③ 新增备用token,可自定义每次请求使用token
中引入依赖(当前最新版本为1.3.6,可前往Github页面查看当前最新版本)
在文件中配置相关参数(Optional为可选参数)
例:
其中token、proxy-host、proxy-port是必填的
上面的session-expiration-time参数很重要,是用来表示这个会话在多久不访问后被销毁,从而实现联系上下文的连续对话。
实现方式是通过ChatCompletionRequest中的user来区分某个会话,而session-expiration-time表示这个会话在多久不访问后被销毁。
如果这里看不懂请看2.1节示例
提供了工具类,里面提供了相关方法进行调用。
其中最简单的使用方法是:
入参即输入的问题的字符串。但是不建议使用。
这里建议使用下面的方式,通过传入user的值,再结合参数,可以实现指定某次会话,或者某个用户的连续对话。
还提供一个通用的静态方法是
入参里包含模型的一些可调参数。
类中还提供了多个可供选择的静态方法,可以自行查看。
上述方法的返回参数是一个list,是因为调整参数返回答案可以一次性返回多条不同的解答(为类中一个参数)。
2.1.1 测试
测试代码:
Post请求
入参输入:Java序列化的方式
返回结果:
再次输入:有没有更加高效的序列化框架
返回结果:
可以看出上述两次问答是在一次会话中的,而前面所说的参数即这个user所代表的会话多久没被继续访问时的销毁时间。单位(min)
最简单的使用方式是
入参表示生成图片的描述文字,还提供了一个通用的静态方法
入参中有一些可以使用的参数,其中表示生成图片的数量,表示生成图片的格式,格式中分为和两种,如果希望返回的是url,则返回的url会在生成一个小时后消失,默认值是。
2.2.1 测试
测试代码
在3.2的基础上做了优化,直接使用为然后解析成图片返回。简单使用方式如下:
通用方式如下:
当对象中设置的返回参数大于1时,会将图片打包成一个zip包返回,当等于1时直接返回图片。
2.3.1 测试
测试代码
我用的get 工具是idea里面下载的插件Fast Request的,用Postman也是可以的,但是要选择 Send and Download,上图中绿色的箭头是Send,蓝色的是Send and Download。
生成流式回答的方法是的方法,本工具类重载了同名的多个参数的方法,其中最通用的方法是
最简单的方法是
其中的content即本次对话的问题。
这里需要主义的是,上述第一个方法中的其实是一个必传的对象,上述的最简单的方法实际上是默认传递的这个对象,也就是将流式问答的结果显示到IDEA的控制台。
如果需要将流式问答的结果显示到其他界面可以自发的传入对象,这里有一个简便的方法是
只需要输入问题,和输出流对象即可。
下面将举例具体说明。(本文所有Demo的示例地址: https://github.com/asleepyfish/chatgpt-demo)
2.4.1 流式回答输出到IDEA控制台
代码如下:
然后使用Postman或者其他可以发送Get请求的工具发送请求。
本次测试的结果如下面的Gif图所示
2.4.2 流式回答输出到浏览器页面
上述的方法中输出流传入的是对象,该对象实际上就是一个对象,会把输出结果展示到控制台。
如果需要将输出结果在浏览器展示,可以从前端传入一个对象,拿到这个以后将这个输出流对象传入方法的入参中。同时,为了避免结果输出到浏览器产生乱码和支持流式输出,需要和。
具体代码如下:
测试结果过程的Gif图如下所示:
2.4.3 流式回答结合Vue输出到前端界面
调用的后端方法同节方法,前端只需要在界面传入问题,点击提问按钮即可返回结果流式输出到文本框中。
测试结果过程的Gif图如下所示:
查询账单提供了两个方法,金额单位均为,且均未对小数位截取,可以根据需要自行选择保留结果小数点位数。
第一个是可以传入开始和结束日期,按照指定日期区间查询的方法:
其中和区间范围不超过100天。
第二个方法是一个入参为可变参数的方法,当不传入参时,查询从距今的账单的方法,如果有人的订阅日早于可以传入自定义账单起始日期:
查询订阅提供了一个方法,这个方法的出参中包括了订阅到期日,总额度等信息:
由于查询总额度和查询使用量是两个接口,这里封装了一个方法来将几个比较有用的参数统一返回的方法,方法如下:
这个方法的入参也是一个可变入参,不传参时,默认为,如果账单开始日早于该天,可以传入指定的。出参中有四个参数:(额度到期日),(额度总量),(已使用量),(余额)。
2.5.1 测试
测试代码如下:
测试结果如下:
由于部分原因,用户可以选择搭建好的代理服务作为baseUrl,而不需要使用官方的。
这部分可以和第4节放在一起看
如果用户基于SpringBoot使用自定义baseUrl,可以参考下面的,配置chatgpt.base-url,如果不配置,则表示默认使用官方的。
然后相关调用代码如下:
如果用户不想和Spring集成,则可以使用main方法调用的方式。
下面为了测试方便性,均以方法做示例,结合SpringBoot使用调用的方法请参考github上的demo示例。
在方法中直接使用请参考第3节扩展部分。
如下所示:
其中自定义了baseUrl为 ,并调用了方法。
提供了两个与模型相关的方法:
测试代码如下:
测试结果(截取如下):
edit功能可以用来检查语句的拼写错误,代码的正确性等,api中重载了多种edit相关的方法,这里介绍最简单的一种,其他重载方法,可通过源码查看。
测试代码如下:
测试结果如下:
有时候需要将文本内容转化成计算机可以识别到的向量形式,可以使用这个方法。api中重载了多种embeddings相关的方法,这里介绍最简单的一种,其他重载方法,可通过源码查看。
测试代码如下:
测试结果截取如下:
转录功能可以将诸如、等格式的音频文件转化成文字输出。
最简单的一种使用方法如下,其他重载方法可通过代码查看。
下面是一首许嵩的《想象之中》的转录测试。
测试结果截取如下:
上述文字输出的时候是繁体,具体使用可以使用重载方法中一个代码入参的方法,其中的可以指定返回的语言,具体使用可以前往官网查看。
翻译功能可以将任意的音频文件翻译成英文。
最简单的一种使用方法如下,其他重载方法可通过代码查看。
下面是一首许嵩的《想象之中》的翻译测试。
测试结果截取如下:
注意:如果没有个性化定义OkHttpClient的需求,请忽略本节,系统会有一个默认的OkHttpClient实现
由于部分用户有自定义默认并发数和设置Proxy的账号密码的需求,为了同时解决这两个问题,做了自定义OkHttpClient的改造,具体使用方法可以分为结合SpringBoot使用和Main方法使用两种。
2.12.1 基于SpringBoot指定OkHttpClient
默认情况下不需要指定OkHttpClient,有一默认实现,如果想要修改OkHttpClient,满足个性化的需求,可以创建一个@Bean,系统会自动使用该Client实例。
如下定义了一个类,指定了Client默认并发数,且指定了Proxy的账号密码:
2.12.2 基于Main方法指定OkHttpClient
直接在创建对象的时候指定,代码如下:
使用方法的测试代码如下:
结合的使用方法请参照demo中类中方法。
使用方法的测试代码如下:
输出为:
问题背景:在之前的项目中只能指定一个,当项目的使用人数增加的时候会出现一个问题,就是单无法支持很多人同时请求,且使用完的免费额度的时候,需要手动更换下一个,很多时候如果不及时更换已经用完额度的会造成服务无法访问的情况。
解决:基于上述问题,现增加参数,可以在原先token的基础上,支持在服务中定义更多的(但是需要注意的是原先的选项仍是必填选项,而则是选填的)。同时增加策略,来在众多中选择使用某个来完成一次请求。当某个额度使用完或者过期时,会自动在服务中移除该。
配置如下:
使用main方法的测试代码:
因为指定获取token的策略为类,所以每次都选择第二个token,即。
输出结果如下:
由于之前的版本中使用@Bean的方式初始化和,导致一个
SpringBoot中实例是唯一的。
但是有时候需要在项目里自定义多个实例,来装配不同的信息(可以实例化多个Token(sk-xxxxxxxxxxx)使用)。
所以在版本中新增了自定义功能。在维持原有SpringBoot项目中全局的一个实例的基础上,现在可以自定义不同的实例,并且实例之间的属性是完全隔离的。
下面是一个Demo用来展示使用方法。
在上述方法中,新new了一个对象,并且set了为(这里不需要设置除了、和以外的其他属性,因为的其他属性拥有默认值,如果需要对其他属性做修改,可以自行设置。注意:sessionExpirationTime没有默认值,表示会话没有过期时间,如果需要设置会话过期时间,请set该值。)
而在中设置的为,这个token是给全局唯一的用的,这样就可以通过的构造方法new出来一个新的实例,其中构造方法的第二个参数直接填就好,表示Http调用请求没有超时时间,后续版本更新中,我会新增一个只有一个入参的构造方法。
这样直接使用new出来的来调用方法,每个都拥有自己的Token。
在一个SpringBoot项目中,就可以有多个,可以有更多的免费额度供使用了。
默认使用OpenAi服务的是 ,众所周知的原因,很多人网络无法直连。如果服务是部署在国外服务器,或者拥有代理,配置和依旧可以直接访问 ,这个也是比较推荐的方式,毕竟这是直连openai的服务,最安全,提供的服务接口也最全。
但是很多人没用国外的服务器,也没有自己的代理,在这里提供一种解决方法,通过使用这种方法,来实现无需国外服务器,也无需代理即可访问OpenAi服务。
在这里先简单介绍一下的概念。
反向代理是一种用于隐藏服务端真实地址的技术。比如说真实地址是B,但是我们不希望用户直连B,让B的地址暴露,我们就可以使用反向代理,让A的请求转发到B。
在这里,我们可以将B理解成 ,由于我们不能直连 ,但是我们可以在一台可以直连 的服务器上反向代理,给我们暴露一个网址A,我们将设置为A,向A发送请求,服务器接受到后自动将请求转发到 ,并且将结果返回。这样的话,我们只需要指定,都不需要设置代理和即可访问OpenAi的服务了。那现在的问题就是怎么简单的获取到这样的一个了。
这里我找到了一个可以提供OpenAi代理的服务。访问https://www.ichati.cn/dashboard/products/tools,注册登录后选择,点击立即使用。
然后输入API-Key,点击开始部署(这里我测试只需要长度保持一致,后面几位的api-key可以随便填)。
然后如下图所示生成了我们的(注意,这里生成的网页最后没用斜杠/,使用服务的使用baseUrl需要在最后带/,例如 )。
在4.1节中已经生成了我们项目的,且因为它给我们转发,我们可以任务,他的服务部署在一台可以直连 的服务器上,也就自然不需要设置和了。
4.2.1 基于SpringBoot使用OpenAiUtils
先设置,只需要设置和即可。
启动SpringBoot项目。
使用Post工具调用下面的接口生成图片。
结果如下:
访问该链接,就可以得到一个生成的图片~
4.2.2 基于Main方法使用OpenAiProxyService
下面是使用Main方法进行调用的具体代码,只需要设置和即可。
输入结果如下: