mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 17:00:15 +01:00
feat: support edit preset,
feat: support view current conversation options. feat: save current conversation as a preset. feat: preset delete all.
This commit is contained in:
parent
dae0c2d5e3
commit
d2579b44d1
15 changed files with 340 additions and 269 deletions
|
|
@ -16,7 +16,7 @@ const optionText =
|
||||||
|
|
||||||
function Settings(props) {
|
function Settings(props) {
|
||||||
// const [showSystemMessage, setShowSystemMessage] = React.useState(false);
|
// const [showSystemMessage, setShowSystemMessage] = React.useState(false);
|
||||||
const { context, setContext, systemMessage, setSystemMessage, jailbreak, setJailbreak } = props;
|
const { readonly, context, setContext, systemMessage, setSystemMessage, jailbreak, setJailbreak } = props;
|
||||||
const showSystemMessage = jailbreak;
|
const showSystemMessage = jailbreak;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -32,6 +32,7 @@ function Settings(props) {
|
||||||
</Label>
|
</Label>
|
||||||
<TextareaAutosize
|
<TextareaAutosize
|
||||||
id="context"
|
id="context"
|
||||||
|
disabled={readonly}
|
||||||
value={context || ''}
|
value={context || ''}
|
||||||
onChange={e => setContext(e.target.value || null)}
|
onChange={e => setContext(e.target.value || null)}
|
||||||
placeholder="Set custom instructions. Defaults to: 'You are ChatGPT, a large language model trained by OpenAI.'"
|
placeholder="Set custom instructions. Defaults to: 'You are ChatGPT, a large language model trained by OpenAI.'"
|
||||||
|
|
@ -47,6 +48,7 @@ function Settings(props) {
|
||||||
<div className="flex items-center space-x-3">
|
<div className="flex items-center space-x-3">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="jailbreak"
|
id="jailbreak"
|
||||||
|
disabled={readonly}
|
||||||
checked={jailbreak}
|
checked={jailbreak}
|
||||||
className="dark:border-gray-500 dark:bg-gray-700 dark:text-gray-50 focus:ring-opacity-20 dark:focus:ring-opacity-50 dark:focus:ring-offset-0 dark:focus:ring-gray-600"
|
className="dark:border-gray-500 dark:bg-gray-700 dark:text-gray-50 focus:ring-opacity-20 dark:focus:ring-opacity-50 dark:focus:ring-offset-0 dark:focus:ring-gray-600"
|
||||||
// onCheckedChange={setJailbreak}
|
// onCheckedChange={setJailbreak}
|
||||||
|
|
@ -79,6 +81,7 @@ function Settings(props) {
|
||||||
</Label> */}
|
</Label> */}
|
||||||
<TextareaAutosize
|
<TextareaAutosize
|
||||||
id="systemMessage"
|
id="systemMessage"
|
||||||
|
disabled={readonly}
|
||||||
value={systemMessage || ''}
|
value={systemMessage || ''}
|
||||||
onChange={e => setSystemMessage(e.target.value || null)}
|
onChange={e => setSystemMessage(e.target.value || null)}
|
||||||
placeholder="Set custom instructions. Defaults to: 'You are ChatGPT, a large language model trained by OpenAI.'"
|
placeholder="Set custom instructions. Defaults to: 'You are ChatGPT, a large language model trained by OpenAI.'"
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,10 @@ import { Input } from '../ui/Input.tsx';
|
||||||
import { Label } from '../ui/Label.tsx';
|
import { Label } from '../ui/Label.tsx';
|
||||||
import Dropdown from '../ui/Dropdown';
|
import Dropdown from '../ui/Dropdown';
|
||||||
import { cn } from '~/utils/';
|
import { cn } from '~/utils/';
|
||||||
|
import cleanupPreset from '~/utils/cleanupPreset';
|
||||||
|
|
||||||
import OpenAISettings from './OpenAI/Settings';
|
import OpenAISettings from './OpenAI/Settings';
|
||||||
|
import BingAISettings from './BingAI/Settings.jsx';
|
||||||
|
|
||||||
import store from '~/store';
|
import store from '~/store';
|
||||||
|
|
||||||
|
|
@ -50,39 +53,29 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset }) => {
|
||||||
setPresP={setOption('frequency_penalty')}
|
setPresP={setOption('frequency_penalty')}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
else if (endpoint === 'bingAI')
|
||||||
|
return (
|
||||||
|
<BingAISettings
|
||||||
|
readonly={true}
|
||||||
|
context={preset?.context}
|
||||||
|
setContext={setOption('context')}
|
||||||
|
systemMessage={preset?.systemMessage}
|
||||||
|
setSystemMessage={setOption('systemMessage')}
|
||||||
|
jailbreak={preset?.jailbreak}
|
||||||
|
setJailbreak={setOption('jailbreak')}
|
||||||
|
/>
|
||||||
|
);
|
||||||
else return null;
|
else return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultTextProps =
|
const defaultTextProps =
|
||||||
'rounded-md border border-gray-200 focus:border-slate-400 focus:bg-gray-50 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.05)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-500 dark:bg-gray-700 focus:dark:bg-gray-600 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';
|
'rounded-md border border-gray-200 focus:border-slate-400 focus:bg-gray-50 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.05)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-500 dark:bg-gray-700 focus:dark:bg-gray-600 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';
|
||||||
|
|
||||||
// in order not to use wrong data from other endpoint
|
|
||||||
const clearPreset = () => {
|
|
||||||
if (preset?.endpoint === 'openAI')
|
|
||||||
return {
|
|
||||||
title: preset?.title,
|
|
||||||
endpoint: preset?.endpoint,
|
|
||||||
model: preset?.model,
|
|
||||||
chatGptLabel: preset?.chatGptLabel,
|
|
||||||
promptPrefix: preset?.promptPrefix,
|
|
||||||
temperature: preset?.temperature,
|
|
||||||
top_p: preset?.top_p,
|
|
||||||
presence_penalty: preset?.presence_penalty,
|
|
||||||
frequency_penalty: preset?.frequency_penalty
|
|
||||||
};
|
|
||||||
else
|
|
||||||
return {
|
|
||||||
title: preset?.title,
|
|
||||||
endpoint: preset?.endpoint
|
|
||||||
};
|
|
||||||
// TODO: else
|
|
||||||
};
|
|
||||||
|
|
||||||
const submitPreset = () => {
|
const submitPreset = () => {
|
||||||
axios({
|
axios({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/api/presets',
|
url: '/api/presets',
|
||||||
data: clearPreset(),
|
data: cleanupPreset(preset),
|
||||||
withCredentials: true
|
withCredentials: true
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
setPresets(res?.data);
|
setPresets(res?.data);
|
||||||
|
|
@ -91,7 +84,7 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset }) => {
|
||||||
|
|
||||||
const exportPreset = () => {
|
const exportPreset = () => {
|
||||||
exportFromJSON({
|
exportFromJSON({
|
||||||
data: clearPreset(),
|
data: cleanupPreset(preset),
|
||||||
fileName: `${preset?.title}.json`,
|
fileName: `${preset?.title}.json`,
|
||||||
exportType: exportFromJSON.types.json
|
exportType: exportFromJSON.types.json
|
||||||
});
|
});
|
||||||
|
|
@ -168,7 +161,7 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset }) => {
|
||||||
<>
|
<>
|
||||||
<DialogButton
|
<DialogButton
|
||||||
onClick={exportPreset}
|
onClick={exportPreset}
|
||||||
className="dark:hover:gray-400 bg-red border-gray-700"
|
className="dark:hover:gray-400 border-gray-700"
|
||||||
>
|
>
|
||||||
Export
|
Export
|
||||||
</DialogButton>
|
</DialogButton>
|
||||||
|
|
|
||||||
134
client/src/components/Endpoints/EndpointOptionsDialog.jsx
Normal file
134
client/src/components/Endpoints/EndpointOptionsDialog.jsx
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { useSetRecoilState, useRecoilValue } from 'recoil';
|
||||||
|
import axios from 'axios';
|
||||||
|
import exportFromJSON from 'export-from-json';
|
||||||
|
import DialogTemplate from '../ui/DialogTemplate.jsx';
|
||||||
|
import { Dialog, DialogClose, DialogButton } from '../ui/Dialog.tsx';
|
||||||
|
import { Input } from '../ui/Input.tsx';
|
||||||
|
import { Label } from '../ui/Label.tsx';
|
||||||
|
import Dropdown from '../ui/Dropdown.jsx';
|
||||||
|
import SaveAsPresetDialog from './SaveAsPresetDialog';
|
||||||
|
import { cn } from '~/utils/';
|
||||||
|
import cleanupPreset from '~/utils/cleanupPreset';
|
||||||
|
|
||||||
|
import OpenAISettings from './OpenAI/Settings.jsx';
|
||||||
|
import BingAISettings from './BingAI/Settings.jsx';
|
||||||
|
|
||||||
|
import store from '~/store';
|
||||||
|
|
||||||
|
// A preset dialog to show readonly preset values.
|
||||||
|
const EndpointOptionsDialog = ({ open, onOpenChange, preset: _preset, title }) => {
|
||||||
|
// const [title, setTitle] = useState('My Preset');
|
||||||
|
const [preset, setPreset] = useState({});
|
||||||
|
|
||||||
|
const [saveAsDialogShow, setSaveAsDialogShow] = useState(false);
|
||||||
|
|
||||||
|
const setOption = param => newValue => {
|
||||||
|
let update = {};
|
||||||
|
update[param] = newValue;
|
||||||
|
setPreset(prevState => ({
|
||||||
|
...prevState,
|
||||||
|
...update
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderSettings = () => {
|
||||||
|
const { endpoint } = preset || {};
|
||||||
|
|
||||||
|
if (endpoint === 'openAI')
|
||||||
|
return (
|
||||||
|
<OpenAISettings
|
||||||
|
readonly={true}
|
||||||
|
model={preset?.model}
|
||||||
|
setModel={setOption('model')}
|
||||||
|
chatGptLabel={preset?.chatGptLabel}
|
||||||
|
setChatGptLabel={setOption('chatGptLabel')}
|
||||||
|
promptPrefix={preset?.promptPrefix}
|
||||||
|
setPromptPrefix={setOption('promptPrefix')}
|
||||||
|
temperature={preset?.temperature}
|
||||||
|
setTemperature={setOption('temperature')}
|
||||||
|
topP={preset?.top_p}
|
||||||
|
setTopP={setOption('top_p')}
|
||||||
|
freqP={preset?.presence_penalty}
|
||||||
|
setFreqP={setOption('presence_penalty')}
|
||||||
|
presP={preset?.frequency_penalty}
|
||||||
|
setPresP={setOption('frequency_penalty')}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
else if (endpoint === 'bingAI')
|
||||||
|
return (
|
||||||
|
<BingAISettings
|
||||||
|
readonly={true}
|
||||||
|
context={preset?.context}
|
||||||
|
setContext={setOption('context')}
|
||||||
|
systemMessage={preset?.systemMessage}
|
||||||
|
setSystemMessage={setOption('systemMessage')}
|
||||||
|
jailbreak={preset?.jailbreak}
|
||||||
|
setJailbreak={setOption('jailbreak')}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
else return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveAsPreset = () => {
|
||||||
|
setSaveAsDialogShow(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const exportPreset = () => {
|
||||||
|
exportFromJSON({
|
||||||
|
data: cleanupPreset(preset),
|
||||||
|
fileName: `${preset?.title}.json`,
|
||||||
|
exportType: exportFromJSON.types.json
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setPreset(_preset);
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dialog
|
||||||
|
open={open}
|
||||||
|
onOpenChange={onOpenChange}
|
||||||
|
>
|
||||||
|
<DialogTemplate
|
||||||
|
title={title || 'View Options'}
|
||||||
|
className="max-w-full sm:max-w-4xl"
|
||||||
|
main={
|
||||||
|
<div className="flex w-full flex-col items-center gap-2">
|
||||||
|
<div className="w-full p-0">{renderSettings()}</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
buttons={
|
||||||
|
<>
|
||||||
|
<DialogButton
|
||||||
|
onClick={saveAsPreset}
|
||||||
|
className="dark:hover:gray-400 border-gray-700 bg-green-600 text-white hover:bg-green-700 dark:hover:bg-green-800"
|
||||||
|
>
|
||||||
|
Save As Preset
|
||||||
|
</DialogButton>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
leftButtons={
|
||||||
|
<>
|
||||||
|
<DialogButton
|
||||||
|
onClick={exportPreset}
|
||||||
|
className="dark:hover:gray-400 border-gray-700"
|
||||||
|
>
|
||||||
|
Export
|
||||||
|
</DialogButton>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Dialog>
|
||||||
|
<SaveAsPresetDialog
|
||||||
|
open={saveAsDialogShow}
|
||||||
|
onOpenChange={setSaveAsDialogShow}
|
||||||
|
preset={preset}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EndpointOptionsDialog;
|
||||||
|
|
@ -4,6 +4,7 @@ import ModelDropDown from '../../ui/ModelDropDown';
|
||||||
import { Input } from '~/components/ui/Input.tsx';
|
import { Input } from '~/components/ui/Input.tsx';
|
||||||
import { Label } from '~/components/ui/Label.tsx';
|
import { Label } from '~/components/ui/Label.tsx';
|
||||||
import { Slider } from '~/components/ui/Slider.tsx';
|
import { Slider } from '~/components/ui/Slider.tsx';
|
||||||
|
import { InputNumber } from '../../ui/InputNumber';
|
||||||
import OptionHover from './OptionHover';
|
import OptionHover from './OptionHover';
|
||||||
import { HoverCard, HoverCardTrigger } from '~/components/ui/HoverCard.tsx';
|
import { HoverCard, HoverCardTrigger } from '~/components/ui/HoverCard.tsx';
|
||||||
import { cn } from '~/utils/';
|
import { cn } from '~/utils/';
|
||||||
|
|
@ -15,6 +16,7 @@ const optionText =
|
||||||
|
|
||||||
function Settings(props) {
|
function Settings(props) {
|
||||||
const {
|
const {
|
||||||
|
readonly,
|
||||||
model,
|
model,
|
||||||
setModel,
|
setModel,
|
||||||
chatGptLabel,
|
chatGptLabel,
|
||||||
|
|
@ -38,6 +40,7 @@ function Settings(props) {
|
||||||
<div className="grid w-full items-center gap-2">
|
<div className="grid w-full items-center gap-2">
|
||||||
<ModelDropDown
|
<ModelDropDown
|
||||||
model={model}
|
model={model}
|
||||||
|
disabled={readonly}
|
||||||
setModel={setModel}
|
setModel={setModel}
|
||||||
endpoint="openAI"
|
endpoint="openAI"
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|
@ -73,6 +76,7 @@ function Settings(props) {
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id="chatGptLabel"
|
id="chatGptLabel"
|
||||||
|
disabled={readonly}
|
||||||
value={chatGptLabel || ''}
|
value={chatGptLabel || ''}
|
||||||
// ref={inputRef}
|
// ref={inputRef}
|
||||||
onChange={e => setChatGptLabel(e.target.value || null)}
|
onChange={e => setChatGptLabel(e.target.value || null)}
|
||||||
|
|
@ -92,6 +96,7 @@ function Settings(props) {
|
||||||
</Label>
|
</Label>
|
||||||
<TextareaAutosize
|
<TextareaAutosize
|
||||||
id="promptPrefix"
|
id="promptPrefix"
|
||||||
|
disabled={readonly}
|
||||||
value={promptPrefix || ''}
|
value={promptPrefix || ''}
|
||||||
onChange={e => setPromptPrefix(e.target.value || null)}
|
onChange={e => setPromptPrefix(e.target.value || null)}
|
||||||
placeholder="Set custom instructions. Defaults to: 'You are ChatGPT, a large language model trained by OpenAI.'"
|
placeholder="Set custom instructions. Defaults to: 'You are ChatGPT, a large language model trained by OpenAI.'"
|
||||||
|
|
@ -123,6 +128,7 @@ function Settings(props) {
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id="temp-int"
|
id="temp-int"
|
||||||
|
disabled
|
||||||
value={temperature}
|
value={temperature}
|
||||||
onChange={e => setTemperature(e.target.value)}
|
onChange={e => setTemperature(e.target.value)}
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|
@ -132,6 +138,7 @@ function Settings(props) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Slider
|
<Slider
|
||||||
|
disabled={readonly}
|
||||||
value={[temperature]}
|
value={[temperature]}
|
||||||
onValueChange={value => setTemperature(value[0])}
|
onValueChange={value => setTemperature(value[0])}
|
||||||
max={2}
|
max={2}
|
||||||
|
|
@ -157,6 +164,7 @@ function Settings(props) {
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id="max-tokens-int"
|
id="max-tokens-int"
|
||||||
|
disabled
|
||||||
value={maxTokens}
|
value={maxTokens}
|
||||||
onChange={e => setMaxTokens(e.target.value)}
|
onChange={e => setMaxTokens(e.target.value)}
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|
@ -166,6 +174,7 @@ function Settings(props) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Slider
|
<Slider
|
||||||
|
disabled={readonly}
|
||||||
value={[maxTokens]}
|
value={[maxTokens]}
|
||||||
onValueChange={value => setMaxTokens(value[0])}
|
onValueChange={value => setMaxTokens(value[0])}
|
||||||
max={2048} // should be dynamic to the currently selected model
|
max={2048} // should be dynamic to the currently selected model
|
||||||
|
|
@ -191,6 +200,7 @@ function Settings(props) {
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id="top-p-int"
|
id="top-p-int"
|
||||||
|
disabled
|
||||||
value={topP}
|
value={topP}
|
||||||
onChange={e => setTopP(e.target.value)}
|
onChange={e => setTopP(e.target.value)}
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|
@ -200,6 +210,7 @@ function Settings(props) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Slider
|
<Slider
|
||||||
|
disabled={readonly}
|
||||||
value={[topP]}
|
value={[topP]}
|
||||||
onValueChange={value => setTopP(value[0])}
|
onValueChange={value => setTopP(value[0])}
|
||||||
max={1}
|
max={1}
|
||||||
|
|
@ -225,6 +236,7 @@ function Settings(props) {
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id="freq-penalty-int"
|
id="freq-penalty-int"
|
||||||
|
disabled
|
||||||
value={freqP}
|
value={freqP}
|
||||||
onChange={e => setFreqP(e.target.value)}
|
onChange={e => setFreqP(e.target.value)}
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|
@ -234,6 +246,7 @@ function Settings(props) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Slider
|
<Slider
|
||||||
|
disabled={readonly}
|
||||||
value={[freqP]}
|
value={[freqP]}
|
||||||
onValueChange={value => setFreqP(value[0])}
|
onValueChange={value => setFreqP(value[0])}
|
||||||
max={2}
|
max={2}
|
||||||
|
|
@ -259,6 +272,7 @@ function Settings(props) {
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id="pres-penalty-int"
|
id="pres-penalty-int"
|
||||||
|
disabled
|
||||||
value={presP}
|
value={presP}
|
||||||
onChange={e => setPresP(e.target.value)}
|
onChange={e => setPresP(e.target.value)}
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|
@ -268,6 +282,7 @@ function Settings(props) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Slider
|
<Slider
|
||||||
|
disabled={readonly}
|
||||||
value={[presP]}
|
value={[presP]}
|
||||||
onValueChange={value => setPresP(value[0])}
|
onValueChange={value => setPresP(value[0])}
|
||||||
max={2}
|
max={2}
|
||||||
|
|
@ -281,158 +296,6 @@ function Settings(props) {
|
||||||
side="left"
|
side="left"
|
||||||
/>
|
/>
|
||||||
</HoverCard>
|
</HoverCard>
|
||||||
{/* <div className="flex justify-around">
|
|
||||||
<HoverCard>
|
|
||||||
<HoverCardTrigger className="group/temp mr-4 flex w-full items-center justify-end gap-4">
|
|
||||||
<Label
|
|
||||||
htmlFor="temperature"
|
|
||||||
className="mr-2 text-right"
|
|
||||||
>
|
|
||||||
Temperature
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
id="temp-int"
|
|
||||||
value={temperature}
|
|
||||||
onChange={e => setTemperature(e.target.value)}
|
|
||||||
className={cn(defaultTextProps, cn(optionText, 'w-10 group-hover/temp:border-gray-200'))}
|
|
||||||
/>
|
|
||||||
</HoverCardTrigger>
|
|
||||||
<OptionHover
|
|
||||||
type="temp"
|
|
||||||
side="right"
|
|
||||||
/>
|
|
||||||
</HoverCard>
|
|
||||||
<HoverCard>
|
|
||||||
<HoverCardTrigger className="group/max mr-4 flex w-full items-center justify-end gap-4">
|
|
||||||
<Label
|
|
||||||
htmlFor="max-tokens"
|
|
||||||
className="mr-2 w-full text-right"
|
|
||||||
>
|
|
||||||
Max tokens
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
id="max-tokens-int"
|
|
||||||
value={maxTokens}
|
|
||||||
onChange={e => setMaxTokens(e.target.value)}
|
|
||||||
className={cn(defaultTextProps, cn(optionText, 'w-11 group-hover/max:border-gray-200'))}
|
|
||||||
/>
|
|
||||||
</HoverCardTrigger>
|
|
||||||
<OptionHover
|
|
||||||
type="max"
|
|
||||||
side="left"
|
|
||||||
/>
|
|
||||||
</HoverCard>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-2 items-center gap-5">
|
|
||||||
<Slider
|
|
||||||
value={[maxTokens]}
|
|
||||||
onValueChange={value => setMaxTokens(value)}
|
|
||||||
max={2048} // should be dynamic to the currently selected model
|
|
||||||
min={1}
|
|
||||||
step={1}
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-around">
|
|
||||||
<HoverCard>
|
|
||||||
<HoverCardTrigger className="group/top mr-4 flex w-full items-center justify-end gap-4">
|
|
||||||
<Label
|
|
||||||
htmlFor="top-p"
|
|
||||||
className="mr-2 text-right"
|
|
||||||
>
|
|
||||||
Top P
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
id="top-p-int"
|
|
||||||
value={topP}
|
|
||||||
onChange={e => setTopP(e.target.value)}
|
|
||||||
className={cn(defaultTextProps, cn(optionText, 'w-10 group-hover/top:border-gray-200'))}
|
|
||||||
/>
|
|
||||||
<OptionHover
|
|
||||||
type="top-p"
|
|
||||||
side="right"
|
|
||||||
/>
|
|
||||||
</HoverCardTrigger>
|
|
||||||
</HoverCard>
|
|
||||||
<HoverCard>
|
|
||||||
<HoverCardTrigger className="group/freq mr-4 flex w-full items-center justify-end gap-4">
|
|
||||||
<Label
|
|
||||||
htmlFor="freq-penalty"
|
|
||||||
className="mr-2 w-full text-right"
|
|
||||||
>
|
|
||||||
Frequency Penalty
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
id="freq-penalty-int"
|
|
||||||
value={freqP}
|
|
||||||
onChange={e => setFreqP(e.target.value)}
|
|
||||||
className={cn(defaultTextProps, cn(optionText, 'w-10 group-hover/freq:border-gray-200'))}
|
|
||||||
/>
|
|
||||||
</HoverCardTrigger>
|
|
||||||
<OptionHover
|
|
||||||
type="freq"
|
|
||||||
side="left"
|
|
||||||
/>
|
|
||||||
</HoverCard>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-2 items-center gap-5">
|
|
||||||
<Slider
|
|
||||||
value={[topP]}
|
|
||||||
onValueChange={value => setTopP(value)}
|
|
||||||
max={1}
|
|
||||||
min={0}
|
|
||||||
step={0.01}
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
<Slider
|
|
||||||
value={[freqP]}
|
|
||||||
onValueChange={value => setFreqP(value)}
|
|
||||||
max={2}
|
|
||||||
min={-2}
|
|
||||||
step={0.01}
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-end">
|
|
||||||
<HoverCard>
|
|
||||||
<HoverCardTrigger className="group/pres mr-4 flex items-center justify-end gap-4">
|
|
||||||
<Label
|
|
||||||
htmlFor="pres-penalty"
|
|
||||||
className="mr-2 text-right"
|
|
||||||
>
|
|
||||||
Presence Penalty
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
id="pres-penalty-int"
|
|
||||||
value={presP}
|
|
||||||
onChange={e => setPresP(e.target.value)}
|
|
||||||
className={cn(defaultTextProps, cn(optionText, 'w-10 group-hover/pres:border-gray-200'))}
|
|
||||||
/>
|
|
||||||
</HoverCardTrigger>
|
|
||||||
<OptionHover
|
|
||||||
type="pres"
|
|
||||||
side="left"
|
|
||||||
/>
|
|
||||||
</HoverCard>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-2 items-center gap-5">
|
|
||||||
<Slider
|
|
||||||
value={[presP]}
|
|
||||||
onValueChange={value => setPresP(value)}
|
|
||||||
max={2}
|
|
||||||
min={-2}
|
|
||||||
step={0.01}
|
|
||||||
className="w-full opacity-0"
|
|
||||||
/>
|
|
||||||
<Slider
|
|
||||||
value={[presP]}
|
|
||||||
onValueChange={value => setPresP(value)}
|
|
||||||
max={2}
|
|
||||||
min={-2}
|
|
||||||
step={0.01}
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
</div> */}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@ import { Dialog } from '../ui/Dialog.tsx';
|
||||||
import { Input } from '../ui/Input.tsx';
|
import { Input } from '../ui/Input.tsx';
|
||||||
import { Label } from '../ui/Label.tsx';
|
import { Label } from '../ui/Label.tsx';
|
||||||
import { cn } from '~/utils/';
|
import { cn } from '~/utils/';
|
||||||
import buildPresetByConversation from '~/utils/buildPresetByConversation';
|
import cleanupPreset from '~/utils/cleanupPreset';
|
||||||
|
|
||||||
import store from '~/store';
|
import store from '~/store';
|
||||||
|
|
||||||
const SaveAsPresetDialog = ({ open, onOpenChange, conversation }) => {
|
const SaveAsPresetDialog = ({ open, onOpenChange, preset }) => {
|
||||||
const [title, setTitle] = useState('My Preset');
|
const [title, setTitle] = useState('My Preset');
|
||||||
const setPresets = useSetRecoilState(store.presets);
|
const setPresets = useSetRecoilState(store.presets);
|
||||||
|
|
||||||
|
|
@ -18,15 +18,15 @@ const SaveAsPresetDialog = ({ open, onOpenChange, conversation }) => {
|
||||||
'rounded-md border border-gray-300 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.10)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-400 dark:bg-gray-700 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';
|
'rounded-md border border-gray-300 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.10)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-400 dark:bg-gray-700 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';
|
||||||
|
|
||||||
const submitPreset = () => {
|
const submitPreset = () => {
|
||||||
const preset = buildPresetByConversation({
|
const _preset = cleanupPreset({
|
||||||
title,
|
...preset,
|
||||||
conversation
|
title
|
||||||
});
|
});
|
||||||
|
|
||||||
axios({
|
axios({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/api/presets',
|
url: '/api/presets',
|
||||||
data: preset,
|
data: _preset,
|
||||||
withCredentials: true
|
withCredentials: true
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
setPresets(res?.data);
|
setPresets(res?.data);
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ function BingAIOptions() {
|
||||||
<SaveAsPresetDialog
|
<SaveAsPresetDialog
|
||||||
open={saveAsDialogShow}
|
open={saveAsDialogShow}
|
||||||
onOpenChange={setSaveAsDialogShow}
|
onOpenChange={setSaveAsDialogShow}
|
||||||
conversation={conversation}
|
preset={conversation}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue, useRecoilState } from 'recoil';
|
||||||
import EditPresetDialog from '../../Endpoints/EditPresetDialog';
|
import EditPresetDialog from '../../Endpoints/EditPresetDialog';
|
||||||
import EndpointItems from './EndpointItems';
|
import EndpointItems from './EndpointItems';
|
||||||
import PresetItems from './PresetItems';
|
import PresetItems from './PresetItems';
|
||||||
import getIcon from '~/utils/getIcon';
|
import getIcon from '~/utils/getIcon';
|
||||||
|
import manualSWR from '~/utils/fetchers';
|
||||||
|
|
||||||
import { Button } from '../../ui/Button.tsx';
|
import { Button } from '../../ui/Button.tsx';
|
||||||
import {
|
import {
|
||||||
|
|
@ -27,13 +28,18 @@ export default function NewConversationMenu() {
|
||||||
// const models = useRecoilValue(store.models);
|
// const models = useRecoilValue(store.models);
|
||||||
const availableEndpoints = useRecoilValue(store.availableEndpoints);
|
const availableEndpoints = useRecoilValue(store.availableEndpoints);
|
||||||
// const setCustomGPTModels = useSetRecoilState(store.customGPTModels);
|
// const setCustomGPTModels = useSetRecoilState(store.customGPTModels);
|
||||||
const presets = useRecoilValue(store.presets);
|
const [presets, setPresets] = useRecoilState(store.presets);
|
||||||
|
|
||||||
const conversation = useRecoilValue(store.conversation) || {};
|
const conversation = useRecoilValue(store.conversation) || {};
|
||||||
const { endpoint, conversationId } = conversation;
|
const { endpoint, conversationId } = conversation;
|
||||||
// const { model, promptPrefix, chatGptLabel, conversationId } = conversation;
|
// const { model, promptPrefix, chatGptLabel, conversationId } = conversation;
|
||||||
const { newConversation } = store.useConversation();
|
const { newConversation } = store.useConversation();
|
||||||
|
|
||||||
|
const { trigger: clearPresetsTrigger } = manualSWR(`/api/presets/delete`, 'post', data => {
|
||||||
|
console.log(data);
|
||||||
|
setPresets(data);
|
||||||
|
});
|
||||||
|
|
||||||
// update the default model when availableModels changes
|
// update the default model when availableModels changes
|
||||||
// typically, availableModels changes => modelsFilter or customGPTModels changes
|
// typically, availableModels changes => modelsFilter or customGPTModels changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -73,6 +79,10 @@ export default function NewConversationMenu() {
|
||||||
setPreset(preset);
|
setPreset(preset);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const clearPreset = () => {
|
||||||
|
clearPresetsTrigger({});
|
||||||
|
};
|
||||||
|
|
||||||
const icon = getIcon({
|
const icon = getIcon({
|
||||||
size: 32,
|
size: 32,
|
||||||
...conversation,
|
...conversation,
|
||||||
|
|
@ -99,7 +109,7 @@ export default function NewConversationMenu() {
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent
|
<DropdownMenuContent
|
||||||
className="min-w-56 dark:bg-gray-700"
|
className="min-w-[300px] dark:bg-gray-700"
|
||||||
onCloseAutoFocus={event => event.preventDefault()}
|
onCloseAutoFocus={event => event.preventDefault()}
|
||||||
>
|
>
|
||||||
<DropdownMenuLabel className="dark:text-gray-300">Select an Endpoint</DropdownMenuLabel>
|
<DropdownMenuLabel className="dark:text-gray-300">Select an Endpoint</DropdownMenuLabel>
|
||||||
|
|
@ -121,7 +131,17 @@ export default function NewConversationMenu() {
|
||||||
|
|
||||||
<div className="mt-6 w-full" />
|
<div className="mt-6 w-full" />
|
||||||
|
|
||||||
<DropdownMenuLabel className="dark:text-gray-300">Select a Preset</DropdownMenuLabel>
|
<DropdownMenuLabel className="flex items-center dark:text-gray-300">
|
||||||
|
<span>Select a Preset</span>
|
||||||
|
<div className="flex-1" />
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
className="h-auto bg-transparent px-2 py-1 text-xs font-medium font-normal text-red-700 hover:bg-slate-200 hover:text-red-700 dark:bg-transparent dark:text-red-400 dark:hover:bg-gray-800 dark:hover:text-red-400"
|
||||||
|
onClick={clearPreset}
|
||||||
|
>
|
||||||
|
Clear All
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuLabel>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
<DropdownMenuRadioGroup
|
<DropdownMenuRadioGroup
|
||||||
onValueChange={onSelectPreset}
|
onValueChange={onSelectPreset}
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ function OpenAIOptions() {
|
||||||
<SaveAsPresetDialog
|
<SaveAsPresetDialog
|
||||||
open={saveAsDialogShow}
|
open={saveAsDialogShow}
|
||||||
onOpenChange={setSaveAsDialogShow}
|
onOpenChange={setSaveAsDialogShow}
|
||||||
conversation={conversation}
|
preset={conversation}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import EndpointOptionsDialog from '../Endpoints/EndpointOptionsDialog';
|
||||||
|
import { Button } from '../ui/Button.tsx';
|
||||||
|
|
||||||
import store from '~/store';
|
import store from '~/store';
|
||||||
|
|
||||||
|
|
@ -14,6 +16,7 @@ const clipPromptPrefix = str => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const MessageHeader = ({ isSearchView = false }) => {
|
const MessageHeader = ({ isSearchView = false }) => {
|
||||||
|
const [saveAsDialogShow, setSaveAsDialogShow] = useState(false);
|
||||||
const [extended, setExtended] = useState(false);
|
const [extended, setExtended] = useState(false);
|
||||||
const conversation = useRecoilValue(store.conversation);
|
const conversation = useRecoilValue(store.conversation);
|
||||||
const searchQuery = useRecoilValue(store.searchQuery);
|
const searchQuery = useRecoilValue(store.searchQuery);
|
||||||
|
|
@ -64,6 +67,7 @@ const MessageHeader = ({ isSearchView = false }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
'dark:text-gray-450 w-full gap-1 border-b border-black/10 bg-gray-50 text-sm text-gray-500 transition-all hover:bg-gray-100 dark:border-gray-900/50 dark:bg-gray-700 dark:hover:bg-gray-600' +
|
'dark:text-gray-450 w-full gap-1 border-b border-black/10 bg-gray-50 text-sm text-gray-500 transition-all hover:bg-gray-100 dark:border-gray-900/50 dark:bg-gray-700 dark:hover:bg-gray-600' +
|
||||||
|
|
@ -85,9 +89,17 @@ const MessageHeader = ({ isSearchView = false }) => {
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
<Button onClick={() => setSaveAsDialogShow(true)}>View</Button>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<EndpointOptionsDialog
|
||||||
|
open={saveAsDialogShow}
|
||||||
|
onOpenChange={setSaveAsDialogShow}
|
||||||
|
preset={conversation}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ export default function DialogTemplate({
|
||||||
{main ? main : null}
|
{main ? main : null}
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<div>{leftButtons ? leftButtons : null}</div>
|
<div>{leftButtons ? leftButtons : null}</div>
|
||||||
<div>
|
<div className="flex gap-2">
|
||||||
<DialogClose className="dark:hover:gray-400 border-gray-700">Cancel</DialogClose>
|
<DialogClose className="dark:hover:gray-400 border-gray-700">Cancel</DialogClose>
|
||||||
{buttons ? buttons : null}
|
{buttons ? buttons : null}
|
||||||
{selection ? (
|
{selection ? (
|
||||||
|
|
|
||||||
43
client/src/components/ui/InputNumber.jsx
Normal file
43
client/src/components/ui/InputNumber.jsx
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
import { NumericFormat } from 'react-number-format';
|
||||||
|
|
||||||
|
// import * as InputNumberPrimitive from 'rc-input-number';
|
||||||
|
|
||||||
|
import { cn } from '../../utils/index.jsx';
|
||||||
|
|
||||||
|
// TODO help needed
|
||||||
|
// const _InputNumber = React.forwardRef< React.ElementRef<typeof InputNumber>, InputNumberPrimitive.InputNumberProps>(
|
||||||
|
// ({ className, ...props }, ref) => {
|
||||||
|
// return (
|
||||||
|
// <InputNumber
|
||||||
|
// className={cn(
|
||||||
|
// "flex h-10 w-full rounded-md border border-slate-300 bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-700 dark:text-slate-50 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900",
|
||||||
|
// className
|
||||||
|
// )}
|
||||||
|
// ref={ref}
|
||||||
|
// {...props}
|
||||||
|
// />
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// _InputNumber.displayName = "Input"
|
||||||
|
|
||||||
|
// console.log(_InputNumber);
|
||||||
|
|
||||||
|
const InputNumber = React.forwardRef(({ className, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<NumericFormat
|
||||||
|
className={cn(
|
||||||
|
'flex h-10 w-full rounded-md border border-slate-300 bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-700 dark:text-slate-50 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export { InputNumber };
|
||||||
|
|
@ -7,6 +7,7 @@ import store from '~/store';
|
||||||
|
|
||||||
function ModelDropDown({
|
function ModelDropDown({
|
||||||
model,
|
model,
|
||||||
|
disabled,
|
||||||
setModel,
|
setModel,
|
||||||
endpoint,
|
endpoint,
|
||||||
showAbove = false,
|
showAbove = false,
|
||||||
|
|
@ -23,6 +24,7 @@ function ModelDropDown({
|
||||||
<Listbox
|
<Listbox
|
||||||
value={model}
|
value={model}
|
||||||
onChange={setModel}
|
onChange={setModel}
|
||||||
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
{({ open }) => (
|
{({ open }) => (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ import getDefaultConversation from '~/utils/getDefaultConversation';
|
||||||
// frequency_penalty: 0,
|
// frequency_penalty: 0,
|
||||||
// // for bingAI only
|
// // for bingAI only
|
||||||
// jailbreak: false,
|
// jailbreak: false,
|
||||||
|
// context: null,
|
||||||
|
// systemMessage: null,
|
||||||
// jailbreakConversationId: null,
|
// jailbreakConversationId: null,
|
||||||
// conversationSignature: null,
|
// conversationSignature: null,
|
||||||
// clientId: null,
|
// clientId: null,
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
const buildPresetByConversation = ({ title, conversation, ...others }) => {
|
|
||||||
const { endpoint } = conversation;
|
|
||||||
|
|
||||||
let preset = {};
|
|
||||||
if (endpoint === 'azureOpenAI' || endpoint === 'openAI') {
|
|
||||||
preset = {
|
|
||||||
endpoint,
|
|
||||||
model: conversation?.model || 'gpt-3.5-turbo',
|
|
||||||
chatGptLabel: conversation?.chatGptLabel || null,
|
|
||||||
promptPrefix: conversation?.promptPrefix || null,
|
|
||||||
temperature: conversation?.temperature || 1,
|
|
||||||
top_p: conversation?.top_p || 1,
|
|
||||||
presence_penalty: conversation?.presence_penalty || 0,
|
|
||||||
frequency_penalty: conversation?.frequency_penalty || 0,
|
|
||||||
title,
|
|
||||||
...others
|
|
||||||
};
|
|
||||||
} else if (endpoint === 'bingAI') {
|
|
||||||
preset = {
|
|
||||||
endpoint,
|
|
||||||
jailbreak: conversation?.jailbreak || false,
|
|
||||||
jailbreakConversationId: conversation?.jailbreakConversationId || null,
|
|
||||||
conversationSignature: null,
|
|
||||||
clientId: null,
|
|
||||||
invocationId: 1,
|
|
||||||
toneStyle: conversation?.toneStyle || 'fast',
|
|
||||||
title,
|
|
||||||
...others
|
|
||||||
};
|
|
||||||
} else if (endpoint === 'chatGPTBrowser') {
|
|
||||||
preset = {
|
|
||||||
endpoint,
|
|
||||||
model: conversation?.model || 'Default (GPT-3.5)',
|
|
||||||
title,
|
|
||||||
...others
|
|
||||||
};
|
|
||||||
} else if (endpoint === null) {
|
|
||||||
preset = {
|
|
||||||
...conversation,
|
|
||||||
endpoint,
|
|
||||||
title,
|
|
||||||
...others
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
console.error(`Unknown endpoint ${endpoint}`);
|
|
||||||
preset = {
|
|
||||||
endpoint: null,
|
|
||||||
title,
|
|
||||||
...others
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return preset;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default buildPresetByConversation;
|
|
||||||
55
client/src/utils/cleanupPreset.js
Normal file
55
client/src/utils/cleanupPreset.js
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
const cleanupPreset = _preset => {
|
||||||
|
const { endpoint } = _preset;
|
||||||
|
|
||||||
|
let preset = {};
|
||||||
|
if (endpoint === 'azureOpenAI' || endpoint === 'openAI') {
|
||||||
|
preset = {
|
||||||
|
endpoint,
|
||||||
|
presetId: _preset?.presetId || null,
|
||||||
|
model: _preset?.model || 'gpt-3.5-turbo',
|
||||||
|
chatGptLabel: _preset?.chatGptLabel || null,
|
||||||
|
promptPrefix: _preset?.promptPrefix || null,
|
||||||
|
temperature: _preset?.temperature || 1,
|
||||||
|
top_p: _preset?.top_p || 1,
|
||||||
|
presence_penalty: _preset?.presence_penalty || 0,
|
||||||
|
frequency_penalty: _preset?.frequency_penalty || 0,
|
||||||
|
title: _preset?.title || 'New Preset'
|
||||||
|
};
|
||||||
|
} else if (endpoint === 'bingAI') {
|
||||||
|
preset = {
|
||||||
|
endpoint,
|
||||||
|
presetId: _preset?.presetId || null,
|
||||||
|
jailbreak: _preset?.jailbreak || false,
|
||||||
|
jailbreakpresetId: _preset?._jailbreakpresetId || null,
|
||||||
|
presetSignature: null,
|
||||||
|
clientId: null,
|
||||||
|
invocationId: 1,
|
||||||
|
toneStyle: _preset?.toneStyle || 'fast',
|
||||||
|
title: _preset?.title || 'New Preset'
|
||||||
|
};
|
||||||
|
} else if (endpoint === 'chatGPTBrowser') {
|
||||||
|
preset = {
|
||||||
|
endpoint,
|
||||||
|
presetId: _preset?.presetId || null,
|
||||||
|
model: _preset?.model || 'Default (GPT-3.5)',
|
||||||
|
title: _preset?.title || 'New Preset'
|
||||||
|
};
|
||||||
|
} else if (endpoint === null) {
|
||||||
|
preset = {
|
||||||
|
endpoint,
|
||||||
|
presetId: _preset?.presetId || null,
|
||||||
|
title: _preset?.title || 'New Preset'
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
console.error(`Unknown endpoint ${endpoint}`);
|
||||||
|
preset = {
|
||||||
|
endpoint: null,
|
||||||
|
presetId: _preset?.presetId || null,
|
||||||
|
title: _preset?.title || 'New Preset'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return preset;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default cleanupPreset;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue