mirror of
https://github.com/sqlchat/sqlchat.git
synced 2025-07-23 23:11:37 +08:00
feat: add NEXT_PUBLIC_ALLOW_SELF_OPENAI_KEY
This commit is contained in:
@ -51,6 +51,8 @@ docker run --name sqlchat --platform linux/amd64 -env NEXTAUTH_SECRET=xxx -p 300
|
||||
|
||||
### Variables relacionadas con OpenAI:
|
||||
|
||||
- `NEXT_PUBLIC_ALLOW_SELF_OPENAI_KEY`: Establezca en "verdadero" para permitir a los usuarios traer su propia clave API de OpenAI.
|
||||
|
||||
- `OPENAI_API_KEY`: Clave API de OpenAI. Puedes conseguir una [aquí](https://beta.openai.com/docs/developer-quickstart/api-keys).
|
||||
|
||||
- `OPENAI_API_ENDPOINT`: Endpoint de la API de OpenAI. El predeterminado es `https://api.openai.com`.
|
||||
|
@ -51,6 +51,7 @@ docker run --name sqlchat --platform linux/amd64 -env NEXTAUTH_SECRET=xxx -p 300
|
||||
|
||||
### OpenAI related variables:
|
||||
|
||||
- `NEXT_PUBLIC_ALLOW_SELF_OPENAI_KEY`: Set to `true` to allow users to bring their own OpenAI API key.
|
||||
- `OPENAI_API_KEY`: OpenAI API key. You can get one from [here](https://beta.openai.com/docs/developer-quickstart/api-keys).
|
||||
|
||||
- `OPENAI_API_ENDPOINT`: OpenAI API endpoint. Defaults to `https://api.openai.com`.
|
||||
|
@ -51,6 +51,7 @@ docker run --name sqlchat --platform linux/amd64 -env NEXTAUTH_SECRET=xxx -p 300
|
||||
|
||||
### OpenAI 相关变量:
|
||||
|
||||
- `NEXT_PUBLIC_ALLOW_SELF_OPENAI_KEY`: 设置为 `true` 如果你允许用户提供自己的 OpenAI API key.
|
||||
- `OPENAI_API_KEY`: OpenAI API Key,通过[这里](https://beta.openai.com/docs/developer-quickstart/api-keys)申请。
|
||||
- `OPENAI_API_ENDPOINT`: OpenAI API 端点,默认为 `https://api.openai.com`。
|
||||
|
||||
|
2
process.d.ts
vendored
2
process.d.ts
vendored
@ -6,6 +6,8 @@ declare namespace NodeJS {
|
||||
// We can't prefix DATABASE_URL with NEXT_PUBLIC_ because it contains sensitive information that
|
||||
// should not be exposed to the client.
|
||||
NEXT_PUBLIC_DATABASE_LESS: string;
|
||||
// Optional. Set to "true" to allow users to bring their own OpenAI API key.
|
||||
NEXT_PUBLIC_ALLOW_SELF_OPENAI_KEY: string;
|
||||
// Required if NEXT_PUBLIC_DATABASE_LESS is false. Postgres database connection string to store
|
||||
// the data. e.g. postgresql://postgres:YOUR_PASSWORD@localhost:5432/sqlchat?schema=sqlchat
|
||||
DATABASE_URL: string;
|
||||
|
@ -3,9 +3,11 @@ import { useTranslation } from "react-i18next";
|
||||
import { useDebounce } from "react-use";
|
||||
import { useSettingStore } from "@/store";
|
||||
import { OpenAIApiConfig } from "@/types";
|
||||
import { allowSelfOpenAIKey } from "@/utils";
|
||||
import Radio from "./kit/Radio";
|
||||
import TextField from "./kit/TextField";
|
||||
import Tooltip from "./kit/Tooltip";
|
||||
|
||||
const OpenAIApiConfigView = () => {
|
||||
const { t } = useTranslation();
|
||||
const settingStore = useSettingStore();
|
||||
@ -75,7 +77,7 @@ const OpenAIApiConfigView = () => {
|
||||
<div className="w-full border border-gray-200 dark:border-zinc-700 p-4 rounded-lg">
|
||||
<div>
|
||||
<label className="text-base font-semibold ">{t("setting.openai-api-configuration.model")}</label>
|
||||
<p className="text-sm text-gray-500">{t("setting.openai-api-configuration.model-description")}</p>
|
||||
{allowSelfOpenAIKey() && <p className="text-sm text-gray-500">{t("setting.openai-api-configuration.model-description")}</p>}
|
||||
<fieldset className="mt-4">
|
||||
<div className="space-y-4 sm:flex sm:items-center sm:space-x-10 sm:space-y-0">
|
||||
{models.map((model) =>
|
||||
@ -90,35 +92,39 @@ const OpenAIApiConfigView = () => {
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div className="flex flex-col mt-4">
|
||||
<label className="text-base font-semibold">OpenAI API Key</label>
|
||||
<p className="text-sm text-gray-500">{t("setting.openai-api-configuration.key-description")}</p>
|
||||
<TextField
|
||||
className="mt-4"
|
||||
placeholder="OpenAI API Key"
|
||||
value={maskKey ? maskedKey(openAIApiConfig.key) : openAIApiConfig.key}
|
||||
onChange={(value) => handleSetOpenAIApiConfig({ key: value })}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col mt-4">
|
||||
<label className="text-base font-semibold">OpenAI API Endpoint</label>
|
||||
<div className="flex">
|
||||
<p className="text-sm text-gray-500">{t("setting.openai-api-configuration.endpoint-description")}</p>
|
||||
<a
|
||||
href="https://platform.openai.com/account/api-keys"
|
||||
target="_blank"
|
||||
className="text-sm text-indigo-600 hover:text-indigo-900"
|
||||
>
|
||||
{t("setting.openai-api-configuration.find-my-key")}
|
||||
</a>
|
||||
</div>
|
||||
<TextField
|
||||
className="mt-4"
|
||||
placeholder="API Endpoint"
|
||||
value={openAIApiConfig.endpoint}
|
||||
onChange={(value) => handleSetOpenAIApiConfig({ endpoint: value })}
|
||||
/>
|
||||
</div>
|
||||
{allowSelfOpenAIKey() && (
|
||||
<>
|
||||
<div className="flex flex-col mt-4">
|
||||
<label className="text-base font-semibold">OpenAI API Key</label>
|
||||
<p className="text-sm text-gray-500">{t("setting.openai-api-configuration.key-description")}</p>
|
||||
<TextField
|
||||
className="mt-4"
|
||||
placeholder="OpenAI API Key"
|
||||
value={maskKey ? maskedKey(openAIApiConfig.key) : openAIApiConfig.key}
|
||||
onChange={(value) => handleSetOpenAIApiConfig({ key: value })}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col mt-4">
|
||||
<label className="text-base font-semibold">OpenAI API Endpoint</label>
|
||||
<div className="flex">
|
||||
<p className="text-sm text-gray-500">{t("setting.openai-api-configuration.endpoint-description")}</p>
|
||||
<a
|
||||
href="https://platform.openai.com/account/api-keys"
|
||||
target="_blank"
|
||||
className="text-sm text-indigo-600 hover:text-indigo-900"
|
||||
>
|
||||
{t("setting.openai-api-configuration.find-my-key")}
|
||||
</a>
|
||||
</div>
|
||||
<TextField
|
||||
className="mt-4"
|
||||
placeholder="API Endpoint"
|
||||
value={openAIApiConfig.endpoint}
|
||||
onChange={(value) => handleSetOpenAIApiConfig({ endpoint: value })}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useLocalStorage } from "react-use";
|
||||
import { allowSelfOpenAIKey } from "@/utils";
|
||||
import Link from "next/link";
|
||||
import Icon from "./Icon";
|
||||
|
||||
@ -22,9 +23,11 @@ const QuotaOverflowBanner = (props: Props) => {
|
||||
>
|
||||
<div className="text-sm leading-6 pr-4 cursor-pointer">
|
||||
{t("banner.quota-overflow")}{" "}
|
||||
<Link className="ml-1 underline hover:opacity-80" href="/setting">
|
||||
{t("banner.use-my-key")}
|
||||
</Link>
|
||||
{allowSelfOpenAIKey() && (
|
||||
<Link className="ml-1 underline hover:opacity-80" href="/setting">
|
||||
{t("banner.use-my-key")}
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
<button className="absolute right-2 sm:right-4 opacity-60 hover:opacity-100" onClick={() => setHideBanner(true)}>
|
||||
<Icon.BiX className="w-6 h-auto" />
|
||||
|
@ -5,6 +5,7 @@ import Link from "next/link";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Quota } from "@/types";
|
||||
import getEventEmitter from "@/utils/event-emitter";
|
||||
import { allowSelfOpenAIKey } from "@/utils";
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
@ -78,7 +79,7 @@ const QuotaView = (props: Props) => {
|
||||
{t("setting.plan.signup-for-more")}
|
||||
</button>
|
||||
))}
|
||||
{!!showSupplyOwnKey && (
|
||||
{allowSelfOpenAIKey() && !!showSupplyOwnKey && (
|
||||
<Link className="text-center rounded-full underline hover:opacity-80 px-2 py-0.5 text-xs font-medium text-gray-700" href="/setting">
|
||||
{t("banner.use-my-key")}
|
||||
</Link>
|
||||
|
@ -50,3 +50,7 @@ export function generateDbPromptFromContext(
|
||||
}
|
||||
return promptGenerator(engine, finalTableList.join("\n\n"));
|
||||
}
|
||||
|
||||
export function allowSelfOpenAIKey() {
|
||||
return process.env.NEXT_PUBLIC_ALLOW_SELF_OPENAI_KEY == "true";
|
||||
}
|
||||
|
Reference in New Issue
Block a user