negoptimAi / frontend /src /components /TokenUsageDisplay.tsx
samir12321's picture
Initial commit: Negoptim AI RAG chatbot (backend + frontend + deploy config)
af404c9
Raw
History Blame Contribute Delete
3.04 kB
import { TokenUsage } from "@/types/chat";
interface Props {
tokenUsage: TokenUsage;
modelUsed: string;
primaryModel?: string;
}
const MODEL_LABELS: Record<string, string> = {
"llama-3.1-8b-instant": "Llama 3.1 · 8B",
"llama-3.3-70b-versatile": "Llama 3.3 · 70B",
"mixtral-8x7b-32768": "Mixtral · 8×7B",
"gemma2-9b-it": "Gemma 2 · 9B",
};
function shortLabel(model: string): string {
return MODEL_LABELS[model] ?? model.split("-").slice(0, 3).join("-");
}
export default function TokenUsageDisplay({ tokenUsage, modelUsed, primaryModel }: Props) {
const isFallback = primaryModel && modelUsed !== primaryModel;
const { prompt_tokens, completion_tokens, total_tokens } = tokenUsage;
// Ratio bar: completion vs prompt (capped at 100%)
const ratio = total_tokens > 0 ? Math.min((completion_tokens / total_tokens) * 100, 100) : 0;
return (
<div className="flex items-center gap-3 mt-2.5 flex-wrap">
{/* Model badge */}
<div className={`flex items-center gap-1.5 rounded-full border px-2.5 py-0.5 ${
isFallback
? "border-amber-200 bg-amber-50 text-amber-600"
: "border-[#E8EDF2] bg-[#F8FAFC] text-[#64748B]"
}`}>
{isFallback ? (
<svg width="9" height="9" viewBox="0 0 10 10" fill="none" className="flex-shrink-0">
<path d="M5 1v4l2.5 1.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
<circle cx="5" cy="5" r="4" stroke="currentColor" strokeWidth="1.2"/>
</svg>
) : (
<svg width="9" height="9" viewBox="0 0 10 10" fill="currentColor" className="flex-shrink-0 opacity-60">
<circle cx="5" cy="5" r="3"/>
</svg>
)}
<span className="text-[10px] font-semibold leading-none">
{shortLabel(modelUsed)}
</span>
{isFallback && (
<span className="text-[9px] font-medium uppercase tracking-wider opacity-70 leading-none">
fallback
</span>
)}
</div>
{/* Token breakdown */}
<div className="flex items-center gap-1.5">
{/* Mini bar */}
<div className="w-12 h-1.5 rounded-full bg-[#E8EDF2] overflow-hidden">
<div
className="h-full rounded-full bg-gradient-to-r from-[#47C3A6] to-[#14B7CC]"
style={{ width: `${ratio}%` }}
/>
</div>
<span className="text-[10px] text-[#94A3B8] font-mono tabular-nums">
<span title="Prompt tokens" className="text-[#94A3B8]">{prompt_tokens.toLocaleString()}</span>
<span className="text-[#CBD5E1] mx-0.5">+</span>
<span title="Completion tokens" className="text-[#47C3A6]">{completion_tokens.toLocaleString()}</span>
<span className="text-[#CBD5E1] mx-1">·</span>
<span title="Total tokens" className="font-semibold text-[#64748B]">{total_tokens.toLocaleString()}</span>
<span className="text-[#CBD5E1] ml-0.5">tok</span>
</span>
</div>
</div>
);
}