如何将 OpenAI 流响应从 Nextjs API 发送到客户端

sam*_*ang 6 javascript node.js next.js openai-api

我尝试了openai-streams + nextjs-openai,它们仅适用于 Node 18+,但是,它们在 Node 17 及更低版本上失败。我仅限于 Node 17 及更低版本,因为 Digital Oceans 应用平台目前不支持 Node 18。

我也尝试过这种方法,它在客户端运行良好,但它暴露了 API 密钥。我想在 NextJS API 路由中实现,但无法将流响应传递给客户端。

使用下面的代码,我只能从 API 路由获取第一块响应,而无法获取具有 ChatGPT 效果的流响应。请帮忙。

// /api/prompt.js

import { Configuration, OpenAIApi } from "openai";
import { Readable } from "readable-stream";

const configuration = new Configuration({
  apiKey: process.env.NEXT_PUBLIC_OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);

export default async function handler(req, res) {
  const completion = await openai.createCompletion(
    {
      model: "text-davinci-003",
      prompt: "tell me a story",
      max_tokens: 500,
      stream: true,
    },
    { responseType: "stream" }
  );

  completion.data.on("data", async (data) => {
    const lines = data
      .toString()
      .split("\n")
      .filter((line) => line.trim() !== "");

    for (const line of lines) {
      const message = line.replace(/^data: /, "");
      if (message === "[DONE]") {
        return;
      }
      try {
        const parsed = JSON.parse(message);
        const string = parsed.choices[0].text;
        Readable.from(string).pipe(res);
      } catch (error) {
        console.error("Could not JSON parse stream message", message, error);
      }
    }
  });
Run Code Online (Sandbox Code Playgroud)

// /components/Completion.js

export default function Completion() {
  const [text, setText] = useState();

  const generate = async () => {
    const response = await fetch("/api/prompt");
    console.log("response: ", response);
    const text = await response.text();
    console.log("text: ", text);
    setText((state) => state + text);
  };
  
  // ... rest
}
Run Code Online (Sandbox Code Playgroud)

C. *_*wis 2

您可以在 Node <18 上使用openai-streams/node入口点,这将返回 Node.jsReadable而不是 WHATWG ReadableStream。我将尽快更新文档以使其更加清晰。


节点:在 Next.js API 路由中使用流

如果您无法使用 Edge 运行时或出于其他原因想要使用 Node.js 流,请使用openai-streams/node

import type { NextApiRequest, NextApiResponse } from "next";
import { OpenAI } from "openai-streams/node";

export default async function test(_: NextApiRequest, res: NextApiResponse) {
  const stream = await OpenAI("completions", {
    model: "text-davinci-003",
    prompt: "Write a happy sentence.\n\n",
    max_tokens: 25,
  });

  stream.pipe(res);
}
Run Code Online (Sandbox Code Playgroud)