fix: user can't use a model in model hub (#1801)

Signed-off-by: James <james@jan.ai>
Co-authored-by: James <james@jan.ai>
This commit is contained in:
NamH 2024-01-26 14:41:42 +07:00 committed by GitHub
parent bdebbca9b5
commit 9fa28d2275
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 61 additions and 60 deletions

View File

@ -36,23 +36,22 @@ import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom'
import { import {
ModelParams, ModelParams,
activeThreadAtom, activeThreadAtom,
getActiveThreadIdAtom,
setThreadModelParamsAtom, setThreadModelParamsAtom,
threadStatesAtom, threadStatesAtom,
} from '@/helpers/atoms/Thread.atom' } from '@/helpers/atoms/Thread.atom'
export const selectedModelAtom = atom<Model | undefined>(undefined) export const selectedModelAtom = atom<Model | undefined>(undefined)
export default function DropdownListSidebar() { const DropdownListSidebar: React.FC = () => {
const activeThreadId = useAtomValue(getActiveThreadIdAtom)
const activeThread = useAtomValue(activeThreadAtom) const activeThread = useAtomValue(activeThreadAtom)
const threadStates = useAtomValue(threadStatesAtom) const threadStates = useAtomValue(threadStatesAtom)
const [selectedModel, setSelectedModel] = useAtom(selectedModelAtom) const [selectedModel, setSelectedModel] = useAtom(selectedModelAtom)
const setThreadModelParams = useSetAtom(setThreadModelParamsAtom) const setThreadModelParams = useSetAtom(setThreadModelParamsAtom)
const { activeModel, stateModel } = useActiveModel()
const { stateModel } = useActiveModel()
const [serverEnabled, setServerEnabled] = useAtom(serverEnabledAtom) const [serverEnabled, setServerEnabled] = useAtom(serverEnabledAtom)
const { setMainViewState } = useMainViewState() const { setMainViewState } = useMainViewState()
const [loader, setLoader] = useState(0)
const { recommendedModel, downloadedModels } = useRecommendedModel() const { recommendedModel, downloadedModels } = useRecommendedModel()
/** /**
@ -65,38 +64,41 @@ export default function DropdownListSidebar() {
} }
useEffect(() => { useEffect(() => {
setSelectedModel(selectedModel || activeModel || recommendedModel) if (!activeThread) return
if (activeThread) { let model = downloadedModels.find(
const finishInit = threadStates[activeThread.id].isFinishInit ?? true (model) => model.id === activeThread.assistants[0].model.id
if (finishInit) return )
const modelParams: ModelParams = { if (!model) {
...recommendedModel?.parameters, model = recommendedModel
...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)
} }
// 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, recommendedModel,
activeThread, activeThread,
setSelectedModel,
setThreadModelParams,
threadStates, threadStates,
downloadedModels,
setThreadModelParams,
setSelectedModel,
]) ])
const [loader, setLoader] = useState(0)
// This is fake loader please fix this when we have realtime percentage when load model // This is fake loader please fix this when we have realtime percentage when load model
useEffect(() => { useEffect(() => {
if (stateModel.loading) { if (stateModel.loading) {
@ -132,20 +134,20 @@ export default function DropdownListSidebar() {
setServerEnabled(false) setServerEnabled(false)
} }
if (activeThreadId) { if (activeThread) {
const modelParams = { const modelParams = {
...model?.parameters, ...model?.parameters,
...model?.settings, ...model?.settings,
} }
setThreadModelParams(activeThreadId, modelParams) setThreadModelParams(activeThread.id, modelParams)
} }
}, },
// eslint-disable-next-line react-hooks/exhaustive-deps
[ [
downloadedModels, downloadedModels,
serverEnabled, serverEnabled,
activeThreadId, activeThread,
activeModel, setSelectedModel,
setServerEnabled,
setThreadModelParams, setThreadModelParams,
] ]
) )
@ -236,10 +238,9 @@ export default function DropdownListSidebar() {
</Select> </Select>
</div> </div>
<OpenAiKeyInput <OpenAiKeyInput />
selectedModel={selectedModel}
serverEnabled={serverEnabled}
/>
</> </>
) )
} }
export default DropdownListSidebar

View File

@ -1,16 +1,19 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { InferenceEngine, Model } from '@janhq/core' import { InferenceEngine } from '@janhq/core'
import { Input } from '@janhq/uikit' import { Input } from '@janhq/uikit'
import { useAtomValue } from 'jotai'
import { useEngineSettings } from '@/hooks/useEngineSettings' import { useEngineSettings } from '@/hooks/useEngineSettings'
type Props = { import { selectedModelAtom } from '../DropdownListSidebar'
selectedModel?: Model
serverEnabled: boolean
}
const OpenAiKeyInput: React.FC<Props> = ({ 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< const [openAISettings, setOpenAISettings] = useState<
{ api_key: string } | undefined { api_key: string } | undefined
>(undefined) >(undefined)
@ -20,8 +23,7 @@ const OpenAiKeyInput: React.FC<Props> = ({ selectedModel, serverEnabled }) => {
readOpenAISettings().then((settings) => { readOpenAISettings().then((settings) => {
setOpenAISettings(settings) setOpenAISettings(settings)
}) })
// eslint-disable-next-line react-hooks/exhaustive-deps }, [readOpenAISettings])
}, [])
if (!selectedModel || selectedModel.engine !== InferenceEngine.openai) { if (!selectedModel || selectedModel.engine !== InferenceEngine.openai) {
return null return null

View File

@ -1,7 +1,9 @@
import { useCallback } from 'react'
import { fs, joinPath, events, AppConfigurationEventName } from '@janhq/core' import { fs, joinPath, events, AppConfigurationEventName } from '@janhq/core'
export const useEngineSettings = () => { export const useEngineSettings = () => {
const readOpenAISettings = async () => { const readOpenAISettings = useCallback(async () => {
if ( if (
!(await fs.existsSync(await joinPath(['file://engines', 'openai.json']))) !(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 typeof settings === 'object' ? settings : JSON.parse(settings)
} }
return {} return {}
} }, [])
const saveOpenAISettings = async ({ const saveOpenAISettings = async ({
apiKey, apiKey,
}: { }: {

View File

@ -43,9 +43,7 @@ export default function useRecommendedModel() {
Model | undefined Model | undefined
> => { > => {
const models = await getAndSortDownloadedModels() const models = await getAndSortDownloadedModels()
if (!activeThread) { if (!activeThread) return
return
}
const finishInit = threadStates[activeThread.id].isFinishInit ?? true const finishInit = threadStates[activeThread.id].isFinishInit ?? true
if (finishInit) { if (finishInit) {

View File

@ -140,10 +140,8 @@ const Sidebar: React.FC = () => {
</div> </div>
</CardSidebar> </CardSidebar>
<CardSidebar title="Model"> <CardSidebar title="Model">
<div className="px-2"> <div className="px-2 pt-4">
<div className="mt-4"> <DropdownListSidebar />
<DropdownListSidebar />
</div>
{componentDataRuntimeSetting.length !== 0 && ( {componentDataRuntimeSetting.length !== 0 && (
<div className="mt-6"> <div className="mt-6">

View File

@ -29,6 +29,7 @@ import { ExternalLinkIcon, InfoIcon } from 'lucide-react'
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
import CardSidebar from '@/containers/CardSidebar' import CardSidebar from '@/containers/CardSidebar'
import DropdownListSidebar, { import DropdownListSidebar, {
selectedModelAtom, selectedModelAtom,
} from '@/containers/DropdownListSidebar' } from '@/containers/DropdownListSidebar'
@ -66,7 +67,7 @@ const LocalServerScreen = () => {
const { openServerLog, clearServerLog } = useServerLog() const { openServerLog, clearServerLog } = useServerLog()
const { startModel, stateModel } = useActiveModel() const { startModel, stateModel } = useActiveModel()
const [selectedModel] = useAtom(selectedModelAtom) const selectedModel = useAtomValue(selectedModelAtom)
const [isCorsEnabled, setIsCorsEnabled] = useAtom(corsEnabledAtom) const [isCorsEnabled, setIsCorsEnabled] = useAtom(corsEnabledAtom)
const [isVerboseEnabled, setIsVerboseEnabled] = useAtom(verboseEnabledAtom) const [isVerboseEnabled, setIsVerboseEnabled] = useAtom(verboseEnabledAtom)
@ -351,10 +352,8 @@ const LocalServerScreen = () => {
: 'w-0 translate-x-full opacity-0' : 'w-0 translate-x-full opacity-0'
)} )}
> >
<div className="px-4"> <div className="px-4 pt-4">
<div className="mt-4"> <DropdownListSidebar />
<DropdownListSidebar />
</div>
{componentDataEngineSetting.filter( {componentDataEngineSetting.filter(
(x) => x.name === 'prompt_template' (x) => x.name === 'prompt_template'