From bab0152c58d414c07a3a33ed83916c0a79cb5fe2 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Fri, 11 Oct 2024 14:20:32 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20feat:=20Enhance=20Assistant=20Mo?= =?UTF-8?q?del=20Handling=20for=20Model=20Specs=20(#4390)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: cleanup type issues in client/src/utils/endpoints * refactor: use Constant enum for 'new' conversationId * refactor: select assistant model if not provided for model spec --- .../components/Chat/Menus/Models/ModelSpecsMenu.tsx | 9 +++++++-- client/src/hooks/Input/useSelectMention.ts | 6 +++++- client/src/hooks/useNewConvo.ts | 11 ++++++----- client/src/utils/endpoints.ts | 9 +++++---- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/client/src/components/Chat/Menus/Models/ModelSpecsMenu.tsx b/client/src/components/Chat/Menus/Models/ModelSpecsMenu.tsx index 2ebb40556d..d04e8ffd8d 100644 --- a/client/src/components/Chat/Menus/Models/ModelSpecsMenu.tsx +++ b/client/src/components/Chat/Menus/Models/ModelSpecsMenu.tsx @@ -1,12 +1,12 @@ import { useMemo } from 'react'; import { useRecoilValue } from 'recoil'; -import { EModelEndpoint } from 'librechat-data-provider'; import { Content, Portal, Root } from '@radix-ui/react-popover'; import { useGetEndpointsQuery } from 'librechat-data-provider/react-query'; +import { EModelEndpoint, isAssistantsEndpoint } from 'librechat-data-provider'; import type { TModelSpec, TConversation, TEndpointsConfig } from 'librechat-data-provider'; +import { useChatContext, useAssistantsMapContext } from '~/Providers'; import { getConvoSwitchLogic, getModelSpecIconURL } from '~/utils'; import { useDefaultConvo, useNewConvo } from '~/hooks'; -import { useChatContext } from '~/Providers'; import MenuButton from './MenuButton'; import ModelSpecs from './ModelSpecs'; import store from '~/store'; @@ -18,6 +18,7 @@ export default function ModelSpecsMenu({ modelSpecs }: { modelSpecs?: TModelSpec const { data: endpointsConfig = {} as TEndpointsConfig } = useGetEndpointsQuery(); const modularChat = useRecoilValue(store.modularChat); const getDefaultConversation = useDefaultConvo(); + const assistantMap = useAssistantsMapContext(); const onSelectSpec = (spec: TModelSpec) => { const { preset } = spec; @@ -47,6 +48,10 @@ export default function ModelSpecsMenu({ modelSpecs }: { modelSpecs?: TModelSpec preset.endpointType = newEndpointType; } + if (isAssistantsEndpoint(newEndpoint) && preset.assistant_id != null && !(preset.model ?? '')) { + preset.model = assistantMap?.[newEndpoint]?.[preset.assistant_id]?.model; + } + const isModular = isCurrentModular && isNewModular && shouldSwitch; if (isExistingConversation && isModular) { template.endpointType = newEndpointType as EModelEndpoint | undefined; diff --git a/client/src/hooks/Input/useSelectMention.ts b/client/src/hooks/Input/useSelectMention.ts index 8c8b1e38f2..a85d4ff14f 100644 --- a/client/src/hooks/Input/useSelectMention.ts +++ b/client/src/hooks/Input/useSelectMention.ts @@ -64,6 +64,10 @@ export default function useSelectMention({ preset.endpointType = newEndpointType; } + if (isAssistantsEndpoint(newEndpoint) && preset.assistant_id != null && !(preset.model ?? '')) { + preset.model = assistantMap?.[newEndpoint]?.[preset.assistant_id]?.model; + } + const isModular = isCurrentModular && isNewModular && shouldSwitch; if (isExistingConversation && isModular) { template.endpointType = newEndpointType as EModelEndpoint | undefined; @@ -90,7 +94,7 @@ export default function useSelectMention({ keepAddedConvos: isModular, }); }, - [conversation, getDefaultConversation, modularChat, newConversation, endpointsConfig], + [conversation, getDefaultConversation, modularChat, newConversation, endpointsConfig, assistantMap], ); type Kwargs = { diff --git a/client/src/hooks/useNewConvo.ts b/client/src/hooks/useNewConvo.ts index 120b0896d5..9dbb98ebbc 100644 --- a/client/src/hooks/useNewConvo.ts +++ b/client/src/hooks/useNewConvo.ts @@ -6,6 +6,7 @@ import { } from 'librechat-data-provider/react-query'; import { useNavigate } from 'react-router-dom'; import { + Constants, FileSources, isParamEndpoint, LocalStorageKeys, @@ -116,7 +117,7 @@ const useNewConvo = (index = 0) => { ) ?? assistants[0]?.id; } - if (currentAssistantId && isAssistantEndpoint && conversation.conversationId === 'new') { + if (currentAssistantId && isAssistantEndpoint && conversation.conversationId === Constants.NEW_CONVO) { const assistant = assistants.find((asst) => asst.id === currentAssistantId); conversation.model = assistant?.model; updateLastSelectedModel({ @@ -147,12 +148,12 @@ const useNewConvo = (index = 0) => { clearAllLatestMessages(); } - if (conversation.conversationId === 'new' && !modelsData) { + if (conversation.conversationId === Constants.NEW_CONVO && !modelsData) { const appTitle = localStorage.getItem(LocalStorageKeys.APP_TITLE) ?? ''; if (appTitle) { document.title = appTitle; } - navigate('/c/new'); + navigate(`/c/${Constants.NEW_CONVO}`); } clearTimeout(timeoutIdRef.current); @@ -189,12 +190,12 @@ const useNewConvo = (index = 0) => { isParamEndpoint(_template.endpoint ?? '', _template.endpointType ?? '') === true || isParamEndpoint(_preset?.endpoint ?? '', _preset?.endpointType ?? ''); const template = - paramEndpoint === true && templateConvoId && templateConvoId === 'new' + paramEndpoint === true && templateConvoId && templateConvoId === Constants.NEW_CONVO ? { endpoint: _template.endpoint } : _template; const conversation = { - conversationId: 'new', + conversationId: Constants.NEW_CONVO as string, title: 'New Chat', endpoint: null, ...template, diff --git a/client/src/utils/endpoints.ts b/client/src/utils/endpoints.ts index 30b2676837..3b8f882608 100644 --- a/client/src/utils/endpoints.ts +++ b/client/src/utils/endpoints.ts @@ -87,22 +87,23 @@ const firstLocalConvoKey = LocalStorageKeys.LAST_CONVO_SETUP + '_0'; * update without updating last convo setup when same endpoint */ export function updateLastSelectedModel({ endpoint, - model, + model = '', }: { endpoint: string; - model: string | undefined; + model?: string; }) { if (!model) { return; } - const lastConversationSetup = JSON.parse(localStorage.getItem(firstLocalConvoKey) || '{}'); + /* Note: an empty string value is possible */ + const lastConversationSetup = JSON.parse((localStorage.getItem(firstLocalConvoKey) ?? '{}') || '{}'); if (lastConversationSetup.endpoint === endpoint) { lastConversationSetup.model = model; localStorage.setItem(firstLocalConvoKey, JSON.stringify(lastConversationSetup)); } - const lastSelectedModels = JSON.parse(localStorage.getItem(LocalStorageKeys.LAST_MODEL) || '{}'); + const lastSelectedModels = JSON.parse((localStorage.getItem(LocalStorageKeys.LAST_MODEL) ?? '{}') || '{}'); lastSelectedModels[endpoint] = model; localStorage.setItem(LocalStorageKeys.LAST_MODEL, JSON.stringify(lastSelectedModels)); }