route.ts 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import { createParser } from "eventsource-parser";
  2. import { NextRequest } from "next/server";
  3. async function createStream(req: NextRequest) {
  4. const encoder = new TextEncoder();
  5. const decoder = new TextDecoder();
  6. let apiKey = process.env.OPENAI_API_KEY;
  7. const userApiKey = req.headers.get("token");
  8. if (userApiKey) {
  9. apiKey = userApiKey;
  10. console.log("[Stream] using user api key");
  11. }
  12. const res = await fetch("https://api.openai.com/v1/chat/completions", {
  13. headers: {
  14. "Content-Type": "application/json",
  15. Authorization: `Bearer ${apiKey}`,
  16. },
  17. method: "POST",
  18. body: req.body,
  19. });
  20. const stream = new ReadableStream({
  21. async start(controller) {
  22. function onParse(event: any) {
  23. if (event.type === "event") {
  24. const data = event.data;
  25. // https://beta.openai.com/docs/api-reference/completions/create#completions/create-stream
  26. if (data === "[DONE]") {
  27. controller.close();
  28. return;
  29. }
  30. try {
  31. const json = JSON.parse(data);
  32. const text = json.choices[0].delta.content;
  33. const queue = encoder.encode(text);
  34. controller.enqueue(queue);
  35. } catch (e) {
  36. controller.error(e);
  37. }
  38. }
  39. }
  40. const parser = createParser(onParse);
  41. for await (const chunk of res.body as any) {
  42. parser.feed(decoder.decode(chunk));
  43. }
  44. },
  45. });
  46. return stream;
  47. }
  48. export async function POST(req: NextRequest) {
  49. try {
  50. const stream = await createStream(req);
  51. return new Response(stream);
  52. } catch (error) {
  53. console.error("[Chat Stream]", error);
  54. }
  55. }
  56. export const config = {
  57. runtime: "edge",
  58. };