From 19949906c61bfc6e3b36a61719f3dcbc9fe17458 Mon Sep 17 00:00:00 2001 From: Duang Cheng Date: Wed, 19 Apr 2023 19:45:37 +0800 Subject: [PATCH 01/14] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0Azure=20opanai?= =?UTF-8?q?=20=E8=83=BD=E5=8A=9B=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/common.ts | 11 ++++++++-- app/components/settings.tsx | 41 ++++++++++++++++++++++++++++++++----- app/locales/cn.ts | 7 +++++++ app/requests.ts | 15 ++++++++++++-- app/store/access.ts | 17 +++++++++++++++ app/store/app.ts | 7 +++++++ 6 files changed, 89 insertions(+), 9 deletions(-) diff --git a/app/api/common.ts b/app/api/common.ts index 53ab18ed6d1..7fb9ff89a0b 100644 --- a/app/api/common.ts +++ b/app/api/common.ts @@ -1,15 +1,21 @@ import { NextRequest } from "next/server"; const OPENAI_URL = "api.openai.com"; +const AZURE_OPENAI_URL = "azure-openai-gpt.openai.azure.com"; const DEFAULT_PROTOCOL = "https"; const PROTOCOL = process.env.PROTOCOL ?? DEFAULT_PROTOCOL; -const BASE_URL = process.env.BASE_URL ?? OPENAI_URL; export async function requestOpenai(req: NextRequest) { const apiKey = req.headers.get("token"); const openaiPath = req.headers.get("path"); - let baseUrl = BASE_URL; + let baseUrl = OPENAI_URL; + if (openaiPath?.includes("/deployments/")) { + baseUrl = AZURE_OPENAI_URL; + } + if (process.env.BASE_URL) { + baseUrl = process.env.BASE_URL; + } if (!baseUrl.startsWith("http")) { baseUrl = `${PROTOCOL}://${baseUrl}`; @@ -22,6 +28,7 @@ export async function requestOpenai(req: NextRequest) { headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}`, + "api-key": apiKey || "", }, method: req.method, body: req.body, diff --git a/app/components/settings.tsx b/app/components/settings.tsx index d81b5b358a2..c0e144876a7 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -23,6 +23,7 @@ import { useUpdateStore, useAccessStore, ModalConfigValidator, + AZURE_API_VERSION, } from "../store"; import { Avatar } from "./chat"; @@ -466,6 +467,34 @@ export function Settings(props: { closeSettings: () => void }) { <> )} + + { + accessStore.switchAOAI(e.currentTarget.checked); + }} + > + + + {accessStore.enableAOAI ? ( + + { + accessStore.updateDeployName(e.currentTarget.value); + }} + /> + + ) : ( + <> + )} + void }) { ); }} > - {ALL_MODELS.map((v) => ( - - ))} + {(accessStore.enableAOAI ? AZURE_API_VERSION : ALL_MODELS).map( + (v) => ( + + ), + )} fetch("/api/openai?_vercel_no_cache=1", { @@ -64,7 +75,7 @@ export function requestOpenaiClient(path: string) { export async function requestChat(messages: Message[]) { const req: ChatRequest = makeRequestParam(messages, { filterBot: true }); - const res = await requestOpenaiClient("v1/chat/completions")(req); + const res = await requestOpenaiClient(getRequestPath())(req); try { const response = (await res.json()) as ChatResponse; @@ -149,7 +160,7 @@ export async function requestChatStream( method: "POST", headers: { "Content-Type": "application/json", - path: "v1/chat/completions", + path: getRequestPath(), ...getHeaders(), }, body: JSON.stringify(req), diff --git a/app/store/access.ts b/app/store/access.ts index aed131684e8..3f132097bb3 100644 --- a/app/store/access.ts +++ b/app/store/access.ts @@ -5,10 +5,15 @@ export interface AccessControlStore { accessCode: string; token: string; + enableAOAI: boolean; + azureDeployName: string; + needCode: boolean; updateToken: (_: string) => void; updateCode: (_: string) => void; + updateDeployName: (_: string) => void; + switchAOAI: (_: boolean) => void; enabledAccessControl: () => boolean; isAuthorized: () => boolean; fetch: () => void; @@ -23,6 +28,8 @@ export const useAccessStore = create()( (set, get) => ({ token: "", accessCode: "", + azureDeployName: "", + enableAOAI: false, needCode: true, enabledAccessControl() { get().fetch(); @@ -35,8 +42,18 @@ export const useAccessStore = create()( updateToken(token: string) { set((state) => ({ token })); }, + updateDeployName(azureDeployName: string) { + set((state) => ({ azureDeployName })); + }, + switchAOAI(switchStatus: boolean) { + set((state) => ({ enableAOAI: switchStatus })); + }, isAuthorized() { // has token or has code or disabled access control + if (get().enableAOAI) { + return !!get().azureDeployName && !!get().token; + } + return ( !!get().token || !!get().accessCode || !get().enabledAccessControl() ); diff --git a/app/store/app.ts b/app/store/app.ts index 8d875fee5fb..e9f7f713400 100644 --- a/app/store/app.ts +++ b/app/store/app.ts @@ -71,6 +71,13 @@ export const ROLES: Message["role"][] = ["system", "user", "assistant"]; const ENABLE_GPT4 = true; +export const AZURE_API_VERSION = [ + { + name: "2023-03-15-preview", + available: true, + }, +]; + export const ALL_MODELS = [ { name: "gpt-4", From ffe4c91be9a9b735964ddbabe5ea1dbc8b5bbbc1 Mon Sep 17 00:00:00 2001 From: Duang Cheng Date: Wed, 19 Apr 2023 19:57:11 +0800 Subject: [PATCH 02/14] feat: support multi-lang. --- app/locales/de.ts | 7 +++++++ app/locales/en.ts | 6 ++++++ app/locales/es.ts | 7 +++++++ app/locales/it.ts | 7 +++++++ app/locales/jp.ts | 7 +++++++ app/locales/tr.ts | 7 +++++++ app/locales/tw.ts | 6 ++++++ 7 files changed, 47 insertions(+) diff --git a/app/locales/de.ts b/app/locales/de.ts index e71abfaf705..465b2e4eed1 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -128,6 +128,13 @@ const de: LocaleType = { "Verwenden Sie Ihren Schlüssel, um das Zugangscode-Limit zu ignorieren", Placeholder: "OpenAI API-Schlüssel", }, + EnableAOAI: "Verwenden von Azure OpenAI", + AzureDeploymentName: { + Title: "Name der Azure OpenAI-Bereitstellungsinstanz", + SubTitle: + "Geben Sie nach dem Aktivieren von Azure OpenAI den Namen der bereitgestellten Instanz ein", + Placeholder: "Instanzname", + }, Usage: { Title: "Kontostand", SubTitle(used: any, total: any) { diff --git a/app/locales/en.ts b/app/locales/en.ts index 20e569606e3..810398bfddc 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -127,6 +127,12 @@ const en: LocaleType = { SubTitle: "Use your key to ignore access code limit", Placeholder: "OpenAI API Key", }, + EnableAOAI: "Use Azure OpenAI", + AzureDeploymentName: { + Title: "Azure OpenAI deployment instance name", + SubTitle: "After enabling Azure OpenAI, enter the deployed instance name", + Placeholder: "instance name", + }, Usage: { Title: "Account Balance", SubTitle(used: any, total: any) { diff --git a/app/locales/es.ts b/app/locales/es.ts index e2a9eb211f4..91ff801404c 100644 --- a/app/locales/es.ts +++ b/app/locales/es.ts @@ -127,6 +127,13 @@ const es: LocaleType = { SubTitle: "Utiliza tu clave para ignorar el límite de código de acceso", Placeholder: "Clave de la API de OpenAI", }, + EnableAOAI: "Uso de Azure Open AI", + AzureDeploymentName: { + Title: "Nombre de la instancia de implementación de Azure OpenAI", + SubTitle: + "Después de habilitar Azure OpenAI, ingrese el nombre de la instancia implementada", + Placeholder: "nombre de instancia", + }, Usage: { Title: "Saldo de la cuenta", SubTitle(used: any, total: any) { diff --git a/app/locales/it.ts b/app/locales/it.ts index f0453b5c35c..c97a5b1ca98 100644 --- a/app/locales/it.ts +++ b/app/locales/it.ts @@ -128,6 +128,13 @@ const it: LocaleType = { "Utilizzare la chiave per ignorare il limite del codice di accesso", Placeholder: "OpenAI API Key", }, + EnableAOAI: "Usa Azure OpenAI", + AzureDeploymentName: { + Title: "Nome dell'istanza di distribuzione di Azure OpenAI", + SubTitle: + "Dopo aver abilitato Azure OpenAI, immettere il nome dell'istanza distribuita", + Placeholder: "Nome istanza", + }, Usage: { Title: "Bilancio Account", SubTitle(used: any, total: any) { diff --git a/app/locales/jp.ts b/app/locales/jp.ts index 2818820b584..d41ba4c874d 100644 --- a/app/locales/jp.ts +++ b/app/locales/jp.ts @@ -128,6 +128,13 @@ const jp = { SubTitle: "自分のキーを使用してパスワードアクセス制限を迂回する", Placeholder: "OpenAI APIキー", }, + EnableAOAI: "Azure OpenAI を使用する", + AzureDeploymentName: { + タイトル: "Azure OpenAI 展開インスタンス名", + SubTitle: + "Azure OpenAI を有効にした後、デプロイされたインスタンス名を入力してください", + プレースホルダー: "インスタンス名", + }, Usage: { Title: "残高照会", SubTitle(used: any, total: any) { diff --git a/app/locales/tr.ts b/app/locales/tr.ts index 04a8462452f..ceef4601ffa 100644 --- a/app/locales/tr.ts +++ b/app/locales/tr.ts @@ -127,6 +127,13 @@ const tr: LocaleType = { SubTitle: "Erişim kodu sınırını yoksaymak için anahtarınızı kullanın", Placeholder: "OpenAI API Anahtarı", }, + EnableAOAI: "Azure OpenAI Kullanın", + AzureDeploymentName: { + Title: "Azure OpenAI dağıtım örneği adı", + SubTitle: + "Azure OpenAI'yi etkinleştirdikten sonra dağıtılan örnek adını girin", + Placeholder: "Örnek Adı", + }, Usage: { Title: "Hesap Bakiyesi", SubTitle(used: any, total: any) { diff --git a/app/locales/tw.ts b/app/locales/tw.ts index 44c07898df5..e28353f0151 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -124,6 +124,12 @@ const tw: LocaleType = { SubTitle: "使用自己的 Key 可規避授權訪問限制", Placeholder: "OpenAI API Key", }, + EnableAOAI: "使用 Azure OpenAI", + AzureDeploymentName: { + Title: "Azure OpenAI 部署實例名稱", + SubTitle: "啟用Azure OpenAI後, 輸入部署的實例名稱", + Placeholder: "實例名稱", + }, Usage: { Title: "帳戶餘額", SubTitle(used: any, total: any) { From 45e077cd187dc174734ec42920d6e5c8d3118904 Mon Sep 17 00:00:00 2001 From: Duang Cheng Date: Wed, 19 Apr 2023 20:04:38 +0800 Subject: [PATCH 03/14] fix: fix bugs when choosing azure api version. --- app/components/settings.tsx | 13 +++++-------- app/requests.ts | 3 +-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/app/components/settings.tsx b/app/components/settings.tsx index c0e144876a7..255881d283c 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -23,7 +23,6 @@ import { useUpdateStore, useAccessStore, ModalConfigValidator, - AZURE_API_VERSION, } from "../store"; import { Avatar } from "./chat"; @@ -617,13 +616,11 @@ export function Settings(props: { closeSettings: () => void }) { ); }} > - {(accessStore.enableAOAI ? AZURE_API_VERSION : ALL_MODELS).map( - (v) => ( - - ), - )} + {ALL_MODELS.map((v) => ( + + ))} Date: Tue, 9 May 2023 13:06:26 +0800 Subject: [PATCH 04/14] feat: change the text of the private version. --- app/components/sidebar.tsx | 2 +- app/constant.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/sidebar.tsx b/app/components/sidebar.tsx index e3273925951..fc141b01df8 100644 --- a/app/components/sidebar.tsx +++ b/app/components/sidebar.tsx @@ -98,7 +98,7 @@ export function SideBar(props: { className?: string }) {
ChatGPT Next
- Build your own AI assistant. + Your own OpenAI / AzureAI assistant.
diff --git a/app/constant.ts b/app/constant.ts index fed20cafad3..f51e3c55c99 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -1,4 +1,4 @@ -export const OWNER = "Yidadaa"; +export const OWNER = "realDuang"; export const REPO = "ChatGPT-Next-Web"; export const REPO_URL = `https://github.com/${OWNER}/${REPO}`; export const ISSUE_URL = `https://github.com/${OWNER}/${REPO}/issues`; From 0c4be68b2ed9c169cc87e1d22e5923ac3d5359a3 Mon Sep 17 00:00:00 2001 From: Duang Cheng Date: Tue, 9 May 2023 15:13:27 +0800 Subject: [PATCH 05/14] Revert "feat: change the text of the private version." This reverts commit cc9fd7cb64d0d1cd7d045708353c3c06b53d9bed. --- app/components/sidebar.tsx | 2 +- app/constant.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/sidebar.tsx b/app/components/sidebar.tsx index fc141b01df8..e3273925951 100644 --- a/app/components/sidebar.tsx +++ b/app/components/sidebar.tsx @@ -98,7 +98,7 @@ export function SideBar(props: { className?: string }) {
ChatGPT Next
- Your own OpenAI / AzureAI assistant. + Build your own AI assistant.
diff --git a/app/constant.ts b/app/constant.ts index f51e3c55c99..fed20cafad3 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -1,4 +1,4 @@ -export const OWNER = "realDuang"; +export const OWNER = "Yidadaa"; export const REPO = "ChatGPT-Next-Web"; export const REPO_URL = `https://github.com/${OWNER}/${REPO}`; export const ISSUE_URL = `https://github.com/${OWNER}/${REPO}/issues`; From 6cd1dbc16a6e1ff99aadc25b71280e579f41f285 Mon Sep 17 00:00:00 2001 From: Duang Cheng Date: Tue, 9 May 2023 16:04:17 +0800 Subject: [PATCH 06/14] feat: support azure openai custom subdomain name config. --- app/api/auth.ts | 2 +- app/api/common.ts | 9 +++++---- app/components/settings.tsx | 22 ++++++++++++++++++++-- app/components/ui-lib.tsx | 8 ++++++++ app/locales/cn.ts | 6 +++++- app/locales/de.ts | 4 ++++ app/locales/en.ts | 4 ++++ app/locales/es.ts | 4 ++++ app/locales/it.ts | 4 ++++ app/locales/jp.ts | 4 ++++ app/locales/tr.ts | 4 ++++ app/locales/tw.ts | 6 +++++- app/locales/vi.ts | 4 ++++ app/requests.ts | 4 +++- app/store/access.ts | 14 ++++++++++++-- 15 files changed, 87 insertions(+), 12 deletions(-) diff --git a/app/api/auth.ts b/app/api/auth.ts index 1c2103adc04..b369c868b6b 100644 --- a/app/api/auth.ts +++ b/app/api/auth.ts @@ -28,7 +28,7 @@ function parseApiKey(bearToken: string) { export function auth(req: NextRequest) { const authToken = req.headers.get("Authorization") ?? ""; - const aoaiApiKey = req.headers.get("api-key") ?? ""; + const aoaiApiKey = req.headers.get("azure-api-key") ?? ""; if (!!aoaiApiKey) { return { diff --git a/app/api/common.ts b/app/api/common.ts index e834183c7a2..4f3223ba18a 100644 --- a/app/api/common.ts +++ b/app/api/common.ts @@ -1,13 +1,14 @@ import { NextRequest } from "next/server"; const OPENAI_URL = "api.openai.com"; -const AZURE_OPENAI_URL = "azure-openai-gpt.openai.azure.com"; const DEFAULT_PROTOCOL = "https"; const PROTOCOL = process.env.PROTOCOL ?? DEFAULT_PROTOCOL; export async function requestOpenai(req: NextRequest) { const authValue = req.headers.get("Authorization") ?? ""; - const aoaiAuthValue = req.headers.get("api-key") ?? ""; + const azureApiKey = req.headers.get("azure-api-key") ?? ""; + const azureDomainName = req.headers.get("azure-domain-name") ?? ""; + const AZURE_OPENAI_URL = `${azureDomainName}.openai.azure.com`; const openaiPath = `${req.nextUrl.pathname}${req.nextUrl.search}`.replaceAll( "/api/openai/", "", @@ -32,7 +33,7 @@ export async function requestOpenai(req: NextRequest) { console.log("[Org ID]", process.env.OPENAI_ORG_ID); } - if (!aoaiAuthValue && (!authValue || !authValue.startsWith("Bearer sk-"))) { + if (!azureApiKey && (!authValue || !authValue.startsWith("Bearer sk-"))) { console.error("[OpenAI Request] invalid api key provided", authValue); } @@ -40,7 +41,7 @@ export async function requestOpenai(req: NextRequest) { headers: { "Content-Type": "application/json", Authorization: authValue, - "api-key": aoaiAuthValue, + "api-key": azureApiKey, ...(process.env.OPENAI_ORG_ID && { "OpenAI-Organization": process.env.OPENAI_ORG_ID, }), diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 797c73d4003..af0414b763c 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -10,7 +10,15 @@ import ClearIcon from "../icons/clear.svg"; import LoadingIcon from "../icons/three-dots.svg"; import EditIcon from "../icons/edit.svg"; import EyeIcon from "../icons/eye.svg"; -import { Input, List, ListItem, Modal, PasswordInput, Popover } from "./ui-lib"; +import { + Input, + List, + ListItem, + Modal, + PasswordInput, + Popover, + TextInput, +} from "./ui-lib"; import { ModelConfigList } from "./model-config"; import { IconButton } from "./button"; @@ -501,11 +509,21 @@ export function Settings() { {accessStore.enableAOAI ? ( <> + + { + accessStore.updateDomainName(e.currentTarget.value); + }} + /> + - ) {
); } + +export function TextInput(props: HTMLProps) { + return ( +
+ +
+ ); +} diff --git a/app/locales/cn.ts b/app/locales/cn.ts index dbfb9372a06..9651ce2b15c 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -140,10 +140,14 @@ const cn = { }, EnableAOAI: "使用 Azure OpenAI", + AzureDomainName: { + Title: "Azure OpenAI 自定义子域名", + Placeholder: "自定义子域名", + }, AzureDeploymentName: { Title: "Azure OpenAI 部署实例名称", SubTitle: "启用Azure OpenAI后, 输入部署的实例名称", - Placeholder: "实例名称", + Placeholder: "部署实例名称", }, AOAIToken: { Title: "Azure OpenAI API Key", diff --git a/app/locales/de.ts b/app/locales/de.ts index 19223516d87..4cc91b6ca4a 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -142,6 +142,10 @@ const de: LocaleType = { Placeholder: "OpenAI API-Schlüssel", }, EnableAOAI: "Verwenden von Azure OpenAI", + AzureDomainName: { + Title: "Benutzerdefinierte Azure OpenAI-Unterdomäne", + Placeholder: "benutzerdefinierte Subdomain", + }, AzureDeploymentName: { Title: "Name der Azure OpenAI-Bereitstellungsinstanz", SubTitle: diff --git a/app/locales/en.ts b/app/locales/en.ts index 28657a73f9b..5469652fac7 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -140,6 +140,10 @@ const en: LocaleType = { Placeholder: "OpenAI API Key", }, EnableAOAI: "Use Azure OpenAI", + AzureDomainName: { + Title: "Azure OpenAI custom subdomain", + Placeholder: "custom subdomain", + }, AzureDeploymentName: { Title: "Azure OpenAI deployment instance name", SubTitle: "After enabling Azure OpenAI, enter the deployed instance name", diff --git a/app/locales/es.ts b/app/locales/es.ts index b5866fcba7d..2f48dd379fd 100644 --- a/app/locales/es.ts +++ b/app/locales/es.ts @@ -140,6 +140,10 @@ const es: LocaleType = { Placeholder: "Clave de la API de OpenAI", }, EnableAOAI: "Uso de Azure Open AI", + AzureDomainName: { + Title: "Subdominio personalizado de Azure OpenAI", + Placeholder: "Subdominio personalizado", + }, AzureDeploymentName: { Title: "Nombre de la instancia de implementación de Azure OpenAI", SubTitle: diff --git a/app/locales/it.ts b/app/locales/it.ts index 9899f8de902..5131d442c64 100644 --- a/app/locales/it.ts +++ b/app/locales/it.ts @@ -141,6 +141,10 @@ const it: LocaleType = { Placeholder: "OpenAI API Key", }, EnableAOAI: "Usa Azure OpenAI", + AzureDomainName: { + Title: "Sottodominio personalizzato di Azure OpenAI", + Placeholder: "Sottodominio personalizzato", + }, AzureDeploymentName: { Title: "Nome dell'istanza di distribuzione di Azure OpenAI", SubTitle: diff --git a/app/locales/jp.ts b/app/locales/jp.ts index 7af633c536e..fac6df34fbe 100644 --- a/app/locales/jp.ts +++ b/app/locales/jp.ts @@ -142,6 +142,10 @@ const jp: LocaleType = { Placeholder: "OpenAI APIキー", }, EnableAOAI: "Azure OpenAI を使用する", + AzureDomainName: { + Title: "Azure OpenAI カスタム サブドメイン", + Placeholder: "カスタム サブドメイン", + }, AzureDeploymentName: { Title: "Azure OpenAI 展開インスタンス名", SubTitle: diff --git a/app/locales/tr.ts b/app/locales/tr.ts index 759ea97d22b..3f2b9175ccb 100644 --- a/app/locales/tr.ts +++ b/app/locales/tr.ts @@ -140,6 +140,10 @@ const tr: LocaleType = { Placeholder: "OpenAI API Anahtarı", }, EnableAOAI: "Azure OpenAI Kullanın", + AzureDomainName: { + Title: "Azure OpenAI özel alt etki alanı", + Placeholder: "özel alt etki alanı", + }, AzureDeploymentName: { Title: "Azure OpenAI dağıtım örneği adı", SubTitle: diff --git a/app/locales/tw.ts b/app/locales/tw.ts index 4e7ff621e80..470cff54be7 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -136,7 +136,11 @@ const tw: LocaleType = { SubTitle: "使用自己的 Key 可規避授權存取限制", Placeholder: "OpenAI API Key", }, - EnableAOAI: "使用 Azure OpenAI", + EnableAOAI: "啟用 Azure OpenAI", + AzureDomainName: { + Title: "Azure OpenAI 自定義子域名", + Placeholder: "自定義子域名", + }, AzureDeploymentName: { Title: "Azure OpenAI 部署實例名稱", SubTitle: "啟用Azure OpenAI後, 輸入部署的實例名稱", diff --git a/app/locales/vi.ts b/app/locales/vi.ts index fb2766a355a..cc77df70665 100644 --- a/app/locales/vi.ts +++ b/app/locales/vi.ts @@ -140,6 +140,10 @@ const vi: LocaleType = { }, EnableAOAI: "Sử dụng Azure OpenAI", + AzureDomainName: { + Title: "Tên miền phụ tùy chỉnh Azure OpenAI", + Placeholder: "tên miền phụ tùy chỉnh", + }, AzureDeploymentName: { Title: "Tên phiên bản triển khai Azure OpenAI", SubTitle: diff --git a/app/requests.ts b/app/requests.ts index 2c9ab346ca8..44f5f5d940c 100644 --- a/app/requests.ts +++ b/app/requests.ts @@ -63,7 +63,9 @@ function getHeaders() { } if (accessStore.enableAOAI && validString(accessStore.aoaiToken)) { - headers["api-key"] = accessStore.aoaiToken; + headers["azure-api-key"] = accessStore.aoaiToken; + headers["azure-domain-name"] = accessStore.azureDomainName; + headers["azure-deployment-name"] = accessStore.azureDeployName; } return headers; diff --git a/app/store/access.ts b/app/store/access.ts index d294964c61d..3846ec94735 100644 --- a/app/store/access.ts +++ b/app/store/access.ts @@ -8,6 +8,7 @@ export interface AccessControlStore { token: string; enableAOAI: boolean; + azureDomainName: string; azureDeployName: string; aoaiToken: string; @@ -18,6 +19,7 @@ export interface AccessControlStore { updateToken: (_: string) => void; updateCode: (_: string) => void; switchAOAI: (_: boolean) => void; + updateDomainName: (_: string) => void; updateDeployName: (_: string) => void; updateAOAIToken: (_: string) => void; enabledAccessControl: () => boolean; @@ -33,7 +35,8 @@ export const useAccessStore = create()( token: "", accessCode: "", - enableAOAI: false, + enableAOAI: false as boolean, + azureDomainName: "", azureDeployName: "", aoaiToken: "", @@ -56,6 +59,9 @@ export const useAccessStore = create()( switchAOAI(switchStatus: boolean) { set((state) => ({ enableAOAI: switchStatus })); }, + updateDomainName(azureDomainName: string) { + set((state) => ({ azureDomainName })); + }, updateDeployName(azureDeployName: string) { set((state) => ({ azureDeployName })); }, @@ -68,7 +74,11 @@ export const useAccessStore = create()( // has token or has code or disabled access control if (get().enableAOAI) { - return !!get().azureDeployName && !!get().aoaiToken; + return ( + !!get().azureDomainName && + !!get().azureDeployName && + !!get().aoaiToken + ); } return ( From d43bb20753f32f974a7d838262448a6a92b38211 Mon Sep 17 00:00:00 2001 From: Duang Cheng Date: Wed, 17 May 2023 17:38:31 +0800 Subject: [PATCH 07/14] fix: fix merge conflict. --- app/client/api.ts | 6 + app/client/platforms/openai.ts | 11 +- app/requests.ts | 309 --------------------------------- yarn.lock | 2 +- 4 files changed, 17 insertions(+), 311 deletions(-) delete mode 100644 app/requests.ts diff --git a/app/client/api.ts b/app/client/api.ts index c76fab57f65..87ff6ff075b 100644 --- a/app/client/api.ts +++ b/app/client/api.ts @@ -79,5 +79,11 @@ export function getHeaders() { ); } + if (accessStore.enableAOAI && validString(accessStore.aoaiToken)) { + headers["azure-api-key"] = accessStore.aoaiToken; + headers["azure-domain-name"] = accessStore.azureDomainName; + headers["azure-deployment-name"] = accessStore.azureDeployName; + } + return headers; } diff --git a/app/client/platforms/openai.ts b/app/client/platforms/openai.ts index 63587440f75..37cdd5c8271 100644 --- a/app/client/platforms/openai.ts +++ b/app/client/platforms/openai.ts @@ -10,10 +10,19 @@ import { import { prettyObject } from "@/app/utils/format"; export class ChatGPTApi implements LLMApi { - public ChatPath = "v1/chat/completions"; + // public ChatPath = "v1/chat/completions"; public UsagePath = "dashboard/billing/usage"; public SubsPath = "dashboard/billing/subscription"; + public get ChatPath() { + const OPENAI_REQUEST_PATH = "v1/chat/completions"; + const { enableAOAI, azureDeployName } = useAccessStore.getState(); + if (!enableAOAI) return OPENAI_REQUEST_PATH; + + const AZURE_REQUEST_PATH = `openai/deployments/${azureDeployName}/chat/completions?api-version=2023-03-15-preview`; + return AZURE_REQUEST_PATH; + } + path(path: string): string { let openaiUrl = useAccessStore.getState().openaiUrl; if (openaiUrl.endsWith("/")) { diff --git a/app/requests.ts b/app/requests.ts deleted file mode 100644 index 44f5f5d940c..00000000000 --- a/app/requests.ts +++ /dev/null @@ -1,309 +0,0 @@ -import type { ChatRequest, ChatResponse } from "./api/openai/typing"; -import { - Message, - ModelConfig, - ModelType, - useAccessStore, - useAppConfig, - useChatStore, -} from "./store"; -import { showToast } from "./components/ui-lib"; -import { ACCESS_CODE_PREFIX } from "./constant"; - -const TIME_OUT_MS = 60000; - -const makeRequestParam = ( - messages: Message[], - options?: { - stream?: boolean; - overrideModel?: ModelType; - }, -): ChatRequest => { - let sendMessages = messages.map((v) => ({ - role: v.role, - content: v.content, - })); - - const modelConfig = { - ...useAppConfig.getState().modelConfig, - ...useChatStore.getState().currentSession().mask.modelConfig, - }; - - // override model config - if (options?.overrideModel) { - modelConfig.model = options.overrideModel; - } - - return { - messages: sendMessages, - stream: options?.stream, - model: modelConfig.model, - temperature: modelConfig.temperature, - presence_penalty: modelConfig.presence_penalty, - }; -}; - -function getHeaders() { - const accessStore = useAccessStore.getState(); - let headers: Record = {}; - - const makeBearer = (token: string) => `Bearer ${token.trim()}`; - const validString = (x: string) => x && x.length > 0; - - // use user's api key first - if (validString(accessStore.token)) { - headers.Authorization = makeBearer(accessStore.token); - } else if ( - accessStore.enabledAccessControl() && - validString(accessStore.accessCode) - ) { - headers.Authorization = makeBearer( - ACCESS_CODE_PREFIX + accessStore.accessCode, - ); - } - - if (accessStore.enableAOAI && validString(accessStore.aoaiToken)) { - headers["azure-api-key"] = accessStore.aoaiToken; - headers["azure-domain-name"] = accessStore.azureDomainName; - headers["azure-deployment-name"] = accessStore.azureDeployName; - } - - return headers; -} - -function getRequestPath() { - const openaiUrl = useAccessStore.getState().openaiUrl; - const OPENAI_REQUEST_PATH = openaiUrl + "v1/chat/completions"; - - const { enableAOAI, azureDeployName } = useAccessStore.getState(); - if (!enableAOAI) return OPENAI_REQUEST_PATH; - - const AZURE_REQUEST_PATH = `${openaiUrl}openai/deployments/${azureDeployName}/chat/completions?api-version=2023-03-15-preview`; - return AZURE_REQUEST_PATH; -} - -export function requestOpenaiClient(path: string) { - return (body: any, method = "POST") => - fetch(path, { - method, - body: body && JSON.stringify(body), - headers: getHeaders(), - }); -} - -export async function requestChat( - messages: Message[], - options?: { - model?: ModelType; - }, -) { - const req: ChatRequest = makeRequestParam(messages, { - overrideModel: options?.model, - }); - - const res = await requestOpenaiClient(getRequestPath())(req); - - try { - const response = (await res.json()) as ChatResponse; - return response; - } catch (error) { - console.error("[Request Chat] ", error, res.body); - } -} - -export async function requestUsage() { - const { enableAOAI } = useAccessStore.getState(); - if (enableAOAI) return; - - const formatDate = (d: Date) => - `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, "0")}-${d - .getDate() - .toString() - .padStart(2, "0")}`; - const ONE_DAY = 1 * 24 * 60 * 60 * 1000; - const now = new Date(); - const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1); - const startDate = formatDate(startOfMonth); - const endDate = formatDate(new Date(Date.now() + ONE_DAY)); - - const openaiUrl = useAccessStore.getState().openaiUrl; - const [used, subs] = await Promise.all([ - requestOpenaiClient( - `${openaiUrl}dashboard/billing/usage?start_date=${startDate}&end_date=${endDate}`, - )(null, "GET"), - requestOpenaiClient(`${openaiUrl}dashboard/billing/subscription`)( - null, - "GET", - ), - ]); - - const response = (await used.json()) as { - total_usage?: number; - error?: { - type: string; - message: string; - }; - }; - - const total = (await subs.json()) as { - hard_limit_usd?: number; - }; - - if (response.error && response.error.type) { - showToast(response.error.message); - return; - } - - if (response.total_usage) { - response.total_usage = Math.round(response.total_usage) / 100; - } - - if (total.hard_limit_usd) { - total.hard_limit_usd = Math.round(total.hard_limit_usd * 100) / 100; - } - - return { - used: response.total_usage, - subscription: total.hard_limit_usd, - }; -} - -export async function requestChatStream( - messages: Message[], - options?: { - modelConfig?: ModelConfig; - overrideModel?: ModelType; - onMessage: (message: string, done: boolean) => void; - onError: (error: Error, statusCode?: number) => void; - onController?: (controller: AbortController) => void; - }, -) { - const req = makeRequestParam(messages, { - stream: true, - overrideModel: options?.overrideModel, - }); - - console.log("[Request] ", req); - - const controller = new AbortController(); - const reqTimeoutId = setTimeout(() => controller.abort(), TIME_OUT_MS); - - try { - const requestPath = getRequestPath(); - const res = await fetch(requestPath, { - method: "POST", - headers: { - "Content-Type": "application/json", - // path: getRequestPath(), - ...getHeaders(), - }, - body: JSON.stringify(req), - signal: controller.signal, - }); - - clearTimeout(reqTimeoutId); - - let responseText = ""; - - const finish = () => { - options?.onMessage(responseText, true); - controller.abort(); - }; - - if (res.ok) { - const reader = res.body?.getReader(); - const decoder = new TextDecoder(); - - options?.onController?.(controller); - - while (true) { - const resTimeoutId = setTimeout(() => finish(), TIME_OUT_MS); - const content = await reader?.read(); - clearTimeout(resTimeoutId); - - if (!content || !content.value) { - break; - } - - const text = decoder.decode(content.value, { stream: true }); - responseText += text; - - const done = content.done; - options?.onMessage(responseText, false); - - if (done) { - break; - } - } - - finish(); - } else if (res.status === 401) { - console.error("Unauthorized"); - options?.onError(new Error("Unauthorized"), res.status); - } else { - console.error("Stream Error", res.body); - options?.onError(new Error("Stream Error"), res.status); - } - } catch (err) { - console.error("NetWork Error", err); - options?.onError(err as Error); - } -} - -export async function requestWithPrompt( - messages: Message[], - prompt: string, - options?: { - model?: ModelType; - }, -) { - messages = messages.concat([ - { - role: "user", - content: prompt, - date: new Date().toLocaleString(), - }, - ]); - - const res = await requestChat(messages, options); - - return res?.choices?.at(0)?.message?.content ?? ""; -} - -// To store message streaming controller -export const ControllerPool = { - controllers: {} as Record, - - addController( - sessionIndex: number, - messageId: number, - controller: AbortController, - ) { - const key = this.key(sessionIndex, messageId); - this.controllers[key] = controller; - return key; - }, - - stop(sessionIndex: number, messageId: number) { - const key = this.key(sessionIndex, messageId); - const controller = this.controllers[key]; - controller?.abort(); - }, - - stopAll() { - Object.values(this.controllers).forEach((v) => v.abort()); - }, - - hasPending() { - return Object.values(this.controllers).length > 0; - }, - - remove(sessionIndex: number, messageId: number) { - const key = this.key(sessionIndex, messageId); - delete this.controllers[key]; - }, - - key(sessionIndex: number, messageIndex: number) { - return `${sessionIndex},${messageIndex}`; - }, -}; diff --git a/yarn.lock b/yarn.lock index e54a69e48cf..4c46f8601ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1113,7 +1113,7 @@ "@microsoft/fetch-event-source@^2.0.1": version "2.0.1" - resolved "https://registry.npmmirror.com/@microsoft/fetch-event-source/-/fetch-event-source-2.0.1.tgz#9ceecc94b49fbaa15666e38ae8587f64acce007d" + resolved "https://registry.yarnpkg.com/@microsoft/fetch-event-source/-/fetch-event-source-2.0.1.tgz#9ceecc94b49fbaa15666e38ae8587f64acce007d" integrity sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA== "@next/env@13.4.2": From 3e5c3827323653b42e74085e81a6eb06d45a54b1 Mon Sep 17 00:00:00 2001 From: Duang Cheng Date: Wed, 17 May 2023 17:45:10 +0800 Subject: [PATCH 08/14] chore: change the owner. --- app/constant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/constant.ts b/app/constant.ts index 577c0af69cd..be59445cfcb 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -1,4 +1,4 @@ -export const OWNER = "Yidadaa"; +export const OWNER = "realDuang"; export const REPO = "ChatGPT-Next-Web"; export const REPO_URL = `https://github.com/${OWNER}/${REPO}`; export const ISSUE_URL = `https://github.com/${OWNER}/${REPO}/issues`; From 1c5e85a258f992a0cce01ee5f850f416b9e92a4a Mon Sep 17 00:00:00 2001 From: Duang Cheng Date: Wed, 17 May 2023 18:52:52 +0800 Subject: [PATCH 09/14] chore: support cs language. --- app/locales/cs.ts | 16 ++++++++++++++++ app/locales/ru.ts | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/app/locales/cs.ts b/app/locales/cs.ts index 1bf7a169623..9eeb7cece28 100644 --- a/app/locales/cs.ts +++ b/app/locales/cs.ts @@ -141,6 +141,22 @@ const cs: LocaleType = { SubTitle: "Použitím klíče ignorujete omezení přístupového kódu", Placeholder: "Klíč API OpenAI", }, + + EnableAOAI: "Use Azure OpenAI", + AzureDomainName: { + Title: "Azure OpenAI custom subdomain", + Placeholder: "custom subdomain", + }, + AzureDeploymentName: { + Title: "Azure OpenAI deployment instance name", + SubTitle: "After enabling Azure OpenAI, enter the deployed instance name", + Placeholder: "instance name", + }, + AOAIToken: { + Title: "Azure OpenAI API Key", + Placeholder: "Azure OpenAI API Key", + }, + Usage: { Title: "Stav účtu", SubTitle(used: any, total: any) { diff --git a/app/locales/ru.ts b/app/locales/ru.ts index 1ee0ec5cabe..ed549176291 100644 --- a/app/locales/ru.ts +++ b/app/locales/ru.ts @@ -142,6 +142,22 @@ const ru: LocaleType = { SubTitle: "Используйте свой ключ, чтобы игнорировать лимит доступа", Placeholder: "API ключ OpenAI", }, + + EnableAOAI: "Use Azure OpenAI", + AzureDomainName: { + Title: "Azure OpenAI custom subdomain", + Placeholder: "custom subdomain", + }, + AzureDeploymentName: { + Title: "Azure OpenAI deployment instance name", + SubTitle: "After enabling Azure OpenAI, enter the deployed instance name", + Placeholder: "instance name", + }, + AOAIToken: { + Title: "Azure OpenAI API Key", + Placeholder: "Azure OpenAI API Key", + }, + Usage: { Title: "Баланс аккаунта", SubTitle(used: any, total: any) { From 501570977bb75760acebdfde6caeab8db0454467 Mon Sep 17 00:00:00 2001 From: Duang Cheng Date: Wed, 24 May 2023 18:27:01 +0800 Subject: [PATCH 10/14] fix: fix the wrong domain request when using azure api --- app/client/api.ts | 6 ++++++ app/client/platforms/openai.ts | 21 +++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/app/client/api.ts b/app/client/api.ts index a966d7334cc..e67e07f0797 100644 --- a/app/client/api.ts +++ b/app/client/api.ts @@ -80,5 +80,11 @@ export function getHeaders() { ); } + if (accessStore.enableAOAI && validString(accessStore.aoaiToken)) { + headers["azure-api-key"] = accessStore.aoaiToken; + headers["azure-domain-name"] = accessStore.azureDomainName; + headers["azure-deployment-name"] = accessStore.azureDeployName; + } + return headers; } diff --git a/app/client/platforms/openai.ts b/app/client/platforms/openai.ts index 84c4a2df077..b1b55d1b039 100644 --- a/app/client/platforms/openai.ts +++ b/app/client/platforms/openai.ts @@ -1,5 +1,10 @@ import { REQUEST_TIMEOUT_MS } from "@/app/constant"; -import { useAccessStore, useAppConfig, useChatStore } from "@/app/store"; +import { + useAccessStore, + useAppConfig, + useChatStore, + AZURE_API_VERSION, +} from "@/app/store"; import { ChatOptions, getHeaders, LLMApi, LLMUsage } from "../api"; import Locale from "../../locales"; @@ -10,10 +15,21 @@ import { import { prettyObject } from "@/app/utils/format"; export class ChatGPTApi implements LLMApi { - public ChatPath = "v1/chat/completions"; public UsagePath = "dashboard/billing/usage"; public SubsPath = "dashboard/billing/subscription"; + public get ChatPath() { + const OPENAI_REQUEST_PATH = "v1/chat/completions"; + const { enableAOAI, azureDeployName } = useAccessStore.getState(); + if (!enableAOAI) return OPENAI_REQUEST_PATH; + + // For now azure api only support one version + const azureApiVersion = AZURE_API_VERSION[0].name; + + const AZURE_REQUEST_PATH = `openai/deployments/${azureDeployName}/chat/completions?api-version=${azureApiVersion}`; + return AZURE_REQUEST_PATH; + } + path(path: string): string { let openaiUrl = useAccessStore.getState().openaiUrl; if (openaiUrl.endsWith("/")) { @@ -163,6 +179,7 @@ export class ChatGPTApi implements LLMApi { } } async usage() { + // const formatDate = (d: Date) => `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, "0")}-${d .getDate() From 39f6d85a264cee87543d970e1a7acdefb3447ae6 Mon Sep 17 00:00:00 2001 From: Duang Cheng Date: Wed, 24 May 2023 18:37:19 +0800 Subject: [PATCH 11/14] fix: disable usage check when aoai enabled. --- app/client/platforms/openai.ts | 1 - app/components/settings.tsx | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/client/platforms/openai.ts b/app/client/platforms/openai.ts index b1b55d1b039..2cdb991daf6 100644 --- a/app/client/platforms/openai.ts +++ b/app/client/platforms/openai.ts @@ -179,7 +179,6 @@ export class ChatGPTApi implements LLMApi { } } async usage() { - // const formatDate = (d: Date) => `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, "0")}-${d .getDate() diff --git a/app/components/settings.tsx b/app/components/settings.tsx index e3730e7d497..bfa3e744372 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -265,7 +265,8 @@ export function Settings() { const customCount = promptStore.getUserPrompts().length ?? 0; const [shouldShowPromptModal, setShowPromptModal] = useState(false); - const showUsage = accessStore.isAuthorized(); + // For now azure openai api do not expose usage api + const showUsage = accessStore.isAuthorized() && !accessStore.enableAOAI; useEffect(() => { // checks per minutes checkUpdate(); From f890741eadad5205df81fdd4eacb8859c482755e Mon Sep 17 00:00:00 2001 From: LaChimere Date: Thu, 1 Jun 2023 21:50:14 +0800 Subject: [PATCH 12/14] Block model config UI when using Azure OpenAI --- app/components/mask.tsx | 33 +++++++++++++++++++-- app/components/model-config.tsx | 52 ++++++++++++++++++++------------- 2 files changed, 61 insertions(+), 24 deletions(-) diff --git a/app/components/mask.tsx b/app/components/mask.tsx index de724e26d23..33d6c0ebd8b 100644 --- a/app/components/mask.tsx +++ b/app/components/mask.tsx @@ -13,15 +13,29 @@ import EyeIcon from "../icons/eye.svg"; import CopyIcon from "../icons/copy.svg"; import { DEFAULT_MASK_AVATAR, Mask, useMaskStore } from "../store/mask"; -import { ChatMessage, ModelConfig, useAppConfig, useChatStore } from "../store"; +import { + ChatMessage, + ModelConfig, + useAccessStore, + useAppConfig, + useChatStore, +} from "../store"; import { ROLES } from "../client/api"; -import { Input, List, ListItem, Modal, Popover, Select } from "./ui-lib"; +import { + Input, + List, + ListItem, + Modal, + Popover, + Select, + TextInput, +} from "./ui-lib"; import { Avatar, AvatarPicker } from "./emoji"; import Locale, { AllLangs, ALL_LANG_OPTIONS, Lang } from "../locales"; import { useNavigate } from "react-router-dom"; import chatStyle from "./chat.module.scss"; -import { useEffect, useState } from "react"; +import { useState } from "react"; import { downloadAs, readFromFile } from "../utils"; import { Updater } from "../typing"; import { ModelConfigList } from "./model-config"; @@ -59,6 +73,8 @@ export function MaskConfig(props: { const globalConfig = useAppConfig(); + const accessStore = useAccessStore(); + return ( <> + {accessStore.enableAOAI ? ( + + + + + + ) : null} + void) => void; }) { + const accessStore = useAccessStore(); + return ( <> - - - + {accessStore.enableAOAI ? null : ( + + + + )} + Date: Thu, 29 Jun 2023 17:49:06 +0800 Subject: [PATCH 13/14] fix: deal some conflict in web endpoint --- app/api/common.ts | 15 +--------- app/client/api.ts | 4 +-- app/client/platforms/openai.ts | 14 +++++---- app/components/settings.tsx | 55 +++++++++++++++++----------------- app/components/ui-lib.tsx | 8 ----- app/locales/cn.ts | 10 +++---- app/locales/cs.ts | 6 ++-- app/locales/de.ts | 6 ++-- app/locales/en.ts | 6 ++-- app/locales/es.ts | 6 ++-- app/locales/it.ts | 6 ++-- app/locales/jp.ts | 6 ++-- app/locales/ru.ts | 6 ++-- app/locales/tr.ts | 6 ++-- app/locales/tw.ts | 6 ++-- app/locales/vi.ts | 6 ++-- app/store/access.ts | 16 +++++----- app/store/config.ts | 4 +++ 18 files changed, 84 insertions(+), 102 deletions(-) diff --git a/app/api/common.ts b/app/api/common.ts index 941284265de..22bd5d4a409 100644 --- a/app/api/common.ts +++ b/app/api/common.ts @@ -9,21 +9,12 @@ const DISABLE_GPT4 = !!process.env.DISABLE_GPT4; export async function requestOpenai(req: NextRequest) { const controller = new AbortController(); const authValue = req.headers.get("Authorization") ?? ""; - const azureApiKey = req.headers.get("azure-api-key") ?? ""; - const azureDomainName = req.headers.get("azure-domain-name") ?? ""; - const AZURE_OPENAI_URL = `${azureDomainName}.openai.azure.com`; const openaiPath = `${req.nextUrl.pathname}${req.nextUrl.search}`.replaceAll( "/api/openai/", "", ); - let baseUrl = OPENAI_URL; - if (openaiPath?.includes("/deployments/")) { - baseUrl = AZURE_OPENAI_URL; - } - if (process.env.BASE_URL) { - baseUrl = process.env.BASE_URL; - } + let baseUrl = BASE_URL; if (!baseUrl.startsWith("http")) { baseUrl = `${PROTOCOL}://${baseUrl}`; @@ -36,9 +27,6 @@ export async function requestOpenai(req: NextRequest) { console.log("[Org ID]", process.env.OPENAI_ORG_ID); } - if (!azureApiKey && (!authValue || !authValue.startsWith("Bearer sk-"))) { - console.error("[OpenAI Request] invalid api key provided", authValue); - } const timeoutId = setTimeout(() => { controller.abort(); }, 10 * 60 * 1000); @@ -48,7 +36,6 @@ export async function requestOpenai(req: NextRequest) { headers: { "Content-Type": "application/json", Authorization: authValue, - "api-key": azureApiKey, ...(process.env.OPENAI_ORG_ID && { "OpenAI-Organization": process.env.OPENAI_ORG_ID, }), diff --git a/app/client/api.ts b/app/client/api.ts index 2c7a5b8f0c0..b62f6638a30 100644 --- a/app/client/api.ts +++ b/app/client/api.ts @@ -142,9 +142,7 @@ export function getHeaders() { } if (accessStore.enableAOAI && validString(accessStore.aoaiToken)) { - headers["azure-api-key"] = accessStore.aoaiToken; - headers["azure-domain-name"] = accessStore.azureDomainName; - headers["azure-deployment-name"] = accessStore.azureDeployName; + headers["api-key"] = accessStore.aoaiToken; } return headers; diff --git a/app/client/platforms/openai.ts b/app/client/platforms/openai.ts index cbab01ee71b..3049e65f7ae 100644 --- a/app/client/platforms/openai.ts +++ b/app/client/platforms/openai.ts @@ -19,12 +19,8 @@ import { import { prettyObject } from "@/app/utils/format"; export class ChatGPTApi implements LLMApi { - // public ChatPath = "v1/chat/completions"; - public UsagePath = "dashboard/billing/usage"; - public SubsPath = "dashboard/billing/subscription"; - public get ChatPath() { - const OPENAI_REQUEST_PATH = "v1/chat/completions"; + const OPENAI_REQUEST_PATH = OpenaiPath.ChatPath; const { enableAOAI, azureDeployName } = useAccessStore.getState(); if (!enableAOAI) return OPENAI_REQUEST_PATH; @@ -40,6 +36,12 @@ export class ChatGPTApi implements LLMApi { if (openaiUrl.length === 0) { openaiUrl = DEFAULT_API_HOST; } + + const { enableAOAI, azureEndpoint } = useAccessStore.getState(); + if (enableAOAI) { + openaiUrl = azureEndpoint; + } + if (openaiUrl.endsWith("/")) { openaiUrl = openaiUrl.slice(0, openaiUrl.length - 1); } @@ -80,7 +82,7 @@ export class ChatGPTApi implements LLMApi { options.onController?.(controller); try { - const chatPath = this.path(OpenaiPath.ChatPath); + const chatPath = this.path(this.ChatPath); const chatPayload = { method: "POST", body: JSON.stringify(requestPayload), diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 446cae56f1e..d0cedf12fc7 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -17,7 +17,6 @@ import { Modal, PasswordInput, Popover, - TextInput, Select, showConfirm, } from "./ui-lib"; @@ -608,26 +607,16 @@ export function Settings() { {accessStore.enableAOAI ? ( <> - - { - accessStore.updateDomainName(e.currentTarget.value); - }} - /> - - { - accessStore.updateDeployName(e.currentTarget.value); + accessStore.updateAzureDeployName(e.currentTarget.value); }} /> @@ -641,6 +630,16 @@ export function Settings() { }} /> + + { + accessStore.updateAzureEndpoint(e.currentTarget.value); + }} + /> + ) : null} @@ -687,23 +686,23 @@ export function Settings() { )} ) : null} + {!accessStore.hideUserApiKey ? ( + + + accessStore.updateOpenAiUrl(e.currentTarget.value) + } + > + + ) : null} ) : null} - {!accessStore.hideUserApiKey ? ( - - - accessStore.updateOpenAiUrl(e.currentTarget.value) - } - > - - ) : null} diff --git a/app/components/ui-lib.tsx b/app/components/ui-lib.tsx index b2483411192..44d89c3fc4a 100644 --- a/app/components/ui-lib.tsx +++ b/app/components/ui-lib.tsx @@ -250,14 +250,6 @@ export function PasswordInput(props: HTMLProps) { ); } -export function TextInput(props: HTMLProps) { - return ( -
- -
- ); -} - export function Select( props: React.DetailedHTMLProps< React.SelectHTMLAttributes, diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 56246e7c7ac..0186814e2a9 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -193,14 +193,14 @@ const cn = { }, EnableAOAI: "使用 Azure OpenAI", - AzureDomainName: { - Title: "Azure OpenAI 自定义子域名", - Placeholder: "自定义子域名", + AzureEndpoint: { + Title: "Azure OpenAI Endpoint", + Placeholder: "https://docs-test-001.openai.azure.com/", }, AzureDeploymentName: { Title: "Azure OpenAI 部署实例名称", - SubTitle: "启用Azure OpenAI后, 输入部署的实例名称", - Placeholder: "部署实例名称", + SubTitle: "此值将对应于在部署模型时为部署选择的自定义名称", + Placeholder: "部署自定义名称", }, AOAIToken: { Title: "Azure OpenAI API Key", diff --git a/app/locales/cs.ts b/app/locales/cs.ts index f346e78b2aa..5752b5e7de2 100644 --- a/app/locales/cs.ts +++ b/app/locales/cs.ts @@ -124,9 +124,9 @@ const cs: PartialLocaleType = { }, EnableAOAI: "Use Azure OpenAI", - AzureDomainName: { - Title: "Azure OpenAI custom subdomain", - Placeholder: "custom subdomain", + AzureEndpoint: { + Title: "Azure OpenAI Endpoint", + Placeholder: "https://docs-test-001.openai.azure.com/", }, AzureDeploymentName: { Title: "Azure OpenAI deployment instance name", diff --git a/app/locales/de.ts b/app/locales/de.ts index c36ebf46fc3..453951eeafe 100644 --- a/app/locales/de.ts +++ b/app/locales/de.ts @@ -124,9 +124,9 @@ const de: PartialLocaleType = { Placeholder: "OpenAI API-Schlüssel", }, EnableAOAI: "Verwenden von Azure OpenAI", - AzureDomainName: { - Title: "Benutzerdefinierte Azure OpenAI-Unterdomäne", - Placeholder: "benutzerdefinierte Subdomain", + AzureEndpoint: { + Title: "Azure OpenAI Endpoint", + Placeholder: "https://docs-test-001.openai.azure.com/", }, AzureDeploymentName: { Title: "Name der Azure OpenAI-Bereitstellungsinstanz", diff --git a/app/locales/en.ts b/app/locales/en.ts index a4dfda7c71d..1c61f35a72a 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -193,9 +193,9 @@ const en: LocaleType = { Placeholder: "OpenAI API Key", }, EnableAOAI: "Use Azure OpenAI", - AzureDomainName: { - Title: "Azure OpenAI custom subdomain", - Placeholder: "custom subdomain", + AzureEndpoint: { + Title: "Azure OpenAI Endpoint", + Placeholder: "https://docs-test-001.openai.azure.com/", }, AzureDeploymentName: { Title: "Azure OpenAI deployment instance name", diff --git a/app/locales/es.ts b/app/locales/es.ts index 8c1c27be7bb..37553ffda8e 100644 --- a/app/locales/es.ts +++ b/app/locales/es.ts @@ -123,9 +123,9 @@ const es: PartialLocaleType = { Placeholder: "Clave de la API de OpenAI", }, EnableAOAI: "Uso de Azure Open AI", - AzureDomainName: { - Title: "Subdominio personalizado de Azure OpenAI", - Placeholder: "Subdominio personalizado", + AzureEndpoint: { + Title: "Azure OpenAI Endpoint", + Placeholder: "https://docs-test-001.openai.azure.com/", }, AzureDeploymentName: { Title: "Nombre de la instancia de implementación de Azure OpenAI", diff --git a/app/locales/it.ts b/app/locales/it.ts index 705f8edb967..d837025177b 100644 --- a/app/locales/it.ts +++ b/app/locales/it.ts @@ -124,9 +124,9 @@ const it: PartialLocaleType = { Placeholder: "OpenAI API Key", }, EnableAOAI: "Usa Azure OpenAI", - AzureDomainName: { - Title: "Sottodominio personalizzato di Azure OpenAI", - Placeholder: "Sottodominio personalizzato", + AzureEndpoint: { + Title: "Azure OpenAI Endpoint", + Placeholder: "https://docs-test-001.openai.azure.com/", }, AzureDeploymentName: { Title: "Nome dell'istanza di distribuzione di Azure OpenAI", diff --git a/app/locales/jp.ts b/app/locales/jp.ts index 9d57fb57b1d..e2a1564a3de 100644 --- a/app/locales/jp.ts +++ b/app/locales/jp.ts @@ -125,9 +125,9 @@ const jp: PartialLocaleType = { Placeholder: "OpenAI APIキー", }, EnableAOAI: "Azure OpenAI を使用する", - AzureDomainName: { - Title: "Azure OpenAI カスタム サブドメイン", - Placeholder: "カスタム サブドメイン", + AzureEndpoint: { + Title: "Azure OpenAI Endpoint", + Placeholder: "https://docs-test-001.openai.azure.com/", }, AzureDeploymentName: { Title: "Azure OpenAI 展開インスタンス名", diff --git a/app/locales/ru.ts b/app/locales/ru.ts index 3b9653d816d..a21148e0e3c 100644 --- a/app/locales/ru.ts +++ b/app/locales/ru.ts @@ -125,9 +125,9 @@ const ru: PartialLocaleType = { }, EnableAOAI: "Use Azure OpenAI", - AzureDomainName: { - Title: "Azure OpenAI custom subdomain", - Placeholder: "custom subdomain", + AzureEndpoint: { + Title: "Azure OpenAI Endpoint", + Placeholder: "https://docs-test-001.openai.azure.com/", }, AzureDeploymentName: { Title: "Azure OpenAI deployment instance name", diff --git a/app/locales/tr.ts b/app/locales/tr.ts index cce8e350843..14d603707e5 100644 --- a/app/locales/tr.ts +++ b/app/locales/tr.ts @@ -123,9 +123,9 @@ const tr: PartialLocaleType = { Placeholder: "OpenAI API Anahtarı", }, EnableAOAI: "Azure OpenAI Kullanın", - AzureDomainName: { - Title: "Azure OpenAI özel alt etki alanı", - Placeholder: "özel alt etki alanı", + AzureEndpoint: { + Title: "Azure OpenAI Endpoint", + Placeholder: "https://docs-test-001.openai.azure.com/", }, AzureDeploymentName: { Title: "Azure OpenAI dağıtım örneği adı", diff --git a/app/locales/tw.ts b/app/locales/tw.ts index 3db990aa77d..6f520ffebfe 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -120,9 +120,9 @@ const tw: PartialLocaleType = { Placeholder: "OpenAI API Key", }, EnableAOAI: "啟用 Azure OpenAI", - AzureDomainName: { - Title: "Azure OpenAI 自定義子域名", - Placeholder: "自定義子域名", + AzureEndpoint: { + Title: "Azure OpenAI Endpoint", + Placeholder: "https://docs-test-001.openai.azure.com/", }, AzureDeploymentName: { Title: "Azure OpenAI 部署實例名稱", diff --git a/app/locales/vi.ts b/app/locales/vi.ts index 9d053cd4a89..90b596c7c69 100644 --- a/app/locales/vi.ts +++ b/app/locales/vi.ts @@ -123,9 +123,9 @@ const vi: PartialLocaleType = { }, EnableAOAI: "Sử dụng Azure OpenAI", - AzureDomainName: { - Title: "Tên miền phụ tùy chỉnh Azure OpenAI", - Placeholder: "tên miền phụ tùy chỉnh", + AzureEndpoint: { + Title: "Azure OpenAI Endpoint", + Placeholder: "https://docs-test-001.openai.azure.com/", }, AzureDeploymentName: { Title: "Tên phiên bản triển khai Azure OpenAI", diff --git a/app/store/access.ts b/app/store/access.ts index b655804519f..eaca155d72e 100644 --- a/app/store/access.ts +++ b/app/store/access.ts @@ -11,7 +11,7 @@ export interface AccessControlStore { token: string; enableAOAI: boolean; - azureDomainName: string; + azureEndpoint: string; azureDeployName: string; aoaiToken: string; @@ -23,8 +23,8 @@ export interface AccessControlStore { updateToken: (_: string) => void; updateCode: (_: string) => void; switchAOAI: (_: boolean) => void; - updateDomainName: (_: string) => void; - updateDeployName: (_: string) => void; + updateAzureEndpoint: (_: string) => void; + updateAzureDeployName: (_: string) => void; updateAOAIToken: (_: string) => void; updateOpenAiUrl: (_: string) => void; enabledAccessControl: () => boolean; @@ -45,7 +45,7 @@ export const useAccessStore = create()( accessCode: "", enableAOAI: false as boolean, - azureDomainName: "", + azureEndpoint: "", azureDeployName: "", aoaiToken: "", @@ -69,10 +69,10 @@ export const useAccessStore = create()( switchAOAI(switchStatus: boolean) { set((state) => ({ enableAOAI: switchStatus })); }, - updateDomainName(azureDomainName: string) { - set((state) => ({ azureDomainName })); + updateAzureEndpoint(azureEndpoint: string) { + set((state) => ({ azureEndpoint })); }, - updateDeployName(azureDeployName: string) { + updateAzureDeployName(azureDeployName: string) { set((state) => ({ azureDeployName })); }, updateAOAIToken(aoaiToken: string) { @@ -88,7 +88,7 @@ export const useAccessStore = create()( // has token or has code or disabled access control if (get().enableAOAI) { return ( - !!get().azureDomainName && + !!get().azureEndpoint && !!get().azureDeployName && !!get().aoaiToken ); diff --git a/app/store/config.ts b/app/store/config.ts index d7df683c5d9..c9d8b83d009 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -55,6 +55,10 @@ export type ModelConfig = ChatConfig["modelConfig"]; const ENABLE_GPT4 = true; export const AZURE_API_VERSION = [ + { + name: "2023-05-15", + available: true, + }, { name: "2023-03-15-preview", available: true, From 44135a9ceb2a24c061839be33d7b6eb798f9f1d7 Mon Sep 17 00:00:00 2001 From: Duang Cheng Date: Thu, 29 Jun 2023 18:47:35 +0800 Subject: [PATCH 14/14] chore: revert author change --- app/constant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/constant.ts b/app/constant.ts index 72d8b426e6a..a0e2887cc4c 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -1,4 +1,4 @@ -export const OWNER = "realDuang"; +export const OWNER = "Yidadaa"; export const REPO = "ChatGPT-Next-Web"; export const REPO_URL = `https://github.com/${OWNER}/${REPO}`; export const ISSUE_URL = `https://github.com/${OWNER}/${REPO}/issues`;