一、ChatGPT
的参考API
地址
API Reference
二、官网相关API
介绍
下图是正常请求时候的请求头和body
体,这样请求的话是等结果都加载出来后一起出现,并且返回的结果也是标准的json
格式。
如果想要实现和ChatGPT
一样的效果,官网的这样推荐的,如下图
从上图可以看到它用的是sse
实现的,并且请求的body
体加上Stream:true
就可以。请求过来的格式可以看到不是标准的json
格式,如下图,所以我们要处理成json
格式,并拿到数据
三、具体实现代码
我们要怎么拿到数据并实现流式输出,具体代码如下:
// 发送消息的方法
// 参数 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){// 解码,并将解码后的数据存放到bufferbuffer += 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解析不成功的部分,会在聊天记录的开始和结尾显示undefinedif (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);})})}
实现效果如下: