File size: 5,700 Bytes
e7ba29d ad5cef3 e7ba29d 6ebf2fd ad5cef3 6ebf2fd 4d810fa 6ebf2fd e7ba29d 4d810fa e7ba29d 4d810fa e7ba29d 6ebf2fd ad5cef3 e7ba29d ad5cef3 e7ba29d ad5cef3 6ebf2fd 4d810fa ad5cef3 6ebf2fd 322c234 6ebf2fd ad5cef3 6ebf2fd 322c234 6ebf2fd e7ba29d 6ebf2fd ad5cef3 6ebf2fd ad5cef3 6ebf2fd ad5cef3 6ebf2fd ad5cef3 6ebf2fd ad5cef3 6ebf2fd ad5cef3 6ebf2fd e7ba29d 6ebf2fd ad5cef3 6ebf2fd ad5cef3 6ebf2fd 322c234 6ebf2fd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
import {
Bot,
Heart,
Download,
Cpu,
DatabaseIcon,
CheckCircle,
XCircle,
ExternalLink
} from 'lucide-react'
import { getModelSize } from '../lib/huggingface'
import { useModel } from '../contexts/ModelContext'
import ModelLoader from './ModelLoader'
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 {
models,
modelInfo,
selectedQuantization,
isFetching
} = useModel()
const ModelInfoSkeleton = () => (
<div className="mt-5 bg-gradient-to-r from-blue-50 to-indigo-50 px-4 py-3 rounded-lg border border-blue-200 space-y-4 h-full min-h-[160px] animate-pulse w-[400px]">
<div className="flex items-center space-x-2">
<Bot className="w-4 h-4 text-blue-300" />
<div className="h-4 bg-gray-300 rounded w-48"></div>
<div className="w-4 h-4 bg-gray-300 rounded-full"></div>
</div>
<div className="flex items-center space-x-2 ml-6">
<div className="h-3 bg-gray-200 rounded w-32"></div>
</div>
<div className="flex items-center justify-self-end space-x-4">
<div className="flex items-center space-x-1">
<Heart className="w-3 h-3 text-red-300" />
<div className="h-3 bg-gray-200 rounded w-8"></div>
</div>
<div className="flex items-center space-x-1">
<Download className="w-3 h-3 text-green-300" />
<div className="h-3 bg-gray-200 rounded w-8"></div>
</div>
<div className="flex items-center space-x-1">
<Cpu className="w-3 h-3 text-purple-300" />
<div className="h-3 bg-gray-200 rounded w-8"></div>
</div>
<div className="flex items-center space-x-1">
<DatabaseIcon className="w-3 h-3 text-purple-300" />
<div className="h-3 bg-gray-200 rounded w-12"></div>
</div>
</div>
<hr className="border-gray-200" />
<div className="h-8 bg-gray-200 rounded w-full"></div>
</div>
)
if (!modelInfo || isFetching || models.length === 0) {
return <ModelInfoSkeleton />
}
return (
<div className="mt-5 bg-gradient-to-r from-blue-50 to-indigo-50 px-4 py-3 rounded-lg border border-blue-200 space-y-3 h-full min-h-[150px]">
{/* Model Name Row */}
<div className="flex items-center space-x-2">
<Bot className="w-4 h-4 text-blue-600" />
<a
href={`https://huggingface.co/${modelInfo.name}`}
target="_blank"
rel="noopener noreferrer"
className="text-sm font-medium text-gray-700 truncate max-w-80 hover:underline"
title={modelInfo.name}
>
<ExternalLink className="w-3 h-3 inline-block mr-1" />
{modelInfo.name}
</a>
{/* Compatibility Status */}
{typeof modelInfo.isCompatible === 'boolean' && (
<div className="flex items-center space-x-1">
{modelInfo.isCompatible ? (
<>
<CheckCircle className="w-4 h-4 text-green-500" />
</>
) : (
<>
<XCircle className="w-4 h-4 text-red-500" />
</>
)}
</div>
)}
</div>
{/* Base Model Link */}
{modelInfo.baseId && (
<div className="flex items-center space-x-2 ml-6 text-xs text-gray-600 truncate max-w-100">
<a
href={`https://huggingface.co/${modelInfo.baseId}`}
target="_blank"
rel="noopener noreferrer"
className=" hover:underline"
title={`Base model: ${modelInfo.baseId}`}
>
<ExternalLink className="w-3 h-3 inline-block mr-1" />
({modelInfo.baseId})
</a>
</div>
)}
{/* Stats Row */}
<div className="flex items-center justify-self-end space-x-4 text-xs text-gray-600">
{modelInfo.likes > 0 && (
<div className="flex items-center space-x-1">
<Heart className="w-3 h-3 text-red-500" />
<span>{formatNumber(modelInfo.likes)}</span>
</div>
)}
{modelInfo.downloads > 0 && (
<div className="flex items-center space-x-1">
<Download className="w-3 h-3 text-green-500" />
<span>{formatNumber(modelInfo.downloads)}</span>
</div>
)}
<div className="flex items-center space-x-1">
<Cpu className="w-3 h-3 text-purple-500" />
{modelInfo.parameters ? (
<span>{formatNumber(modelInfo.parameters)}</span>
) : (
<span>?</span>
)}
</div>
<div className="flex items-center space-x-1">
<DatabaseIcon className="w-3 h-3 text-purple-500" />
{modelInfo.parameters ? (
<span>
{`~${getModelSize(
modelInfo.parameters,
selectedQuantization
).toFixed(1)}MB`}
</span>
) : (
<span>?</span>
)}
</div>
</div>
<ModelLoader />
{/* Incompatibility Message */}
{modelInfo.isCompatible === false && modelInfo.incompatibilityReason && (
<div className="bg-red-50 border border-red-200 rounded-md px-3 py-2">
<p className="text-sm text-red-700 whitespace-break-spaces">
{modelInfo.incompatibilityReason}
</p>
</div>
)}
</div>
)
}
export default ModelInfo
|