如何在使用密钥登录的时候请求ChatGPT的聊天接口并实现流式输出

一、ChatGPT的参考API地址

API Reference

二、官网相关API介绍

        下图是正常请求时候的请求头和body体,这样请求的话是等结果都加载出来后一起出现,并且返回的结果也是标准的json格式。
如何在使用密钥登录的时候请求ChatGPT的聊天接口并实现流式输出_第1张图片
如果想要实现和ChatGPT一样的效果,官网的这样推荐的,如下图
如何在使用密钥登录的时候请求ChatGPT的聊天接口并实现流式输出_第2张图片
如何在使用密钥登录的时候请求ChatGPT的聊天接口并实现流式输出_第3张图片
从上图可以看到它用的是sse实现的,并且请求的body体加上Stream:true就可以。请求过来的格式可以看到不是标准的json格式,如下图,所以我们要处理成json格式,并拿到数据
如何在使用密钥登录的时候请求ChatGPT的聊天接口并实现流式输出_第4张图片
如何在使用密钥登录的时候请求ChatGPT的聊天接口并实现流式输出_第5张图片

三、具体实现代码

       我们要怎么拿到数据并实现流式输出,具体代码如下:

// 发送消息的方法
// 参数 content 是发送的消息
function sendAnswer(content) {
    // 请求的body体
    const data = JSON.stringify({
      model: 'gpt-3.5-turbo',
      messages: [{ role: 'user', content: content }],
      stream: true
    })
    fetch('https://api.openai.com/v1/chat/completions', {
      method: 'POST',
     // 这个headers包括 "Content-Type":"application/json" 和 "Authorization", `Bearer ${key}`
     // 其中这个key是你的登录密钥
      headers: headers,  
      body: JSON.stringify({
        model: 'gpt-3.5-turbo',
        messages: [{ role: 'user', content: content }],
        // 启用流式处理
        stream:true
      }),
    })
      .then( response => {
      
      // 创建一个可读取响应体数据的读取器对象
        const reader = response.body.getReader();
        let buffer = '';
        // 这一部分是创建了一个装回复聊天信息的盒子
        const layoutBox = document.createElement("div");
        layoutBox.classList.add("layout");
        // dialogue 是创建的一个大的父盒子的名称
        dialogue.appendChild(layoutBox);
        const answerBox = document.createElement("span")
        answerBox.classList.add("answerList","list")
        layoutBox.appendChild(answerBox)   

        // 因为流式输出会逐个字出来,所以定义 answers 存放回复的消息,不存放的话后续用innerHTML插入的时候会被覆盖,只显示最后一个字符
        let answers = [];   
        // 这是一个JavaScript Promise的语法,表示当读取器(reader)读取完成后,执行一个函数(processResult)来处理结果(result)
        return reader.read().then(function processResult(result){
        // 解码,并将解码后的数据存放到buffer
          buffer += new TextDecoder().decode(result.value || new Uint8Array(),
          {stream: !result.done});
          // 这是以换行符将字符串分为多个部分,并过滤掉以[DONE]结尾的部分
          const parts = buffer.split('\n').filter(part => !part.endsWith('[DONE]'));;
          buffer = parts.pop();
          for(const part of parts){
            if(part.trim()){
              try {
                const response = JSON.parse(part.slice('data:'.length));
                console.log(response.choices[0].delta.content);
                answerContent = response.choices[0].delta.content;
                // 将内容存放到数组中,这个判断是answerContent 开头和结尾存在JSON解析不成功的部分,会在聊天记录的开始和结尾显示undefined
                if (answerContent !== undefined) {
                  answers.push(answerContent)
                }
              } catch (error) {
                console.error(`Failed to parse JSON: ${error.message}`);
                continue;
              }
           
            }
          }
          // 将数组中的内容以html的形式插入到聊天回复框中,如果不加join("")数组中的每一个字符都会被逗号隔开
          // 引入第三方库 marked 进行markdown格式化   import {marked} from "marked";
          answerBox.innerHTML = marked( answers.join(""),{
            headerIds: false,
            mangle: false
         });
         // 引入第三方库 hljs ,实现代码块高亮   import hljs from 'highlight.js'
         hljs.highlightAll(); 

         if(result.done){
            return;
          }
           return reader.read().then(processResult);
        })
      })
  }

实现效果如下:
如何在使用密钥登录的时候请求ChatGPT的聊天接口并实现流式输出_第6张图片

你可能感兴趣的:(chatgpt,javascript,html5,前端)