mirror of
https://github.com/sqlchat/sqlchat.git
synced 2025-07-25 16:13:10 +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:
|
### 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_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`.
|
- `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:
|
### 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_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`.
|
- `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 相关变量:
|
### 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_KEY`: OpenAI API Key,通过[这里](https://beta.openai.com/docs/developer-quickstart/api-keys)申请。
|
||||||
- `OPENAI_API_ENDPOINT`: OpenAI API 端点,默认为 `https://api.openai.com`。
|
- `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
|
// We can't prefix DATABASE_URL with NEXT_PUBLIC_ because it contains sensitive information that
|
||||||
// should not be exposed to the client.
|
// should not be exposed to the client.
|
||||||
NEXT_PUBLIC_DATABASE_LESS: string;
|
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
|
// 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
|
// the data. e.g. postgresql://postgres:YOUR_PASSWORD@localhost:5432/sqlchat?schema=sqlchat
|
||||||
DATABASE_URL: string;
|
DATABASE_URL: string;
|
||||||
|
@ -3,9 +3,11 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { useDebounce } from "react-use";
|
import { useDebounce } from "react-use";
|
||||||
import { useSettingStore } from "@/store";
|
import { useSettingStore } from "@/store";
|
||||||
import { OpenAIApiConfig } from "@/types";
|
import { OpenAIApiConfig } from "@/types";
|
||||||
|
import { allowSelfOpenAIKey } from "@/utils";
|
||||||
import Radio from "./kit/Radio";
|
import Radio from "./kit/Radio";
|
||||||
import TextField from "./kit/TextField";
|
import TextField from "./kit/TextField";
|
||||||
import Tooltip from "./kit/Tooltip";
|
import Tooltip from "./kit/Tooltip";
|
||||||
|
|
||||||
const OpenAIApiConfigView = () => {
|
const OpenAIApiConfigView = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const settingStore = useSettingStore();
|
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 className="w-full border border-gray-200 dark:border-zinc-700 p-4 rounded-lg">
|
||||||
<div>
|
<div>
|
||||||
<label className="text-base font-semibold ">{t("setting.openai-api-configuration.model")}</label>
|
<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">
|
<fieldset className="mt-4">
|
||||||
<div className="space-y-4 sm:flex sm:items-center sm:space-x-10 sm:space-y-0">
|
<div className="space-y-4 sm:flex sm:items-center sm:space-x-10 sm:space-y-0">
|
||||||
{models.map((model) =>
|
{models.map((model) =>
|
||||||
@ -90,35 +92,39 @@ const OpenAIApiConfigView = () => {
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col mt-4">
|
{allowSelfOpenAIKey() && (
|
||||||
<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>
|
<div className="flex flex-col mt-4">
|
||||||
<TextField
|
<label className="text-base font-semibold">OpenAI API Key</label>
|
||||||
className="mt-4"
|
<p className="text-sm text-gray-500">{t("setting.openai-api-configuration.key-description")}</p>
|
||||||
placeholder="OpenAI API Key"
|
<TextField
|
||||||
value={maskKey ? maskedKey(openAIApiConfig.key) : openAIApiConfig.key}
|
className="mt-4"
|
||||||
onChange={(value) => handleSetOpenAIApiConfig({ key: value })}
|
placeholder="OpenAI API Key"
|
||||||
/>
|
value={maskKey ? maskedKey(openAIApiConfig.key) : openAIApiConfig.key}
|
||||||
</div>
|
onChange={(value) => handleSetOpenAIApiConfig({ key: value })}
|
||||||
<div className="flex flex-col mt-4">
|
/>
|
||||||
<label className="text-base font-semibold">OpenAI API Endpoint</label>
|
</div>
|
||||||
<div className="flex">
|
<div className="flex flex-col mt-4">
|
||||||
<p className="text-sm text-gray-500">{t("setting.openai-api-configuration.endpoint-description")}</p>
|
<label className="text-base font-semibold">OpenAI API Endpoint</label>
|
||||||
<a
|
<div className="flex">
|
||||||
href="https://platform.openai.com/account/api-keys"
|
<p className="text-sm text-gray-500">{t("setting.openai-api-configuration.endpoint-description")}</p>
|
||||||
target="_blank"
|
<a
|
||||||
className="text-sm text-indigo-600 hover:text-indigo-900"
|
href="https://platform.openai.com/account/api-keys"
|
||||||
>
|
target="_blank"
|
||||||
{t("setting.openai-api-configuration.find-my-key")}
|
className="text-sm text-indigo-600 hover:text-indigo-900"
|
||||||
</a>
|
>
|
||||||
</div>
|
{t("setting.openai-api-configuration.find-my-key")}
|
||||||
<TextField
|
</a>
|
||||||
className="mt-4"
|
</div>
|
||||||
placeholder="API Endpoint"
|
<TextField
|
||||||
value={openAIApiConfig.endpoint}
|
className="mt-4"
|
||||||
onChange={(value) => handleSetOpenAIApiConfig({ endpoint: value })}
|
placeholder="API Endpoint"
|
||||||
/>
|
value={openAIApiConfig.endpoint}
|
||||||
</div>
|
onChange={(value) => handleSetOpenAIApiConfig({ endpoint: value })}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useLocalStorage } from "react-use";
|
import { useLocalStorage } from "react-use";
|
||||||
|
import { allowSelfOpenAIKey } from "@/utils";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
|
|
||||||
@ -22,9 +23,11 @@ const QuotaOverflowBanner = (props: Props) => {
|
|||||||
>
|
>
|
||||||
<div className="text-sm leading-6 pr-4 cursor-pointer">
|
<div className="text-sm leading-6 pr-4 cursor-pointer">
|
||||||
{t("banner.quota-overflow")}{" "}
|
{t("banner.quota-overflow")}{" "}
|
||||||
<Link className="ml-1 underline hover:opacity-80" href="/setting">
|
{allowSelfOpenAIKey() && (
|
||||||
{t("banner.use-my-key")}
|
<Link className="ml-1 underline hover:opacity-80" href="/setting">
|
||||||
</Link>
|
{t("banner.use-my-key")}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<button className="absolute right-2 sm:right-4 opacity-60 hover:opacity-100" onClick={() => setHideBanner(true)}>
|
<button className="absolute right-2 sm:right-4 opacity-60 hover:opacity-100" onClick={() => setHideBanner(true)}>
|
||||||
<Icon.BiX className="w-6 h-auto" />
|
<Icon.BiX className="w-6 h-auto" />
|
||||||
|
@ -5,6 +5,7 @@ import Link from "next/link";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Quota } from "@/types";
|
import { Quota } from "@/types";
|
||||||
import getEventEmitter from "@/utils/event-emitter";
|
import getEventEmitter from "@/utils/event-emitter";
|
||||||
|
import { allowSelfOpenAIKey } from "@/utils";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -78,7 +79,7 @@ const QuotaView = (props: Props) => {
|
|||||||
{t("setting.plan.signup-for-more")}
|
{t("setting.plan.signup-for-more")}
|
||||||
</button>
|
</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">
|
<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")}
|
{t("banner.use-my-key")}
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -50,3 +50,7 @@ export function generateDbPromptFromContext(
|
|||||||
}
|
}
|
||||||
return promptGenerator(engine, finalTableList.join("\n\n"));
|
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