diff --git a/web/containers/DropdownListSidebar/index.tsx b/web/containers/DropdownListSidebar/index.tsx index fdc39063a..31753c39c 100644 --- a/web/containers/DropdownListSidebar/index.tsx +++ b/web/containers/DropdownListSidebar/index.tsx @@ -36,23 +36,22 @@ import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom' import { ModelParams, activeThreadAtom, - getActiveThreadIdAtom, setThreadModelParamsAtom, threadStatesAtom, } from '@/helpers/atoms/Thread.atom' export const selectedModelAtom = atom(undefined) -export default function DropdownListSidebar() { - const activeThreadId = useAtomValue(getActiveThreadIdAtom) +const DropdownListSidebar: React.FC = () => { const activeThread = useAtomValue(activeThreadAtom) const threadStates = useAtomValue(threadStatesAtom) const [selectedModel, setSelectedModel] = useAtom(selectedModelAtom) const setThreadModelParams = useSetAtom(setThreadModelParamsAtom) - const { activeModel, stateModel } = useActiveModel() + + const { stateModel } = useActiveModel() const [serverEnabled, setServerEnabled] = useAtom(serverEnabledAtom) const { setMainViewState } = useMainViewState() - + const [loader, setLoader] = useState(0) const { recommendedModel, downloadedModels } = useRecommendedModel() /** @@ -65,38 +64,41 @@ export default function DropdownListSidebar() { } useEffect(() => { - setSelectedModel(selectedModel || activeModel || recommendedModel) + if (!activeThread) return - if (activeThread) { - const finishInit = threadStates[activeThread.id].isFinishInit ?? true - if (finishInit) return - const modelParams: ModelParams = { - ...recommendedModel?.parameters, - ...recommendedModel?.settings, - /** - * This is to set default value for these settings instead of maximum value - * Should only apply when model.json has these settings - */ - ...(recommendedModel?.parameters.max_tokens && { - max_tokens: defaultValue(recommendedModel?.parameters.max_tokens), - }), - ...(recommendedModel?.settings.ctx_len && { - ctx_len: defaultValue(recommendedModel?.settings.ctx_len), - }), - } - setThreadModelParams(activeThread.id, modelParams) + let model = downloadedModels.find( + (model) => model.id === activeThread.assistants[0].model.id + ) + if (!model) { + model = recommendedModel } - // eslint-disable-next-line react-hooks/exhaustive-deps + setSelectedModel(model) + const finishInit = threadStates[activeThread.id].isFinishInit ?? true + if (finishInit) return + const modelParams: ModelParams = { + ...model?.parameters, + ...model?.settings, + /** + * This is to set default value for these settings instead of maximum value + * Should only apply when model.json has these settings + */ + ...(model?.parameters.max_tokens && { + max_tokens: defaultValue(model?.parameters.max_tokens), + }), + ...(model?.settings.ctx_len && { + ctx_len: defaultValue(model?.settings.ctx_len), + }), + } + setThreadModelParams(activeThread.id, modelParams) }, [ recommendedModel, activeThread, - setSelectedModel, - setThreadModelParams, threadStates, + downloadedModels, + setThreadModelParams, + setSelectedModel, ]) - const [loader, setLoader] = useState(0) - // This is fake loader please fix this when we have realtime percentage when load model useEffect(() => { if (stateModel.loading) { @@ -132,20 +134,20 @@ export default function DropdownListSidebar() { setServerEnabled(false) } - if (activeThreadId) { + if (activeThread) { const modelParams = { ...model?.parameters, ...model?.settings, } - setThreadModelParams(activeThreadId, modelParams) + setThreadModelParams(activeThread.id, modelParams) } }, - // eslint-disable-next-line react-hooks/exhaustive-deps [ downloadedModels, serverEnabled, - activeThreadId, - activeModel, + activeThread, + setSelectedModel, + setServerEnabled, setThreadModelParams, ] ) @@ -236,10 +238,9 @@ export default function DropdownListSidebar() { - + ) } + +export default DropdownListSidebar diff --git a/web/containers/OpenAiKeyInput/index.tsx b/web/containers/OpenAiKeyInput/index.tsx index abd79e6a8..444c8074f 100644 --- a/web/containers/OpenAiKeyInput/index.tsx +++ b/web/containers/OpenAiKeyInput/index.tsx @@ -1,16 +1,19 @@ import React, { useEffect, useState } from 'react' -import { InferenceEngine, Model } from '@janhq/core' +import { InferenceEngine } from '@janhq/core' import { Input } from '@janhq/uikit' +import { useAtomValue } from 'jotai' + import { useEngineSettings } from '@/hooks/useEngineSettings' -type Props = { - selectedModel?: Model - serverEnabled: boolean -} +import { selectedModelAtom } from '../DropdownListSidebar' -const OpenAiKeyInput: React.FC = ({ selectedModel, serverEnabled }) => { +import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom' + +const OpenAiKeyInput: React.FC = () => { + const selectedModel = useAtomValue(selectedModelAtom) + const serverEnabled = useAtomValue(serverEnabledAtom) const [openAISettings, setOpenAISettings] = useState< { api_key: string } | undefined >(undefined) @@ -20,8 +23,7 @@ const OpenAiKeyInput: React.FC = ({ selectedModel, serverEnabled }) => { readOpenAISettings().then((settings) => { setOpenAISettings(settings) }) - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + }, [readOpenAISettings]) if (!selectedModel || selectedModel.engine !== InferenceEngine.openai) { return null diff --git a/web/hooks/useEngineSettings.ts b/web/hooks/useEngineSettings.ts index 49e6607b3..4a17f91df 100644 --- a/web/hooks/useEngineSettings.ts +++ b/web/hooks/useEngineSettings.ts @@ -1,7 +1,9 @@ +import { useCallback } from 'react' + import { fs, joinPath, events, AppConfigurationEventName } from '@janhq/core' export const useEngineSettings = () => { - const readOpenAISettings = async () => { + const readOpenAISettings = useCallback(async () => { if ( !(await fs.existsSync(await joinPath(['file://engines', 'openai.json']))) ) @@ -14,7 +16,8 @@ export const useEngineSettings = () => { return typeof settings === 'object' ? settings : JSON.parse(settings) } return {} - } + }, []) + const saveOpenAISettings = async ({ apiKey, }: { diff --git a/web/hooks/useRecommendedModel.ts b/web/hooks/useRecommendedModel.ts index dd474d0b5..cc47d3fe6 100644 --- a/web/hooks/useRecommendedModel.ts +++ b/web/hooks/useRecommendedModel.ts @@ -43,9 +43,7 @@ export default function useRecommendedModel() { Model | undefined > => { const models = await getAndSortDownloadedModels() - if (!activeThread) { - return - } + if (!activeThread) return const finishInit = threadStates[activeThread.id].isFinishInit ?? true if (finishInit) { diff --git a/web/screens/Chat/Sidebar/index.tsx b/web/screens/Chat/Sidebar/index.tsx index 64e58d4d3..500787218 100644 --- a/web/screens/Chat/Sidebar/index.tsx +++ b/web/screens/Chat/Sidebar/index.tsx @@ -140,10 +140,8 @@ const Sidebar: React.FC = () => { -
-
- -
+
+ {componentDataRuntimeSetting.length !== 0 && (
diff --git a/web/screens/LocalServer/index.tsx b/web/screens/LocalServer/index.tsx index 5e9eb1d04..f752baf2d 100644 --- a/web/screens/LocalServer/index.tsx +++ b/web/screens/LocalServer/index.tsx @@ -29,6 +29,7 @@ import { ExternalLinkIcon, InfoIcon } from 'lucide-react' import { twMerge } from 'tailwind-merge' import CardSidebar from '@/containers/CardSidebar' + import DropdownListSidebar, { selectedModelAtom, } from '@/containers/DropdownListSidebar' @@ -66,7 +67,7 @@ const LocalServerScreen = () => { const { openServerLog, clearServerLog } = useServerLog() const { startModel, stateModel } = useActiveModel() - const [selectedModel] = useAtom(selectedModelAtom) + const selectedModel = useAtomValue(selectedModelAtom) const [isCorsEnabled, setIsCorsEnabled] = useAtom(corsEnabledAtom) const [isVerboseEnabled, setIsVerboseEnabled] = useAtom(verboseEnabledAtom) @@ -351,10 +352,8 @@ const LocalServerScreen = () => { : 'w-0 translate-x-full opacity-0' )} > -
-
- -
+
+ {componentDataEngineSetting.filter( (x) => x.name === 'prompt_template'