Spaces:
Paused
Paused
| import { createParser } from "eventsource-parser"; | |
| import { NextRequest, NextResponse } from "next/server"; | |
| import { auth } from "../../auth"; | |
| import { requestOpenai } from "../../common"; | |
| async function createStream(res: Response) { | |
| const encoder = new TextEncoder(); | |
| const decoder = new TextDecoder(); | |
| const stream = new ReadableStream({ | |
| async start(controller) { | |
| function onParse(event: any) { | |
| if (event.type === "event") { | |
| const data = event.data; | |
| // console.log(data) | |
| // https://beta.openai.com/docs/api-reference/completions/create#completions/create-stream | |
| if (data === "[DONE]") { | |
| controller.close(); | |
| return; | |
| } | |
| try { | |
| const json = JSON.parse(data); | |
| const text = json.choices[0].delta.content; | |
| const queue = encoder.encode(text); | |
| controller.enqueue(queue); | |
| } catch (e) { | |
| controller.error(e); | |
| } | |
| } | |
| } | |
| const parser = createParser(onParse); | |
| for await (const chunk of res.body as any) { | |
| parser.feed(decoder.decode(chunk, { stream: true })); | |
| } | |
| }, | |
| }); | |
| return stream; | |
| } | |
| function formatResponse(msg: any) { | |
| const jsonMsg = ["```json\n", JSON.stringify(msg, null, " "), "\n```"].join( | |
| "", | |
| ); | |
| return new Response(jsonMsg); | |
| } | |
| async function handle( | |
| req: NextRequest, | |
| { params }: { params: { path: string[] } }, | |
| ) { | |
| console.log("[OpenAI Route] params ", params); | |
| const authResult = auth(req); | |
| if (authResult.error) { | |
| return NextResponse.json(authResult, { | |
| status: 401, | |
| }); | |
| } | |
| try { | |
| const api = await requestOpenai(req); | |
| const contentType = api.headers.get("Content-Type") ?? ""; | |
| // streaming response | |
| if (contentType.includes("stream")) { | |
| const stream = await createStream(api); | |
| const res = new Response(stream); | |
| res.headers.set("Content-Type", contentType); | |
| return res; | |
| } | |
| // try to parse error msg | |
| try { | |
| const mayBeErrorBody = await api.json(); | |
| if (mayBeErrorBody.error) { | |
| console.error("[OpenAI Response] ", mayBeErrorBody); | |
| return formatResponse(mayBeErrorBody); | |
| } else { | |
| const res = new Response(JSON.stringify(mayBeErrorBody)); | |
| res.headers.set("Content-Type", "application/json"); | |
| res.headers.set("Cache-Control", "no-cache"); | |
| return res; | |
| } | |
| } catch (e) { | |
| console.error("[OpenAI Parse] ", e); | |
| return formatResponse({ | |
| msg: "invalid response from openai server", | |
| error: e, | |
| }); | |
| } | |
| } catch (e) { | |
| console.error("[OpenAI] ", e); | |
| return formatResponse(e); | |
| } | |
| } | |
| export const GET = handle; | |
| export const POST = handle; | |
| export const runtime = "edge"; | |