import { Fragment, useCallback, useMemo } from 'react' import { Button, Progress } from '@janhq/joi' import { useAtomValue, useSetAtom } from 'jotai' import Spinner from '@/containers/Loader/Spinner' import { toaster } from '@/containers/Toast' import useAbortDownload from '@/hooks/useAbortDownload' import useAssistantQuery from '@/hooks/useAssistantQuery' import { downloadStateListAtom } from '@/hooks/useDownloadState' import useHfRepoDataQuery from '@/hooks/useHfRepoDataQuery' import useModelDownloadMutation from '@/hooks/useModelDownloadMutation' import useThreads from '@/hooks/useThreads' import { formatDownloadPercentage, toGibibytes } from '@/utils/converter' import { downloadProgress } from '@/utils/download' import { MainViewState, mainViewStateAtom } from '@/helpers/atoms/App.atom' import { localModelModalStageAtom } from '@/helpers/atoms/DownloadLocalModel.atom' import { downloadedModelsAtom } from '@/helpers/atoms/Model.atom' type Props = { modelHandle: string } const HfListModel: React.FC = ({ modelHandle }) => { const { data, isLoading } = useHfRepoDataQuery(modelHandle) const downloadableModels = useMemo( () => data?.siblings .filter((item) => item.rfilename.endsWith('.gguf')) .sort((a, b) => (a.fileSize ?? 0) - (b.fileSize ?? 0)) ?? [] ?? [], [data] ) if (isLoading) return (
) return (
{downloadableModels.map((item) => ( ))}
{item.quantization}
{item.rfilename}
{toGibibytes(item.fileSize)}
) } type DownloadContainerProps = { modelHandle: string fileName: string } const DownloadContainer: React.FC = ({ modelHandle, fileName, }) => { const downloadModelMutation = useModelDownloadMutation() const { abortDownload } = useAbortDownload() const setMainViewState = useSetAtom(mainViewStateAtom) const { createThread } = useThreads() const { data: assistants } = useAssistantQuery() const setDownloadLocalModelModalStage = useSetAtom(localModelModalStageAtom) const downloadedModels = useAtomValue(downloadedModelsAtom) const allDownloadState = useAtomValue(downloadStateListAtom) const persistModelId = modelHandle .replaceAll('/', '_') .concat('_') .concat(fileName) const downloadState = allDownloadState.find((s) => s.id === persistModelId) const downloadedModel = useMemo( () => downloadedModels.find((m) => m.model === persistModelId), [downloadedModels, persistModelId] ) const onDownloadClick = useCallback(async () => { downloadModelMutation.mutate({ modelId: modelHandle, fileName: fileName, persistedModelId: persistModelId, }) }, [downloadModelMutation, modelHandle, fileName, persistModelId]) const onUseModelClick = useCallback(async () => { if (!assistants || assistants.length === 0) { toaster({ title: 'No assistant available.', description: 'Please create an assistant to create a new thread', type: 'error', }) return } await createThread(fileName, { ...assistants[0], model: fileName, }) setDownloadLocalModelModalStage('NONE', undefined) setMainViewState(MainViewState.Thread) }, [ setDownloadLocalModelModalStage, setMainViewState, createThread, fileName, assistants, ]) return (
{downloadedModel ? ( ) : downloadState != null ? ( ) : ( )}
) } export default HfListModel