mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 08:12:00 +02:00
basic settings done for openAI
This commit is contained in:
commit
580d82ffe8
9 changed files with 483 additions and 153 deletions
39
client/package-lock.json
generated
39
client/package-lock.json
generated
|
@ -12,6 +12,7 @@
|
|||
"@radix-ui/react-alert-dialog": "^1.0.2",
|
||||
"@radix-ui/react-dialog": "^1.0.2",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.2",
|
||||
"@radix-ui/react-hover-card": "^1.0.5",
|
||||
"@radix-ui/react-label": "^2.0.0",
|
||||
"@radix-ui/react-slider": "^1.1.1",
|
||||
"@radix-ui/react-tabs": "^1.0.3",
|
||||
|
@ -2974,6 +2975,27 @@
|
|||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-hover-card": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.0.5.tgz",
|
||||
"integrity": "sha512-jXRuZEkxSWdHZbVyL0J46cm7pQjmOMpwJEFKY+VqAJnV+FxS+zIZExI1OCeIiDwCBzUy6If1FfouOsfqBxr86g==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/primitive": "1.0.0",
|
||||
"@radix-ui/react-compose-refs": "1.0.0",
|
||||
"@radix-ui/react-context": "1.0.0",
|
||||
"@radix-ui/react-dismissable-layer": "1.0.3",
|
||||
"@radix-ui/react-popper": "1.1.1",
|
||||
"@radix-ui/react-portal": "1.0.2",
|
||||
"@radix-ui/react-presence": "1.0.0",
|
||||
"@radix-ui/react-primitive": "1.0.2",
|
||||
"@radix-ui/react-use-controllable-state": "1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-id": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.0.tgz",
|
||||
|
@ -15802,6 +15824,23 @@
|
|||
"@radix-ui/react-use-callback-ref": "1.0.0"
|
||||
}
|
||||
},
|
||||
"@radix-ui/react-hover-card": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.0.5.tgz",
|
||||
"integrity": "sha512-jXRuZEkxSWdHZbVyL0J46cm7pQjmOMpwJEFKY+VqAJnV+FxS+zIZExI1OCeIiDwCBzUy6If1FfouOsfqBxr86g==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/primitive": "1.0.0",
|
||||
"@radix-ui/react-compose-refs": "1.0.0",
|
||||
"@radix-ui/react-context": "1.0.0",
|
||||
"@radix-ui/react-dismissable-layer": "1.0.3",
|
||||
"@radix-ui/react-popper": "1.1.1",
|
||||
"@radix-ui/react-portal": "1.0.2",
|
||||
"@radix-ui/react-presence": "1.0.0",
|
||||
"@radix-ui/react-primitive": "1.0.2",
|
||||
"@radix-ui/react-use-controllable-state": "1.0.0"
|
||||
}
|
||||
},
|
||||
"@radix-ui/react-id": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.0.tgz",
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
"@radix-ui/react-alert-dialog": "^1.0.2",
|
||||
"@radix-ui/react-dialog": "^1.0.2",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.2",
|
||||
"@radix-ui/react-hover-card": "^1.0.5",
|
||||
"@radix-ui/react-label": "^2.0.0",
|
||||
"@radix-ui/react-slider": "^1.1.1",
|
||||
"@radix-ui/react-tabs": "^1.0.3",
|
||||
|
|
54
client/src/components/Input/OpenAIOptions/ModelSelect.jsx
Normal file
54
client/src/components/Input/OpenAIOptions/ModelSelect.jsx
Normal file
|
@ -0,0 +1,54 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Button } from '../../ui/Button.tsx';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuRadioItem
|
||||
} from '../../ui/DropdownMenu.tsx';
|
||||
|
||||
const ModelSelect = ({ model, onChange, models, ...props }) => {
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
|
||||
models = ['gpt-4', 'text-davinci-003', 'gpt-3.5-turbo', 'gpt-3.5-turbo-0301'];
|
||||
|
||||
return (
|
||||
<DropdownMenu
|
||||
open={menuOpen}
|
||||
onOpenChange={setMenuOpen}
|
||||
>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button {...props}>
|
||||
<span className="w-full text-center text-xs font-medium font-normal">Model: {model}</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
className="w-56 dark:bg-gray-700"
|
||||
onCloseAutoFocus={event => event.preventDefault()}
|
||||
>
|
||||
<DropdownMenuLabel className="dark:text-gray-300">Select a model</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuRadioGroup
|
||||
value={model}
|
||||
onValueChange={onChange}
|
||||
className="overflow-y-auto"
|
||||
>
|
||||
{models.map(model => (
|
||||
<DropdownMenuRadioItem
|
||||
key={model}
|
||||
value={model}
|
||||
className="dark:font-semibold dark:text-gray-100 dark:hover:bg-gray-800"
|
||||
>
|
||||
{model}
|
||||
</DropdownMenuRadioItem>
|
||||
))}
|
||||
</DropdownMenuRadioGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModelSelect;
|
53
client/src/components/Input/OpenAIOptions/OptionHover.jsx
Normal file
53
client/src/components/Input/OpenAIOptions/OptionHover.jsx
Normal file
|
@ -0,0 +1,53 @@
|
|||
import React from 'react';
|
||||
import {
|
||||
// HoverCard,
|
||||
// HoverCardTrigger,
|
||||
HoverCardPortal,
|
||||
HoverCardContent
|
||||
} from '~/components/ui/HoverCard.tsx';
|
||||
|
||||
// import { cn } from '~/utils/';
|
||||
|
||||
const types = {
|
||||
temp: {
|
||||
description:
|
||||
'Higher values = more random, while lower values = more focused and deterministic. We recommend altering this or Top P but not both.'
|
||||
},
|
||||
max: {
|
||||
description:
|
||||
'The max tokens to generate. The total length of input tokens and generated tokens is limited by the model\'s context length.'
|
||||
},
|
||||
'top-p': {
|
||||
description:
|
||||
'An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We recommend altering this or temperature but not both.'
|
||||
},
|
||||
freq: {
|
||||
description:
|
||||
'Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model\'s likelihood to repeat the same line verbatim.'
|
||||
},
|
||||
pres: {
|
||||
description:
|
||||
'Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model\'s likelihood to talk about new topics.'
|
||||
},
|
||||
};
|
||||
|
||||
function OptionHover({ type, side }) {
|
||||
|
||||
const options = {};
|
||||
|
||||
if (type === 'pres') {
|
||||
options.sideOffset = 45;
|
||||
}
|
||||
|
||||
return (
|
||||
<HoverCardPortal>
|
||||
<HoverCardContent side={side} className="w-52 " {...options}>
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300">{types[type].description}</p>
|
||||
</div>
|
||||
</HoverCardContent>
|
||||
</HoverCardPortal>
|
||||
);
|
||||
}
|
||||
|
||||
export default OptionHover;
|
|
@ -3,17 +3,24 @@ import TextareaAutosize from 'react-textarea-autosize';
|
|||
import { Input } from '~/components/ui/Input.tsx';
|
||||
import { Label } from '~/components/ui/Label.tsx';
|
||||
import { Slider } from '~/components/ui/Slider.tsx';
|
||||
import OptionHover from './OptionHover';
|
||||
import {
|
||||
HoverCard,
|
||||
HoverCardTrigger
|
||||
// HoverCardContent,
|
||||
} from '~/components/ui/HoverCard.tsx';
|
||||
import { cn } from '~/utils/';
|
||||
const defaultTextProps =
|
||||
'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-none dark:bg-gray-700 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-none dark:focus:border-transparent dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';
|
||||
|
||||
const optionText = 'p-0 shadow-none text-right pr-1 h-8';
|
||||
const optionText =
|
||||
'p-0 shadow-none text-right pr-1 h-8 border-transparent focus:ring-[#10a37f] focus:ring-offset-0 focus:ring-opacity-100';
|
||||
|
||||
function Settings() {
|
||||
const [chatGptLabel, setChatGptLabel] = useState('');
|
||||
const [promptPrefix, setPromptPrefix] = useState('');
|
||||
const [temperature, setTemperature] = useState(1);
|
||||
const [maxLength, setMaxLength] = useState(2048);
|
||||
const [maxTokens, setMaxTokens] = useState(2048);
|
||||
const [topP, setTopP] = useState(1);
|
||||
const [freqP, setFreqP] = useState(0);
|
||||
const [presP, setPresP] = useState(0);
|
||||
|
@ -32,6 +39,7 @@ function Settings() {
|
|||
<u>More info here</u>
|
||||
</a>
|
||||
</DialogDescription> */}
|
||||
<>
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label
|
||||
|
@ -75,7 +83,9 @@ function Settings() {
|
|||
/>
|
||||
</div>
|
||||
<div className="flex justify-around">
|
||||
<div className="flex w-full items-center justify-end mr-4 gap-4">
|
||||
<HoverCard>
|
||||
<HoverCardTrigger className="group/temp mr-4 flex w-full items-center justify-end gap-4">
|
||||
{/* <div className="mr-4 flex w-full items-center justify-end gap-4"> */}
|
||||
<Label
|
||||
htmlFor="temperature"
|
||||
className="mr-2 text-right"
|
||||
|
@ -86,30 +96,42 @@ function Settings() {
|
|||
id="temp-int"
|
||||
value={temperature}
|
||||
onChange={e => setTemperature(e.target.value)}
|
||||
placeholder="1.0"
|
||||
className={cn(defaultTextProps, `w-9 ${optionText}`)}
|
||||
className={cn(defaultTextProps, cn(optionText, 'w-10 group-hover/temp:border-gray-200'))}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-end mr-4 gap-4">
|
||||
{/* </div> */}
|
||||
</HoverCardTrigger>
|
||||
<OptionHover
|
||||
type="temp"
|
||||
side="right"
|
||||
/>
|
||||
</HoverCard>
|
||||
{/* <div className="mr-4 flex w-full items-center justify-end gap-4"> */}
|
||||
<HoverCard>
|
||||
<HoverCardTrigger className="group/max mr-4 flex w-full items-center justify-end gap-4">
|
||||
<Label
|
||||
htmlFor="max-length"
|
||||
htmlFor="max-tokens"
|
||||
className="mr-2 w-full text-right"
|
||||
>
|
||||
Max. length
|
||||
Max tokens
|
||||
</Label>
|
||||
<Input
|
||||
id="max-length-int"
|
||||
value={maxLength}
|
||||
onChange={e => setMaxLength(e.target.value)}
|
||||
placeholder="1.0"
|
||||
className={cn(defaultTextProps, `w-11 ${optionText}`)}
|
||||
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'))}
|
||||
/>
|
||||
</div>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover
|
||||
type="max"
|
||||
side="left"
|
||||
/>
|
||||
</HoverCard>
|
||||
{/* </div> */}
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 items-center gap-4">
|
||||
<div className="grid grid-cols-2 items-center gap-5">
|
||||
<Slider
|
||||
defaultValue={[1]}
|
||||
value={[temperature]}
|
||||
onValueChange={value => setTemperature(value)}
|
||||
max={2}
|
||||
min={0}
|
||||
|
@ -117,17 +139,17 @@ function Settings() {
|
|||
className="w-full"
|
||||
/>
|
||||
<Slider
|
||||
defaultValue={[2048]}
|
||||
onValueChange={value => setMaxLength(value)}
|
||||
max={2048}
|
||||
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">
|
||||
<div className="flex w-full items-center justify-end mr-4 gap-4">
|
||||
<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"
|
||||
|
@ -138,45 +160,95 @@ function Settings() {
|
|||
id="top-p-int"
|
||||
value={topP}
|
||||
onChange={e => setTopP(e.target.value)}
|
||||
placeholder="1.0"
|
||||
className={cn(defaultTextProps, `w-9 ${optionText}`)}
|
||||
className={cn(defaultTextProps, cn(optionText, 'w-10 group-hover/top:border-gray-200'))}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-end mr-4 gap-4">
|
||||
<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"
|
||||
>
|
||||
Freq. Penalty
|
||||
Frequency Penalty
|
||||
</Label>
|
||||
<Input
|
||||
id="freq-penalty-int"
|
||||
value={freqP}
|
||||
onChange={e => setFreqP(e.target.value)}
|
||||
placeholder="1.0"
|
||||
className={cn(defaultTextProps, `w-9 ${optionText}`)}
|
||||
className={cn(defaultTextProps, cn(optionText, 'w-10 group-hover/freq:border-gray-200'))}
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover
|
||||
type="freq"
|
||||
side="left"
|
||||
/>
|
||||
</HoverCard>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 items-center gap-4">
|
||||
<div className="grid grid-cols-2 items-center gap-5">
|
||||
<Slider
|
||||
defaultValue={[0]}
|
||||
value={[topP]}
|
||||
onValueChange={value => setTopP(value)}
|
||||
max={2}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="w-full"
|
||||
/>
|
||||
<Slider
|
||||
defaultValue={[0]}
|
||||
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={0}
|
||||
step={0.01}
|
||||
className="w-full opacity-0"
|
||||
/>
|
||||
<Slider
|
||||
value={[0]}
|
||||
onValueChange={value => setPresP(value)}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState, useEffect, forwardRef } from 'react';
|
||||
import { Tabs, TabsList, TabsTrigger } from '../../ui/Tabs.tsx';
|
||||
import { useRecoilValue, useRecoilState } from 'recoil';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import ModelSelect from './ModelSelect';
|
||||
import { Button } from '../../ui/Button.tsx';
|
||||
import Settings from './Settings.jsx';
|
||||
|
||||
|
@ -8,29 +8,75 @@ import store from '~/store';
|
|||
|
||||
function OpenAIOptions({ conversation = {} }) {
|
||||
const { endpoint } = conversation;
|
||||
const { advancedMode, setAdvancedMode } = useState(false);
|
||||
const [advancedMode, setAdvancedMode] = useState(false);
|
||||
const setConversation = useSetRecoilState(store.conversation);
|
||||
|
||||
const triggerAdvancedMode = () => setAdvancedMode(prev => !prev);
|
||||
|
||||
const switchToSimpleMode = () => {
|
||||
setConversation(prevState => ({
|
||||
...prevState,
|
||||
chatGptLabel: null,
|
||||
promptPrefix: null,
|
||||
temperature: 0.8,
|
||||
top_p: 1,
|
||||
presence_penalty: 1
|
||||
}));
|
||||
setAdvancedMode(false);
|
||||
};
|
||||
|
||||
const setModel = newModel => {
|
||||
setConversation(prevState => ({
|
||||
...prevState,
|
||||
model: newModel
|
||||
}));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const { endpoint, chatGptLabel, promptPrefix, temperature, top_p, presence_penalty } = conversation;
|
||||
|
||||
if (endpoint !== 'openAI') return;
|
||||
|
||||
const mustInAdvancedMode =
|
||||
chatGptLabel !== null ||
|
||||
promptPrefix !== null ||
|
||||
temperature !== 0.8 ||
|
||||
top_p !== 1 ||
|
||||
presence_penalty !== 1;
|
||||
|
||||
if (mustInAdvancedMode && !advancedMode) setAdvancedMode(true);
|
||||
}, [conversation, advancedMode]);
|
||||
|
||||
if (endpoint !== 'openAI') return null;
|
||||
|
||||
const { model } = conversation;
|
||||
|
||||
const cardStyle =
|
||||
'shadow-md px-4 h-[40px] rounded-md min-w-[75px] font-normal bg-white border-black/10 border dark:bg-gray-700 text-black dark:text-white';
|
||||
'shadow-md rounded-md min-w-[75px] font-normal bg-white border-black/10 border dark:bg-gray-700 text-black dark:text-white';
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex w-full items-center justify-center gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
className={cardStyle + ' flex items-center justify-center hover:bg-slate-50 dark:hover:bg-gray-600'}
|
||||
<div
|
||||
className={
|
||||
'openAIOptions-simple-container flex w-full items-center justify-center gap-2' +
|
||||
(!advancedMode ? ' show' : '')
|
||||
}
|
||||
>
|
||||
<span className="w-full text-center text-xs font-medium font-normal">Model: {model}</span>
|
||||
</Button>
|
||||
<ModelSelect
|
||||
model={model}
|
||||
onChange={setModel}
|
||||
type="button"
|
||||
className={
|
||||
cardStyle +
|
||||
' flex h-[40px] items-center justify-center px-4 hover:bg-slate-50 data-[state=open]:bg-slate-50 dark:hover:bg-gray-600 dark:data-[state=open]:bg-gray-600'
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
className={cardStyle + ' flex items-center justify-center hover:bg-slate-50 dark:hover:bg-gray-600'}
|
||||
className={
|
||||
cardStyle +
|
||||
' flex h-[40px] items-center justify-center px-4 hover:bg-slate-50 dark:hover:bg-gray-600'
|
||||
}
|
||||
onClick={triggerAdvancedMode}
|
||||
>
|
||||
<span className="w-full text-center text-xs font-medium font-normal">More</span>
|
||||
|
@ -39,12 +85,21 @@ function OpenAIOptions({ conversation = {} }) {
|
|||
<div
|
||||
className={
|
||||
cardStyle +
|
||||
' p-b-[40px] absolute left-4 right-4 bottom-[40px] flex h-[300px] flex-col rounded-md bg-white'
|
||||
' p-b-[40px] openAIOptions-advanced-container absolute left-4 right-4 bottom-[40px] flex flex-col overflow-hidden rounded-md bg-slate-100 bg-white px-0' +
|
||||
(advancedMode ? ' show' : '')
|
||||
}
|
||||
>
|
||||
<div>hi there</div>
|
||||
{/* <div>content</div> */}
|
||||
<Settings />
|
||||
<div className="flex w-full items-center justify-between bg-slate-100 px-4 py-2 dark:bg-white/10">
|
||||
<span className="text-xs font-medium font-normal">Advanced settings for OpenAI endpoint</span>
|
||||
<Button
|
||||
type="button"
|
||||
className="h-auto bg-transparent px-2 py-1 text-xs font-medium font-normal text-black hover:bg-slate-200 hover:text-black dark:bg-transparent dark:text-white dark:hover:bg-gray-700 dark:hover:text-white"
|
||||
onClick={switchToSimpleMode}
|
||||
>
|
||||
Switch to simple mode
|
||||
</Button>
|
||||
</div>
|
||||
<div className="h-[375px] p-5"><Settings/></div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
31
client/src/components/ui/HoverCard.tsx
Normal file
31
client/src/components/ui/HoverCard.tsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
|
||||
|
||||
import { cn } from "../../utils"
|
||||
|
||||
const HoverCard = HoverCardPrimitive.Root
|
||||
|
||||
const HoverCardTrigger = HoverCardPrimitive.Trigger
|
||||
|
||||
const HoverCardPortal = HoverCardPrimitive.Portal
|
||||
|
||||
const HoverCardContent = React.forwardRef<
|
||||
React.ElementRef<typeof HoverCardPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
|
||||
>(({ className, align = "center", sideOffset = 6, ...props }, ref) => (
|
||||
<HoverCardPrimitive.Content
|
||||
ref={ref}
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"animate-in fade-in-0 z-50 w-64 rounded-md border border-gray-100 bg-white p-4 shadow-md outline-none dark:border-gray-800 dark:bg-gray-800",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
|
||||
|
||||
export { HoverCard, HoverCardTrigger, HoverCardContent, HoverCardPortal }
|
|
@ -17,10 +17,10 @@ const Slider = React.forwardRef<
|
|||
)}
|
||||
{...props}
|
||||
>
|
||||
<SliderPrimitive.Track className="relative h-1 w-full grow overflow-hidden rounded-full bg-gray-200 dark:bg-gray-900">
|
||||
<SliderPrimitive.Range className="absolute h-full bg-gray-700 dark:bg-gray-400" />
|
||||
<SliderPrimitive.Track className="relative h-1 w-full grow overflow-hidden rounded-full bg-gray-100 dark:bg-gray-900">
|
||||
<SliderPrimitive.Range className="absolute h-full bg-gray-400 dark:bg-gray-400" />
|
||||
</SliderPrimitive.Track>
|
||||
<SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border-2 border-gray-700 bg-white transition-colors focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 dark:border-gray-100 dark:bg-gray-400 dark:focus:ring-gray-400 dark:focus:ring-offset-gray-900" />
|
||||
<SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border-2 border-gray-400 bg-white transition-colors focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 dark:border-gray-100 dark:bg-gray-400 dark:focus:ring-gray-400 dark:focus:ring-offset-gray-900" />
|
||||
</SliderPrimitive.Root>
|
||||
))
|
||||
Slider.displayName = SliderPrimitive.Root.displayName
|
||||
|
|
|
@ -28,6 +28,31 @@
|
|||
transition: all 1s ease-in-out;
|
||||
} */
|
||||
|
||||
.openAIOptions-simple-container {
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: all 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.openAIOptions-simple-container.show {
|
||||
pointer-events: fill;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.openAIOptions-advanced-container {
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: all 0.2s ease-in-out;
|
||||
transform: scaleY(0);
|
||||
transform-origin: bottom center;
|
||||
}
|
||||
|
||||
.openAIOptions-advanced-container.show {
|
||||
pointer-events: fill;
|
||||
opacity: 1;
|
||||
transform: scaleY(1)
|
||||
}
|
||||
|
||||
.bing-styles {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue