* fix: error while importing local model is not shown Signed-off-by: James <namnh0122@gmail.com> * fix: failed download should not be added to download state (#3297) Signed-off-by: James <namnh0122@gmail.com> --------- Signed-off-by: James <namnh0122@gmail.com>
103 lines
3.2 KiB
TypeScript
103 lines
3.2 KiB
TypeScript
import { useCallback } from 'react'
|
|
|
|
import { HuggingFaceRepoData } from '@janhq/core'
|
|
import { useQueryClient } from '@tanstack/react-query'
|
|
|
|
import { toaster } from '@/containers/Toast'
|
|
|
|
import { fetchHuggingFaceRepoData } from '@/utils/huggingface'
|
|
|
|
import { fetchHuggingFaceRepoDataQueryKey } from './useHfRepoDataQuery'
|
|
import useModelDownloadMutation from './useModelDownloadMutation'
|
|
|
|
/**
|
|
* Fetches the data for a Hugging Face model and downloads it.
|
|
* This function will query local cache data first, before send request
|
|
* to HuggingFace to prevent unnecessary requests.
|
|
*
|
|
* @param modelHandle The model handle to fetch and download. E.g: "NousResearch/Hermes-2-Theta-Llama-3-8B-GGUF"
|
|
*/
|
|
const useHfModelFetchAndDownload = () => {
|
|
const downloadModelMutation = useModelDownloadMutation()
|
|
const queryClient = useQueryClient()
|
|
|
|
const fetchData = useCallback(
|
|
async (modelHandle: string): Promise<HuggingFaceRepoData | undefined> => {
|
|
const data = queryClient.getQueryData([
|
|
...fetchHuggingFaceRepoDataQueryKey,
|
|
modelHandle,
|
|
])
|
|
|
|
if (data) return data as HuggingFaceRepoData
|
|
console.debug(`No cache data found for ${modelHandle}`)
|
|
const repoData = await fetchHuggingFaceRepoData(modelHandle)
|
|
await queryClient.setQueryData(
|
|
[...fetchHuggingFaceRepoDataQueryKey, data],
|
|
repoData
|
|
)
|
|
return repoData
|
|
},
|
|
[queryClient]
|
|
)
|
|
|
|
const fetchDataAndDownload = useCallback(
|
|
async (modelHandle: string) => {
|
|
const repoData = await fetchData(modelHandle)
|
|
if (!repoData) {
|
|
console.error(`Could not fetch data for repo ${modelHandle}`)
|
|
toaster({
|
|
title: `Failed to get data`,
|
|
description: `Could not get data for repo ${modelHandle}`,
|
|
type: 'error',
|
|
})
|
|
return
|
|
}
|
|
|
|
const recommendedQuant = 'Q4_K_S'
|
|
let recommendedModel = repoData.siblings.find(
|
|
(sibling) =>
|
|
sibling.quantization?.toLowerCase() === recommendedQuant.toLowerCase()
|
|
)
|
|
|
|
if (!recommendedModel) {
|
|
console.debug('Q4_K_S model not found. Try with smallest model')
|
|
// get filesize min from repoData.siblings
|
|
|
|
repoData.siblings
|
|
.filter((sibling) => {
|
|
sibling.fileSize != null && sibling.quantization != null
|
|
})
|
|
.sort((a, b) => a.fileSize! - b.fileSize!)
|
|
recommendedModel = repoData.siblings[0]
|
|
console.debug('Min size recommended model:', recommendedModel)
|
|
}
|
|
|
|
if (!recommendedModel) {
|
|
toaster({
|
|
title: `Failed to get recommended model`,
|
|
description: `Could not get recommended model for repo ${modelHandle}. Please open the details page and select model manually!`,
|
|
type: 'error',
|
|
})
|
|
return
|
|
}
|
|
|
|
const persistModelId = modelHandle
|
|
.replaceAll('/', '_')
|
|
.concat('_')
|
|
.concat(recommendedModel.rfilename)
|
|
|
|
downloadModelMutation.mutate({
|
|
modelId: modelHandle,
|
|
fileName: recommendedModel.rfilename,
|
|
persistedModelId: persistModelId,
|
|
})
|
|
},
|
|
|
|
[fetchData, downloadModelMutation]
|
|
)
|
|
|
|
return { fetchDataAndDownload }
|
|
}
|
|
|
|
export default useHfModelFetchAndDownload
|