利用ChatGPT的API接口,搞一个UI模板吧

738 阅读2分钟

ChatGPT-UI

最近看到了 川虎 ChatGPT 的项目,感觉很有意思,但是整个项目都是python写的,那咱大前端不也得整一个玩玩?

项目/预览

看了川虎的项目,真心感觉不错,但是UI毕竟是用python写的,确实差点儿意思 然后看到了 New Bing 的聊天页面,感觉确实还不错,那就:拿来吧你[狗头]

实现分析

其实搞一个ui体验模板倒是不难,问题就在于很多人注册不了openAi的账号,科学上网和手机好的问题就困扰了很多人,本篇文章就不做介绍这些前置的东西了,网上很多文章都介绍的很详细。

介绍一下 api 调用的整体流程吧 (一个vue的项目搭建这里就省略了吧)

1、安装 openAi 的依赖

npm install openai

2、按官方文档的介绍 初始化

import { Configuration, OpenAIApi } from "openai";

let openAiInstance

function initChatAi() {
  const configuration = new Configuration({ apiKey: 'sk-xxxxxxxxxx' });
  const openAi = new OpenAIApi(configuration);
  openAiInstance = openAi
}

3、初始化之后就是调用接口了,调用创建聊天的 api

    const params = {
      model: modelMap.chat,
      messages: [{role: 'user', content: 'hello' }],
    };

    openAiInstance.value
      .createChatCompletion(params)
      .then((res) => {
        const [response] = res.data.choices;
        // 拿到了返回的信息
        console.log(response)
      })

这里调用成功的话接口便会返回聊天内容啦,但是发现回复的内容并不像官网那样,是实时的聊天,文字是一个一个展示的。

4、配置接口返回模式为实时返回模式

这里就用到了 接口返回数据 content-type: text/event-stream 格式的,需要特殊处理一下了。整体就是利用 fetch 请求数据, 然后使用TextDecoder来解析响应数据

这个咱一开始也是不知道怎么解析,也是问了ChatGPT解决的 🐶

  const params = {
      model: modelMap.chat,
      messages: [{role: 'user', content: 'hello' }],
      stream: true
    };
    
    
    const openAiHeaders = openAiInstance.value.configuration.baseOptions.headers;
    fetch(openAiInstance.value.basePath + "/chat/completions", {
      method: "POST",
      body: JSON.stringify(params),
      headers: {
        "Content-Type": "application/json",
        Authorization: openAiHeaders.Authorization,
      },
    })
      .then((response) => {
        const stream = response.body;
        const reader = stream.getReader();
        let buffer = "";

        // 逐行读取数据
        reader.read().then(function processText({ done, value }) {
          if (done) return;

          buffer += new TextDecoder().decode(value);
          const lines = buffer.split("\n");

          // 处理数据流
          lines.forEach((line) => {
            if (line.length < 1) return;
            const value = line.slice(6);
            if (value === "[DONE]") {
              pending.value = false;
              return;
            }
            const result = JSON.parse(value);
            const [content] = result.choices;
            // ToDo 这里可以设置结果文本啦

          });

          buffer = lines.pop();
          return reader.read().then(processText);
        });
      })

核心逻辑差不多就这么多啦,感兴趣的小伙伴可以看一下 GitHub 的源码