route.ts 1.7 KB

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