jan/web/hooks/useHfModelFetchAndDownload.ts
NamH 26be941e84
fix: error while importing local model is not shown (#3294)
* 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>
2024-08-07 17:55:01 +07:00

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