注意:流式输出在2.4节,请仔细阅读到最后,谢谢!
pom.xml中引入依赖(当前最新版本为1.1.4,可前往Github页面查看当前最新版本)
例:
chatgpt:token:sk-xxxxxxxxxxxxxxxproxy-host:127.0.0.1proxy-port:xxxxsession-expiration-time:30其中token、proxy-host、proxy-port是必填的
上面的session-expiration-time参数很重要,是用来表示这个会话在多久不访问后被销毁,从而实现联系上下文的连续对话。
实现方式是通过ChatCompletionRequest中的user来区分某个会话,而session-expiration-time表示这个会话在多久不访问后被销毁。
如果这里看不懂请看2.1节示例
启动类上加入图中的注解则将服务注入到Spring中。
OpenAiUtils.createChatCompletion(content);//不建议使用入参content即输入的问题的字符串。但是不建议使用。
这里建议使用下面的方式,通过传入user的值,再结合session-expiration-time参数,可以实现指定某次会话,或者某个用户的连续对话。
OpenAiUtils.createChatCompletion(content,user);//建议使用入参ChatCompletionRequest里包含模型的一些可调参数。
OpenAiUtils类中还提供了多个可供选择的静态方法,可以自行查看。
上述方法的返回参数是一个list,是因为调整参数返回答案n可以一次性返回多条不同的解答(n为ChatCompletionRequest类中一个参数)。
测试代码:
@PostMapping("/chatTest")publicList
入参输入:Java序列化的方式
返回结果:
["\n\nJava序列化是将Java对象转换为字节序列的过程,以便在网络上传输或将其保存到磁盘上。Java提供了两种序列化方式:\n\n1.基于Serializable接口的序列化\n\nSerializable接口是Java提供的一个标记接口,用于标记一个类可以被序列化。如果一个类实现了Serializable接口,那么它的所有非瞬态字段都会被序列化。序列化的过程可以通过ObjectOutputStream类来实现,反序列化的过程可以通过ObjectInputStream类来实现。\n\n2.基于Externalizable接口的序列化\n\nExternalizable接口也是Java提供的一个标记接口,用于标记一个类可以被序列化。与Serializable接口不同的是,Externalizable接口需要实现writeExternal和readExternal方法,这两个方法分别用于序列化和反序列化。在序列化的过程中,只有被writeExternal方法显式写入的字段才会被序列化,而在反序列化的过程中,只有被readExternal方法显式读取的字段才会被反序列化。\n\n总的来说,基于Serializable接口的序列化更加简单,但是它会序列化所有非瞬态字段,包括一些不需要序列化的字段,而基于Externalizable接口的序列化可以更加灵活地控制序列化的过程。"]再次输入:有没有更加高效的序列化框架
最简单的使用方式是
OpenAiUtils.createImage(prompt);入参表示生成图片的描述文字,还提供了一个通用的静态方法
publicstaticList
测试代码
@TestpublicvoidtestGenerateImg(){OpenAiUtils.createImage("英短").forEach(System.out::println);}结果默认情况下会生成一个url,点击去就可以看到图片。
在3.2的基础上做了优化,直接使用responseFormat为b64_json然后解析成图片返回。简单使用方式如下:
OpenAiUtils.downloadImage(prompt,response);通用方式如下:
publicstaticvoiddownloadImage(CreateImageRequestcreateImageRequest,HttpServletResponseresponse){...}当CreateImageRequest对象中设置的返回参数n大于1时,会将图片打包成一个zip包返回,当n等于1时直接返回图片。
@RestControllerpublicclassChatGPTController{@GetMapping("/downloadImage")publicvoiddownloadImage(Stringprompt,HttpServletResponseresponse){OpenAiUtils.downloadImage(prompt,response);}}发送get请求,然后选择SendandDownload
我用的get工具是idea里面下载的插件FastRequest的,用Postman也是可以的,但是要选择SendandDownload,上图中绿色的箭头是Send,蓝色的是SendandDownload。
生成流式回答的方法是OpenAiUtils的createStreamChatCompletion方法,本工具类重载了同名的多个参数的方法,其中最通用的方法是
publicstaticvoidcreateStreamChatCompletion(ChatCompletionRequestchatCompletionRequest,OutputStreamos){...}最简单的方法是
publicstaticvoidcreateStreamChatCompletion(Stringcontent){...}其中的content即本次对话的问题。
这里需要主义的是,上述第一个方法中的OutputStreamos其实是一个必传的对象,上述的最简单的方法实际上是默认传递的System.out这个os对象,也就是将流式问答的结果显示到IDEA的控制台。
如果需要将流式问答的结果显示到其他界面可以自发的传入OutputStreamos对象,这里有一个简便的方法是
publicstaticvoidcreateStreamChatCompletion(Stringcontent,OutputStreamos){...}只需要输入问题,和输出流对象即可。
代码如下:
本次测试的结果如下面的Gif图所示
上述的方法中输出流传入的是System.out对象,该对象实际上就是一个PrintStream对象,会把输出结果展示到控制台。
如果需要将输出结果在浏览器展示,可以从前端传入一个HttpServletResponseresponse对象,拿到这个response以后将response.getOutputStream()这个输出流对象传入createStreamChatCompletion方法的入参中。同时,为了避免结果输出到浏览器产生乱码和支持流式输出,需要ContentType和CharacterEncoding。
@GetMapping("/streamChatWithWeb")publicvoidstreamChatWithWeb(Stringcontent,HttpServletResponseresponse)throwsIOException{//需要指定response的ContentType为流式输出,且字符编码为UTF-8response.setContentType("text/event-stream");response.setCharacterEncoding("UTF-8");//禁用缓存response.setHeader("Cache-Control","no-cache");OpenAiUtils.createStreamChatCompletion(content,response.getOutputStream());}测试结果过程的Gif图如下所示:
调用的后端方法同2.4.2节方法streamChatWithWeb,前端只需要在界面传入问题,点击提问按钮即可返回结果流式输出到文本框中。