feat: add openai api key and endpoint in setting (#23)

This commit is contained in:
boojack
2023-04-07 10:34:08 +08:00
committed by GitHub
parent 3341af871f
commit de861ae5c5
7 changed files with 106 additions and 4 deletions

View File

@ -1,7 +1,14 @@
import { head, last } from "lodash-es";
import { useEffect, useRef, useState } from "react";
import { toast } from "react-hot-toast";
import { getAssistantById, getPromptGeneratorOfAssistant, useConversationStore, useMessageStore, useConnectionStore } from "@/store";
import {
getAssistantById,
getPromptGeneratorOfAssistant,
useConversationStore,
useMessageStore,
useConnectionStore,
useSettingStore,
} from "@/store";
import { CreatorRole, Message } from "@/types";
import { countTextTokens, generateUUID } from "@/utils";
import Header from "./Header";
@ -15,6 +22,7 @@ import DataStorageBanner from "../DataStorageBanner";
const MAX_TOKENS = 4000;
const ConversationView = () => {
const settingStore = useSettingStore();
const connectionStore = useConnectionStore();
const conversationStore = useConversationStore();
const messageStore = useMessageStore();
@ -151,6 +159,7 @@ const ConversationView = () => {
method: "POST",
body: JSON.stringify({
messages: formatedMessageList,
openAIApiConfig: settingStore.setting.openAIApiConfig,
}),
});

View File

@ -9,7 +9,7 @@ const LocaleSelector = () => {
};
return (
<select className="select select-bordered !h-auto !min-h-fit" value={locale} onChange={handleLocaleChange}>
<select className="select select-bordered select-sm" value={locale} onChange={handleLocaleChange}>
<option value="en">English</option>
<option value="zh"></option>
</select>

View File

@ -0,0 +1,64 @@
import { useState } from "react";
import { useDebounce } from "react-use";
import { useSettingStore } from "@/store";
import { OpenAIApiConfig } from "@/types";
const OpenAIApiConfigView = () => {
const settingStore = useSettingStore();
const [openAIApiConfig, setOpenAIApiConfig] = useState(settingStore.setting.openAIApiConfig);
useDebounce(
() => {
settingStore.setOpenAIApiConfig(openAIApiConfig);
},
300,
[openAIApiConfig]
);
const handleSetOpenAIApiConfig = (config: Partial<OpenAIApiConfig>) => {
setOpenAIApiConfig({
...openAIApiConfig,
...config,
});
};
return (
<>
<h3>OpenAI API configuration</h3>
<div className="w-full border border-gray-200 p-4 rounded-lg">
<div className="flex flex-col">
<label htmlFor="openai-api-key">Key</label>
<input
id="openai-api-key"
className="input input-bordered input-sm mt-1"
type="text"
placeholder="OpenAI API Key"
value={openAIApiConfig.key}
onChange={(e) => {
handleSetOpenAIApiConfig({
key: e.target.value,
});
}}
/>
</div>
<div className="flex flex-col mt-2">
<label htmlFor="openai-api-endpoint">Endpoint</label>
<input
id="openai-api-endpoint"
className="input input-bordered input-sm mt-1"
type="text"
placeholder="OpenAI API Endpoint"
value={openAIApiConfig.endpoint}
onChange={(e) => {
handleSetOpenAIApiConfig({
endpoint: e.target.value,
});
}}
/>
</div>
</div>
</>
);
};
export default OpenAIApiConfigView;

View File

@ -3,6 +3,7 @@ import Icon from "./Icon";
import WeChatQRCodeView from "./WeChatQRCodeView";
import ClearDataButton from "./ClearDataButton";
import LocaleSelector from "./LocaleSelector";
import OpenAIApiConfigView from "./OpenAIApiConfigView";
interface Props {
show: boolean;
@ -40,6 +41,8 @@ const SettingModal = (props: Props) => {
</div>
</div>
<OpenAIApiConfigView />
<h3>Danger Zone</h3>
<div className="w-full border border-red-200 p-4 rounded-lg">
<div className="w-full flex flex-row justify-between items-center gap-2">

View File

@ -6,14 +6,19 @@ export const config = {
runtime: "edge",
};
const apiEndpoint = new URL(`${openAIApiEndpoint}/v1/chat/completions`);
const getApiEndpoint = (apiEndpoint: string) => {
return new URL(`${apiEndpoint}/v1/chat/completions`);
};
const handler = async (req: NextRequest) => {
const reqBody = await req.json();
const openAIApiConfig = reqBody.openAIApiConfig;
const apiKey = openAIApiConfig?.key || openAIApiKey;
const apiEndpoint = getApiEndpoint(openAIApiConfig?.endpoint || openAIApiEndpoint);
const res = await fetch(apiEndpoint, {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${openAIApiKey}`,
Authorization: `Bearer ${apiKey}`,
},
method: "POST",
body: JSON.stringify({

View File

@ -1,3 +1,4 @@
import { merge } from "lodash-es";
import { create } from "zustand";
import { persist } from "zustand/middleware";
import { Setting } from "@/types";
@ -5,12 +6,17 @@ import { Setting } from "@/types";
const getDefaultSetting = (): Setting => {
return {
locale: "en",
openAIApiConfig: {
key: "",
endpoint: "",
},
};
};
interface SettingState {
setting: Setting;
setLocale: (locale: Setting["locale"]) => void;
setOpenAIApiConfig: (openAIApiConfig: Setting["openAIApiConfig"]) => void;
}
export const useSettingStore = create<SettingState>()(
@ -26,9 +32,18 @@ export const useSettingStore = create<SettingState>()(
},
});
},
setOpenAIApiConfig: (openAIApiConfig: Setting["openAIApiConfig"]) => {
set({
setting: {
...get().setting,
openAIApiConfig,
},
});
},
}),
{
name: "setting-storage",
merge: (persistedState, currentState) => merge(currentState, persistedState),
}
)
);

View File

@ -1,5 +1,11 @@
export type Locale = "en" | "zh";
export interface OpenAIApiConfig {
key: string;
endpoint: string;
}
export interface Setting {
locale: Locale;
openAIApiConfig: OpenAIApiConfig;
}