Spaces:
Running
Running
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"; | |