fix: local server blank parameters if there is no thread selected (#2028)

* fix: local server blank parameters if there is no thread selected

* fix: show errors only when the selected model is started while starting the server

* fix: show loading progress of selected model only
This commit is contained in:
Louis 2024-02-15 15:48:45 +07:00 committed by GitHub
parent 9cc9b4dffc
commit 3ab23d571f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 91 additions and 77 deletions

View File

@ -94,7 +94,7 @@ const DropdownListSidebar = ({
// 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.model === selectedModel?.id && stateModel.loading) {
if (loader === 24) { if (loader === 24) {
setTimeout(() => { setTimeout(() => {
setLoader(loader + 1) setLoader(loader + 1)
@ -115,7 +115,7 @@ const DropdownListSidebar = ({
} else { } else {
setLoader(0) setLoader(0)
} }
}, [stateModel.loading, loader]) }, [stateModel.loading, loader, selectedModel, stateModel.model])
const onValueSelected = useCallback( const onValueSelected = useCallback(
async (modelId: string) => { async (modelId: string) => {
@ -159,12 +159,16 @@ const DropdownListSidebar = ({
return null return null
} }
const selectedModelLoading =
stateModel.model === selectedModel?.id && stateModel.loading
return ( return (
<> <>
<div <div
className={twMerge( className={twMerge(
'relative w-full overflow-hidden rounded-md', 'relative w-full overflow-hidden rounded-md',
stateModel.loading && 'pointer-events-none bg-blue-200 text-blue-600' stateModel.loading && 'pointer-events-none',
selectedModelLoading && 'bg-blue-200 text-blue-600'
)} )}
> >
<Select <Select
@ -174,7 +178,7 @@ const DropdownListSidebar = ({
> >
<SelectTrigger className="relative w-full"> <SelectTrigger className="relative w-full">
<SelectValue placeholder="Choose model to start"> <SelectValue placeholder="Choose model to start">
{stateModel.loading && ( {selectedModelLoading && (
<div <div
className="z-5 absolute left-0 top-0 h-full w-full rounded-md bg-blue-100/80" className="z-5 absolute left-0 top-0 h-full w-full rounded-md bg-blue-100/80"
style={{ width: `${loader}%` }} style={{ width: `${loader}%` }}
@ -183,7 +187,7 @@ const DropdownListSidebar = ({
<span <span
className={twMerge( className={twMerge(
'relative z-20', 'relative z-20',
stateModel.loading && 'font-medium' selectedModelLoading && 'font-medium'
)} )}
> >
{selectedModel?.name} {selectedModel?.name}

View File

@ -28,6 +28,10 @@ export const isGeneratingResponseAtom = atom<boolean | undefined>(undefined)
* Stores all thread states for the current user * Stores all thread states for the current user
*/ */
export const threadStatesAtom = atom<Record<string, ThreadState>>({}) export const threadStatesAtom = atom<Record<string, ThreadState>>({})
// Whether thread data is ready or not
export const threadDataReadyAtom = atom<boolean>(false)
export const activeThreadStateAtom = atom<ThreadState | undefined>((get) => { export const activeThreadStateAtom = atom<ThreadState | undefined>((get) => {
const threadId = get(activeThreadIdAtom) const threadId = get(activeThreadIdAtom)
if (!threadId) { if (!threadId) {

View File

@ -14,6 +14,7 @@ import useSetActiveThread from './useSetActiveThread'
import { extensionManager } from '@/extension/ExtensionManager' import { extensionManager } from '@/extension/ExtensionManager'
import { import {
ModelParams, ModelParams,
threadDataReadyAtom,
threadModelParamsAtom, threadModelParamsAtom,
threadStatesAtom, threadStatesAtom,
threadsAtom, threadsAtom,
@ -24,6 +25,7 @@ const useThreads = () => {
const setThreads = useSetAtom(threadsAtom) const setThreads = useSetAtom(threadsAtom)
const setThreadModelRuntimeParams = useSetAtom(threadModelParamsAtom) const setThreadModelRuntimeParams = useSetAtom(threadModelParamsAtom)
const { setActiveThread } = useSetActiveThread() const { setActiveThread } = useSetActiveThread()
const setThreadDataReady = useSetAtom(threadDataReadyAtom)
useEffect(() => { useEffect(() => {
const getThreads = async () => { const getThreads = async () => {
@ -58,6 +60,7 @@ const useThreads = () => {
if (localThreads.length > 0) { if (localThreads.length > 0) {
setActiveThread(localThreads[0]) setActiveThread(localThreads[0])
} }
setThreadDataReady(true)
} }
getThreads() getThreads()
@ -66,6 +69,7 @@ const useThreads = () => {
setThreadModelRuntimeParams, setThreadModelRuntimeParams,
setThreadStates, setThreadStates,
setThreads, setThreads,
setThreadDataReady,
]) ])
} }

View File

@ -1,36 +1,25 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ import SettingComponentBuilder from '../../Chat/ModelSetting/SettingComponent'
import { useAtomValue } from 'jotai' import { SettingComponentData } from '../ModelSetting/SettingComponent'
import { selectedModelAtom } from '@/containers/DropdownListSidebar'
import { getConfigurationsData } from '@/utils/componentSettings'
import { toSettingParams } from '@/utils/modelParam'
import SettingComponentBuilder from '../ModelSetting/SettingComponent'
import { getActiveThreadModelParamsAtom } from '@/helpers/atoms/Thread.atom'
const EngineSetting = ({ enabled = true }: { enabled?: boolean }) => {
const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom)
const selectedModel = useAtomValue(selectedModelAtom)
if (!selectedModel || !activeModelParams) return null
const modelSettingParams = toSettingParams(activeModelParams)
const componentData = getConfigurationsData(
modelSettingParams,
selectedModel
).toSorted((a, b) => a.title.localeCompare(b.title))
const EngineSetting = ({
componentData,
enabled = true,
}: {
componentData: SettingComponentData[]
enabled?: boolean
}) => {
return ( return (
<div className="flex flex-col"> <>
<SettingComponentBuilder {componentData.filter((e) => e.name !== 'prompt_template').length && (
componentData={componentData} <div className="flex flex-col">
enabled={enabled} <SettingComponentBuilder
selector={(e) => e.name !== 'prompt_template'} componentData={componentData}
/> enabled={enabled}
</div> selector={(e) => e.name !== 'prompt_template'}
/>
</div>
)}
</>
) )
} }

View File

@ -1,37 +1,26 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import React from 'react' import React from 'react'
import { useAtomValue } from 'jotai' import SettingComponentBuilder, {
SettingComponentData,
import { selectedModelAtom } from '@/containers/DropdownListSidebar' } from './SettingComponent'
import { getConfigurationsData } from '@/utils/componentSettings'
import { toRuntimeParams } from '@/utils/modelParam'
import SettingComponentBuilder from './SettingComponent'
import { getActiveThreadModelParamsAtom } from '@/helpers/atoms/Thread.atom'
const ModelSetting = () => {
const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom)
const selectedModel = useAtomValue(selectedModelAtom)
if (!selectedModel || !activeModelParams) return null
const modelRuntimeParams = toRuntimeParams(activeModelParams)
const componentData = getConfigurationsData(
modelRuntimeParams,
selectedModel
).toSorted((a, b) => a.title.localeCompare(b.title))
const ModelSetting = ({
componentData,
}: {
componentData: SettingComponentData[]
}) => {
return ( return (
<div className="flex flex-col"> <>
<SettingComponentBuilder {componentData.filter((e) => e.name !== 'prompt_template').length && (
componentData={componentData} <div className="flex flex-col">
selector={(e) => e.name !== 'prompt_template'} <SettingComponentBuilder
/> componentData={componentData}
</div> selector={(e) => e.name !== 'prompt_template'}
/>
</div>
)}
</>
) )
} }

View File

@ -59,8 +59,14 @@ const Sidebar: React.FC = () => {
activeThread?.assistants[0]?.tools[0]?.settings) ?? activeThread?.assistants[0]?.tools[0]?.settings) ??
{} {}
) )
const componentDataEngineSetting = getConfigurationsData(modelEngineParams) const componentDataEngineSetting = getConfigurationsData(
const componentDataRuntimeSetting = getConfigurationsData(modelRuntimeParams) modelEngineParams,
selectedModel
)
const componentDataRuntimeSetting = getConfigurationsData(
modelRuntimeParams,
selectedModel
)
return ( return (
<div <div
@ -319,7 +325,7 @@ const Sidebar: React.FC = () => {
<div className="mt-6"> <div className="mt-6">
<CardSidebar title="Inference Parameters" asChild> <CardSidebar title="Inference Parameters" asChild>
<div className="px-2 py-4"> <div className="px-2 py-4">
<ModelSetting /> <ModelSetting componentData={componentDataRuntimeSetting} />
</div> </div>
</CardSidebar> </CardSidebar>
</div> </div>
@ -344,7 +350,7 @@ const Sidebar: React.FC = () => {
<div className="my-4"> <div className="my-4">
<CardSidebar title="Engine Parameters" asChild> <CardSidebar title="Engine Parameters" asChild>
<div className="px-2 py-4"> <div className="px-2 py-4">
<EngineSetting /> <EngineSetting componentData={componentDataEngineSetting} />
</div> </div>
</CardSidebar> </CardSidebar>
</div> </div>

View File

@ -1,4 +1,4 @@
import { useCallback } from 'react' import { useCallback, useEffect } from 'react'
import { Thread } from '@janhq/core/' import { Thread } from '@janhq/core/'
@ -8,6 +8,7 @@ import { GalleryHorizontalEndIcon, MoreVerticalIcon } from 'lucide-react'
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
import { useCreateNewThread } from '@/hooks/useCreateNewThread'
import useSetActiveThread from '@/hooks/useSetActiveThread' import useSetActiveThread from '@/hooks/useSetActiveThread'
import { displayDate } from '@/utils/datetime' import { displayDate } from '@/utils/datetime'
@ -16,8 +17,10 @@ import CleanThreadModal from '../CleanThreadModal'
import DeleteThreadModal from '../DeleteThreadModal' import DeleteThreadModal from '../DeleteThreadModal'
import { assistantsAtom } from '@/helpers/atoms/Assistant.atom'
import { import {
getActiveThreadIdAtom, getActiveThreadIdAtom,
threadDataReadyAtom,
threadStatesAtom, threadStatesAtom,
threadsAtom, threadsAtom,
} from '@/helpers/atoms/Thread.atom' } from '@/helpers/atoms/Thread.atom'
@ -27,6 +30,9 @@ export default function ThreadList() {
const threads = useAtomValue(threadsAtom) const threads = useAtomValue(threadsAtom)
const activeThreadId = useAtomValue(getActiveThreadIdAtom) const activeThreadId = useAtomValue(getActiveThreadIdAtom)
const { setActiveThread } = useSetActiveThread() const { setActiveThread } = useSetActiveThread()
const assistants = useAtomValue(assistantsAtom)
const threadDataReady = useAtomValue(threadDataReadyAtom)
const { requestCreateNewThread } = useCreateNewThread()
const onThreadClick = useCallback( const onThreadClick = useCallback(
(thread: Thread) => { (thread: Thread) => {
@ -35,6 +41,17 @@ export default function ThreadList() {
[setActiveThread] [setActiveThread]
) )
/**
* Auto create thread
* This will create a new thread if there are assistants available
* and there are no threads available
*/
useEffect(() => {
if (threadDataReady && assistants.length > 0 && threads.length === 0) {
requestCreateNewThread(assistants[0])
}
}, [assistants, threads, threadDataReady, requestCreateNewThread])
return ( return (
<div className="px-3 py-4"> <div className="px-3 py-4">
{threads.length === 0 ? ( {threads.length === 0 ? (

View File

@ -52,7 +52,6 @@ import SettingComponentBuilder from '../Chat/ModelSetting/SettingComponent'
import { showRightSideBarAtom } from '../Chat/Sidebar' import { showRightSideBarAtom } from '../Chat/Sidebar'
import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom' import { serverEnabledAtom } from '@/helpers/atoms/LocalServer.atom'
import { getActiveThreadModelParamsAtom } from '@/helpers/atoms/Thread.atom'
const corsEnabledAtom = atom(true) const corsEnabledAtom = atom(true)
const verboseEnabledAtom = atom(true) const verboseEnabledAtom = atom(true)
@ -63,16 +62,15 @@ const LocalServerScreen = () => {
const [errorRangePort, setErrorRangePort] = useState(false) const [errorRangePort, setErrorRangePort] = useState(false)
const [serverEnabled, setServerEnabled] = useAtom(serverEnabledAtom) const [serverEnabled, setServerEnabled] = useAtom(serverEnabledAtom)
const showRightSideBar = useAtomValue(showRightSideBarAtom) const showRightSideBar = useAtomValue(showRightSideBarAtom)
const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom)
const setModalTroubleShooting = useSetAtom(modalTroubleShootingAtom) const setModalTroubleShooting = useSetAtom(modalTroubleShootingAtom)
const modelEngineParams = toSettingParams(activeModelParams)
const componentDataEngineSetting = getConfigurationsData(modelEngineParams)
const { openServerLog, clearServerLog } = useLogs() const { openServerLog, clearServerLog } = useLogs()
const { startModel, stateModel } = useActiveModel() const { startModel, stateModel } = useActiveModel()
const selectedModel = useAtomValue(selectedModelAtom) const selectedModel = useAtomValue(selectedModelAtom)
const modelEngineParams = toSettingParams(selectedModel?.settings)
const componentDataEngineSetting = getConfigurationsData(modelEngineParams)
const [isCorsEnabled, setIsCorsEnabled] = useAtom(corsEnabledAtom) const [isCorsEnabled, setIsCorsEnabled] = useAtom(corsEnabledAtom)
const [isVerboseEnabled, setIsVerboseEnabled] = useAtom(verboseEnabledAtom) const [isVerboseEnabled, setIsVerboseEnabled] = useAtom(verboseEnabledAtom)
const [host, setHost] = useAtom(hostAtom) const [host, setHost] = useAtom(hostAtom)
@ -396,7 +394,7 @@ const LocalServerScreen = () => {
</p> </p>
</div> </div>
<DropdownListSidebar strictedThread={false} /> <DropdownListSidebar strictedThread={false} />
{loadModelError && ( {loadModelError && serverEnabled && (
<div className="mt-3 flex space-x-2 text-xs"> <div className="mt-3 flex space-x-2 text-xs">
<AlertTriangleIcon size={16} className="text-danger" /> <AlertTriangleIcon size={16} className="text-danger" />
<span> <span>
@ -431,7 +429,10 @@ const LocalServerScreen = () => {
<div className="my-4"> <div className="my-4">
<CardSidebar title="Engine Parameters" asChild> <CardSidebar title="Engine Parameters" asChild>
<div className="px-2 py-4"> <div className="px-2 py-4">
<EngineSetting enabled={!serverEnabled} /> <EngineSetting
enabled={!serverEnabled}
componentData={componentDataEngineSetting}
/>
</div> </div>
</CardSidebar> </CardSidebar>
</div> </div>