mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-02-07 02:01:50 +01:00
refactor: Settings/Presets UI Restructure, convert many files to TS (#740)
* progress on settings refactor * fix(helpers.js): replace fs.rmdirSync with fs.rm to delete node_modules directory recursively fix(packages.js): delete package-lock.json if it exists before running the script * feat(CrossIcon.tsx): add CrossIcon component * wip: refactor Options for modularity into higher order components, OptionsBar > ModelSelect/Settings * refactor: import more from utils/index, including cardStyle used by model select/settings * refactor(AnthropicOptions): refactor to new format, OpenAI: reduce format to name of endpoint * refactor(AnthropicSettings): refactor to new format, match defaults to API docs * fix: google and anthropic defaults * refactor(conversation/submission atoms): add typing, remove unused code * chore(types.ts): add missing type definitions for TMessages, TMessagesAtom, TConversationAtom, and ModelSelectProps feat(types.ts): make endpoint property nullable in TSubmission, TEndpointOption, TConversation, and TPreset types * refactor(ChatGPT): refactor to new format, add omit settings logic * refactor(EndpointSettings/BingAI): new dir structure and format BingAI options/settings to new * fix: update useUpdateTokenCountMutation to accept an object with a 'text' property instead of a string * fix(endpoints): ensure expected behaviors for preset dialogs * chore(index.ts): add defaultTextProps to utils/index.ts for use in settings components * chore(index.ts): add optionText to utils/index.ts for use in settings components * wip: refactor google settings * wip: progress with Google refactor, needs AdditionalButtons handling and global state setters * refactor(OptionsBar.tsx): The setOption function has been refactored to use the useSetOptions custom hook for setting conversation options. * chore(Anthropic.tsx, BingAI.tsx, Google.tsx, OpenAI.tsx): adjust height of container div in Settings component; chore(Examples.tsx): adjust height in Examples component * refactor(Google): complete google refactor feat(client): add new component PopoverButtons for displaying popover buttons in EndpointPopover feat(data-provider): add types for PopoverButton and EndpointOptionsPopoverProps * fix(OptionsBar.tsx): add useEffect hook to handle opacity class based on messagesTree and advancedMode fix(style.css): rename class from 'openAIOptions-simple-container' to 'options-bar' and update references * refactor(Plugins/OptionsBar): complete refactor of Plugins Select options, consolidate logic from TextChat to OptionsBar * fix(Plugins.tsx): filter lastSelectedTools to remove any tools that are not in the current tools list fix(useSetOptions.ts): remove unnecessary empty line * feat(useSetOptions.ts): add setAgentOption function to update agentOptions in conversation state feat(types.ts): add setAgentOption function to UseSetOptions type * refactor(Settings/Plugins): refactor to new format, refactor(OptionHover): use same component for all endpoints * refactor(OptionHover.tsx): refactor types object to use nested objects for openAI and gptPlugins feat(OptionHover.tsx): add openAI object with specific properties for openAI configuration * refactor(AgentSettings): new format, feat(types.ts): add TAgentOptions type for defining agent options in a conversation * feat(PopoverButtons.tsx): add support for GPT plugin settings button feat(Plugins.tsx): create PluginsView component for displaying plugin settings feat(optionSettings.ts): add showAgentSettings atom for controlling agent settings visibility * feat(client): add support for PluginsSettings in Input/Settings component fix(client): change import path for PluginsSettings in Input/Settings component * refactor(Settings/Plugins): complete refactor, store: refactor to TS, refactor: import defaultTextPropsLabel from utils * feat(EndpointSettings, AgentSettings, Anthropic, Google, types.ts): Add support for Recoil state management and useRecoilValue hook; Pass models from endpointsConfig to various components; Add TModels type and update ModelSelectProps type. fix(AgentSettings, Anthropic, Google, GoogleView, Plugins, OpenAI, Settings.tsx): Change import statements for ModelSelectProps from librechat-data-provider; Add models as a parameter to various components; Add models prop to PluginsView, Settings, and other components. * refactor(EditPresetDialog.jsx): update import statements for Examples and AgentSettings components feat(Settings/index.ts): add export statements for Examples and AgentSettings components * chore(package.json): update eslint-plugin-import to version 2.28.0 * fix(eslint): dependency cycle rule is now working * fix: dependency cycle errors and type errors * refactor(EditPresetDialog.jsx): update import path for DialogTemplate component refactor(NewConversationMenu/index.jsx): update import path for DialogTemplate component refactor(ExportModel.jsx): update import path for DialogTemplate component * refactor: rename NewConversationMenu to EndpointMenu * style: mobile and desktop optimizations * chore: eslint changes * chore(eslintrc.js): update eslint configuration to use 'prettier' plugin chore(postcss.config.cjs): update postcss configuration to use single quotes for require statements fix(helpers.js): fix fs.rmSync function call to delete node_modules directory recursively feat(update.js): add support for skipping git commands with '-g' flag * chore(ModelSelect.tsx): add support for azureOpenAI option component chore(Settings.tsx): add support for azureOpenAI option component chore(package.json): add rebuild:package-lock and update:branch scripts * fix(OptionHover.tsx): fix accessing nested properties in types object feat(OptionHover.tsx): add check for existence of text before rendering HoverCardContent * chore(style.css): update transition duration for options-bar from 0.3s to 0.25s * fix(ScrollToBottom.jsx): fix z-index value for scroll button * style: improve dialogs * fix(Nav.jsx): adjust width and max-width of nav component * chore(Nav.jsx): update max-width class for nav component in different screen sizes chore(Dialog.tsx): update class for DialogFooter component to use flex-row layout * fix(client): fix node_module resolution with path mapping * fix(AdjustToneButton.jsx): add z-index to adjust tone button for proper layering fix(TextChat.jsx): change onClick function to use arrow function to avoid immediate execution fix(mobile.css): update z-index for nav and nav-mask for proper layering chore(package.json): rename update:branch script to reinstall for clarity and consistency * fix(OptionsBar/Settings): add null checks for conversation in BingAI.tsx, ChatGPT.tsx, Plugins.tsx, Settings.tsx * style(TextChat/OptionsBar): match official site styles, setup regen/continue/stop buttons div * chore: Import and apply removeFocusOutlines utility across various components, and rename removeButtonOutline to removeFocusOutlines chore(Settings): Remove unused import and conditionally return null if conversation is falsy * feat(hooks): add useLocalize hook The useLocalize hook is added to the hooks/index.ts file. This hook allows for localization of phrases using the localize function from the ~/localization/Translation module. The hook uses the lang value from the store to determine the current language and returns a function that takes a phraseKey and optional values array as arguments and returns the localized phrase. * refactor(OptionHover.tsx): Update text keys for OptionHover component, use new hook: useLocalize * refactor(useDocumentTitle.ts): refactor to TS * fix(typescript): type issues and update typescript linting deps * refactor: Update ThemeContext and useOnClickOutside to TypeScript chore(useDidMountEffect.js): Remove useDidMountEffect hook * feat: GenerationButtons for stop/continue/regen, remove AdjustToneButton in favor of alternate advanced mode/Settings in OptionsBar * fix(EndpointOptionsPopover.tsx): change switchToSimpleMode function name to closePopover fix(GenerationButtons.tsx): change advancedMode prop name to showPopover fix(OptionsBar.tsx): change advancedMode state name to showPopover feat(OptionsBar.tsx): add logic to show/hide popover based on showPopover state fix(types.ts): change switchToSimpleMode function name to closePopover * chore: remove template button * chore(GenerationButtons.tsx): adjust positioning of the div element chore(Plugins.tsx): adjust width of the MultiSelectDropDown component chore(OptionsBar.tsx): adjust padding of the button element * refactor(EditPresetDialog): use new modular higher order components * chore(newoptionsbar.html): delete unused file newoptionsbar.html * refactor(EditPresetDialog): convert to TS * chore(babel.config.cjs): update babel configuration, linting * chore(EditPresetDialog.tsx): update className for DialogTemplate to include pb-0 chore(EndpointOptionsDialog.jsx): update className for DialogTemplate to include pb-0 chore(PopoverButtons.tsx): add buttonClass prop to PopoverButtons component chore(DialogTemplate.tsx): update className for the footer div to include h-auto chore(Dropdown.jsx): remove id prop from Dropdown component chore(mobile.css): update transition duration for .nav class from 0.2s to 0.15s * refactor(EditPresetDialog.tsx): simplify localization usage with hook * chore(EditPresetDialog.tsx): update containerClassName to include z-index value * fix(endpoints.ts): change type of endpointsConfig atom to TEndpointsConfig refactor(cleanupPreset.ts): convert to TS fix(index.ts): export cleanupPreset utility function fix(types.ts): add missing properties to TPreset type * refactor(EndpointOptionsDialog): convert to TS * fix(EditPresetDialog.tsx): - import cleanupPreset from index - add null check before submitting preset - add null check before exporting preset refactor(SaveAsPresetDialog.tsx): convert to TS fix(usePresetOptions.ts): import cleanupPreset from index fix(types.ts): - make title prop optional in EditPresetProps - change preset prop in CleanupPreset to be partial * chore: reorganize imports in App, EndpointMenu, Messages, and ExportModel components feat(ScreenshotContext.jsx): add ScreenshotContext to hooks/index chore(index.ts): export ThemeContext, ScreenshotContext, ApiErrorBoundaryContext hooks, cleanupPreset, and getIcon functions from utils * wip: add headerClassName for dialog template * chore(EndpointOptionsDialog.tsx): remove unused headerClassName prop chore(EndpointOptionsDialog.tsx): adjust height of main container in mobile and desktop view * fix(react-query-service.ts): change return type of useGetEndpointsQuery to QueryObserverResult<t.TEndpointsConfig> * refactor: imports from index and refactor to TS * refactor: refactor all svg components to TS * refactor: refactor all UI components to TS, remove unused component * fix(SelectDropDown.tsx): remove file extension from import statement for CheckMark component * fix: SaveAsPresetDialog typing issue * fix(OptionsBar): close popover when an endpoint with no settings is selected * chore(ChatGPT.tsx): update width of model select dropdown to 60px refactor(types.ts): decouple ModelSelectProps from SettingsProps * fix(popover Settings): space taken from the options menu for each endpoint * fix:'Set token first' element alignment, add padding to endpointmenu icon in mobile * style: match official site header * refactor(EndpointOptionsDialog): make functionality explicitly saving current convos as presets * fix(useLocalize.ts): change values parameter from an array to rest parameters * refactor(EndpointSettings): Utilize useLocalize hook for all endpoint settings * fix(Popover): correct spacing/center and remove focus outlines for close button * chore: employ use of cn (clsx) in Popover styles * chore(EditPresetDialog.tsx): update className to add padding bottom chore(EndpointOptionsDialog.tsx): update className to add padding bottom * style(EndpointMenu, TextChat): add better styling at diff. breakpoints * refactor(EndpointSettings): consolidate container style to higher order component * refactor(EditPresetDialog.tsx): pass custom style to Settings from here * style: setting dialogs improved in all views * style(EndpointMenu): improve UX for mobile * style(PresetDialog): increase height so scrollbar isn't triggered * chore(EditPresetDialog.tsx): update className to include xl height for DialogTemplate chore(InputNumber.tsx): update className to include max height for InputNumber component * fix: light mode styling * fix(OptionsBar/ScrollToBottom/Popover): quick fix to rework in future: hide scrollToBottom when Popover is open * style: remove bg-gradient around textarea in mobile view * chore(ThemeContext.tsx): refactor ThemeContext to use default context value, also fixes type issue * chore(EditPresetDialog.tsx): adjust grid layout in EditPresetDialog component * style(TextChat): make gradient more opaque/smoother * fix(TextChat.jsx): fix background gradient color based on theme and system preference * test(layout-test-utils.tsx): add mock implementation for window.matchMedia in test setup feat(layout-test-utils.tsx): add authConfig prop to AuthContextProvider in renderWithProvidersWrapper function chore(tsconfig.json): include test directory in tsconfig include section * chore(jest.config.cjs): update test file paths in jest configuration chore(Login.spec.tsx): update test file path in import statement chore(LoginForm.spec.tsx): update test file path in import statement chore(Registration.spec.tsx): update test file path in import statement chore(PluginAuthForm.spec.tsx): update test file path in import statement chore(PluginStoreDialog.spec.tsx): update test file path in import statement chore(layout-test-utils.tsx): move matchMedia mock to separate file chore(tsconfig.json): add path mapping for test files in client directory * test: add import for 'test/matchMedia.mock' in test files The changes in this commit add an import statement for 'test/matchMedia.mock' in multiple test files. This import is necessary for mocking the behavior of the matchMedia function during testing. * style(ClearConvosDialog): remove borders from button and modal, uniform button size * fix(AgentSettings.tsx): overlapping issue * fix(PresetDialogs): improve spacing of top row and dialog content * style(Settings): 2nd column will now dynamically adjust better across all screen sizes * style(ModelSelect): improve styling for mobile/desktop, add hover shadow feat(ModelSelect/Plugins): hide ModelSelect when screen is small * refactor(RowButton, buildTree): convert to TS * style(ModelSelect): add transition effect to shadows on hover
This commit is contained in:
parent
fb99e5a7da
commit
956aa6c674
203 changed files with 5062 additions and 4327 deletions
242
client/src/components/Endpoints/Settings/AgentSettings.tsx
Normal file
242
client/src/components/Endpoints/Settings/AgentSettings.tsx
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
import { ModelSelectProps, Side } from 'librechat-data-provider';
|
||||
import {
|
||||
Switch,
|
||||
SelectDropDown,
|
||||
Label,
|
||||
Slider,
|
||||
InputNumber,
|
||||
HoverCard,
|
||||
HoverCardTrigger,
|
||||
} from '~/components';
|
||||
import OptionHover from './OptionHover';
|
||||
import { cn, optionText, defaultTextProps, removeFocusOutlines } from '~/utils/';
|
||||
import { useLocalize } from '~/hooks';
|
||||
|
||||
export default function Settings({ conversation, setOption, models, readonly }: ModelSelectProps) {
|
||||
const localize = useLocalize();
|
||||
if (!conversation) {
|
||||
return null;
|
||||
}
|
||||
const { agent, skipCompletion, model, temperature } = conversation.agentOptions ?? {};
|
||||
|
||||
const setModel = setOption('model');
|
||||
const setTemperature = setOption('temperature');
|
||||
const setAgent = setOption('agent');
|
||||
const setSkipCompletion = setOption('skipCompletion');
|
||||
const onCheckedChangeAgent = (checked: boolean) => {
|
||||
setAgent(checked ? 'functions' : 'classic');
|
||||
};
|
||||
|
||||
const onCheckedChangeSkip = (checked: boolean) => {
|
||||
setSkipCompletion(checked);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-5 gap-6">
|
||||
<div className="col-span-5 flex flex-col items-center justify-start gap-6 sm:col-span-3">
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<SelectDropDown
|
||||
title={localize('com_endpoint_agent_model')}
|
||||
value={model ?? ''}
|
||||
setValue={setModel}
|
||||
availableValues={models}
|
||||
disabled={readonly}
|
||||
className={cn(defaultTextProps, 'flex w-full resize-none', removeFocusOutlines)}
|
||||
containerClassName="flex w-full resize-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-5 flex flex-col items-center justify-start gap-6 px-3 sm:col-span-2">
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="temp-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_temperature')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default')}: 0)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="temp-int"
|
||||
disabled={readonly}
|
||||
value={temperature}
|
||||
onChange={(value) => setTemperature(Number(value))}
|
||||
max={2}
|
||||
min={0}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[temperature ?? 0]}
|
||||
onValueChange={(value) => setTemperature(value[0])}
|
||||
doubleClickHandler={() => setTemperature(1)}
|
||||
max={2}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation.endpoint ?? ''} type="temp" side={Side.Left} />
|
||||
</HoverCard>
|
||||
<div className="grid w-full grid-cols-2 items-center gap-10">
|
||||
<HoverCard openDelay={500}>
|
||||
<HoverCardTrigger className="w-[100px]">
|
||||
<label
|
||||
htmlFor="functions-agent"
|
||||
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 dark:text-gray-50"
|
||||
>
|
||||
<small>{localize('com_endpoint_plug_use_functions')}</small>
|
||||
</label>
|
||||
<Switch
|
||||
id="functions-agent"
|
||||
checked={agent === 'functions'}
|
||||
onCheckedChange={onCheckedChangeAgent}
|
||||
disabled={readonly}
|
||||
className="ml-4 mt-2"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation.endpoint ?? ''} type="func" side={Side.Bottom} />
|
||||
</HoverCard>
|
||||
<HoverCard openDelay={500}>
|
||||
<HoverCardTrigger className="ml-[-60px] w-[100px]">
|
||||
<label
|
||||
htmlFor="skip-completion"
|
||||
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 dark:text-gray-50"
|
||||
>
|
||||
<small>{localize('com_endpoint_plug_skip_completion')}</small>
|
||||
</label>
|
||||
<Switch
|
||||
id="skip-completion"
|
||||
checked={skipCompletion === true}
|
||||
onCheckedChange={onCheckedChangeSkip}
|
||||
disabled={readonly}
|
||||
className="ml-4 mt-2"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation.endpoint ?? ''} type="skip" side={Side.Bottom} />
|
||||
</HoverCard>
|
||||
</div>
|
||||
{/* <HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="top-p-int" className="text-left text-sm font-medium">
|
||||
Top P <small className="opacity-40">(default: 1)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="top-p-int"
|
||||
disabled={readonly}
|
||||
value={topP}
|
||||
onChange={(value) => setTopP(value)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200'
|
||||
)
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[topP]}
|
||||
onValueChange={(value) => setTopP(value[0])}
|
||||
doubleClickHandler={() => setTopP(1)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover type="topp" side="left" />
|
||||
</HoverCard>
|
||||
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="freq-penalty-int" className="text-left text-sm font-medium">
|
||||
Frequency Penalty <small className="opacity-40">(default: 0)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="freq-penalty-int"
|
||||
disabled={readonly}
|
||||
value={freqP}
|
||||
onChange={(value) => setFreqP(value)}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200'
|
||||
)
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[freqP]}
|
||||
onValueChange={(value) => setFreqP(value[0])}
|
||||
doubleClickHandler={() => setFreqP(0)}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover type="freq" side="left" />
|
||||
</HoverCard>
|
||||
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="pres-penalty-int" className="text-left text-sm font-medium">
|
||||
Presence Penalty <small className="opacity-40">(default: 0)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="pres-penalty-int"
|
||||
disabled={readonly}
|
||||
value={presP}
|
||||
onChange={(value) => setPresP(value)}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200'
|
||||
)
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[presP]}
|
||||
onValueChange={(value) => setPresP(value[0])}
|
||||
doubleClickHandler={() => setPresP(0)}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover type="pres" side="left" />
|
||||
</HoverCard> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
235
client/src/components/Endpoints/Settings/Anthropic.tsx
Normal file
235
client/src/components/Endpoints/Settings/Anthropic.tsx
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
import React from 'react';
|
||||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
import { ModelSelectProps, Side } from 'librechat-data-provider';
|
||||
import {
|
||||
Input,
|
||||
Label,
|
||||
Slider,
|
||||
InputNumber,
|
||||
HoverCard,
|
||||
HoverCardTrigger,
|
||||
SelectDropDown,
|
||||
} from '~/components/ui';
|
||||
import OptionHover from './OptionHover';
|
||||
import { cn, defaultTextProps, optionText, removeFocusOutlines } from '~/utils/';
|
||||
|
||||
export default function Settings({ conversation, setOption, models, readonly }: ModelSelectProps) {
|
||||
if (!conversation) {
|
||||
return null;
|
||||
}
|
||||
const { model, modelLabel, promptPrefix, temperature, topP, topK, maxOutputTokens } =
|
||||
conversation;
|
||||
|
||||
const setModel = setOption('model');
|
||||
const setModelLabel = setOption('modelLabel');
|
||||
const setPromptPrefix = setOption('promptPrefix');
|
||||
const setTemperature = setOption('temperature');
|
||||
const setTopP = setOption('topP');
|
||||
const setTopK = setOption('topK');
|
||||
const setMaxOutputTokens = setOption('maxOutputTokens');
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-5 gap-6">
|
||||
<div className="col-span-5 flex flex-col items-center justify-start gap-6 sm:col-span-3">
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<SelectDropDown
|
||||
value={model ?? ''}
|
||||
setValue={setModel}
|
||||
availableValues={models}
|
||||
disabled={readonly}
|
||||
className={cn(defaultTextProps, 'z-50 flex w-full resize-none', removeFocusOutlines)}
|
||||
containerClassName="flex w-full resize-none"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="modelLabel" className="text-left text-sm font-medium">
|
||||
Custom Name <small className="opacity-40">(default: blank)</small>
|
||||
</Label>
|
||||
<Input
|
||||
id="modelLabel"
|
||||
disabled={readonly}
|
||||
value={modelLabel || ''}
|
||||
onChange={(e) => setModelLabel(e.target.value ?? null)}
|
||||
placeholder="Set a custom name for Claude"
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex h-10 max-h-10 w-full resize-none px-3 py-2',
|
||||
removeFocusOutlines,
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="promptPrefix" className="text-left text-sm font-medium">
|
||||
Prompt Prefix <small className="opacity-40">(default: blank)</small>
|
||||
</Label>
|
||||
<TextareaAutosize
|
||||
id="promptPrefix"
|
||||
disabled={readonly}
|
||||
value={promptPrefix || ''}
|
||||
onChange={(e) => setPromptPrefix(e.target.value ?? null)}
|
||||
placeholder="Set custom instructions or context. Ignored if empty."
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[300px] min-h-[100px] w-full resize-none px-3 py-2 ',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-5 flex flex-col items-center justify-start gap-6 px-3 sm:col-span-2">
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="temp-int" className="text-left text-sm font-medium">
|
||||
Temperature <small className="opacity-40">(default: 1)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="temp-int"
|
||||
disabled={readonly}
|
||||
value={temperature}
|
||||
onChange={(value) => setTemperature(Number(value))}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[temperature ?? 1]}
|
||||
onValueChange={(value) => setTemperature(value[0])}
|
||||
doubleClickHandler={() => setTemperature(1)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="temp" side={Side.Left} />
|
||||
</HoverCard>
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="top-p-int" className="text-left text-sm font-medium">
|
||||
Top P <small className="opacity-40">(default: 0.7)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="top-p-int"
|
||||
disabled={readonly}
|
||||
value={topP}
|
||||
onChange={(value) => setTopP(Number(value))}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[topP ?? 0.7]}
|
||||
onValueChange={(value) => setTopP(value[0])}
|
||||
doubleClickHandler={() => setTopP(1)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="topp" side={Side.Left} />
|
||||
</HoverCard>
|
||||
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="top-k-int" className="text-left text-sm font-medium">
|
||||
Top K <small className="opacity-40">(default: 5)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="top-k-int"
|
||||
disabled={readonly}
|
||||
value={topK}
|
||||
onChange={(value) => setTopK(Number(value))}
|
||||
max={40}
|
||||
min={1}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[topK ?? 5]}
|
||||
onValueChange={(value) => setTopK(value[0])}
|
||||
doubleClickHandler={() => setTopK(0)}
|
||||
max={40}
|
||||
min={1}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="topk" side={Side.Left} />
|
||||
</HoverCard>
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="max-tokens-int" className="text-left text-sm font-medium">
|
||||
Max Output Tokens <small className="opacity-40">(default: 1024)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="max-tokens-int"
|
||||
disabled={readonly}
|
||||
value={maxOutputTokens}
|
||||
onChange={(value) => setMaxOutputTokens(Number(value))}
|
||||
max={1024}
|
||||
min={1}
|
||||
step={1}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[maxOutputTokens ?? 1024]}
|
||||
onValueChange={(value) => setMaxOutputTokens(value[0])}
|
||||
doubleClickHandler={() => setMaxOutputTokens(0)}
|
||||
max={1024}
|
||||
min={1}
|
||||
step={1}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover
|
||||
endpoint={conversation?.endpoint ?? ''}
|
||||
type="maxoutputtokens"
|
||||
side={Side.Left}
|
||||
/>
|
||||
</HoverCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
149
client/src/components/Endpoints/Settings/BingAI.tsx
Normal file
149
client/src/components/Endpoints/Settings/BingAI.tsx
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
import {
|
||||
useUpdateTokenCountMutation,
|
||||
TUpdateTokenCountResponse,
|
||||
SettingsProps,
|
||||
} from 'librechat-data-provider';
|
||||
import { Label, Checkbox, SelectDropDown } from '~/components/ui';
|
||||
import { cn, defaultTextProps, removeFocusOutlines } from '~/utils/';
|
||||
import { useLocalize, useDebounce } from '~/hooks';
|
||||
|
||||
export default function Settings({ conversation, setOption, readonly }: SettingsProps) {
|
||||
const localize = useLocalize();
|
||||
const [tokenCount, setTokenCount] = useState(0);
|
||||
const debouncedContext = useDebounce(conversation?.context?.trim() ?? '', 250);
|
||||
const updateTokenCountMutation = useUpdateTokenCountMutation();
|
||||
|
||||
useEffect(() => {
|
||||
if (!debouncedContext || debouncedContext === '') {
|
||||
setTokenCount(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const handleTextChange = (context: string) => {
|
||||
updateTokenCountMutation.mutate(
|
||||
{ text: context },
|
||||
{
|
||||
onSuccess: (data: TUpdateTokenCountResponse) => {
|
||||
setTokenCount(data.count);
|
||||
},
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
handleTextChange(debouncedContext);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [debouncedContext]);
|
||||
|
||||
if (!conversation) {
|
||||
return null;
|
||||
}
|
||||
const { context, systemMessage, jailbreak, toneStyle } = conversation;
|
||||
const showSystemMessage = jailbreak;
|
||||
|
||||
const setContext = setOption('context');
|
||||
const setSystemMessage = setOption('systemMessage');
|
||||
const setJailbreak = setOption('jailbreak');
|
||||
const setToneStyle = (value: string) => setOption('toneStyle')(value.toLowerCase());
|
||||
|
||||
return (
|
||||
<div className="grid gap-6 sm:grid-cols-2">
|
||||
<div className="col-span-1 flex flex-col items-center justify-start gap-6">
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="toneStyle-dropdown" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_tone_style')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_creative')})</small>
|
||||
</Label>
|
||||
<SelectDropDown
|
||||
id="toneStyle-dropdown"
|
||||
title={''}
|
||||
value={`${toneStyle?.charAt(0).toUpperCase()}${toneStyle?.slice(1)}`}
|
||||
setValue={setToneStyle}
|
||||
availableValues={['Creative', 'Fast', 'Balanced', 'Precise']}
|
||||
disabled={readonly}
|
||||
className={cn(defaultTextProps, 'flex w-full resize-none', removeFocusOutlines)}
|
||||
containerClassName="flex w-full resize-none"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="context" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_context')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_blank')})</small>
|
||||
</Label>
|
||||
<TextareaAutosize
|
||||
id="context"
|
||||
disabled={readonly}
|
||||
value={context || ''}
|
||||
onChange={(e) => setContext(e.target.value ?? null)}
|
||||
placeholder={localize('com_endpoint_bing_context_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[300px] min-h-[100px] w-full resize-none px-3 py-2',
|
||||
)}
|
||||
/>
|
||||
<small className="mb-5 text-black dark:text-white">{`${localize(
|
||||
'com_endpoint_token_count',
|
||||
)}: ${tokenCount}`}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-1 flex flex-col items-center justify-start gap-6">
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="jailbreak" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_bing_enable_sydney')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_false')})</small>
|
||||
</Label>
|
||||
<div className="flex h-[40px] w-full items-center space-x-3">
|
||||
<Checkbox
|
||||
id="jailbreak"
|
||||
disabled={readonly}
|
||||
checked={jailbreak}
|
||||
className="focus:ring-opacity-20 dark:border-gray-500 dark:bg-gray-700 dark:text-gray-50 dark:focus:ring-gray-600 dark:focus:ring-opacity-50 dark:focus:ring-offset-0"
|
||||
onCheckedChange={setJailbreak}
|
||||
/>
|
||||
<label
|
||||
htmlFor="jailbreak"
|
||||
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 dark:text-gray-50"
|
||||
>
|
||||
{localize('com_endpoint_bing_jailbreak')}{' '}
|
||||
<small>{localize('com_endpoint_bing_to_enable_sydney')}</small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{showSystemMessage && (
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label
|
||||
htmlFor="systemMessage"
|
||||
className="text-left text-sm font-medium"
|
||||
style={{ opacity: showSystemMessage ? '1' : '0' }}
|
||||
>
|
||||
<a
|
||||
href="https://github.com/danny-avila/LibreChat/blob/main/docs/features/bing_jailbreak.md#default-system-message-for-jailbreak-mode-sydney"
|
||||
target="_blank"
|
||||
className="text-blue-500 transition-colors duration-200 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-500"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{localize('com_endpoint_system_message')}
|
||||
</a>{' '}
|
||||
<small className="opacity-40 dark:text-gray-50">
|
||||
( {localize('com_endpoint_default_blank')})
|
||||
</small>
|
||||
</Label>
|
||||
|
||||
<TextareaAutosize
|
||||
id="systemMessage"
|
||||
disabled={readonly}
|
||||
value={systemMessage || ''}
|
||||
onChange={(e) => setSystemMessage(e.target.value ?? null)}
|
||||
placeholder={localize('com_endpoint_bing_system_message_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[300px] min-h-[100px] w-full resize-none px-3 py-2 placeholder:text-red-400',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
88
client/src/components/Endpoints/Settings/Examples.tsx
Normal file
88
client/src/components/Endpoints/Settings/Examples.tsx
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import React from 'react';
|
||||
import { Plus, Minus } from 'lucide-react';
|
||||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
import { ExamplesProps } from 'librechat-data-provider';
|
||||
import { Button, Label } from '~/components/ui';
|
||||
import { cn, defaultTextProps } from '~/utils/';
|
||||
import { useLocalize } from '~/hooks';
|
||||
|
||||
function Examples({ readonly, examples, setExample, addExample, removeExample }: ExamplesProps) {
|
||||
const localize = useLocalize();
|
||||
return (
|
||||
<>
|
||||
<div id="examples-grid" className="grid gap-6 sm:grid-cols-2">
|
||||
{examples.map((example, idx) => (
|
||||
<React.Fragment key={idx}>
|
||||
{/* Input */}
|
||||
<div
|
||||
className={`col-span-${
|
||||
examples.length === 1 ? '1' : 'full'
|
||||
} flex flex-col items-center justify-start gap-6 sm:col-span-1`}
|
||||
>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor={`input-${idx}`} className="text-left text-sm font-medium">
|
||||
{localize('com_ui_input')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_blank')})</small>
|
||||
</Label>
|
||||
<TextareaAutosize
|
||||
id={`input-${idx}`}
|
||||
disabled={readonly}
|
||||
value={example?.input?.content || ''}
|
||||
onChange={(e) => setExample(idx, 'input', e.target.value ?? null)}
|
||||
placeholder="Set example input. Example is ignored if empty."
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[300px] min-h-[75px] w-full resize-none px-3 py-2 ',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Output */}
|
||||
<div
|
||||
className={`col-span-${
|
||||
examples.length === 1 ? '1' : 'full'
|
||||
} flex flex-col items-center justify-start gap-6 sm:col-span-1`}
|
||||
>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor={`output-${idx}`} className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_output')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_blank')})</small>
|
||||
</Label>
|
||||
<TextareaAutosize
|
||||
id={`output-${idx}`}
|
||||
disabled={readonly}
|
||||
value={example?.output?.content || ''}
|
||||
onChange={(e) => setExample(idx, 'output', e.target.value ?? null)}
|
||||
placeholder={'Set example output. Example is ignored if empty.'}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[300px] min-h-[75px] w-full resize-none px-3 py-2 ',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
type="button"
|
||||
className="mr-2 mt-1 h-auto items-center justify-center bg-transparent px-3 py-2 text-xs font-medium font-normal text-black hover:bg-slate-200 hover:text-black focus:ring-0 focus:ring-offset-0 dark:bg-transparent dark:text-white dark:hover:bg-gray-600 dark:hover:text-white dark:focus:outline-none dark:focus:ring-offset-0"
|
||||
onClick={removeExample}
|
||||
>
|
||||
<Minus className="w-[16px]" />
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
className="mt-1 h-auto items-center justify-center bg-transparent px-3 py-2 text-xs font-medium font-normal text-black hover:bg-slate-200 hover:text-black focus:ring-0 focus:ring-offset-0 dark:bg-transparent dark:text-white dark:hover:bg-gray-600 dark:hover:text-white dark:focus:outline-none dark:focus:ring-offset-0"
|
||||
onClick={addExample}
|
||||
>
|
||||
<Plus className="w-[16px]" />
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default Examples;
|
||||
259
client/src/components/Endpoints/Settings/Google.tsx
Normal file
259
client/src/components/Endpoints/Settings/Google.tsx
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
import React from 'react';
|
||||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
import { ModelSelectProps, Side } from 'librechat-data-provider';
|
||||
import {
|
||||
SelectDropDown,
|
||||
Input,
|
||||
Label,
|
||||
Slider,
|
||||
InputNumber,
|
||||
HoverCard,
|
||||
HoverCardTrigger,
|
||||
} from '~/components/ui';
|
||||
import OptionHover from './OptionHover';
|
||||
import { cn, defaultTextProps, optionText, removeFocusOutlines } from '~/utils/';
|
||||
import { useLocalize } from '~/hooks';
|
||||
|
||||
export default function Settings({ conversation, setOption, models, readonly }: ModelSelectProps) {
|
||||
const localize = useLocalize();
|
||||
if (!conversation) {
|
||||
return null;
|
||||
}
|
||||
const { model, modelLabel, promptPrefix, temperature, topP, topK, maxOutputTokens } =
|
||||
conversation;
|
||||
|
||||
const setModel = setOption('model');
|
||||
const setModelLabel = setOption('modelLabel');
|
||||
const setPromptPrefix = setOption('promptPrefix');
|
||||
const setTemperature = setOption('temperature');
|
||||
const setTopP = setOption('topP');
|
||||
const setTopK = setOption('topK');
|
||||
const setMaxOutputTokens = setOption('maxOutputTokens');
|
||||
|
||||
const codeChat = model?.startsWith('codechat-');
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-5 gap-6">
|
||||
<div className="col-span-5 flex flex-col items-center justify-start gap-6 sm:col-span-3">
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<SelectDropDown
|
||||
value={model ?? ''}
|
||||
setValue={setModel}
|
||||
availableValues={models}
|
||||
disabled={readonly}
|
||||
className={cn(defaultTextProps, 'z-50 flex w-full resize-none', removeFocusOutlines)}
|
||||
containerClassName="flex w-full resize-none"
|
||||
/>
|
||||
</div>
|
||||
{!codeChat && (
|
||||
<>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="modelLabel" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_custom_name')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_blank')})</small>
|
||||
</Label>
|
||||
<Input
|
||||
id="modelLabel"
|
||||
disabled={readonly}
|
||||
value={modelLabel || ''}
|
||||
onChange={(e) => setModelLabel(e.target.value ?? null)}
|
||||
placeholder={localize('com_endpoint_google_custom_name_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex h-10 max-h-10 w-full resize-none px-3 py-2',
|
||||
removeFocusOutlines,
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="promptPrefix" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_prompt_prefix')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_blank')})</small>
|
||||
</Label>
|
||||
<TextareaAutosize
|
||||
id="promptPrefix"
|
||||
disabled={readonly}
|
||||
value={promptPrefix || ''}
|
||||
onChange={(e) => setPromptPrefix(e.target.value ?? null)}
|
||||
placeholder={localize('com_endpoint_google_prompt_prefix_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[300px] min-h-[100px] w-full resize-none px-3 py-2 ',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-span-5 flex flex-col items-center justify-start gap-6 px-3 sm:col-span-2">
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="temp-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_temperature')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default')}: 0.2)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="temp-int"
|
||||
disabled={readonly}
|
||||
value={temperature}
|
||||
onChange={(value) => setTemperature(value ?? 0.2)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[temperature ?? 0.2]}
|
||||
onValueChange={(value) => setTemperature(value[0])}
|
||||
doubleClickHandler={() => setTemperature(0.2)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="temp" side={Side.Left} />
|
||||
</HoverCard>
|
||||
{!codeChat && (
|
||||
<>
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="top-p-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_top_p')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', '0.95')})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="top-p-int"
|
||||
disabled={readonly}
|
||||
value={topP}
|
||||
onChange={(value) => setTopP(value ?? '0.95')}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[topP ?? 0.95]}
|
||||
onValueChange={(value) => setTopP(value[0])}
|
||||
doubleClickHandler={() => setTopP(0.95)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="topp" side={Side.Left} />
|
||||
</HoverCard>
|
||||
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="top-k-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_top_k')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', '40')})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="top-k-int"
|
||||
disabled={readonly}
|
||||
value={topK}
|
||||
onChange={(value) => setTopK(value ?? 40)}
|
||||
max={40}
|
||||
min={1}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[topK ?? 40]}
|
||||
onValueChange={(value) => setTopK(value[0])}
|
||||
doubleClickHandler={() => setTopK(40)}
|
||||
max={40}
|
||||
min={1}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="topk" side={Side.Left} />
|
||||
</HoverCard>
|
||||
</>
|
||||
)}
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="max-tokens-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_max_output_tokens')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', '1024')})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="max-tokens-int"
|
||||
disabled={readonly}
|
||||
value={maxOutputTokens}
|
||||
onChange={(value) => setMaxOutputTokens(value ?? 1024)}
|
||||
max={1024}
|
||||
min={1}
|
||||
step={1}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[maxOutputTokens ?? 1024]}
|
||||
onValueChange={(value) => setMaxOutputTokens(value[0])}
|
||||
doubleClickHandler={() => setMaxOutputTokens(1024)}
|
||||
max={1024}
|
||||
min={1}
|
||||
step={1}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover
|
||||
endpoint={conversation?.endpoint ?? ''}
|
||||
type="maxoutputtokens"
|
||||
side={Side.Left}
|
||||
/>
|
||||
</HoverCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import Settings from '../Google';
|
||||
import Examples from '../Examples';
|
||||
import { useSetOptions } from '~/hooks';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import store from '~/store';
|
||||
|
||||
export default function GoogleView({ conversation, models, isPreset = false }) {
|
||||
const optionSettings = useRecoilValue(store.optionSettings);
|
||||
const { setOption, setExample, addExample, removeExample } = useSetOptions(
|
||||
isPreset ? conversation : null,
|
||||
);
|
||||
if (!conversation) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { examples } = conversation;
|
||||
const { showExamples, isCodeChat } = optionSettings;
|
||||
return showExamples && !isCodeChat ? (
|
||||
<Examples
|
||||
examples={examples ?? []}
|
||||
setExample={setExample}
|
||||
addExample={addExample}
|
||||
removeExample={removeExample}
|
||||
/>
|
||||
) : (
|
||||
<Settings conversation={conversation} setOption={setOption} models={models} />
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import Settings from '../Plugins';
|
||||
import AgentSettings from '../AgentSettings';
|
||||
import { useSetOptions } from '~/hooks';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import store from '~/store';
|
||||
|
||||
export default function PluginsView({ conversation, models, isPreset = false }) {
|
||||
const showAgentSettings = useRecoilValue(store.showAgentSettings);
|
||||
const { setOption, setAgentOption } = useSetOptions(isPreset ? conversation : null);
|
||||
if (!conversation) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return showAgentSettings ? (
|
||||
<AgentSettings conversation={conversation} setOption={setAgentOption} models={models} />
|
||||
) : (
|
||||
<Settings conversation={conversation} setOption={setOption} models={models} />
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
export { default as GoogleSettings } from './Google';
|
||||
export { default as PluginsSettings } from './Plugins';
|
||||
254
client/src/components/Endpoints/Settings/OpenAI.tsx
Normal file
254
client/src/components/Endpoints/Settings/OpenAI.tsx
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
import { ModelSelectProps, Side } from 'librechat-data-provider';
|
||||
import {
|
||||
SelectDropDown,
|
||||
Input,
|
||||
Label,
|
||||
Slider,
|
||||
InputNumber,
|
||||
HoverCard,
|
||||
HoverCardTrigger,
|
||||
} from '~/components/ui';
|
||||
import OptionHover from './OptionHover';
|
||||
import { cn, defaultTextProps, optionText, removeFocusOutlines } from '~/utils/';
|
||||
import { useLocalize } from '~/hooks';
|
||||
|
||||
export default function Settings({ conversation, setOption, models, readonly }: ModelSelectProps) {
|
||||
const localize = useLocalize();
|
||||
if (!conversation) {
|
||||
return null;
|
||||
}
|
||||
const {
|
||||
model,
|
||||
chatGptLabel,
|
||||
promptPrefix,
|
||||
temperature,
|
||||
top_p: topP,
|
||||
frequency_penalty: freqP,
|
||||
presence_penalty: presP,
|
||||
} = conversation;
|
||||
const endpoint = conversation.endpoint || 'openAI';
|
||||
const isOpenAI = endpoint === 'openAI' || endpoint === 'azureOpenAI';
|
||||
|
||||
const setModel = setOption('model');
|
||||
const setChatGptLabel = setOption('chatGptLabel');
|
||||
const setPromptPrefix = setOption('promptPrefix');
|
||||
const setTemperature = setOption('temperature');
|
||||
const setTopP = setOption('top_p');
|
||||
const setFreqP = setOption('frequency_penalty');
|
||||
const setPresP = setOption('presence_penalty');
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-5 gap-6">
|
||||
<div className="col-span-5 flex flex-col items-center justify-start gap-6 sm:col-span-3">
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<SelectDropDown
|
||||
value={model ?? ''}
|
||||
setValue={setModel}
|
||||
availableValues={models}
|
||||
disabled={readonly}
|
||||
className={cn(defaultTextProps, 'flex w-full resize-none', removeFocusOutlines)}
|
||||
containerClassName="flex w-full resize-none"
|
||||
/>
|
||||
</div>
|
||||
{isOpenAI && (
|
||||
<>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="chatGptLabel" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_custom_name')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_blank')})</small>
|
||||
</Label>
|
||||
<Input
|
||||
id="chatGptLabel"
|
||||
disabled={readonly}
|
||||
value={chatGptLabel || ''}
|
||||
onChange={(e) => setChatGptLabel(e.target.value ?? null)}
|
||||
placeholder={localize('com_endpoint_openai_custom_name_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex h-10 max-h-10 w-full resize-none px-3 py-2',
|
||||
removeFocusOutlines,
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="promptPrefix" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_prompt_prefix')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default_blank')})</small>
|
||||
</Label>
|
||||
<TextareaAutosize
|
||||
id="promptPrefix"
|
||||
disabled={readonly}
|
||||
value={promptPrefix || ''}
|
||||
onChange={(e) => setPromptPrefix(e.target.value ?? null)}
|
||||
placeholder={localize('com_endpoint_openai_prompt_prefix_placeholder')}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[300px] min-h-[100px] w-full resize-none px-3 py-2 ',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-span-5 flex flex-col items-center justify-start gap-6 px-3 sm:col-span-2">
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="temp-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_temperature')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', isOpenAI ? '1' : '0')})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="temp-int"
|
||||
disabled={readonly}
|
||||
value={temperature}
|
||||
onChange={(value) => setTemperature(Number(value))}
|
||||
max={2}
|
||||
min={0}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[temperature ?? 1]}
|
||||
onValueChange={(value) => setTemperature(value[0])}
|
||||
doubleClickHandler={() => setTemperature(1)}
|
||||
max={2}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="temp" side={Side.Left} />
|
||||
</HoverCard>
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="top-p-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_top_p')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default')}: 1)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="top-p-int"
|
||||
disabled={readonly}
|
||||
value={topP}
|
||||
onChange={(value) => setTopP(Number(value))}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[topP ?? 1]}
|
||||
onValueChange={(value) => setTopP(value[0])}
|
||||
doubleClickHandler={() => setTopP(1)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="topp" side={Side.Left} />
|
||||
</HoverCard>
|
||||
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="freq-penalty-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_frequency_penalty')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default')}: 0)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="freq-penalty-int"
|
||||
disabled={readonly}
|
||||
value={freqP}
|
||||
onChange={(value) => setFreqP(Number(value))}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[freqP ?? 0]}
|
||||
onValueChange={(value) => setFreqP(value[0])}
|
||||
doubleClickHandler={() => setFreqP(0)}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="freq" side={Side.Left} />
|
||||
</HoverCard>
|
||||
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="pres-penalty-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_presence_penalty')}{' '}
|
||||
<small className="opacity-40">({localize('com_endpoint_default')}: 0)</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="pres-penalty-int"
|
||||
disabled={readonly}
|
||||
value={presP}
|
||||
onChange={(value) => setPresP(Number(value))}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[presP ?? 0]}
|
||||
onValueChange={(value) => setPresP(value[0])}
|
||||
doubleClickHandler={() => setPresP(0)}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="pres" side={Side.Left} />
|
||||
</HoverCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
53
client/src/components/Endpoints/Settings/OptionHover.tsx
Normal file
53
client/src/components/Endpoints/Settings/OptionHover.tsx
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import React from 'react';
|
||||
import { HoverCardPortal, HoverCardContent } from '~/components/ui';
|
||||
import { OptionHoverProps } from 'librechat-data-provider';
|
||||
import { useLocalize } from '~/hooks';
|
||||
|
||||
const openAI = {
|
||||
max: 'com_endpoint_openai_max',
|
||||
temp: 'com_endpoint_openai_temp',
|
||||
topp: 'com_endpoint_openai_topp',
|
||||
freq: 'com_endpoint_openai_freq',
|
||||
pres: 'com_endpoint_openai_pres',
|
||||
};
|
||||
|
||||
const types = {
|
||||
anthropic: {
|
||||
temp: 'com_endpoint_anthropic_temp',
|
||||
topp: 'com_endpoint_anthropic_topp',
|
||||
topk: 'com_endpoint_anthropic_topk',
|
||||
maxoutputtokens: 'com_endpoint_anthropic_maxoutputtokens',
|
||||
},
|
||||
google: {
|
||||
temp: 'com_endpoint_google_temp',
|
||||
topp: 'com_endpoint_google_topp',
|
||||
topk: 'com_endpoint_google_topk',
|
||||
maxoutputtokens: 'com_endpoint_google_maxoutputtokens',
|
||||
},
|
||||
openAI,
|
||||
azureOpenAI: openAI,
|
||||
gptPlugins: {
|
||||
func: 'com_endpoint_func_hover',
|
||||
skip: 'com_endpoint_skip_hover',
|
||||
...openAI,
|
||||
},
|
||||
};
|
||||
|
||||
function OptionHover({ endpoint, type, side }: OptionHoverProps) {
|
||||
const localize = useLocalize();
|
||||
const text = types?.[endpoint]?.[type];
|
||||
if (!text) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<HoverCardPortal>
|
||||
<HoverCardContent side={side} className="w-80 ">
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300">{localize(text)}</p>
|
||||
</div>
|
||||
</HoverCardContent>
|
||||
</HoverCardPortal>
|
||||
);
|
||||
}
|
||||
|
||||
export default OptionHover;
|
||||
274
client/src/components/Endpoints/Settings/Plugins.tsx
Normal file
274
client/src/components/Endpoints/Settings/Plugins.tsx
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
import TextareaAutosize from 'react-textarea-autosize';
|
||||
import {
|
||||
SelectDropDown,
|
||||
Input,
|
||||
Label,
|
||||
Slider,
|
||||
InputNumber,
|
||||
HoverCard,
|
||||
HoverCardTrigger,
|
||||
} from '~/components';
|
||||
import OptionHover from './OptionHover';
|
||||
import { ModelSelectProps, Side } from 'librechat-data-provider';
|
||||
import { cn, defaultTextProps, optionText, removeFocusOutlines } from '~/utils/';
|
||||
import { useLocalize } from '~/hooks';
|
||||
|
||||
export default function Settings({ conversation, setOption, models, readonly }: ModelSelectProps) {
|
||||
const localize = useLocalize();
|
||||
if (!conversation) {
|
||||
return null;
|
||||
}
|
||||
const {
|
||||
model,
|
||||
chatGptLabel,
|
||||
promptPrefix,
|
||||
temperature,
|
||||
top_p: topP,
|
||||
frequency_penalty: freqP,
|
||||
presence_penalty: presP,
|
||||
tools,
|
||||
} = conversation;
|
||||
|
||||
const setModel = setOption('model');
|
||||
const setChatGptLabel = setOption('chatGptLabel');
|
||||
const setPromptPrefix = setOption('promptPrefix');
|
||||
const setTemperature = setOption('temperature');
|
||||
const setTopP = setOption('top_p');
|
||||
const setFreqP = setOption('presence_penalty');
|
||||
const setPresP = setOption('frequency_penalty');
|
||||
|
||||
const toolsSelected = tools && tools.length > 0;
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-5 gap-6">
|
||||
<div className="col-span-5 flex flex-col items-center justify-start gap-6 sm:col-span-3">
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<SelectDropDown
|
||||
title={localize('com_endpoint_completion_model')}
|
||||
value={model ?? ''}
|
||||
setValue={setModel}
|
||||
availableValues={models}
|
||||
disabled={readonly}
|
||||
className={cn(defaultTextProps, 'flex w-full resize-none', removeFocusOutlines)}
|
||||
containerClassName="flex w-full resize-none"
|
||||
/>
|
||||
</div>
|
||||
<>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="chatGptLabel" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_custom_name')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_empty')} |{' '}
|
||||
{localize('com_endpoint_disabled_with_tools')})
|
||||
</small>
|
||||
</Label>
|
||||
<Input
|
||||
id="chatGptLabel"
|
||||
disabled={readonly || toolsSelected}
|
||||
value={chatGptLabel || ''}
|
||||
onChange={(e) => setChatGptLabel(e.target.value ?? null)}
|
||||
placeholder={
|
||||
toolsSelected
|
||||
? localize('com_endpoint_disabled_with_tools_placeholder')
|
||||
: localize('com_endpoint_openai_custom_name_placeholder')
|
||||
}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex h-10 max-h-10 w-full resize-none px-3 py-2',
|
||||
removeFocusOutlines,
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid w-full items-center gap-2">
|
||||
<Label htmlFor="promptPrefix" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_prompt_prefix')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_empty')} |{' '}
|
||||
{localize('com_endpoint_disabled_with_tools')})
|
||||
</small>
|
||||
</Label>
|
||||
<TextareaAutosize
|
||||
id="promptPrefix"
|
||||
disabled={readonly || toolsSelected}
|
||||
value={promptPrefix || ''}
|
||||
onChange={(e) => setPromptPrefix(e.target.value ?? null)}
|
||||
placeholder={
|
||||
toolsSelected
|
||||
? localize('com_endpoint_disabled_with_tools_placeholder')
|
||||
: localize('com_endpoint_plug_set_custom_instructions_for_gpt_placeholder')
|
||||
}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
'flex max-h-[300px] min-h-[100px] w-full resize-none px-3 py-2 ',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
<div className="col-span-5 flex flex-col items-center justify-start gap-6 px-3 sm:col-span-2">
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="temp-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_temperature')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', '0.8')})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="temp-int"
|
||||
disabled={readonly}
|
||||
value={temperature}
|
||||
onChange={(value) => setTemperature(Number(value))}
|
||||
max={2}
|
||||
min={0}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[temperature ?? 0.8]}
|
||||
onValueChange={(value) => setTemperature(value[0])}
|
||||
doubleClickHandler={() => setTemperature(0.8)}
|
||||
max={2}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="temp" side={Side.Left} />
|
||||
</HoverCard>
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="top-p-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_top_p')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', '1')})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="top-p-int"
|
||||
disabled={readonly}
|
||||
value={topP}
|
||||
onChange={(value) => setTopP(Number(value))}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[topP ?? 1]}
|
||||
onValueChange={(value) => setTopP(value[0])}
|
||||
doubleClickHandler={() => setTopP(1)}
|
||||
max={1}
|
||||
min={0}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="topp" side={Side.Left} />
|
||||
</HoverCard>
|
||||
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="freq-penalty-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_frequency_penalty')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', '0')})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="freq-penalty-int"
|
||||
disabled={readonly}
|
||||
value={freqP}
|
||||
onChange={(value) => setFreqP(Number(value))}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[freqP ?? 0]}
|
||||
onValueChange={(value) => setFreqP(value[0])}
|
||||
doubleClickHandler={() => setFreqP(0)}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="freq" side={Side.Left} />
|
||||
</HoverCard>
|
||||
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||
<div className="flex justify-between">
|
||||
<Label htmlFor="pres-penalty-int" className="text-left text-sm font-medium">
|
||||
{localize('com_endpoint_presence_penalty')}{' '}
|
||||
<small className="opacity-40">
|
||||
({localize('com_endpoint_default_with_num', '0')})
|
||||
</small>
|
||||
</Label>
|
||||
<InputNumber
|
||||
id="pres-penalty-int"
|
||||
disabled={readonly}
|
||||
value={presP}
|
||||
onChange={(value) => setPresP(Number(value))}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
controls={false}
|
||||
className={cn(
|
||||
defaultTextProps,
|
||||
cn(
|
||||
optionText,
|
||||
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200',
|
||||
),
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
disabled={readonly}
|
||||
value={[presP ?? 0]}
|
||||
onValueChange={(value) => setPresP(value[0])}
|
||||
doubleClickHandler={() => setPresP(0)}
|
||||
max={2}
|
||||
min={-2}
|
||||
step={0.01}
|
||||
className="flex h-4 w-full"
|
||||
/>
|
||||
</HoverCardTrigger>
|
||||
<OptionHover endpoint={conversation?.endpoint ?? ''} type="pres" side={Side.Left} />
|
||||
</HoverCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
7
client/src/components/Endpoints/Settings/index.ts
Normal file
7
client/src/components/Endpoints/Settings/index.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export { default as OpenAISettings } from './OpenAI';
|
||||
export { default as BingAISettings } from './BingAI';
|
||||
export { default as GoogleSettings } from './Google';
|
||||
export { default as PluginsSettings } from './Plugins';
|
||||
export { default as Examples } from './Examples';
|
||||
export { default as AgentSettings } from './AgentSettings';
|
||||
export { default as AnthropicSettings } from './Anthropic';
|
||||
Loading…
Add table
Add a link
Reference in a new issue