mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-19 09:50:15 +01:00
📦 feat: Model & Assistants Combobox for Side Panel (#2380)
* WIP: dynamic settings * WIP: update tests and validations * refactor(SidePanel): use hook for Links * WIP: dynamic settings, slider implemented * feat(useDebouncedInput): dynamic typing with generic * refactor(generate): add `custom` optionType to be non-conforming to conversation schema * feat: DynamicDropdown * refactor(DynamicSlider): custom optionType handling and useEffect for conversation updates elsewhere * refactor(Panel): add more test cases * chore(DynamicSlider): note * refactor(useDebouncedInput): import defaultDebouncedDelay from ~/common` * WIP: implement remaining ComponentTypes * chore: add com_sidepanel_parameters * refactor: add langCode handling for dynamic settings * chore(useOriginNavigate): change path to '/c/' * refactor: explicit textarea focus on new convo, share textarea idea via ~/common * refactor: useParameterEffects: reset if convo or preset Ids change, share and maintain statefulness in side panel * wip: combobox * chore: minor styling for Select components * wip: combobox select styling for side panel * feat: complete combobox * refactor: model select for side panel switcher * refactor(Combobox): add portal * chore: comment out dynamic parameters panel for future PR and delete prompt files * refactor(Combobox): add icon field for options, change hover bg-color, add displayValue * fix(useNewConvo): proper textarea focus with setTimeout * refactor(AssistantSwitcher): use Combobox * refactor(ModelSwitcher): add textarea focus on model switch
This commit is contained in:
parent
f64a2cb0b0
commit
8e5f1ad575
33 changed files with 2850 additions and 462 deletions
215
client/src/components/SidePanel/Parameters/Panel.tsx
Normal file
215
client/src/components/SidePanel/Parameters/Panel.tsx
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
import { ComponentTypes } from 'librechat-data-provider';
|
||||
import type {
|
||||
DynamicSettingProps,
|
||||
SettingDefinition,
|
||||
SettingsConfiguration,
|
||||
} from 'librechat-data-provider';
|
||||
import { useSetIndexOptions } from '~/hooks';
|
||||
import DynamicDropdown from './DynamicDropdown';
|
||||
import DynamicCheckbox from './DynamicCheckbox';
|
||||
import DynamicTextarea from './DynamicTextarea';
|
||||
import DynamicSlider from './DynamicSlider';
|
||||
import DynamicSwitch from './DynamicSwitch';
|
||||
import DynamicInput from './DynamicInput';
|
||||
|
||||
const settingsConfiguration: SettingsConfiguration = [
|
||||
{
|
||||
key: 'temperature',
|
||||
label: 'com_endpoint_temperature',
|
||||
labelCode: true,
|
||||
description: 'com_endpoint_openai_temp',
|
||||
descriptionCode: true,
|
||||
type: 'number',
|
||||
default: 1,
|
||||
range: {
|
||||
min: 0,
|
||||
max: 2,
|
||||
step: 0.01,
|
||||
},
|
||||
component: 'slider',
|
||||
optionType: 'model',
|
||||
// columnSpan: 2,
|
||||
// includeInput: false,
|
||||
},
|
||||
{
|
||||
key: 'top_p',
|
||||
label: 'com_endpoint_top_p',
|
||||
labelCode: true,
|
||||
description: 'com_endpoint_openai_topp',
|
||||
descriptionCode: true,
|
||||
type: 'number',
|
||||
default: 1,
|
||||
range: {
|
||||
min: 0,
|
||||
max: 1,
|
||||
step: 0.01,
|
||||
},
|
||||
component: 'slider',
|
||||
optionType: 'model',
|
||||
},
|
||||
{
|
||||
key: 'presence_penalty',
|
||||
label: 'com_endpoint_presence_penalty',
|
||||
labelCode: true,
|
||||
description: 'com_endpoint_openai_pres',
|
||||
descriptionCode: true,
|
||||
type: 'number',
|
||||
default: 0,
|
||||
range: {
|
||||
min: -2,
|
||||
max: 2,
|
||||
step: 0.01,
|
||||
},
|
||||
component: 'slider',
|
||||
optionType: 'model',
|
||||
},
|
||||
{
|
||||
key: 'frequency_penalty',
|
||||
label: 'com_endpoint_frequency_penalty',
|
||||
labelCode: true,
|
||||
description: 'com_endpoint_openai_freq',
|
||||
descriptionCode: true,
|
||||
type: 'number',
|
||||
default: 0,
|
||||
range: {
|
||||
min: -2,
|
||||
max: 2,
|
||||
step: 0.01,
|
||||
},
|
||||
component: 'slider',
|
||||
optionType: 'model',
|
||||
},
|
||||
{
|
||||
key: 'chatGptLabel',
|
||||
label: 'com_endpoint_custom_name',
|
||||
labelCode: true,
|
||||
type: 'string',
|
||||
default: '',
|
||||
component: 'input',
|
||||
placeholder: 'com_endpoint_openai_custom_name_placeholder',
|
||||
placeholderCode: true,
|
||||
optionType: 'conversation',
|
||||
},
|
||||
{
|
||||
key: 'promptPrefix',
|
||||
label: 'com_endpoint_prompt_prefix',
|
||||
labelCode: true,
|
||||
type: 'string',
|
||||
default: '',
|
||||
component: 'textarea',
|
||||
placeholder: 'com_endpoint_openai_prompt_prefix_placeholder',
|
||||
placeholderCode: true,
|
||||
optionType: 'conversation',
|
||||
// columnSpan: 2,
|
||||
},
|
||||
{
|
||||
key: 'resendFiles',
|
||||
label: 'com_endpoint_plug_resend_files',
|
||||
labelCode: true,
|
||||
description: 'com_endpoint_openai_resend_files',
|
||||
descriptionCode: true,
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
component: 'switch',
|
||||
optionType: 'conversation',
|
||||
showDefault: false,
|
||||
columnSpan: 2,
|
||||
},
|
||||
{
|
||||
key: 'imageDetail',
|
||||
label: 'com_endpoint_plug_image_detail',
|
||||
labelCode: true,
|
||||
description: 'com_endpoint_openai_detail',
|
||||
descriptionCode: true,
|
||||
type: 'enum',
|
||||
default: 'auto',
|
||||
options: ['low', 'auto', 'high'],
|
||||
optionType: 'conversation',
|
||||
component: 'slider',
|
||||
showDefault: false,
|
||||
columnSpan: 2,
|
||||
},
|
||||
];
|
||||
|
||||
const componentMapping: Record<ComponentTypes, React.ComponentType<DynamicSettingProps>> = {
|
||||
[ComponentTypes.Slider]: DynamicSlider,
|
||||
[ComponentTypes.Dropdown]: DynamicDropdown,
|
||||
[ComponentTypes.Switch]: DynamicSwitch,
|
||||
[ComponentTypes.Textarea]: DynamicTextarea,
|
||||
[ComponentTypes.Input]: DynamicInput,
|
||||
[ComponentTypes.Checkbox]: DynamicCheckbox,
|
||||
};
|
||||
|
||||
export default function Parameters() {
|
||||
const { setOption } = useSetIndexOptions();
|
||||
|
||||
const temperature = settingsConfiguration.find(
|
||||
(setting) => setting.key === 'temperature',
|
||||
) as SettingDefinition;
|
||||
const TempComponent = componentMapping[temperature.component];
|
||||
const { key: temp, default: tempDefault, ...tempSettings } = temperature;
|
||||
|
||||
const imageDetail = settingsConfiguration.find(
|
||||
(setting) => setting.key === 'imageDetail',
|
||||
) as SettingDefinition;
|
||||
const DetailComponent = componentMapping[imageDetail.component];
|
||||
const { key: detail, default: detailDefault, ...detailSettings } = imageDetail;
|
||||
|
||||
const resendFiles = settingsConfiguration.find(
|
||||
(setting) => setting.key === 'resendFiles',
|
||||
) as SettingDefinition;
|
||||
const Switch = componentMapping[resendFiles.component];
|
||||
const { key: switchKey, default: switchDefault, ...switchSettings } = resendFiles;
|
||||
|
||||
const promptPrefix = settingsConfiguration.find(
|
||||
(setting) => setting.key === 'promptPrefix',
|
||||
) as SettingDefinition;
|
||||
const Textarea = componentMapping[promptPrefix.component];
|
||||
const { key: textareaKey, default: textareaDefault, ...textareaSettings } = promptPrefix;
|
||||
|
||||
const chatGptLabel = settingsConfiguration.find(
|
||||
(setting) => setting.key === 'chatGptLabel',
|
||||
) as SettingDefinition;
|
||||
const Input = componentMapping[chatGptLabel.component];
|
||||
const { key: inputKey, default: inputDefault, ...inputSettings } = chatGptLabel;
|
||||
|
||||
return (
|
||||
<div className="h-auto max-w-full overflow-x-hidden p-3">
|
||||
<div className="grid grid-cols-4 gap-6">
|
||||
{' '}
|
||||
{/* This is the parent element containing all settings */}
|
||||
{/* Below is an example of an applied dynamic setting, each be contained by a div with the column span specified */}
|
||||
<Input
|
||||
settingKey={inputKey}
|
||||
defaultValue={inputDefault}
|
||||
{...inputSettings}
|
||||
setOption={setOption}
|
||||
/>
|
||||
<Textarea
|
||||
settingKey={textareaKey}
|
||||
defaultValue={textareaDefault}
|
||||
{...textareaSettings}
|
||||
setOption={setOption}
|
||||
/>
|
||||
<TempComponent
|
||||
settingKey={temp}
|
||||
defaultValue={tempDefault}
|
||||
{...tempSettings}
|
||||
setOption={setOption}
|
||||
/>
|
||||
<Switch
|
||||
settingKey={switchKey}
|
||||
defaultValue={switchDefault}
|
||||
{...switchSettings}
|
||||
setOption={setOption}
|
||||
/>
|
||||
<DetailComponent
|
||||
settingKey={detail}
|
||||
defaultValue={detailDefault}
|
||||
{...detailSettings}
|
||||
setOption={setOption}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue