chatGPT流式输出的几种方式

全屏阅读
  • 基本信息
  • 作者:
  • 作者已发布:925篇文章
  • 发布时间:2023年05月20日 9:44:35
  • 所属分类:Chat GPT / Open Ai
  • 阅读次数:769次阅读
  • 标签:

前言:

chatGPT是一款高效强大的语言模型,能够给我们的生活带来极大的改变。无论是学习知识还是工作效率,chatGPT都能为我们提供有力的帮助。它可以帮助我们快速获取所需的知识,同时可以帮助我们提高工作效率,包括写文章、文案、推荐策略、生成代码、写周报,流程图等等。此外,它还可以成为您智能的助手,帮您打理日常事务,如一键预约、贴心提醒等。对于小朋友们来说,他还可以为他们写作文。总之,chatGPT是一个多功能的智能管家,不管您的需求是什么,它都能为您提供强大的支持。

SseEmitter

这种方式比较常用,我们这里引入github上PlexPt大神封装好的类直接引用即可,地址为:chatgpt-java,也可以自己封装哈

<dependency>
    <groupId>com.github.plexpt</groupId>
    <artifactId>chatgpt</artifactId>
    <version>4.0.7</version>
</dependency>
   private static final String OPENAI_API_HOST = "https://api.openai.com/";
    
    @PostMapping(value = "/v1/stream")
public SseEmitter streamEvents(@RequestBody  ChatRequest chatRequest) {
	  SseEmitter sseEmitter = new SseEmitter(-1L);
	    
	   // 不需要代理的话,注销此行
	   Proxy proxy = Proxys.http("192.168.1.98", 7890);
	   ChatGPTStream chatGPTStream = ChatGPTStream.builder()
	           .timeout(600)
	           .apiKey("你的openApiKey")
	           .proxy(proxy)
	           .apiHost(OPENAI_API_HOST)
	           .build()
	           .init();
	
	   MySseStreamListener listener = new MySseStreamListener(sseEmitter);
	   Message message = Message.of(chatRequest.getInput());
	   ChatCompletion chatCompletion = ChatCompletion.builder()
	        .model(ChatCompletion.Model.GPT_3_5_TURBO.getName())
	        .messages(Arrays.asList(message))
	        .build();
	   chatGPTStream.streamChatCompletion(chatCompletion, listener);
	   listener.setOnComplate(msg -> {
	       //回答完成,可以做一些事情
	       sseEmitter.complete();
	   });
	   return sseEmitter;
	}

前端调用,这里使用fetchEventSource,普通的eventSource不能发送post参数

import { fetchEventSource } from '@microsoft/fetch-event-source';
const reqData = {
   id: '111',
   input: 'java编码实现快速排序算法',
   chatlog: [],
 };
 const headers = {
   'Content-Type': 'application/json',
 };
const eventSource = new fetchEventSource('/api/v1/stream', {
	method: 'POST',
	headers: headers,
	body: JSON.stringify(reqData),
	onopen(response) {
		console.info('eventSource open: ', response);
     },
     onmessage(event) {
          console.log('eventSource msg: ', event.data);
     },
     onerror(err) {
         console.log('eventSource error: ' + err);
     },
     onclose() {
        console.log('eventSource close'); 
     }
});

HTTP Chunked方式

Message、ChatCompletion、ChatCompletionResponse 类都是根据官方需要的参数封装的实体,这里暂不能提供了,主要看思路吧

<dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.8.15</version>
 </dependency>
 private static final String OPENAI_API_HOST = "https://api.openai.com/";

 private static final Map<String, Integer> API_KEY_MAP = new LinkedHashMap<String, Integer>() {
     {
         put("你的openApiKey", 5);
         put("你的openApiKey", 5); 
     }
 };
 @PostMapping("/v1/stream")
 public void streamHandler(@RequestBody ChatRequest chatRequest, HttpServletResponse response) throws Exception {
     String input = chatRequest.getInput();
     // 本地测试不配置nginx的话,这里需要放开
     // response.setHeader("Transfer-Encoding", "chunked");
     // response.setHeader("Connection", "keep-alive");
     
     //按权重分配key
     List<String> weightList = new ArrayList<>(API_KEY_MAP.entrySet().size());
     for (Map.Entry<String, Integer> entry : API_KEY_MAP.entrySet()) {
         String element = entry.getKey();
         Integer weight = entry.getValue();
         for (int i = 0; i < weight; i++) {
             weightList.add(element);
         }
     }

    // 不需要代理的话,注销此行
     proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("192.168.1.98", 7890));
     Message message = Message.builder().role(Message.Role.USER).content(input).build();
     ChatCompletion chatCompletion = ChatCompletion.builder().messages(Arrays.asList(message)).stream(true).build();
     
     String requestBody = JSONUtil.toJsonStr(chatCompletion);
     HttpRequest client = HttpRequest.post(OPENAI_API_HOST + "v1/chat/completions")
             .header(Header.CONTENT_TYPE,  ContentType.JSON.name())
             .header(Header.AUTHORIZATION, "Bearer " + RandomUtil.randomEle(weightList))
             .setProxy(proxy)
             .timeout(60000)
             .body(requestBody);

     BufferedReader reader = new BufferedReader(new InputStreamReader(client.executeAsync().bodyStream()));
     String line;
     while ((line = reader.readLine()) != null) {
         line = StrUtil.replace(line, "data: ", "");
         if (StrUtil.isEmpty(line)) {
             continue;
         }
         if (!StrUtil.equals("[DONE]", line)) {
             ChatCompletionResponse chatCompletionResponse = JSONUtil.toBean(line, ChatCompletionResponse.class);
             if (!StrUtil.equals("stop", chatCompletionResponse.getChoices().get(0).getFinishReason())) {
                 String content = chatCompletionResponse.getChoices().get(0).getDelta().getContent();
                 if (StrUtil.isEmpty(content)) {
                     continue;
                 }
                 response.getWriter().write(content);
                 response.getWriter().flush();
             }
         }
     }
     reader.close();
     response.getWriter().close();
 }

nginx配置,这三个必须加上

 proxy_buffering off;
 proxy_http_version 1.1;
 chunked_transfer_encoding on;

前端调用,这里使用axios,比较简单

import axios from 'axios';

const reqData = {
   id: '111',
   input: 'java编码实现快速排序算法',
   chatlog: [],
 };
 const headers = {
   'Content-Type': 'application/json',
 };
axios.post('/api/v1/stream', reqData , { headers })
	 .then(function (response) {
      	console.log(response);
     })
     .catch(function (error) {
	      console.log(error);
     });

顶一下
(0)
100%
订阅 回复
踩一下
(0)
100%
» 郑重声明:本文由mpxq168发布,所有内容仅代表个人观点。版权归恒富网mpxq168共有,欢迎转载, 但未经作者同意必须保留此段声明,并给出文章连接,否则保留追究法律责任的权利! 如果本文侵犯了您的权益,请留言。

目前有 0 条留言 其中:访客:0 条, 博主:0 条

给我留言

您必须 [ 登录 ] 才能发表留言!