likes
comments
collection
share

2024版: 用 Node.js 调用 ChatGPT API 实现 Stream 流式聊天效果

作者站长头像
站长
· 阅读数 3

大家好,我是前端双越老师~

开始

我要做一个 AIGC 知识库(类似 Notion AI 和协同编辑)划水AI —— 对,虽然还没开始做(4月开始做),但域名、证书、服务器、包括 ChatGPT API 都已经搞好了,要玩点真格的。

PS:如果你想围观这个项目进展,或详细学习这个项目研发过程,申请参与到项目研发团队中,可看 划水AI 首页,也可私信我~

本文主要介绍一下原生 Node.js 如何调用 ChatGPT API ,并且实现 Stream 流式打印效果。文章最后有源码链接。

【注意】网上有些较早(其实也就是 2023 去年😄)的资料已经过时了,不再适合 OpenAI 当前的文档和要求,本文是 2024 上半年最新的。亲测过,希望能给你带来帮助~

下图是最终的 demo 效果。如果你再记录下输入信息和返回信息,优化一下样式,那就是一个山寨版的 ChatGPT 聊天机器人。

2024版: 用 Node.js 调用 ChatGPT API 实现 Stream 流式聊天效果

PS:为何去年一下子出来那么多套壳聊天机器人?因为它开发很简单。但做 AIGC 知识库 AI 编辑器 AI 写作,那可就麻烦了,虽有价值,所以没几个人做得了这个。

前置条件

这些条件也可能是障碍,大家尽力而为~

开通 OpenAI API keys

首先,你得能访问 OpenAI 和 ChatGPT 网站。

其次,你要有一个 OpenAI 账号,并且已经开通了 API keys 。注意,如果你是较早(2023上半年)注册的号,可直接开通;近期注册的号,可能需要国外手机号验证,这是个障碍。

2024版: 用 Node.js 调用 ChatGPT API 实现 Stream 流式聊天效果

然后,你要有额度可用,因为调用 API 是付费的。刚注册的账号有 5 刀免费额度,够你把玩的。如果你也像我一样过期了,那只能自己充值,这可能又是个障碍。OpenAI 对信用卡屏蔽的厉害,虚拟卡都不能用了。PS:真是第一次见这种公司,上赶着给钱都不要!!!

2024版: 用 Node.js 调用 ChatGPT API 实现 Stream 流式聊天效果

以上都具备了,然后你可以访问 OpenAI platform 查阅开发文档了。

临时的G外服务器

国内的网络环境目前无法正常调用 OpenAI API 。对,即便你能通过浏览器打开 ChatGPT ,你也无法调用 API 。

我看有些 2023 年的资料说,通过某些代理的方式可以,我试了一下也不行。不知道是我操作问题还是 OpenAI 有了新的策略,我没深究。

因为我有了新的方式:搞一个临时的G外服务器,用完关掉。方式很多种,几乎不用花钱。例如

  • 阿里云、腾讯云,按量付费,最低配的,一天几块钱(少喝一瓶可乐)
  • cherryServers 按小时付费,可充值 1 刀(支付宝扫码)。我上次用了 1 小时,花费 0.02 刀
  • 新用户去申请亚马逊的免费试用,需要 visa 信用卡

本文代码比较简单,直接在服务器上安装 node 环境,用 vim 编写代码运行即可。如果代码再复杂了,就把代码提交到 github 弄一个 actions 自动部署,以后再分享这些。

【注意】服务器开通以后,拿到公网 IP 看看能否在本地 ping 通,有些服务商的 IP 一开始就 ping 不通(如 vultr.com,我里面还有 20 刀,也几乎没用了)

Node 调用接口

按照 OpenAI Platform 文档 介绍,安装 npm i openai ,然后几行代码即可。

import OpenAI from 'openai'
const openai = new OpenAI({ apiKey: 'xxxxxxxxxxxx' })

async function main() {
  const completion = await openai.chat.completions.create({
    messages: [{ role: 'user', content: 'How are you today?' }], // 消息内容
    model: 'gpt-3.5-turbo',
    max_tokens: 20, // 限制返回字符,帮你节省额度
  })
  const result = completion.choices[0]
  console.log('result: ', result)
}
main()

执行代码效果如下:

2024版: 用 Node.js 调用 ChatGPT API 实现 Stream 流式聊天效果

三种 role 定义 prompt 格式

以上代码中 messages: [{ role: 'user', content: 'How are you today?' }] 其中 role 分为三种 :

  • system 设定系统身份和背景
  • user 用户信息
  • asistant 助理信息,一般用于举例 (这个比较难理解)

可以看看 OpenAI 给出的 Prompt examples ,我觉得这些例子每一个都值得看看。

例如翻译一段文字

2024版: 用 Node.js 调用 ChatGPT API 实现 Stream 流式聊天效果

再例如,一个讽刺风格的聊天机器人。这个能很好的体现 asistant 的作用。

2024版: 用 Node.js 调用 ChatGPT API 实现 Stream 流式聊天效果

Stream 流式效果

上述代码是一次性打印的,限制 20 个字符没问题,但字符数量多了就可能比较慢。

Stream 是编程开发中非常重要的概念,凡 I/O 操作都会用到 stream ,例如读取一个日志文件,发送一个网路请求等。纯前端可能接触的少,虽然也在用,但不知道。

OpenAI platform 文档中直接给出了 stream 代码非常简单,只需要加一个 stream: true 标记。

import OpenAI from 'openai'
const openai = new OpenAI({ apiKey: 'xxxxxxxxxxxx' })

async function main() {
  const stream = await openai.chat.completions.create({
    model: 'gpt-3.5-turbo',
    messages: [{ role: 'user', content: 'Introduce yourself' }],
    max_tokens: 100,
    stream: true, // stream
  })
  // 打印 stream
  for await (const chunk of stream) {
    process.stdout.write(chunk.choices[0]?.delta?.content || '')
  }
}
main()

执行代码代码效果如下

2024版: 用 Node.js 调用 ChatGPT API 实现 Stream 流式聊天效果

使用 Server-sent events 发送到前端

上述代码是在控台打印,如何把这种效果应用到 Web 网页呢?OpenAI 文档推荐使用 Server-sent events 实现。完整代码在文章最后,这只说重点。

首先,服务端要定义一个 http 服务。在返回信息时,设置 res header 'Content-Type': 'text/event-stream' ,然后通过 res.write 逐步分片返回。

res.writeHead(200, { 'Content-Type': 'text/event-stream' }) // 'text/event-stream' 标识 SSE 即 Server-Sent Events
for await (const chunk of gptStream) {
  // console.log('chunk ', JSON.stringify(chunk))
  res.write(`data: ${JSON.stringify(chunk)}\n\n`) // 注意,格式必须是 `data: xxx\n\n` !!!
}

然后,在前端网页中,定义 EventSource 并接受服务端返回的信息

  const es = new EventSource(url) // 向服务端发起请求
  es.onmessage = (event) => {
    const data = event.data || ''
    if (data === '[DONE]') {
      es.close() // 结束
      return
    }

    const obj = JSON.parse(data) // 服务端每次 res.write 返回的信息

    const content = obj.choices[0].delta.content
    if (content == null) {
      console.log('stop...')  // 可能因为其他原因停止
      es.close()
      return
    }

    answerElem.textContent += content  // 把内容追加显示到网页中,实现 stream 效果
  }

最终的效果如下图

源码链接

如对 Node 全栈 AIGC 知识库(AI 写作、协同编辑)项目 划水AI 感兴趣,欢迎私信我沟通~

源码地址 github.com/wangfupeng1… 注意看说明文档,需要新建一个 .env 文件,用于记录你的 API token ,而且这个不要泄露。

如代码运行什么问题,可以在本文评论讨论。

转载自:https://juejin.cn/post/7341797865109798938
评论
请登录