@@ -31,56 +39,39 @@ export function AuthPage() {
{Locale.Auth.Title}
{Locale.Auth.Tips}
- {!getClientConfig()?.isApp && ( // Conditionally render the input access code based on whether it's an app
- <>
-
{
- accessStore.update(
- (access) => (access.accessCode = e.currentTarget.value),
- );
- }}
- />
-
{Locale.Auth.SubTips}
-
{
- accessStore.update(
- (access) => (access.token = e.currentTarget.value),
- );
- }}
- />
- >
- )}
-
- {getClientConfig()?.isApp && ( // Conditionally render the input access token based on whether it's an app
+
{
+ accessStore.update(
+ (access) => (access.accessCode = e.currentTarget.value),
+ );
+ }}
+ />
+ {!accessStore.hideUserApiKey ? (
<>
{Locale.Auth.SubTips}
{
accessStore.update(
- (access) => (access.token = e.currentTarget.value),
+ (access) => (access.openaiApiKey = e.currentTarget.value),
);
}}
/>
>
- )}
+ ) : null}
{
if (!res) return;
if (payload.key) {
- accessStore.update((access) => (access.token = payload.key!));
+ accessStore.update(
+ (access) => (access.openaiApiKey = payload.key!),
+ );
}
if (payload.url) {
accessStore.update((access) => (access.openaiUrl = payload.url!));
diff --git a/app/components/settings.tsx b/app/components/settings.tsx
index a023f5e51a5..367784c5acf 100644
--- a/app/components/settings.tsx
+++ b/app/components/settings.tsx
@@ -51,10 +51,13 @@ import Locale, {
import { copyToClipboard } from "../utils";
import Link from "next/link";
import {
+ Azure,
OPENAI_BASE_URL,
Path,
RELEASE_URL,
STORAGE_KEY,
+ ServiceProvider,
+ SlotID,
UPDATE_URL,
} from "../constant";
import { Prompt, SearchService, usePromptStore } from "../store/prompt";
@@ -685,8 +688,16 @@ export function Settings() {
const accessStore = useAccessStore();
const shouldHideBalanceQuery = useMemo(() => {
const isOpenAiUrl = accessStore.openaiUrl.includes(OPENAI_BASE_URL);
- return accessStore.hideBalanceQuery || isOpenAiUrl;
- }, [accessStore.hideBalanceQuery, accessStore.openaiUrl]);
+ return (
+ accessStore.hideBalanceQuery ||
+ isOpenAiUrl ||
+ accessStore.provider === ServiceProvider.Azure
+ );
+ }, [
+ accessStore.hideBalanceQuery,
+ accessStore.openaiUrl,
+ accessStore.provider,
+ ]);
const usage = {
used: updateStore.used,
@@ -982,16 +993,16 @@ export function Settings() {
-
- {showAccessCode ? (
+
+ {showAccessCode && (
{
accessStore.update(
(access) => (access.accessCode = e.currentTarget.value),
@@ -999,44 +1010,152 @@ export function Settings() {
}}
/>
- ) : (
- <>>
)}
- {!accessStore.hideUserApiKey ? (
+ {!accessStore.hideUserApiKey && (
<>
accessStore.update(
- (access) => (access.openaiUrl = e.currentTarget.value),
+ (access) =>
+ (access.useCustomConfig = e.currentTarget.checked),
)
}
>
-
- {
- accessStore.update(
- (access) => (access.token = e.currentTarget.value),
- );
- }}
- />
-
+ {accessStore.useCustomConfig && (
+ <>
+
+
+
+
+ {accessStore.provider === "OpenAI" ? (
+ <>
+
+
+ accessStore.update(
+ (access) =>
+ (access.openaiUrl = e.currentTarget.value),
+ )
+ }
+ >
+
+
+ {
+ accessStore.update(
+ (access) =>
+ (access.openaiApiKey = e.currentTarget.value),
+ );
+ }}
+ />
+
+ >
+ ) : (
+ <>
+
+
+ accessStore.update(
+ (access) =>
+ (access.azureUrl = e.currentTarget.value),
+ )
+ }
+ >
+
+
+ {
+ accessStore.update(
+ (access) =>
+ (access.azureApiKey = e.currentTarget.value),
+ );
+ }}
+ />
+
+
+
+ accessStore.update(
+ (access) =>
+ (access.azureApiVersion =
+ e.currentTarget.value),
+ )
+ }
+ >
+
+ >
+ )}
+ >
+ )}
>
- ) : null}
+ )}
{!shouldHideBalanceQuery ? (
- | JSX.Element
- | null
- | undefined;
-}) {
- return {props.children}
;
+export function List(props: { children: React.ReactNode; id?: string }) {
+ return (
+
+ {props.children}
+
+ );
}
export function Loading() {
diff --git a/app/config/server.ts b/app/config/server.ts
index 5760a875379..0dde3f4308f 100644
--- a/app/config/server.ts
+++ b/app/config/server.ts
@@ -4,22 +4,28 @@ import { DEFAULT_MODELS } from "../constant";
declare global {
namespace NodeJS {
interface ProcessEnv {
+ PROXY_URL?: string; // docker only
+
OPENAI_API_KEY?: string;
CODE?: string;
+
BASE_URL?: string;
- MODEL_LIST?: string;
- PROXY_URL?: string;
- OPENAI_ORG_ID?: string;
+ OPENAI_ORG_ID?: string; // openai only
+
VERCEL?: string;
+ BUILD_MODE?: "standalone" | "export";
+ BUILD_APP?: string; // is building desktop app
VERCEL_ANALYTICS?: string; // vercel web analytics
HIDE_USER_API_KEY?: string; // disable user's api key input
DISABLE_GPT4?: string; // allow user to use gpt-4 or not
- BUILD_MODE?: "standalone" | "export";
- BUILD_APP?: string; // is building desktop app
- HIDE_BALANCE_QUERY?: string; // allow user to query balance or not
ENABLE_BALANCE_QUERY?: string; // allow user to query balance or not
DISABLE_FAST_LINK?: string; // disallow parse settings from url or not
CUSTOM_MODELS?: string; // to control custom models
+
+ // azure only
+ AZURE_URL?: string; // https://{azure-url}/openai/deployments/{deploy-name}
+ AZURE_API_KEY?: string;
+ AZURE_API_VERSION?: string;
}
}
}
@@ -44,7 +50,7 @@ export const getServerSideConfig = () => {
);
}
- let disableGPT4 = !!process.env.DISABLE_GPT4;
+ const disableGPT4 = !!process.env.DISABLE_GPT4;
let customModels = process.env.CUSTOM_MODELS ?? "";
if (disableGPT4) {
@@ -54,16 +60,26 @@ export const getServerSideConfig = () => {
.join(",");
}
+ const isAzure = !!process.env.AZURE_URL;
+
return {
+ baseUrl: process.env.BASE_URL,
apiKey: process.env.OPENAI_API_KEY,
+ openaiOrgId: process.env.OPENAI_ORG_ID,
+
+ isAzure,
+ azureUrl: process.env.AZURE_URL,
+ azureApiKey: process.env.AZURE_API_KEY,
+ azureApiVersion: process.env.AZURE_API_VERSION,
+
+ needCode: ACCESS_CODES.size > 0,
code: process.env.CODE,
codes: ACCESS_CODES,
- needCode: ACCESS_CODES.size > 0,
- baseUrl: process.env.BASE_URL,
+
proxyUrl: process.env.PROXY_URL,
- openaiOrgId: process.env.OPENAI_ORG_ID,
isVercel: !!process.env.VERCEL,
isVercelWebAnalytics: !!process.env.VERCEL_ANALYTICS,
+
hideUserApiKey: !!process.env.HIDE_USER_API_KEY,
disableGPT4,
hideBalanceQuery: !process.env.ENABLE_BALANCE_QUERY,
diff --git a/app/constant.ts b/app/constant.ts
index d23c2fa491f..d9b7b7abf96 100644
--- a/app/constant.ts
+++ b/app/constant.ts
@@ -25,10 +25,12 @@ export enum Path {
export enum ApiPath {
Cors = "/api/cors",
+ OpenAI = "/api/openai",
}
export enum SlotID {
AppBody = "app-body",
+ CustomModel = "custom-model",
}
// This will automatically generate JSON files without the need to include the ".json" extension.
export enum FileName {
@@ -62,6 +64,11 @@ export const REQUEST_TIMEOUT_MS = 60000;
export const EXPORT_MESSAGE_CLASS_NAME = "export-markdown";
+export enum ServiceProvider {
+ OpenAI = "OpenAI",
+ Azure = "Azure",
+}
+
export const OpenaiPath = {
ChatPath: "v1/chat/completions",
// text moderation
@@ -77,6 +84,10 @@ export const OpenaiPath = {
ListModelPath: "v1/models",
};
+export const Azure = {
+ ExampleEndpoint: "https://{resource-url}/openai/deployments/{deploy-id}",
+};
+
export const DEFAULT_INPUT_TEMPLATE = `{{input}}`; // input / time / model / lang
export const DEFAULT_SYSTEM_TEMPLATE = `
You are ChatGPT, a large language model trained by OpenAI.
diff --git a/app/locales/ar.ts b/app/locales/ar.ts
index a5ac797db63..d463497ffa1 100644
--- a/app/locales/ar.ts
+++ b/app/locales/ar.ts
@@ -167,11 +167,7 @@ ${builtin} مدمجة، ${custom} تم تعريفها من قبل المستخد
Title: "حد الضغط للتاريخ",
SubTitle: "سيتم الضغط إذا تجاوزت طول الرسائل غير المضغوطة الحد المحدد",
},
- Token: {
- Title: "مفتاح API",
- SubTitle: "استخدم مفتاحك لتجاوز حد رمز الوصول",
- Placeholder: "مفتاح OpenAI API",
- },
+
Usage: {
Title: "رصيد الحساب",
SubTitle(used: any, total: any) {
@@ -184,15 +180,7 @@ ${builtin} مدمجة، ${custom} تم تعريفها من قبل المستخد
Check: "التحقق",
NoAccess: `أدخل مفتاح الجلسة في مفتاح واجهة برمجة التطبيقات بدءًا من البادئة "sess-" للتحقق من الرصيد.`,
},
- AccessCode: {
- Title: "رمز الوصول",
- SubTitle: "تم تمكين التحكم في الوصول",
- Placeholder: "رمز الوصول المطلوب",
- },
- Endpoint: {
- Title: "نقطة النهاية",
- SubTitle: "يجب أن تبدأ نقطة النهاية المخصصة بـ http(s)://",
- },
+
Model: "النموذج",
Temperature: {
Title: "الحرارة",
diff --git a/app/locales/bn.ts b/app/locales/bn.ts
index 515ddf601fd..745f2d66781 100644
--- a/app/locales/bn.ts
+++ b/app/locales/bn.ts
@@ -199,11 +199,7 @@ const bn: PartialLocaleType = {
SubTitle:
"নকুল বার্তা দৈর্ঘ্য সীমা অতিক্রান্ত হলে ঐ বার্তাটি সঙ্কুচিত হবে",
},
- Token: {
- Title: "অ্যাপি কী",
- SubTitle: "অ্যাক্সেস কোড সীমা উপেক্ষা করতে আপনার কীটি ব্যবহার করুন",
- Placeholder: "OpenAI API কী",
- },
+
Usage: {
Title: "একাউন্ট ব্যালেন্স",
SubTitle(used: any, total: any) {
@@ -216,15 +212,7 @@ const bn: PartialLocaleType = {
Check: "চেক",
NoAccess: `ব্যালেন্স চেক করতে, API কি-তে "sess-" উপসর্গ দিয়ে সেশন কি প্রবেশ করান।`,
},
- AccessCode: {
- Title: "অ্যাক্সেস কোড",
- SubTitle: "অ্যাক্সেস নিয়ন্ত্রণ সক্রিয়",
- Placeholder: "অ্যাক্সেস কোড প্রয়োজন",
- },
- Endpoint: {
- Title: "ইনটারপয়েন্ট",
- SubTitle: "কাস্টম এন্ডপয়েন্টটি হতে হবে http(s):// দিয়ে শুরু হতে হবে",
- },
+
Model: "মডেল",
Temperature: {
Title: "তাপমাত্রা",
diff --git a/app/locales/cn.ts b/app/locales/cn.ts
index 6d9e26011c0..7378f05fbcf 100644
--- a/app/locales/cn.ts
+++ b/app/locales/cn.ts
@@ -352,10 +352,56 @@ const cn = {
Title: "接口地址",
SubTitle: "除默认地址外,必须包含 http(s)://",
},
- CustomModel: {
- Title: "自定义模型名",
- SubTitle: "增加自定义模型可选项,使用英文逗号隔开",
+
+ Access: {
+ AccessCode: {
+ Title: "访问密码",
+ SubTitle: "管理员已开启加密访问",
+ Placeholder: "请输入访问密码",
+ },
+ CustomEndpoint: {
+ Title: "自定义接口",
+ SubTitle: "是否使用自定义 Azure 或 OpenAI 服务",
+ },
+ Provider: {
+ Title: "模型服务商",
+ SubTitle: "切换不同的服务商",
+ },
+ OpenAI: {
+ ApiKey: {
+ Title: "API Key",
+ SubTitle: "使用自定义 OpenAI Key 绕过密码访问限制",
+ Placeholder: "OpenAI API Key",
+ },
+
+ Endpoint: {
+ Title: "接口地址",
+ SubTitle: "除默认地址外,必须包含 http(s)://",
+ },
+ },
+ Azure: {
+ ApiKey: {
+ Title: "接口密钥",
+ SubTitle: "使用自定义 Azure Key 绕过密码访问限制",
+ Placeholder: "Azure API Key",
+ },
+
+ Endpoint: {
+ Title: "接口地址",
+ SubTitle: "样例:",
+ },
+
+ ApiVerion: {
+ Title: "接口版本 (azure api version)",
+ SubTitle: "选择指定的部分版本",
+ },
+ },
+ CustomModel: {
+ Title: "自定义模型名",
+ SubTitle: "增加自定义模型可选项,使用英文逗号隔开",
+ },
},
+
Model: "模型 (model)",
Temperature: {
Title: "随机性 (temperature)",
diff --git a/app/locales/cs.ts b/app/locales/cs.ts
index 37d6584fdfa..dd4d8ebcd00 100644
--- a/app/locales/cs.ts
+++ b/app/locales/cs.ts
@@ -124,11 +124,7 @@ const cs: PartialLocaleType = {
SubTitle:
"Komprese proběhne, pokud délka nekomprimovaných zpráv přesáhne tuto hodnotu",
},
- Token: {
- Title: "API klíč",
- SubTitle: "Použitím klíče ignorujete omezení přístupového kódu",
- Placeholder: "Klíč API OpenAI",
- },
+
Usage: {
Title: "Stav účtu",
SubTitle(used: any, total: any) {
@@ -141,11 +137,7 @@ const cs: PartialLocaleType = {
Check: "Zkontrolovat",
NoAccess: `Zadejte klíč relace ve vstupním klíči API s předponou "sess-" pro kontrolu zůstatku.`,
},
- AccessCode: {
- Title: "Přístupový kód",
- SubTitle: "Kontrola přístupu povolena",
- Placeholder: "Potřebujete přístupový kód",
- },
+
Model: "Model",
Temperature: {
Title: "Teplota",
diff --git a/app/locales/de.ts b/app/locales/de.ts
index a6176a3889d..bb93fc179b7 100644
--- a/app/locales/de.ts
+++ b/app/locales/de.ts
@@ -124,12 +124,7 @@ const de: PartialLocaleType = {
SubTitle:
"Komprimierung, wenn die Länge der unkomprimierten Nachrichten den Wert überschreitet",
},
- Token: {
- Title: "API-Schlüssel",
- SubTitle:
- "Verwenden Sie Ihren Schlüssel, um das Zugangscode-Limit zu ignorieren",
- Placeholder: "OpenAI API-Schlüssel",
- },
+
Usage: {
Title: "Kontostand",
SubTitle(used: any, total: any) {
@@ -142,11 +137,6 @@ const de: PartialLocaleType = {
Check: "Erneut prüfen",
NoAccess: `Geben Sie den Sitzungsschlüssel in den API-Schlüssel ein, der mit dem Präfix "sess-" beginnt, um den Saldo zu überprüfen.`,
},
- AccessCode: {
- Title: "Zugangscode",
- SubTitle: "Zugangskontrolle aktiviert",
- Placeholder: "Zugangscode erforderlich",
- },
Model: "Modell",
Temperature: {
Title: "Temperature", //Temperatur
diff --git a/app/locales/en.ts b/app/locales/en.ts
index 4de9db7053d..8714c5bcb79 100644
--- a/app/locales/en.ts
+++ b/app/locales/en.ts
@@ -336,6 +336,7 @@ const en: LocaleType = {
SubTitle: "Use your key to ignore access code limit",
Placeholder: "OpenAI API Key",
},
+
Usage: {
Title: "Account Balance",
SubTitle(used: any, total: any) {
@@ -357,10 +358,55 @@ const en: LocaleType = {
Title: "Endpoint",
SubTitle: "Custom endpoint must start with http(s)://",
},
- CustomModel: {
- Title: "Custom Models",
- SubTitle: "Add extra model options, separate by comma",
+ Access: {
+ AccessCode: {
+ Title: "Access Code",
+ SubTitle: "Access control Enabled",
+ Placeholder: "Enter Code",
+ },
+ CustomEndpoint: {
+ Title: "Custom Endpoint",
+ SubTitle: "Use custom Azure or OpenAI service",
+ },
+ Provider: {
+ Title: "Model Provider",
+ SubTitle: "Select Azure or OpenAI",
+ },
+ OpenAI: {
+ ApiKey: {
+ Title: "OpenAI API Key",
+ SubTitle: "User custom OpenAI Api Key",
+ Placeholder: "sk-xxx",
+ },
+
+ Endpoint: {
+ Title: "OpenAI Endpoint",
+ SubTitle: "Must starts with http(s):// or use /api/openai as default",
+ },
+ },
+ Azure: {
+ ApiKey: {
+ Title: "Azure Api Key",
+ SubTitle: "Check your api key from Azure console",
+ Placeholder: "Azure Api Key",
+ },
+
+ Endpoint: {
+ Title: "Azure Endpoint",
+ SubTitle: "Example: ",
+ },
+
+ ApiVerion: {
+ Title: "Azure Api Version",
+ SubTitle: "Check your api version from azure console",
+ },
+ },
+ CustomModel: {
+ Title: "Custom Models",
+ SubTitle: "Custom model options, seperated by comma",
+ },
},
+
Model: "Model",
Temperature: {
Title: "Temperature",
diff --git a/app/locales/es.ts b/app/locales/es.ts
index 0028400ca4f..4f8d7c6e750 100644
--- a/app/locales/es.ts
+++ b/app/locales/es.ts
@@ -124,11 +124,7 @@ const es: PartialLocaleType = {
SubTitle:
"Se comprimirán los mensajes si la longitud de los mensajes no comprimidos supera el valor",
},
- Token: {
- Title: "Clave de API",
- SubTitle: "Utiliza tu clave para ignorar el límite de código de acceso",
- Placeholder: "Clave de la API de OpenAI",
- },
+
Usage: {
Title: "Saldo de la cuenta",
SubTitle(used: any, total: any) {
@@ -141,11 +137,7 @@ const es: PartialLocaleType = {
Check: "Comprobar de nuevo",
NoAccess: `Ingresa la clave de sesión en la clave API comenzando con el prefijo "sess-" para verificar el saldo.`,
},
- AccessCode: {
- Title: "Código de acceso",
- SubTitle: "Control de acceso habilitado",
- Placeholder: "Necesita código de acceso",
- },
+
Model: "Modelo",
Temperature: {
Title: "Temperatura",
diff --git a/app/locales/fr.ts b/app/locales/fr.ts
index 5a8233af4b9..a50cc4e37cd 100644
--- a/app/locales/fr.ts
+++ b/app/locales/fr.ts
@@ -173,11 +173,7 @@ const fr: PartialLocaleType = {
SubTitle:
"Comprimera si la longueur des messages non compressés dépasse cette valeur",
},
- Token: {
- Title: "Clé API",
- SubTitle: "Utilisez votre clé pour ignorer la limite du code d'accès",
- Placeholder: "Clé OpenAI API",
- },
+
Usage: {
Title: "Solde du compte",
SubTitle(used: any, total: any) {
@@ -190,11 +186,7 @@ const fr: PartialLocaleType = {
Check: "Vérifier",
NoAccess: `Entrez la clé de session dans la clé API en commençant par le préfixe "sess-" pour vérifier le solde.`,
},
- AccessCode: {
- Title: "Code d'accès",
- SubTitle: "Contrôle d'accès activé",
- Placeholder: "Code d'accès requis",
- },
+
Model: "Modèle",
Temperature: {
Title: "Température",
diff --git a/app/locales/it.ts b/app/locales/it.ts
index f534d3acc21..865f042e057 100644
--- a/app/locales/it.ts
+++ b/app/locales/it.ts
@@ -124,12 +124,7 @@ const it: PartialLocaleType = {
SubTitle:
"Comprimerà se la lunghezza dei messaggi non compressi supera il valore",
},
- Token: {
- Title: "API Key",
- SubTitle:
- "Utilizzare la chiave per ignorare il limite del codice di accesso",
- Placeholder: "OpenAI API Key",
- },
+
Usage: {
Title: "Bilancio Account",
SubTitle(used: any, total: any) {
@@ -142,11 +137,7 @@ const it: PartialLocaleType = {
Check: "Controlla ancora",
NoAccess: `Inserisci la chiave di sessione nella chiave API che inizia con il prefisso "sess-" per verificare il saldo.`,
},
- AccessCode: {
- Title: "Codice d'accesso",
- SubTitle: "Controllo d'accesso abilitato",
- Placeholder: "Inserisci il codice d'accesso",
- },
+
Model: "Modello GPT",
Temperature: {
Title: "Temperature",
diff --git a/app/locales/jp.ts b/app/locales/jp.ts
index 497b0cd633b..121ef7fc57c 100644
--- a/app/locales/jp.ts
+++ b/app/locales/jp.ts
@@ -147,11 +147,7 @@ const jp: PartialLocaleType = {
SubTitle:
"圧縮されていない履歴メッセージがこの値を超えた場合、圧縮が行われます。",
},
- Token: {
- Title: "APIキー",
- SubTitle: "自分のキーを使用してパスワードアクセス制限を迂回する",
- Placeholder: "OpenAI APIキー",
- },
+
Usage: {
Title: "残高照会",
SubTitle(used: any, total: any) {
@@ -164,11 +160,7 @@ const jp: PartialLocaleType = {
Check: "再確認",
NoAccess: `残高を確認するには、APIキーの先頭に「sess-」を付けたセッションキーを入力してください。`,
},
- AccessCode: {
- Title: "アクセスパスワード",
- SubTitle: "暗号化アクセスが有効になっています",
- Placeholder: "アクセスパスワードを入力してください",
- },
+
Model: "モデル (model)",
Temperature: {
Title: "ランダム性 (temperature)",
diff --git a/app/locales/ko.ts b/app/locales/ko.ts
index 3ae328356f2..9e814d031f1 100644
--- a/app/locales/ko.ts
+++ b/app/locales/ko.ts
@@ -124,11 +124,7 @@ const ko: PartialLocaleType = {
Title: "기록 압축 임계값",
SubTitle: "미압축 메시지 길이가 임계값을 초과하면 압축됨",
},
- Token: {
- Title: "API 키",
- SubTitle: "액세스 코드 제한을 무시하기 위해 키 사용",
- Placeholder: "OpenAI API 키",
- },
+
Usage: {
Title: "계정 잔액",
SubTitle(used: any, total: any) {
@@ -141,11 +137,7 @@ const ko: PartialLocaleType = {
Check: "확인",
NoAccess: `잔액을 확인하려면, API 키에 "sess-" 접두사로 시작하는 세션 키를 입력하세요.`,
},
- AccessCode: {
- Title: "액세스 코드",
- SubTitle: "액세스 제어가 활성화됨",
- Placeholder: "액세스 코드 입력",
- },
+
Model: "모델",
Temperature: {
Title: "온도 (temperature)",
diff --git a/app/locales/no.ts b/app/locales/no.ts
index 31a71e009bf..a6ecd31ae52 100644
--- a/app/locales/no.ts
+++ b/app/locales/no.ts
@@ -106,12 +106,7 @@ const no: PartialLocaleType = {
SubTitle:
"Komprimer dersom ikke-komprimert lengde på meldinger overskrider denne verdien",
},
- Token: {
- Title: "API Key",
- SubTitle:
- "Bruk din egen API-nøkkel for å ignorere tilgangskoden begrensning",
- Placeholder: "OpenAI API-nøkkel",
- },
+
Usage: {
Title: "Saldo for konto",
SubTitle(used: any, total: any) {
@@ -124,11 +119,7 @@ const no: PartialLocaleType = {
Check: "Sjekk",
NoAccess: `Skriv inn øktnøkkelen i API-nøkkelen som starter med prefikset "sess-" for å sjekke saldoen.`,
},
- AccessCode: {
- Title: "Tilgangskode",
- SubTitle: "Tilgangskontroll på",
- Placeholder: "Trenger tilgangskode",
- },
+
Model: "Model",
Temperature: {
Title: "Temperatur",
diff --git a/app/locales/ru.ts b/app/locales/ru.ts
index 1643d258914..53a404f5f97 100644
--- a/app/locales/ru.ts
+++ b/app/locales/ru.ts
@@ -125,11 +125,7 @@ const ru: PartialLocaleType = {
SubTitle:
"Будет сжимать, если длина несжатых сообщений превышает указанное значение",
},
- Token: {
- Title: "API ключ",
- SubTitle: "Используйте свой ключ, чтобы игнорировать лимит доступа",
- Placeholder: "API ключ OpenAI",
- },
+
Usage: {
Title: "Баланс аккаунта",
SubTitle(used: any, total: any) {
@@ -142,11 +138,7 @@ const ru: PartialLocaleType = {
Check: "Проверить",
NoAccess: `Введите ключ сеанса в ключ API, начинающийся с префикса "sess-", чтобы проверить баланс.`,
},
- AccessCode: {
- Title: "Код доступа",
- SubTitle: "Контроль доступа включен",
- Placeholder: "Требуется код доступа",
- },
+
Model: "Модель",
Temperature: {
Title: "Температура",
diff --git a/app/locales/tr.ts b/app/locales/tr.ts
index ebc9d0f3129..7438429c107 100644
--- a/app/locales/tr.ts
+++ b/app/locales/tr.ts
@@ -124,11 +124,7 @@ const tr: PartialLocaleType = {
SubTitle:
"Sıkıştırılmamış mesajların uzunluğu bu değeri aşarsa sıkıştırılır",
},
- Token: {
- Title: "API Anahtarı",
- SubTitle: "Erişim kodu sınırını yoksaymak için anahtarınızı kullanın",
- Placeholder: "OpenAI API Anahtarı",
- },
+
Usage: {
Title: "Hesap Bakiyesi",
SubTitle(used: any, total: any) {
@@ -141,11 +137,7 @@ const tr: PartialLocaleType = {
Check: "Tekrar Kontrol Et",
NoAccess: `Bakiyeyi kontrol etmek için, API Anahtarında "sess-" önekiyle başlayan Oturum Anahtarını girin.`,
},
- AccessCode: {
- Title: "Erişim Kodu",
- SubTitle: "Erişim kontrolü etkinleştirme",
- Placeholder: "Erişim Kodu Gerekiyor",
- },
+
Model: "Model",
Temperature: {
Title: "Gerçeklik",
diff --git a/app/locales/tw.ts b/app/locales/tw.ts
index f9e43d68e78..311469e2dc4 100644
--- a/app/locales/tw.ts
+++ b/app/locales/tw.ts
@@ -120,11 +120,7 @@ const tw: PartialLocaleType = {
Title: "歷史訊息長度壓縮閾值",
SubTitle: "當未壓縮的歷史訊息超過該值時,將進行壓縮",
},
- Token: {
- Title: "API Key",
- SubTitle: "使用自己的 Key 可規避授權存取限制",
- Placeholder: "OpenAI API Key",
- },
+
Usage: {
Title: "帳戶餘額",
SubTitle(used: any, total: any) {
@@ -137,11 +133,7 @@ const tw: PartialLocaleType = {
Check: "重新檢查",
NoAccess: `輸入以"sess-"為前綴的API金鑰中的會話金鑰以檢查餘額。`,
},
- AccessCode: {
- Title: "授權碼",
- SubTitle: "目前是未授權存取狀態",
- Placeholder: "請輸入授權碼",
- },
+
Model: "模型 (model)",
Temperature: {
Title: "隨機性 (temperature)",
diff --git a/app/locales/vi.ts b/app/locales/vi.ts
index b15770f64c9..8bd6d7e5e01 100644
--- a/app/locales/vi.ts
+++ b/app/locales/vi.ts
@@ -123,11 +123,7 @@ const vi: PartialLocaleType = {
Title: "Ngưỡng nén lịch sử tin nhắn",
SubTitle: "Thực hiện nén nếu số lượng tin nhắn chưa nén vượt quá ngưỡng",
},
- Token: {
- Title: "API Key",
- SubTitle: "Sử dụng khóa của bạn để bỏ qua giới hạn mã truy cập",
- Placeholder: "OpenAI API Key",
- },
+
Usage: {
Title: "Hạn mức tài khoản",
SubTitle(used: any, total: any) {
@@ -140,11 +136,7 @@ const vi: PartialLocaleType = {
Check: "Kiểm tra",
NoAccess: `Nhập Khóa Phiên vào Khóa API bắt đầu bằng tiền tố "sess-" để kiểm tra số dư.`,
},
- AccessCode: {
- Title: "Mã truy cập",
- SubTitle: "Đã bật kiểm soát truy cập",
- Placeholder: "Nhập mã truy cập",
- },
+
Model: "Mô hình",
Temperature: {
Title: "Tính ngẫu nhiên (temperature)",
diff --git a/app/store/access.ts b/app/store/access.ts
index f87e44a2ac4..2abe1e3cc9f 100644
--- a/app/store/access.ts
+++ b/app/store/access.ts
@@ -1,25 +1,41 @@
-import { DEFAULT_API_HOST, DEFAULT_MODELS, StoreKey } from "../constant";
+import {
+ ApiPath,
+ DEFAULT_API_HOST,
+ ServiceProvider,
+ StoreKey,
+} from "../constant";
import { getHeaders } from "../client/api";
import { getClientConfig } from "../config/client";
import { createPersistStore } from "../utils/store";
+import { ensure } from "../utils/clone";
let fetchState = 0; // 0 not fetch, 1 fetching, 2 done
const DEFAULT_OPENAI_URL =
- getClientConfig()?.buildMode === "export" ? DEFAULT_API_HOST : "/api/openai/";
-console.log("[API] default openai url", DEFAULT_OPENAI_URL);
+ getClientConfig()?.buildMode === "export" ? DEFAULT_API_HOST : ApiPath.OpenAI;
const DEFAULT_ACCESS_STATE = {
- token: "",
accessCode: "",
+ useCustomConfig: false,
+
+ provider: ServiceProvider.OpenAI,
+
+ // openai
+ openaiUrl: DEFAULT_OPENAI_URL,
+ openaiApiKey: "",
+
+ // azure
+ azureUrl: "",
+ azureApiKey: "",
+ azureApiVersion: "2023-08-01-preview",
+
+ // server config
needCode: true,
hideUserApiKey: false,
hideBalanceQuery: false,
disableGPT4: false,
disableFastLink: false,
customModels: "",
-
- openaiUrl: DEFAULT_OPENAI_URL,
};
export const useAccessStore = createPersistStore(
@@ -31,12 +47,24 @@ export const useAccessStore = createPersistStore(
return get().needCode;
},
+
+ isValidOpenAI() {
+ return ensure(get(), ["openaiUrl", "openaiApiKey"]);
+ },
+
+ isValidAzure() {
+ return ensure(get(), ["azureUrl", "azureApiKey", "azureApiVersion"]);
+ },
+
isAuthorized() {
this.fetch();
// has token or has code or disabled access control
return (
- !!get().token || !!get().accessCode || !this.enabledAccessControl()
+ this.isValidOpenAI() ||
+ this.isValidAzure() ||
+ !this.enabledAccessControl() ||
+ (this.enabledAccessControl() && ensure(get(), ["accessCode"]))
);
},
fetch() {
@@ -64,6 +92,19 @@ export const useAccessStore = createPersistStore(
}),
{
name: StoreKey.Access,
- version: 1,
+ version: 2,
+ migrate(persistedState, version) {
+ if (version < 2) {
+ const state = persistedState as {
+ token: string;
+ openaiApiKey: string;
+ azureApiVersion: string;
+ };
+ state.openaiApiKey = state.token;
+ state.azureApiVersion = "2023-08-01-preview";
+ }
+
+ return persistedState as any;
+ },
},
);
diff --git a/app/store/sync.ts b/app/store/sync.ts
index 235dced63ca..ce78a37ab44 100644
--- a/app/store/sync.ts
+++ b/app/store/sync.ts
@@ -181,7 +181,7 @@ export const useSyncStore = createPersistStore(
if (overwriteAccessControl !== false) { // default is false ref #DEFAULT_SYNC_STATE
const accessControl = localState['access-control'];
- accessControl.token
+ accessControl.openaiApiKey
accessControl.accessCode
accessControl.needCode
accessControl.hideUserApiKey
diff --git a/app/utils/clone.ts b/app/utils/clone.ts
index 2958b6b9c35..c42288f7789 100644
--- a/app/utils/clone.ts
+++ b/app/utils/clone.ts
@@ -1,3 +1,10 @@
export function deepClone(obj: T) {
return JSON.parse(JSON.stringify(obj));
}
+
+export function ensure(
+ obj: T,
+ keys: Array<[keyof T][number]>,
+) {
+ return keys.every((k) => obj[k] !== undefined && obj[k] !== null);
+}
diff --git a/app/utils/store.ts b/app/utils/store.ts
index cd151dc4925..684a1911279 100644
--- a/app/utils/store.ts
+++ b/app/utils/store.ts
@@ -1,5 +1,5 @@
import { create } from "zustand";
-import { persist } from "zustand/middleware";
+import { combine, persist } from "zustand/middleware";
import { Updater } from "../typing";
import { deepClone } from "./clone";
@@ -23,33 +23,42 @@ type SetStoreState = (
replace?: boolean | undefined,
) => void;
-export function createPersistStore(
- defaultState: T,
+export function createPersistStore(
+ state: T,
methods: (
set: SetStoreState>,
get: () => T & MakeUpdater,
) => M,
persistOptions: SecondParam>>,
) {
- return create>()(
- persist((set, get) => {
- return {
- ...defaultState,
- ...methods(set as any, get),
-
- lastUpdateTime: 0,
- markUpdate() {
- set({ lastUpdateTime: Date.now() } as Partial<
- T & M & MakeUpdater
- >);
+ return create(
+ persist(
+ combine(
+ {
+ ...state,
+ lastUpdateTime: 0,
},
- update(updater) {
- const state = deepClone(get());
- updater(state);
- get().markUpdate();
- set(state);
+ (set, get) => {
+ return {
+ ...methods(set, get as any),
+
+ markUpdate() {
+ set({ lastUpdateTime: Date.now() } as Partial<
+ T & M & MakeUpdater
+ >);
+ },
+ update(updater) {
+ const state = deepClone(get());
+ updater(state);
+ set({
+ ...state,
+ lastUpdateTime: Date.now(),
+ });
+ },
+ } as M & MakeUpdater;
},
- };
- }, persistOptions),
+ ),
+ persistOptions as any,
+ ),
);
}