import keyBy from 'lodash/keyBy'; import React, { useMemo, useEffect } from 'react'; import { ChevronLeft, RotateCcw } from 'lucide-react'; import { useFormContext, useWatch, Controller } from 'react-hook-form'; import { componentMapping } from '~/components/SidePanel/Parameters/components'; import { alternateName, getSettingsKeys, LocalStorageKeys, SettingDefinition, agentParamSettings, } from 'librechat-data-provider'; import type * as t from 'librechat-data-provider'; import type { AgentForm, AgentModelPanelProps, StringOption } from '~/common'; import ControlCombobox from '~/components/ui/ControlCombobox'; import { useGetEndpointsQuery } from '~/data-provider'; import { getEndpointField, cn } from '~/utils'; import { useLocalize } from '~/hooks'; import { Panel } from '~/common'; export default function ModelPanel({ providers, setActivePanel, models: modelsData, }: Pick) { const localize = useLocalize(); const { control, setValue } = useFormContext(); const model = useWatch({ control, name: 'model' }); const providerOption = useWatch({ control, name: 'provider' }); const modelParameters = useWatch({ control, name: 'model_parameters' }); const provider = useMemo(() => { const value = typeof providerOption === 'string' ? providerOption : (providerOption as StringOption | undefined)?.value; return value ?? ''; }, [providerOption]); const models = useMemo( () => (provider ? (modelsData[provider] ?? []) : []), [modelsData, provider], ); useEffect(() => { const _model = model ?? ''; if (provider && _model) { const modelExists = models.includes(_model); if (!modelExists) { const newModels = modelsData[provider] ?? []; setValue('model', newModels[0] ?? ''); } localStorage.setItem(LocalStorageKeys.LAST_AGENT_MODEL, _model); localStorage.setItem(LocalStorageKeys.LAST_AGENT_PROVIDER, provider); } if (provider && !_model) { setValue('model', models[0] ?? ''); } }, [provider, models, modelsData, setValue, model]); const { data: endpointsConfig = {} } = useGetEndpointsQuery(); const bedrockRegions = useMemo(() => { return endpointsConfig?.[provider]?.availableRegions ?? []; }, [endpointsConfig, provider]); const endpointType = useMemo( () => getEndpointField(endpointsConfig, provider, 'type'), [provider, endpointsConfig], ); const parameters = useMemo((): SettingDefinition[] => { const customParams = endpointsConfig[provider]?.customParams ?? {}; const [combinedKey, endpointKey] = getSettingsKeys(endpointType ?? provider, model ?? ''); const overriddenEndpointKey = customParams.defaultParamsEndpoint ?? endpointKey; const defaultParams = agentParamSettings[combinedKey] ?? agentParamSettings[overriddenEndpointKey] ?? []; const overriddenParams = endpointsConfig[provider]?.customParams?.paramDefinitions ?? []; const overriddenParamsMap = keyBy(overriddenParams, 'key'); return defaultParams.map( (param) => (overriddenParamsMap[param.key] as SettingDefinition) ?? param, ); }, [endpointType, endpointsConfig, model, provider]); const setOption = (optionKey: keyof t.AgentModelParameters) => (value: t.AgentParameterValue) => { setValue(`model_parameters.${optionKey}`, value); }; const handleResetParameters = () => { setValue('model_parameters', {} as t.AgentModelParameters); }; return (
{localize('com_ui_model_parameters')}
{/* Endpoint aka Provider for Agents */}
{ const value = typeof field.value === 'string' ? field.value : ((field.value as StringOption)?.value ?? ''); const display = typeof field.value === 'string' ? field.value : ((field.value as StringOption)?.label ?? ''); return ( <> ({ label: typeof provider === 'string' ? provider : provider.label, value: typeof provider === 'string' ? provider : provider.value, }))} className={cn(error ? 'border-2 border-red-500' : '')} ariaLabel={localize('com_ui_provider')} isCollapsed={false} showCarat={true} /> {error && ( {localize('com_ui_field_required')} )} ); }} />
{/* Model */}
{ return ( <> ({ label: model, value: model, }))} disabled={!provider} className={cn('disabled:opacity-50', error ? 'border-2 border-red-500' : '')} ariaLabel={localize('com_ui_model')} isCollapsed={false} showCarat={true} /> {provider && error && ( {localize('com_ui_field_required')} )} ); }} />
{/* Model Parameters */} {parameters && (
{/* 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 */} {parameters.map((setting) => { const Component = componentMapping[setting.component]; if (!Component) { return null; } const { key, default: defaultValue, ...rest } = setting; if (key === 'region' && bedrockRegions.length) { rest.options = bedrockRegions; } return ( } /> ); })}
)} {/* Reset Parameters Button */}
); }