diff --git a/app/api/common.ts b/app/api/common.ts index dd1cc0bb80e..e0008d106b6 100644 --- a/app/api/common.ts +++ b/app/api/common.ts @@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from "next/server"; import { getServerSideConfig } from "../config/server"; import { DEFAULT_MODELS, OPENAI_BASE_URL } from "../constant"; import { collectModelTable } from "../utils/model"; -import { makeAzurePath } from "../azure"; +import { makeAzurePath, makeAzureBaseUrl } from "../azure"; const serverConfig = getServerSideConfig(); @@ -17,8 +17,42 @@ export async function requestOpenai(req: NextRequest) { "", ); - let baseUrl = - serverConfig.azureUrl || serverConfig.baseUrl || OPENAI_BASE_URL; + let requestBody: ReadableStream | string | null = req.body; + let azureUrl = serverConfig.azureUrl; + if (serverConfig.customModels && requestBody) { + try { + const modelTable = collectModelTable( + DEFAULT_MODELS, + serverConfig.customModels, + ); + const clonedBody = await req.text(); + requestBody = clonedBody; + const jsonBody = JSON.parse(clonedBody) as { model?: string }; + + const model = modelTable[jsonBody?.model ?? ""]; + if (!azureUrl && model.available === false) { + // not undefined and is false + // #1815 try to refuse gpt4 request + return NextResponse.json( + { + error: true, + message: `you are not allowed to use ${jsonBody?.model} model`, + }, + { + status: 403, + }, + ); + } else if (azureUrl && model.available === true) { + // if there is an avaliable model, update the deployment id in the url. + // otherwise leave the url unchanged. + azureUrl = makeAzureBaseUrl(azureUrl, model.name); + } + } catch (e) { + console.error("[OpenAI] gpt4 filter", e); + } + } + + let baseUrl = azureUrl || serverConfig.baseUrl || OPENAI_BASE_URL; if (!baseUrl.startsWith("http")) { baseUrl = `https://${baseUrl}`; @@ -60,7 +94,7 @@ export async function requestOpenai(req: NextRequest) { }), }, method: req.method, - body: req.body, + body: requestBody, // to fix #2485: https://stackoverflow.com/questions/55920957/cloudflare-worker-typeerror-one-time-use-body redirect: "manual", // @ts-ignore @@ -68,35 +102,6 @@ export async function requestOpenai(req: NextRequest) { signal: controller.signal, }; - // #1815 try to refuse gpt4 request - if (serverConfig.customModels && req.body) { - try { - const modelTable = collectModelTable( - DEFAULT_MODELS, - serverConfig.customModels, - ); - const clonedBody = await req.text(); - fetchOptions.body = clonedBody; - - const jsonBody = JSON.parse(clonedBody) as { model?: string }; - - // not undefined and is false - if (modelTable[jsonBody?.model ?? ""].available === false) { - return NextResponse.json( - { - error: true, - message: `you are not allowed to use ${jsonBody?.model} model`, - }, - { - status: 403, - }, - ); - } - } catch (e) { - console.error("[OpenAI] gpt4 filter", e); - } - } - try { const res = await fetch(fetchUrl, fetchOptions); diff --git a/app/azure.ts b/app/azure.ts index 48406c55ba5..774cfaa90a4 100644 --- a/app/azure.ts +++ b/app/azure.ts @@ -7,3 +7,16 @@ export function makeAzurePath(path: string, apiVersion: string) { return path; } + +export function makeAzureBaseUrl( + url: string, + deploymentId: string | undefined, +) { + const DEPLOYMENTS = "deployments"; + if (!deploymentId || url.indexOf(DEPLOYMENTS) == -1) { + return url; + } + + const end = url.indexOf(DEPLOYMENTS) + DEPLOYMENTS.length; + return url.substring(0, end) + "/" + deploymentId; +}