jan/web/hooks/useConvertHuggingFaceModel.ts
Helloyunho e86cd7e661
feat: add a simple way to convert Hugging Face model to GGUF (#1972)
* chore: add react developer tools to electron

* feat: add small convert modal

* feat: separate modals and add hugging face extension

* feat: fully implement hugging face converter

* fix: forgot to uncomment this...

* fix: typo

* feat: try hf-to-gguf script first and then use convert.py

HF-to-GGUF has support for some unusual models
maybe using convert.py first would be better but we can change the usage order later

* fix: pre-install directory changed

* fix: sometimes exit code is undefined

* chore: download additional files for qwen

* fix: event handling changed

* chore: add one more necessary package

* feat: download gguf-py from llama.cpp

* fix: cannot interpret wildcards on GNU tar

Co-authored-by: hiento09 <136591877+hiento09@users.noreply.github.com>

---------

Co-authored-by: hiento09 <136591877+hiento09@users.noreply.github.com>
2024-02-26 10:57:53 +07:00

82 lines
2.3 KiB
TypeScript

import { useContext } from 'react'
import {
ExtensionTypeEnum,
HuggingFaceExtension,
HuggingFaceRepoData,
Quantization,
} from '@janhq/core'
import { useSetAtom } from 'jotai'
import { FeatureToggleContext } from '@/context/FeatureToggle'
import { extensionManager } from '@/extension/ExtensionManager'
import {
conversionStatusAtom,
conversionErrorAtom,
} from '@/helpers/atoms/HFConverter.atom'
export const useConvertHuggingFaceModel = () => {
const { ignoreSSL, proxy } = useContext(FeatureToggleContext)
const setConversionStatus = useSetAtom(conversionStatusAtom)
const setConversionError = useSetAtom(conversionErrorAtom)
const convertHuggingFaceModel = async (
repoID: string,
repoData: HuggingFaceRepoData,
quantization: Quantization
) => {
const extension = await extensionManager.get<HuggingFaceExtension>(
ExtensionTypeEnum.HuggingFace
)
try {
if (extension) {
extension.interrupted = false
}
setConversionStatus('downloading')
await extension?.downloadModelFiles(repoID, repoData, {
ignoreSSL,
proxy,
})
if (extension?.interrupted) return
setConversionStatus('converting')
await extension?.convert(repoID)
if (extension?.interrupted) return
setConversionStatus('quantizing')
await extension?.quantize(repoID, quantization)
if (extension?.interrupted) return
setConversionStatus('generating')
await extension?.generateMetadata(repoID, repoData, quantization)
setConversionStatus('done')
} catch (err) {
if (extension?.interrupted) return
extension?.cancelConvert(repoID, repoData)
if (typeof err === 'number') {
setConversionError(new Error(`exit code: ${err}`))
} else {
setConversionError(err as Error)
}
console.error(err)
}
}
const cancelConvertHuggingFaceModel = async (
repoID: string,
repoData: HuggingFaceRepoData
) => {
const extension = await extensionManager.get<HuggingFaceExtension>(
ExtensionTypeEnum.HuggingFace
)
setConversionStatus('stopping')
await extension?.cancelConvert(repoID, repoData)
setConversionStatus(null)
}
return {
convertHuggingFaceModel,
cancelConvertHuggingFaceModel,
}
}