Vokturz's picture
Add error handling and message improvements
63dbafb
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'
import Tooltip from './Tooltip'
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,
status,
modelInfo,
selectedQuantization,
isFetching,
errorText
} = useModel()
const ModelInfoSkeleton = () => (
<div className="bg-gradient-to-r from-secondary to-accent px-3 py-3 rounded-lg border border-border space-y-3 animate-pulse w-4/5">
<div className="flex items-center space-x-2">
<Bot className="w-4 h-4 text-green-500" />
<div className="h-4 bg-muted rounded-sm flex-1"></div>
<div className="w-4 h-4 bg-muted rounded-full"></div>
</div>
<div className="flex items-center space-x-2 ml-6">
<div className="h-3 bg-muted/80 rounded-sm w-32"></div>
</div>
<div className="grid grid-cols-2 gap-2 text-xs">
<div className="flex items-center space-x-1">
<Heart className="w-3 h-3 text-destructive/60" />
<div className="h-3 bg-muted/80 rounded-sm w-8"></div>
</div>
<div className="flex items-center space-x-1">
<Download className="w-3 h-3 text-purple-500" />
<div className="h-3 bg-muted/80 rounded-sm w-8"></div>
</div>
<div className="flex items-center space-x-1">
<Cpu className="w-3 h-3 text-chart-4/60" />
<div className="h-3 bg-muted/80 rounded-sm w-8"></div>
</div>
<div className="flex items-center space-x-1">
<DatabaseIcon className="w-3 h-3 text-purple-500" />
<div className="h-3 bg-muted/80 rounded-sm w-12"></div>
</div>
</div>
<hr className="border-border" />
<div className="h-8 bg-muted/80 rounded-sm w-full"></div>
</div>
)
if (!modelInfo || isFetching || models.length === 0) {
return <ModelInfoSkeleton />
}
return (
<div className="relative bg-gradient-to-r from-secondary to-accent px-3 py-3 rounded-lg border border-border space-y-3 h-full w-4/5">
{/* Model Name Row */}
<div className="flex justify-center items-center space-x-2">
{/* Compatibility Status */}
{typeof modelInfo.isCompatible === 'boolean' && (
<div className="shrink-0 ">
{modelInfo.isCompatible && status !== 'error' ? (
<CheckCircle className="w-4 h-4 text-green-500" />
) : (
<XCircle className="w-4 h-4 text-destructive" />
)}
</div>
)}
<div className="flex-1 min-w-0">
<a
href={`https://huggingface.co/${modelInfo.name}`}
target="_blank"
rel="noopener noreferrer"
className="text-sm font-medium text-foreground/80 hover:underline block truncate"
title={modelInfo.name}
>
<ExternalLink className="w-3 h-3 inline-block mr-1" />
{modelInfo.name}
</a>
{/* Base Model Link */}
{modelInfo.baseId && modelInfo.baseId !== modelInfo.id && (
<a
href={`https://huggingface.co/${modelInfo.baseId}`}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-muted-foreground hover:underline block truncate mt-1"
title={`Base model: ${modelInfo.baseId}`}
>
<ExternalLink className="w-3 h-3 inline-block mr-1" />(
{modelInfo.baseId})
</a>
)}
</div>
</div>
{/* Stats Grid */}
<div className="grid grid-cols-2 gap-2 text-xs text-muted-foreground">
{modelInfo.likes > 0 && (
<div className="flex items-center space-x-1">
<Heart className="w-3 h-3 text-destructive" />
<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>
)}
<Tooltip content="Model parameters according to Hugging Face API">
<div className="flex items-center space-x-1 cursor-default">
<Cpu className="w-3 h-3 text-purple-500" />
{modelInfo.parameters ? (
<span>{formatNumber(modelInfo.parameters)}</span>
) : (
<span>?</span>
)}
</div>
</Tooltip>
<Tooltip
content={`Estimated size with ${selectedQuantization} quantization`}
>
<div className="flex items-center space-x-1 cursor-default">
<DatabaseIcon className="w-3 h-3 text-purple-500" />
{modelInfo.parameters ? (
<span>
{`~${getModelSize(
modelInfo.parameters,
selectedQuantization
).toFixed(1)}MB`}
</span>
) : (
<span>?</span>
)}
</div>
</Tooltip>
</div>
<ModelLoader />
{/* Incompatibility Message */}
{((modelInfo.isCompatible === false && modelInfo.incompatibilityReason) ||
errorText) && (
<div className="bg-destructive/10 border border-destructive/20 rounded-md px-2 py-2">
<p className="text-xs text-destructive whitespace-break-spaces">
{errorText ? errorText : modelInfo.incompatibilityReason}
</p>
</div>
)}
</div>
)
}
export default ModelInfo