import { Bot, Heart, Download, Cpu, DatabaseIcon, CheckCircle, XCircle, ExternalLink, ChevronDown } from 'lucide-react' import { getModelSize } from '../lib/huggingface' import { useModel } from '../contexts/ModelContext' import { useEffect, useCallback } from 'react' import { QuantizationType, WorkerMessage } from '../types' import { getWorker } from '../lib/workerManager' const ModelInfo = () => { const formatNumber = (num: number) => { if (num >= 1000000000) { return (num / 1000000000).toFixed(1) + 'B' } else if (num >= 1000000) { return (num / 1000000).toFixed(1) + 'M' } else if (num >= 1000) { return (num / 1000).toFixed(1) + 'K' } return num.toString() } const { modelInfo, selectedQuantization, setSelectedQuantization, status, setStatus, setProgress, activeWorker, setActiveWorker, pipeline, workerLoaded, setWorkerLoaded } = useModel() useEffect(() => { if (modelInfo.isCompatible && modelInfo.supportedQuantizations.length > 0) { const quantizations = modelInfo.supportedQuantizations let defaultQuant: QuantizationType = 'fp32' if (quantizations.includes('int8')) { defaultQuant = 'int8' } else if (quantizations.includes('q8')) { defaultQuant = 'q8' } else if (quantizations.includes('q4')) { defaultQuant = 'q4' } setSelectedQuantization(defaultQuant) } }, [ modelInfo.supportedQuantizations, modelInfo.isCompatible, setSelectedQuantization ]) useEffect(() => { const newWorker = getWorker(pipeline) if (!newWorker) { return } setStatus('idle') setWorkerLoaded(false) setActiveWorker(newWorker) const onMessageReceived = (e: MessageEvent) => { const { status, output } = e.data if (status === 'initiate') { setStatus('loading') } else if (status === 'ready') { setStatus('ready') setWorkerLoaded(true) } else if (status === 'progress' && output) { setStatus('progress') if ( output.progress && typeof output.file === 'string' && output.file.startsWith('onnx') ) { setProgress(output.progress) } } } newWorker.addEventListener('message', onMessageReceived) return () => { newWorker.removeEventListener('message', onMessageReceived) // terminateWorker(pipeline); } }, [pipeline, selectedQuantization, setActiveWorker, setStatus, setProgress, setWorkerLoaded]) const loadModel = useCallback(() => { if (!modelInfo.name || !selectedQuantization) return setStatus('loading') const message = { type: 'load', model: modelInfo.name, quantization: selectedQuantization } activeWorker?.postMessage(message) }, [modelInfo.name, selectedQuantization, setStatus, activeWorker]) const busy: boolean = status !== 'idle' if (!modelInfo.name) { return null } return (
{/* Model Name Row */}
{modelInfo.name} {/* Compatibility Status */} {typeof modelInfo.isCompatible === 'boolean' && (
{modelInfo.isCompatible ? ( <> ) : ( <> )}
)}
{/* Base Model Link */} {modelInfo.baseId && (
{modelInfo.baseId}
)} {/* Stats Row */}
{modelInfo.likes > 0 && (
{formatNumber(modelInfo.likes)}
)} {modelInfo.downloads > 0 && (
{formatNumber(modelInfo.downloads)}
)} {modelInfo.parameters > 0 && (
{formatNumber(modelInfo.parameters)}
)} {modelInfo.parameters > 0 && (
{`~${getModelSize( modelInfo.parameters, selectedQuantization ).toFixed(1)}MB`}
)}
{/* Separator */} {modelInfo.isCompatible && modelInfo.supportedQuantizations.length > 0 && (
)} {/* Quantization Dropdown */} {modelInfo.isCompatible && modelInfo.supportedQuantizations.length > 0 && (
Quantization:
)} {/* Load Model Button */} {modelInfo.isCompatible && selectedQuantization && (
)} {/* Incompatibility Message */} {modelInfo.isCompatible === false && modelInfo.incompatibilityReason && (

Incompatible:{' '} {modelInfo.incompatibilityReason}

)}
) } export default ModelInfo