Skip to content
This repository has been archived by the owner on Sep 15, 2024. It is now read-only.

Implement Custom Service Provider #188

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 76 additions & 33 deletions app/components/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ import {
import Link from "next/link";
import {
Azure,
Custom,
DEFAULT_API_HOST,
OPENAI_BASE_URL,
Path,
RELEASE_URL,
Expand Down Expand Up @@ -1319,8 +1321,7 @@ export function Settings() {
))}
</Select>
</ListItem>

{accessStore.provider === "OpenAI" || accessStore.provider === "Custom" ? (
{accessStore.provider === "OpenAI" && (
<>
<ListItem
title={Locale.Settings.Access.OpenAI.Endpoint.Title}
Expand Down Expand Up @@ -1359,64 +1360,106 @@ export function Settings() {
/>
</ListItem>
</>
) : (
)}
{accessStore.provider === "Azure" && (
<>
<ListItem
title={Locale.Settings.Access.Azure.Endpoint.Title}
subTitle={
Locale.Settings.Access.Azure.Endpoint.SubTitle +
Azure.ExampleEndpoint
}
>
<input
type="text"
value={accessStore.azureUrl}
placeholder={Azure.ExampleEndpoint}
onChange={(e) =>
accessStore.update(
(access) =>
(access.azureUrl = e.currentTarget.value),
)
}
></input>
</ListItem>
<ListItem
title={Locale.Settings.Access.Azure.ApiKey.Title}
subTitle={Locale.Settings.Access.Azure.ApiKey.SubTitle}
>
<PasswordInput
value={accessStore.azureApiKey}
type="text"
placeholder={
Locale.Settings.Access.Azure.ApiKey.Placeholder
}
onChange={(e) => {
accessStore.update(
(access) =>
(access.azureApiKey = e.currentTarget.value),
);
}}
/>
</ListItem>
<ListItem
title={Locale.Settings.Access.Azure.ApiVerion.Title}
subTitle={
Locale.Settings.Access.Azure.ApiVerion.SubTitle
}
>
<input
type="text"
value={accessStore.azureApiVersion}
placeholder="2023-08-01-preview"
onChange={(e) =>
accessStore.update(
(access) =>
(access.azureApiVersion =
e.currentTarget.value),
)
}
></input>
</ListItem>
</>
)}
{accessStore.provider === "Custom" && (
<>
<ListItem
title={Locale.Settings.Access.Azure.Endpoint.Title}
title={Locale.Settings.Access.Custom.Endpoint.Title}
subTitle={
Locale.Settings.Access.Azure.Endpoint.SubTitle +
Azure.ExampleEndpoint
Locale.Settings.Access.Custom.Endpoint.SubTitle +
Custom.ExampleEndpoint
}
>
<input
type="text"
value={accessStore.azureUrl}
placeholder={Azure.ExampleEndpoint}
value={accessStore.customUrl}
placeholder={DEFAULT_API_HOST}
onChange={(e) =>
accessStore.update(
(access) =>
(access.azureUrl = e.currentTarget.value),
(access.customUrl = e.currentTarget.value),
)
}
></input>
</ListItem>
<ListItem
title={Locale.Settings.Access.Azure.ApiKey.Title}
subTitle={Locale.Settings.Access.Azure.ApiKey.SubTitle}
title={Locale.Settings.Access.Custom.ApiKey.Title}
subTitle={Locale.Settings.Access.Custom.ApiKey.SubTitle}
>
<PasswordInput
value={accessStore.azureApiKey}
value={accessStore.customApiKey}
type="text"
placeholder={
Locale.Settings.Access.Azure.ApiKey.Placeholder
Locale.Settings.Access.Custom.ApiKey.Placeholder
}
onChange={(e) => {
accessStore.update(
(access) =>
(access.azureApiKey = e.currentTarget.value),
(access.customApiKey = e.currentTarget.value),
);
}}
/>
</ListItem>
<ListItem
title={Locale.Settings.Access.Azure.ApiVerion.Title}
subTitle={
Locale.Settings.Access.Azure.ApiVerion.SubTitle
}
>
<input
type="text"
value={accessStore.azureApiVersion}
placeholder="2023-08-01-preview"
onChange={(e) =>
accessStore.update(
(access) =>
(access.azureApiVersion =
e.currentTarget.value),
)
}
></input>
</ListItem>
</>
)}
</>
Expand Down
9 changes: 9 additions & 0 deletions app/config/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ declare global {
AZURE_URL?: string; // https://{azure-url}/openai/deployments/{deploy-name}
AZURE_API_KEY?: string;
AZURE_API_VERSION?: string;

// custom service provider
CUSTOM_URL?: string;
CUstom_API_KEY?: string;
}
}
}
Expand Down Expand Up @@ -61,6 +65,7 @@ export const getServerSideConfig = () => {
}

const isAzure = !!process.env.AZURE_URL;
const isCustom = !!process.env.CUSTOM_URL;

const apiKeyEnvVar = process.env.OPENAI_API_KEY ?? "";
const apiKeys = apiKeyEnvVar.split(",").map((v) => v.trim());
Expand Down Expand Up @@ -93,5 +98,9 @@ export const getServerSideConfig = () => {
hideBalanceQuery: !process.env.ENABLE_BALANCE_QUERY,
disableFastLink: !!process.env.DISABLE_FAST_LINK,
customModels,

isCustom,
customUrl: process.env.CUSTOM_URL,
customApiKey: process.env.CUstom_API_KEY,
};
};
4 changes: 4 additions & 0 deletions app/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ export const Azure = {
ExampleEndpoint: "https://{resource-url}/openai/deployments/{deploy-id}",
};

export const Custom = {
ExampleEndpoint: DEFAULT_API_HOST,
};

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.
Expand Down
12 changes: 12 additions & 0 deletions app/locales/cn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,18 @@ const cn = {
SubTitle: "选择指定的部分版本",
},
},
Custom: {
ApiKey: {
Title: "自定义 API 密钥",
SubTitle: "用户自定义 Api 密钥",
Placeholder: "sk-xxx",
},

Endpoint: {
Title: "自定义端点",
SubTitle: "必须以 http(s):// 开头",
},
},
CustomModel: {
Title: "自定义模型名",
SubTitle: "增加自定义模型可选项,使用英文逗号隔开",
Expand Down
12 changes: 12 additions & 0 deletions app/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,18 @@ const en: LocaleType = {
SubTitle: "Check your api version from azure console",
},
},
Custom: {
ApiKey: {
Title: "Custom API Key",
SubTitle: "User custom Api Key",
Placeholder: "sk-xxx",
},

Endpoint: {
Title: "Custom Endpoint",
SubTitle: "Must starts with http(s):// Example: ",
},
},
CustomModel: {
Title: "Custom Models",
SubTitle: "Custom model options, seperated by comma",
Expand Down
21 changes: 20 additions & 1 deletion app/store/access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ const DEFAULT_ACCESS_STATE = {
azureApiKey: "",
azureApiVersion: "2023-08-01-preview",

// custom used example desktop app or self-hosted e.g, is https://chatgpt.btz.sh/api/proxy/
customUrl: DEFAULT_API_HOST,
customApiKey: "",

// server config
needCode: true,
hideUserApiKey: false,
Expand Down Expand Up @@ -56,13 +60,18 @@ export const useAccessStore = createPersistStore(
return ensure(get(), ["azureUrl", "azureApiKey", "azureApiVersion"]);
},

isValidCustom() {
return ensure(get(), ["customUrl", "customApiKey"]);
},

isAuthorized() {
this.fetch();

// has token or has code or disabled access control
return (
this.isValidOpenAI() ||
this.isValidAzure() ||
this.isValidCustom() ||
!this.enabledAccessControl() ||
(this.enabledAccessControl() && ensure(get(), ["accessCode"]))
);
Expand Down Expand Up @@ -92,7 +101,7 @@ export const useAccessStore = createPersistStore(
}),
{
name: StoreKey.Access,
version: 2,
version: 2.1,
migrate(persistedState, version) {
if (version < 2) {
const state = persistedState as {
Expand All @@ -104,6 +113,16 @@ export const useAccessStore = createPersistStore(
state.azureApiVersion = "2023-08-01-preview";
}

if (version < 2.1) {
const state = persistedState as {
token: string;
customApiKey: string;
customUrl: string;
};
state.customApiKey = state.token;
state.customUrl = `${DEFAULT_API_HOST}`;
}

return persistedState as any;
},
},
Expand Down