@tokcalc/mcp-server 0.1.3 → 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -406
- package/dist/http.js +23504 -0
- package/dist/index.js +21290 -0
- package/package.json +36 -92
- package/.zscripts/build.sh +0 -175
- package/.zscripts/database-runtime-build.sh +0 -33
- package/.zscripts/dev.pid +0 -1
- package/.zscripts/dev.sh +0 -154
- package/.zscripts/mini-services-build.sh +0 -78
- package/.zscripts/mini-services-install.sh +0 -65
- package/.zscripts/mini-services-start.sh +0 -123
- package/.zscripts/python-runtime-build.sh +0 -120
- package/.zscripts/start.sh +0 -145
- package/CAPACITY_STUDY.md +0 -283
- package/CODE_OF_CONDUCT.md +0 -55
- package/CONTRIBUTING.md +0 -177
- package/Caddyfile +0 -23
- package/LICENSE +0 -204
- package/bun.lock +0 -1965
- package/components.json +0 -21
- package/db/custom.db +0 -0
- package/download/README.md +0 -1
- package/download/tokcalc-dark-calculator.png +0 -0
- package/download/tokcalc-dark-default.png +0 -0
- package/download/tokcalc-demo.webm +0 -0
- package/download/tokcalc-github-link.png +0 -0
- package/download/tokcalc-hydration-fixed.png +0 -0
- package/download/tokcalc-issue-resolved.png +0 -0
- package/download/tokcalc-light-mode.png +0 -0
- package/download/tokcalc-light-reference.png +0 -0
- package/download/tokcalc-long-context-qwen.png +0 -0
- package/download/tokcalc-long-context.png +0 -0
- package/download/tokcalc-og-image-preview.png +0 -0
- package/download/tokcalc-phase2-3.png +0 -0
- package/download/tokcalc-plain-english.png +0 -0
- package/download/tokcalc-preview.png +0 -0
- package/download/tokcalc-share-bvb.png +0 -0
- package/download/tokcalc-share-feature.png +0 -0
- package/download/tokcalc-tab-build-vs-buy.png +0 -0
- package/download/tokcalc-tab-calculator.png +0 -0
- package/download/tokcalc-tab-reference.png +0 -0
- package/eslint.config.mjs +0 -50
- package/examples/websocket/frontend.tsx +0 -196
- package/examples/websocket/server.ts +0 -138
- package/mini-services/.gitkeep +0 -0
- package/mini-services/mcp-server/README.md +0 -86
- package/mini-services/mcp-server/bun.lock +0 -202
- package/mini-services/mcp-server/index.ts +0 -504
- package/mini-services/mcp-server/package.json +0 -40
- package/next.config.ts +0 -12
- package/postcss.config.mjs +0 -5
- package/prisma/schema.prisma +0 -32
- package/public/google6f58ca6be85fa903.html +0 -1
- package/public/logo.svg +0 -29
- package/public/manifest.json +0 -51
- package/public/og-icon-256.png +0 -0
- package/public/og.png +0 -0
- package/public/robots.txt +0 -25
- package/public/sitemap.xml +0 -23
- package/public/tokcalc-demo.gif +0 -0
- package/scripts/og-template.html +0 -120
- package/scripts/render-og.mjs +0 -43
- package/server.json +0 -21
- package/src/app/api/pricing/aws/route.ts +0 -186
- package/src/app/api/pricing/azure/route.ts +0 -168
- package/src/app/api/pricing/gcp/route.ts +0 -230
- package/src/app/api/pricing/vast-ai/route.ts +0 -164
- package/src/app/api/route.ts +0 -5
- package/src/app/compare/h100-vs-h200/layout.tsx +0 -30
- package/src/app/compare/h100-vs-h200/page.tsx +0 -328
- package/src/app/globals.css +0 -122
- package/src/app/layout.tsx +0 -276
- package/src/app/page.tsx +0 -2670
- package/src/components/azure-live-pricing.tsx +0 -185
- package/src/components/benchmark-import.tsx +0 -340
- package/src/components/confidence-badge.tsx +0 -116
- package/src/components/live-pricing-comparison.tsx +0 -241
- package/src/components/theme-provider.tsx +0 -11
- package/src/components/theme-toggle.tsx +0 -55
- package/src/components/ui/accordion.tsx +0 -66
- package/src/components/ui/alert-dialog.tsx +0 -157
- package/src/components/ui/alert.tsx +0 -66
- package/src/components/ui/aspect-ratio.tsx +0 -11
- package/src/components/ui/avatar.tsx +0 -53
- package/src/components/ui/badge.tsx +0 -46
- package/src/components/ui/breadcrumb.tsx +0 -109
- package/src/components/ui/button.tsx +0 -59
- package/src/components/ui/calendar.tsx +0 -213
- package/src/components/ui/card.tsx +0 -92
- package/src/components/ui/carousel.tsx +0 -241
- package/src/components/ui/chart.tsx +0 -353
- package/src/components/ui/checkbox.tsx +0 -32
- package/src/components/ui/collapsible.tsx +0 -33
- package/src/components/ui/command.tsx +0 -184
- package/src/components/ui/context-menu.tsx +0 -252
- package/src/components/ui/dialog.tsx +0 -143
- package/src/components/ui/drawer.tsx +0 -135
- package/src/components/ui/dropdown-menu.tsx +0 -257
- package/src/components/ui/form.tsx +0 -167
- package/src/components/ui/hover-card.tsx +0 -44
- package/src/components/ui/input-otp.tsx +0 -77
- package/src/components/ui/input.tsx +0 -21
- package/src/components/ui/label.tsx +0 -24
- package/src/components/ui/menubar.tsx +0 -276
- package/src/components/ui/navigation-menu.tsx +0 -168
- package/src/components/ui/pagination.tsx +0 -127
- package/src/components/ui/popover.tsx +0 -48
- package/src/components/ui/progress.tsx +0 -31
- package/src/components/ui/radio-group.tsx +0 -45
- package/src/components/ui/resizable.tsx +0 -56
- package/src/components/ui/scroll-area.tsx +0 -58
- package/src/components/ui/select.tsx +0 -185
- package/src/components/ui/separator.tsx +0 -28
- package/src/components/ui/sheet.tsx +0 -139
- package/src/components/ui/sidebar.tsx +0 -726
- package/src/components/ui/skeleton.tsx +0 -13
- package/src/components/ui/slider.tsx +0 -63
- package/src/components/ui/sonner.tsx +0 -25
- package/src/components/ui/switch.tsx +0 -31
- package/src/components/ui/table.tsx +0 -116
- package/src/components/ui/tabs.tsx +0 -66
- package/src/components/ui/textarea.tsx +0 -18
- package/src/components/ui/toast.tsx +0 -129
- package/src/components/ui/toaster.tsx +0 -35
- package/src/components/ui/toggle-group.tsx +0 -73
- package/src/components/ui/toggle.tsx +0 -47
- package/src/components/ui/tooltip.tsx +0 -61
- package/src/components/vast-ai-live-pricing.tsx +0 -176
- package/src/hooks/use-mobile.ts +0 -19
- package/src/hooks/use-toast.ts +0 -194
- package/src/lib/benchmark-parser-sglang.ts +0 -150
- package/src/lib/benchmark-parser-tokcalc.ts +0 -247
- package/src/lib/benchmark-parser-trtllm.ts +0 -152
- package/src/lib/benchmark-parser-vllm.ts +0 -198
- package/src/lib/benchmark-schema.ts +0 -263
- package/src/lib/db.ts +0 -13
- package/src/lib/engine-presets.ts +0 -183
- package/src/lib/price-schema.ts +0 -141
- package/src/lib/token-calc.ts +0 -808
- package/src/lib/track.ts +0 -31
- package/src/lib/url-state.ts +0 -256
- package/src/lib/utils.ts +0 -6
- package/tailwind.config.ts +0 -64
- package/tests/database-runtime-build.sh +0 -75
- package/tests/python-runtime-build.sh +0 -64
- package/tests/python-runtime-container.sh +0 -31
- package/tool-results/bash_1789888171144_2c5381860539.txt +0 -161
- package/tool-results/bash_1789888175925_49c53ba3c61b.txt +0 -191
- package/tool-results/bash_1789888181202_49c53ba3c61b.txt +0 -191
- package/tool-results/bash_1789888195219_4a86a5c91411.txt +0 -200
- package/tool-results/bash_1789888203128_6cca13c71b47.txt +0 -199
- package/tool-results/bash_1789929256963_2a52aff0d0a8.txt +0 -160
- package/tool-results/read_1789888151021_69f58eec6a5b.txt +0 -653
- package/tool-results/read_1789888153837_1d3a8bfc2a94.txt +0 -653
- package/tool-results/read_1789888163087_ccc406d47505.txt +0 -122
- package/tool-results/read_1789888167347_67d1d7c9830a.txt +0 -122
- package/tool-results/read_1789929252529_d90e8f383a25.txt +0 -285
- package/tsconfig.json +0 -42
- package/upload/Pasted Content_1789887800864.txt +0 -652
- package/upload/Pasted Content_1789887909561.txt +0 -652
- package/upload/Pasted Content_1789887918428.txt +0 -652
- package/upload/Pasted Content_1789887959420.txt +0 -652
- package/upload/Pasted Content_1789888020485.txt +0 -652
- package/upload/Pasted Content_1789888058079.txt +0 -652
- package/upload/Pasted Content_1789888885033.txt +0 -686
- package/upload/Pasted Content_1789928912741.txt +0 -285
- package/upload/Pasted Content_1789928938402.txt +0 -285
- package/upload/Pasted Content_1789929160389.txt +0 -285
- package/upload/Pasted Content_1789929176660.txt +0 -285
- package/upload/issue_vision.json +0 -28
- package/upload/pasted_image_1789883175209.png +0 -0
- package/upload/pasted_image_1789899056690.png +0 -0
- package/upload/pasted_image_1789900371483.png +0 -0
- package/upload/pasted_image_1789900472823.png +0 -0
- package/upload/pasted_image_1789900490374.png +0 -0
- package/upload/pasted_image_1789900585552.png +0 -0
- package/upload/pasted_image_1789900606519.png +0 -0
- package/upload/pasted_image_1789901598705.png +0 -0
- package/upload/pasted_image_1789901613545.png +0 -0
- package/upload/pasted_image_1789978382674.png +0 -0
- package/upload/pasted_image_1789978392749.png +0 -0
- package/upload/pasted_image_1789978474879.png +0 -0
- package/upload/pasted_image_1789978523652.png +0 -0
- package/upload/pasted_image_1789984219089.png +0 -0
- package/upload/pasted_image_1789984491896.png +0 -0
- package/upload/pasted_image_1789985017950.png +0 -0
- package/upload/pasted_image_1789985036765.png +0 -0
- package/upload/pasted_image_1789985049848.png +0 -0
- package/upload/pasted_image_1790002427833.png +0 -0
- package/upload/pasted_image_1790002659944.png +0 -0
- package/upload/pasted_image_1790037038476.png +0 -0
- package/upload/screenshot_analysis.json +0 -28
- package/upload/vision_output.json +0 -28
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useMemo, useState } from "react";
|
|
4
|
-
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
|
5
|
-
import { Badge } from "@/components/ui/badge";
|
|
6
|
-
import { Button } from "@/components/ui/button";
|
|
7
|
-
import { ArrowLeft, Cpu, Zap, DollarSign, MemoryStick, Gauge } from "lucide-react";
|
|
8
|
-
import {
|
|
9
|
-
calculate,
|
|
10
|
-
fmtTokens,
|
|
11
|
-
fmtBytes,
|
|
12
|
-
fmtMs,
|
|
13
|
-
fmtMoney,
|
|
14
|
-
GPU_MAP,
|
|
15
|
-
MODELS,
|
|
16
|
-
QUANT_MAP,
|
|
17
|
-
type Quantization,
|
|
18
|
-
} from "@/lib/token-calc";
|
|
19
|
-
import { ConfidenceDot } from "@/components/confidence-badge";
|
|
20
|
-
import {
|
|
21
|
-
Bar,
|
|
22
|
-
BarChart,
|
|
23
|
-
CartesianGrid,
|
|
24
|
-
ResponsiveContainer,
|
|
25
|
-
XAxis,
|
|
26
|
-
YAxis,
|
|
27
|
-
Tooltip,
|
|
28
|
-
Bar as BarChartBar,
|
|
29
|
-
} from "recharts";
|
|
30
|
-
import Link from "next/link";
|
|
31
|
-
|
|
32
|
-
const MODEL_ID = "llama3-3-70b";
|
|
33
|
-
const QUANT: Quantization = "fp8";
|
|
34
|
-
|
|
35
|
-
const H100 = GPU_MAP["h100-sxm"];
|
|
36
|
-
const H200 = GPU_MAP["h200-sxm"];
|
|
37
|
-
const model = MODELS.find((m) => m.id === MODEL_ID)!;
|
|
38
|
-
const quant = QUANT_MAP[QUANT];
|
|
39
|
-
|
|
40
|
-
function calcForGpu(gpuId: string, gpuCount: number, contextTokens: number) {
|
|
41
|
-
return calculate({
|
|
42
|
-
modelId: MODEL_ID,
|
|
43
|
-
gpuId,
|
|
44
|
-
quantization: QUANT,
|
|
45
|
-
numGpus: gpuCount,
|
|
46
|
-
batchSize: 8,
|
|
47
|
-
promptTokens: contextTokens,
|
|
48
|
-
outputTokens: 500,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const SPEC_ROWS = [
|
|
53
|
-
{ label: "VRAM", h100: "80 GB HBM3", h200: "141 GB HBM3e", winner: "h200" },
|
|
54
|
-
{ label: "Memory bandwidth", h100: "3,350 GB/s", h200: "4,800 GB/s", winner: "h200" },
|
|
55
|
-
{ label: "FP16/BF16 dense TFLOPS", h100: "990 TF", h200: "990 TF", winner: "tie" },
|
|
56
|
-
{ label: "FP8 support", h100: "Native", h200: "Native", winner: "tie" },
|
|
57
|
-
{ label: "NVLink bandwidth", h100: "900 GB/s", h200: "900 GB/s", winner: "tie" },
|
|
58
|
-
{ label: "Typical cloud price", h100: "~$2.50/hr", h200: "~$4.00/hr", winner: "h100" },
|
|
59
|
-
{ label: "Release year", h100: "2022", h200: "2024", winner: "h200" },
|
|
60
|
-
{ label: "TDP (power)", h100: "700W", h200: "700W", winner: "tie" },
|
|
61
|
-
];
|
|
62
|
-
|
|
63
|
-
export default function H100vsH200Page() {
|
|
64
|
-
const [context, setContext] = useState(50000);
|
|
65
|
-
const [gpuCount, setGpuCount] = useState(2);
|
|
66
|
-
|
|
67
|
-
const h100Result = useMemo(() => calcForGpu("h100-sxm", gpuCount, context), [gpuCount, context]);
|
|
68
|
-
const h200Result = useMemo(() => calcForGpu("h200-sxm", gpuCount, context), [gpuCount, context]);
|
|
69
|
-
|
|
70
|
-
const chartData = useMemo(() => {
|
|
71
|
-
const ctxs = [4096, 8192, 16384, 32768, 65536, 131072];
|
|
72
|
-
return ctxs.map((ctx) => ({
|
|
73
|
-
context: `${ctx / 1000}K`,
|
|
74
|
-
h100: Math.max(0, Math.round(calcForGpu("h100-sxm", gpuCount, ctx).aggregateTokensPerSec)),
|
|
75
|
-
h200: Math.max(0, Math.round(calcForGpu("h200-sxm", gpuCount, ctx).aggregateTokensPerSec)),
|
|
76
|
-
}));
|
|
77
|
-
}, [gpuCount]);
|
|
78
|
-
|
|
79
|
-
const chartConcurrency = useMemo(() => {
|
|
80
|
-
const ctxs = [4096, 8192, 16384, 32768, 65536, 131072];
|
|
81
|
-
return ctxs.map((ctx) => {
|
|
82
|
-
const r1 = calcForGpu("h100-sxm", gpuCount, ctx);
|
|
83
|
-
const r2 = calcForGpu("h200-sxm", gpuCount, ctx);
|
|
84
|
-
return {
|
|
85
|
-
context: `${ctx / 1000}K`,
|
|
86
|
-
h100: r1.vramFits ? Math.floor(((H100!.vramGb * gpuCount) - model.paramsB * quant.bytesPerParam) / (r1.kvCachePerTokenKb * 1024 / 1e6 / ctx)) : 0,
|
|
87
|
-
h200: r2.vramFits ? Math.floor(((H200!.vramGb * gpuCount) - model.paramsB * quant.bytesPerParam) / (r2.kvCachePerTokenKb * 1024 / 1e6 / ctx)) : 0,
|
|
88
|
-
};
|
|
89
|
-
});
|
|
90
|
-
}, [gpuCount]);
|
|
91
|
-
|
|
92
|
-
const shareH100 = `https://tokcalc.vercel.app/#t=calculator&m=${MODEL_ID}&g=h100-sxm&q=${QUANT}&n=${gpuCount}&b=8&p=${context}&o=500&cb=1&cbm=2`;
|
|
93
|
-
const shareH200 = `https://tokcalc.vercel.app/#t=calculator&m=${MODEL_ID}&g=h200-sxm&q=${QUANT}&n=${gpuCount}&b=8&p=${context}&o=500&cb=1&cbm=2`;
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<div className="min-h-screen bg-background text-foreground">
|
|
97
|
-
<div className="max-w-4xl mx-auto px-4 sm:px-6 py-8 sm:py-12">
|
|
98
|
-
<Link href="/" className="inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground mb-6">
|
|
99
|
-
<ArrowLeft className="size-4" />
|
|
100
|
-
Back to tokcalc
|
|
101
|
-
</Link>
|
|
102
|
-
|
|
103
|
-
<h1 className="text-3xl sm:text-4xl font-bold tracking-tight mb-3">
|
|
104
|
-
H100 vs H200 for LLM Inference: <span className="text-emerald-500">Throughput, Latency, VRAM & Cost</span>
|
|
105
|
-
</h1>
|
|
106
|
-
<p className="text-muted-foreground text-sm sm:text-base leading-relaxed mb-8">
|
|
107
|
-
Side-by-side comparison of NVIDIA H100 SXM5 80GB vs H200 SXM5 141GB for serving
|
|
108
|
-
Llama 3.3 70B (FP8). See exactly how context length, VRAM, and bandwidth affect
|
|
109
|
-
your deployment capacity — with transparent formulas, not marketing claims.
|
|
110
|
-
</p>
|
|
111
|
-
|
|
112
|
-
{/* Spec comparison */}
|
|
113
|
-
<Card className="border-border/60 shadow-sm mb-8">
|
|
114
|
-
<CardHeader>
|
|
115
|
-
<CardTitle className="text-base flex items-center gap-2">
|
|
116
|
-
<Cpu className="size-4 text-emerald-500" />
|
|
117
|
-
Specification comparison
|
|
118
|
-
</CardTitle>
|
|
119
|
-
</CardHeader>
|
|
120
|
-
<CardContent className="p-0">
|
|
121
|
-
<table className="w-full text-sm">
|
|
122
|
-
<thead className="bg-muted/40 text-[10px] uppercase">
|
|
123
|
-
<tr>
|
|
124
|
-
<th className="text-left px-4 py-2">Spec</th>
|
|
125
|
-
<th className="text-left px-4 py-2">H100 SXM5</th>
|
|
126
|
-
<th className="text-left px-4 py-2">H200 SXM5</th>
|
|
127
|
-
<th className="text-center px-4 py-2">Winner</th>
|
|
128
|
-
</tr>
|
|
129
|
-
</thead>
|
|
130
|
-
<tbody>
|
|
131
|
-
{SPEC_ROWS.map((row, i) => (
|
|
132
|
-
<tr key={i} className="border-t border-border/40">
|
|
133
|
-
<td className="px-4 py-2 font-medium">{row.label}</td>
|
|
134
|
-
<td className="px-4 py-2 font-mono text-xs">{row.h100}</td>
|
|
135
|
-
<td className="px-4 py-2 font-mono text-xs">{row.h200}</td>
|
|
136
|
-
<td className="px-4 py-2 text-center">
|
|
137
|
-
{row.winner === "h200" && <Badge className="text-[9px] bg-emerald-500">H200</Badge>}
|
|
138
|
-
{row.winner === "h100" && <Badge className="text-[9px] bg-blue-500">H100</Badge>}
|
|
139
|
-
{row.winner === "tie" && <span className="text-[10px] text-muted-foreground">Tie</span>}
|
|
140
|
-
</td>
|
|
141
|
-
</tr>
|
|
142
|
-
))}
|
|
143
|
-
</tbody>
|
|
144
|
-
</table>
|
|
145
|
-
</CardContent>
|
|
146
|
-
</Card>
|
|
147
|
-
|
|
148
|
-
{/* Interactive comparison */}
|
|
149
|
-
<Card className="border-emerald-500/30 shadow-sm mb-8">
|
|
150
|
-
<CardHeader>
|
|
151
|
-
<CardTitle className="text-base flex items-center gap-2">
|
|
152
|
-
<Gauge className="size-4 text-emerald-500" />
|
|
153
|
-
Live comparison — adjust context length & GPU count
|
|
154
|
-
</CardTitle>
|
|
155
|
-
<CardDescription className="text-xs">
|
|
156
|
-
All numbers computed by tokcalc's open-source formulas. Click a config to open the full calculator.
|
|
157
|
-
</CardDescription>
|
|
158
|
-
</CardHeader>
|
|
159
|
-
<CardContent className="space-y-4">
|
|
160
|
-
<div className="flex flex-wrap items-end gap-4">
|
|
161
|
-
<div>
|
|
162
|
-
<label className="text-xs text-muted-foreground block mb-1">Context length (tokens)</label>
|
|
163
|
-
<select
|
|
164
|
-
value={context}
|
|
165
|
-
onChange={(e) => setContext(Number(e.target.value))}
|
|
166
|
-
className="bg-muted border border-border rounded-md px-3 py-1.5 text-sm"
|
|
167
|
-
>
|
|
168
|
-
<option value={500}>500 (chat)</option>
|
|
169
|
-
<option value={8192}>8K</option>
|
|
170
|
-
<option value={32768}>32K (RAG)</option>
|
|
171
|
-
<option value={50000}>50K</option>
|
|
172
|
-
<option value={131072}>128K (long context)</option>
|
|
173
|
-
</select>
|
|
174
|
-
</div>
|
|
175
|
-
<div>
|
|
176
|
-
<label className="text-xs text-muted-foreground block mb-1">GPUs (tensor parallel)</label>
|
|
177
|
-
<select
|
|
178
|
-
value={gpuCount}
|
|
179
|
-
onChange={(e) => setGpuCount(Number(e.target.value))}
|
|
180
|
-
className="bg-muted border border-border rounded-md px-3 py-1.5 text-sm"
|
|
181
|
-
>
|
|
182
|
-
<option value={1}>1×</option>
|
|
183
|
-
<option value={2}>2×</option>
|
|
184
|
-
<option value={4}>4×</option>
|
|
185
|
-
<option value={8}>8×</option>
|
|
186
|
-
</select>
|
|
187
|
-
</div>
|
|
188
|
-
</div>
|
|
189
|
-
|
|
190
|
-
<div className="grid grid-cols-2 gap-4">
|
|
191
|
-
{/* H100 results */}
|
|
192
|
-
<div className={`rounded-lg border p-4 ${h100Result.vramFits ? "border-border/60" : "border-red-500/40 bg-red-500/5"}`}>
|
|
193
|
-
<div className="flex items-center gap-2 mb-3">
|
|
194
|
-
<span className="text-sm font-bold">H100 SXM5</span>
|
|
195
|
-
<Badge variant="outline" className="text-[9px]">80GB</Badge>
|
|
196
|
-
</div>
|
|
197
|
-
<div className="space-y-2 text-sm">
|
|
198
|
-
<div className="flex justify-between"><span className="text-muted-foreground">Decode tok/s</span><span className="font-mono font-semibold">{fmtTokens(h100Result.decodeTokensPerSec)}</span></div>
|
|
199
|
-
<div className="flex justify-between"><span className="text-muted-foreground">Aggregate tok/s</span><span className="font-mono">{fmtTokens(h100Result.aggregateTokensPerSec)}</span></div>
|
|
200
|
-
<div className="flex justify-between"><span className="text-muted-foreground">TTFT</span><span className="font-mono">{fmtMs(h100Result.ttftMs)}</span></div>
|
|
201
|
-
<div className="flex justify-between"><span className="text-muted-foreground">VRAM needed</span><span className={`font-mono ${h100Result.vramFits ? "" : "text-red-500"}`}>{fmtBytes(h100Result.totalVramNeededGb)} / {H100!.vramGb * gpuCount}GB</span></div>
|
|
202
|
-
<div className="flex justify-between"><span className="text-muted-foreground">Cost/M tokens</span><span className="font-mono text-emerald-500">{fmtMoney(h100Result.costPerMillionOutputTokens)}</span></div>
|
|
203
|
-
<div className="flex justify-between"><span className="text-muted-foreground">Fits?</span><span className={h100Result.vramFits ? "text-emerald-500" : "text-red-500"}>{h100Result.vramFits ? "✓ Yes" : "✗ No — over budget"}</span></div>
|
|
204
|
-
</div>
|
|
205
|
-
<Button asChild variant="outline" size="sm" className="w-full mt-3 text-xs">
|
|
206
|
-
<a href={shareH100} target="_blank" rel="noopener noreferrer">Open in calculator →</a>
|
|
207
|
-
</Button>
|
|
208
|
-
</div>
|
|
209
|
-
|
|
210
|
-
{/* H200 results */}
|
|
211
|
-
<div className={`rounded-lg border p-4 ${h200Result.vramFits ? "border-emerald-500/40 bg-emerald-500/5" : "border-red-500/40"}`}>
|
|
212
|
-
<div className="flex items-center gap-2 mb-3">
|
|
213
|
-
<span className="text-sm font-bold">H200 SXM5</span>
|
|
214
|
-
<Badge variant="outline" className="text-[9px] bg-emerald-500/10">141GB</Badge>
|
|
215
|
-
</div>
|
|
216
|
-
<div className="space-y-2 text-sm">
|
|
217
|
-
<div className="flex justify-between"><span className="text-muted-foreground">Decode tok/s</span><span className="font-mono font-semibold">{fmtTokens(h200Result.decodeTokensPerSec)}</span></div>
|
|
218
|
-
<div className="flex justify-between"><span className="text-muted-foreground">Aggregate tok/s</span><span className="font-mono">{fmtTokens(h200Result.aggregateTokensPerSec)}</span></div>
|
|
219
|
-
<div className="flex justify-between"><span className="text-muted-foreground">TTFT</span><span className="font-mono">{fmtMs(h200Result.ttftMs)}</span></div>
|
|
220
|
-
<div className="flex justify-between"><span className="text-muted-foreground">VRAM needed</span><span className="font-mono">{fmtBytes(h200Result.totalVramNeededGb)} / {H200!.vramGb * gpuCount}GB</span></div>
|
|
221
|
-
<div className="flex justify-between"><span className="text-muted-foreground">Cost/M tokens</span><span className="font-mono text-emerald-500">{fmtMoney(h200Result.costPerMillionOutputTokens)}</span></div>
|
|
222
|
-
<div className="flex justify-between"><span className="text-muted-foreground">Fits?</span><span className={h200Result.vramFits ? "text-emerald-500" : "text-red-500"}>{h200Result.vramFits ? "✓ Yes" : "✗ No"}</span></div>
|
|
223
|
-
</div>
|
|
224
|
-
<Button asChild variant="outline" size="sm" className="w-full mt-3 text-xs">
|
|
225
|
-
<a href={shareH200} target="_blank" rel="noopener noreferrer">Open in calculator →</a>
|
|
226
|
-
</Button>
|
|
227
|
-
</div>
|
|
228
|
-
</div>
|
|
229
|
-
</CardContent>
|
|
230
|
-
</Card>
|
|
231
|
-
|
|
232
|
-
{/* Throughput chart */}
|
|
233
|
-
<Card className="border-border/60 shadow-sm mb-8">
|
|
234
|
-
<CardHeader>
|
|
235
|
-
<CardTitle className="text-base flex items-center gap-2"><Zap className="size-4 text-emerald-500" /> Throughput by context length</CardTitle>
|
|
236
|
-
<CardDescription className="text-xs">Llama 3.3 70B FP8, {gpuCount}× GPU, batch 8, continuous batching 2.0×</CardDescription>
|
|
237
|
-
</CardHeader>
|
|
238
|
-
<CardContent>
|
|
239
|
-
<div className="h-[280px] w-full">
|
|
240
|
-
<ResponsiveContainer width="100%" height="100%">
|
|
241
|
-
<BarChart data={chartData} margin={{ top: 8, right: 16, bottom: 0, left: 0 }}>
|
|
242
|
-
<CartesianGrid strokeDasharray="3 3" stroke="var(--border)" opacity={0.3} />
|
|
243
|
-
<XAxis dataKey="context" stroke="var(--muted-foreground)" fontSize={11} />
|
|
244
|
-
<YAxis stroke="var(--muted-foreground)" fontSize={11} tickFormatter={(v) => v >= 1000 ? `${(v/1000).toFixed(0)}k` : v} />
|
|
245
|
-
<Tooltip contentStyle={{ backgroundColor: "var(--background)", border: "1px solid var(--border)", borderRadius: "6px", fontSize: "12px" }} />
|
|
246
|
-
<BarChartBar dataKey="h100" name="H100" fill="#3b82f6" radius={[3,3,0,0]} />
|
|
247
|
-
<BarChartBar dataKey="h200" name="H200" fill="#10b981" radius={[3,3,0,0]} />
|
|
248
|
-
</BarChart>
|
|
249
|
-
</ResponsiveContainer>
|
|
250
|
-
</div>
|
|
251
|
-
</CardContent>
|
|
252
|
-
</Card>
|
|
253
|
-
|
|
254
|
-
{/* Key findings */}
|
|
255
|
-
<div className="prose dark:prose-invert max-w-none mb-8">
|
|
256
|
-
<h2 className="text-xl font-semibold mb-4">Key findings</h2>
|
|
257
|
-
<div className="space-y-4 text-sm leading-relaxed">
|
|
258
|
-
<div className="flex gap-3">
|
|
259
|
-
<span className="text-emerald-500 font-bold">1.</span>
|
|
260
|
-
<p><strong>H200 doubles H100 concurrency at every context length</strong> due to 76% more VRAM (141 vs 80 GB). The free VRAM after loading model weights is the bottleneck — H200 has 70 GB free vs H100's 9 GB for Llama 70B FP8.</p>
|
|
261
|
-
</div>
|
|
262
|
-
<div className="flex gap-3">
|
|
263
|
-
<span className="text-emerald-500 font-bold">2.</span>
|
|
264
|
-
<p><strong>H100 can't serve 32K+ context for Llama 70B FP8 on a single GPU</strong> — the KV cache alone needs 10+ GB, exceeding the 9 GB free after loading 70.6 GB of weights. H200 handles 32K with room for 6 concurrent users.</p>
|
|
265
|
-
</div>
|
|
266
|
-
<div className="flex gap-3">
|
|
267
|
-
<span className="text-emerald-500 font-bold">3.</span>
|
|
268
|
-
<p><strong>H200 is 43% faster per-token</strong> (4,800 vs 3,350 GB/s HBM bandwidth) — decode throughput scales linearly with memory bandwidth for memory-bound LLM inference.</p>
|
|
269
|
-
</div>
|
|
270
|
-
<div className="flex gap-3">
|
|
271
|
-
<span className="text-emerald-500 font-bold">4.</span>
|
|
272
|
-
<p><strong>H100 is 60% cheaper per GPU-hour</strong> (~$2.50 vs ~$4.00) but the cost-per-token is often LOWER on H200 because the higher throughput more than compensates for the higher hourly price.</p>
|
|
273
|
-
</div>
|
|
274
|
-
</div>
|
|
275
|
-
</div>
|
|
276
|
-
|
|
277
|
-
{/* FAQ */}
|
|
278
|
-
<div className="prose dark:prose-invert max-w-none mb-8">
|
|
279
|
-
<h2 className="text-xl font-semibold mb-4">FAQ</h2>
|
|
280
|
-
<div className="space-y-4 text-sm">
|
|
281
|
-
<details className="group">
|
|
282
|
-
<summary className="font-medium cursor-pointer">Should I use H100 or H200 for Llama 3.3 70B?</summary>
|
|
283
|
-
<p className="mt-2 text-muted-foreground">For context lengths under 8K, H100 is sufficient and cheaper. For 8K-32K, H200 is strongly preferred (H100 can't fit 32K on a single GPU). For 128K+, H200 is the minimum — H100 can't fit it even with TP×2.</p>
|
|
284
|
-
</details>
|
|
285
|
-
<details className="group">
|
|
286
|
-
<summary className="font-medium cursor-pointer">How much faster is H200 than H100 for LLM inference?</summary>
|
|
287
|
-
<p className="mt-2 text-muted-foreground">H200 is ~43% faster per-token decode throughput (4,800 vs 3,350 GB/s HBM bandwidth). For aggregate batched throughput, H200 is 2-8× better than H100 at long context because it has 7× more free VRAM for KV cache.</p>
|
|
288
|
-
</details>
|
|
289
|
-
<details className="group">
|
|
290
|
-
<summary className="font-medium cursor-pointer">Is H200 worth the extra cost over H100?</summary>
|
|
291
|
-
<p className="mt-2 text-muted-foreground">At 32K+ context, yes — H100 can't even fit the workload, so H200 is the only option. At short context (4K), H100 may be more cost-effective. Use the calculator above to find your break-even point.</p>
|
|
292
|
-
</details>
|
|
293
|
-
<details className="group">
|
|
294
|
-
<summary className="font-medium cursor-pointer">Can H100 serve 128K context for Llama 70B?</summary>
|
|
295
|
-
<p className="mt-2 text-muted-foreground">No — a single H100 (80 GB) can't fit Llama 70B FP8 (70.6 GB weights) + 128K KV cache (~42 GB) = 112 GB total. You'd need at least 2× H100 (160 GB) or 1× H200 (141 GB).</p>
|
|
296
|
-
</details>
|
|
297
|
-
</div>
|
|
298
|
-
</div>
|
|
299
|
-
|
|
300
|
-
{/* Internal links */}
|
|
301
|
-
<div className="border-t border-border/60 pt-6 mt-8">
|
|
302
|
-
<p className="text-xs text-muted-foreground mb-3">Related comparisons:</p>
|
|
303
|
-
<div className="flex flex-wrap gap-2">
|
|
304
|
-
<Link href="/compare/gguf-q4-k-m-vs-q5-k-m" className="text-xs text-emerald-500 hover:underline">GGUF Q4_K_M vs Q5_K_M →</Link>
|
|
305
|
-
<Link href="/self-host-vs-openai-api" className="text-xs text-emerald-500 hover:underline">Self-host vs OpenAI API →</Link>
|
|
306
|
-
<Link href="/" className="text-xs text-emerald-500 hover:underline">Full capacity calculator →</Link>
|
|
307
|
-
</div>
|
|
308
|
-
</div>
|
|
309
|
-
|
|
310
|
-
{/* JSON-LD structured data */}
|
|
311
|
-
<script
|
|
312
|
-
type="application/ld+json"
|
|
313
|
-
dangerouslySetInnerHTML={{
|
|
314
|
-
__html: JSON.stringify({
|
|
315
|
-
"@context": "https://schema.org",
|
|
316
|
-
"@type": "FAQPage",
|
|
317
|
-
mainEntity: [
|
|
318
|
-
{ "@type": "Question", name: "Should I use H100 or H200 for Llama 3.3 70B?", acceptedAnswer: { "@type": "Answer", text: "For context under 8K, H100 is sufficient. For 8K-32K+, H200 is strongly preferred or required." } },
|
|
319
|
-
{ "@type": "Question", name: "How much faster is H200 than H100?", acceptedAnswer: { "@type": "Answer", text: "H200 is ~43% faster per-token and 2-8× better aggregate throughput at long context due to 76% more VRAM." } },
|
|
320
|
-
{ "@type": "Question", name: "Is H200 worth the extra cost?", acceptedAnswer: { "@type": "Answer", text: "At 32K+ context, yes. At short context, H100 may be cheaper. Use the calculator to find your break-even." } },
|
|
321
|
-
],
|
|
322
|
-
}),
|
|
323
|
-
}}
|
|
324
|
-
/>
|
|
325
|
-
</div>
|
|
326
|
-
</div>
|
|
327
|
-
);
|
|
328
|
-
}
|
package/src/app/globals.css
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
@import "tailwindcss";
|
|
2
|
-
@import "tw-animate-css";
|
|
3
|
-
|
|
4
|
-
@custom-variant dark (&:is(.dark *));
|
|
5
|
-
|
|
6
|
-
@theme inline {
|
|
7
|
-
--color-background: var(--background);
|
|
8
|
-
--color-foreground: var(--foreground);
|
|
9
|
-
--font-sans: var(--font-geist-sans);
|
|
10
|
-
--font-mono: var(--font-geist-mono);
|
|
11
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
12
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
13
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
14
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
15
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
16
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
17
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
18
|
-
--color-sidebar: var(--sidebar);
|
|
19
|
-
--color-chart-5: var(--chart-5);
|
|
20
|
-
--color-chart-4: var(--chart-4);
|
|
21
|
-
--color-chart-3: var(--chart-3);
|
|
22
|
-
--color-chart-2: var(--chart-2);
|
|
23
|
-
--color-chart-1: var(--chart-1);
|
|
24
|
-
--color-ring: var(--ring);
|
|
25
|
-
--color-input: var(--input);
|
|
26
|
-
--color-border: var(--border);
|
|
27
|
-
--color-destructive: var(--destructive);
|
|
28
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
29
|
-
--color-accent: var(--accent);
|
|
30
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
31
|
-
--color-muted: var(--muted);
|
|
32
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
33
|
-
--color-secondary: var(--secondary);
|
|
34
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
35
|
-
--color-primary: var(--primary);
|
|
36
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
37
|
-
--color-popover: var(--popover);
|
|
38
|
-
--color-card-foreground: var(--card-foreground);
|
|
39
|
-
--color-card: var(--card);
|
|
40
|
-
--radius-sm: calc(var(--radius) - 4px);
|
|
41
|
-
--radius-md: calc(var(--radius) - 2px);
|
|
42
|
-
--radius-lg: var(--radius);
|
|
43
|
-
--radius-xl: calc(var(--radius) + 4px);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
:root {
|
|
47
|
-
--radius: 0.625rem;
|
|
48
|
-
--background: oklch(1 0 0);
|
|
49
|
-
--foreground: oklch(0.145 0 0);
|
|
50
|
-
--card: oklch(1 0 0);
|
|
51
|
-
--card-foreground: oklch(0.145 0 0);
|
|
52
|
-
--popover: oklch(1 0 0);
|
|
53
|
-
--popover-foreground: oklch(0.145 0 0);
|
|
54
|
-
--primary: oklch(0.205 0 0);
|
|
55
|
-
--primary-foreground: oklch(0.985 0 0);
|
|
56
|
-
--secondary: oklch(0.97 0 0);
|
|
57
|
-
--secondary-foreground: oklch(0.205 0 0);
|
|
58
|
-
--muted: oklch(0.97 0 0);
|
|
59
|
-
--muted-foreground: oklch(0.556 0 0);
|
|
60
|
-
--accent: oklch(0.97 0 0);
|
|
61
|
-
--accent-foreground: oklch(0.205 0 0);
|
|
62
|
-
--destructive: oklch(0.577 0.245 27.325);
|
|
63
|
-
--border: oklch(0.922 0 0);
|
|
64
|
-
--input: oklch(0.922 0 0);
|
|
65
|
-
--ring: oklch(0.708 0 0);
|
|
66
|
-
--chart-1: oklch(0.646 0.222 41.116);
|
|
67
|
-
--chart-2: oklch(0.6 0.118 184.704);
|
|
68
|
-
--chart-3: oklch(0.398 0.07 227.392);
|
|
69
|
-
--chart-4: oklch(0.828 0.189 84.429);
|
|
70
|
-
--chart-5: oklch(0.769 0.188 70.08);
|
|
71
|
-
--sidebar: oklch(0.985 0 0);
|
|
72
|
-
--sidebar-foreground: oklch(0.145 0 0);
|
|
73
|
-
--sidebar-primary: oklch(0.205 0 0);
|
|
74
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
75
|
-
--sidebar-accent: oklch(0.97 0 0);
|
|
76
|
-
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
77
|
-
--sidebar-border: oklch(0.922 0 0);
|
|
78
|
-
--sidebar-ring: oklch(0.708 0 0);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
.dark {
|
|
82
|
-
--background: oklch(0.145 0 0);
|
|
83
|
-
--foreground: oklch(0.985 0 0);
|
|
84
|
-
--card: oklch(0.205 0 0);
|
|
85
|
-
--card-foreground: oklch(0.985 0 0);
|
|
86
|
-
--popover: oklch(0.205 0 0);
|
|
87
|
-
--popover-foreground: oklch(0.985 0 0);
|
|
88
|
-
--primary: oklch(0.922 0 0);
|
|
89
|
-
--primary-foreground: oklch(0.205 0 0);
|
|
90
|
-
--secondary: oklch(0.269 0 0);
|
|
91
|
-
--secondary-foreground: oklch(0.985 0 0);
|
|
92
|
-
--muted: oklch(0.269 0 0);
|
|
93
|
-
--muted-foreground: oklch(0.708 0 0);
|
|
94
|
-
--accent: oklch(0.269 0 0);
|
|
95
|
-
--accent-foreground: oklch(0.985 0 0);
|
|
96
|
-
--destructive: oklch(0.704 0.191 22.216);
|
|
97
|
-
--border: oklch(1 0 0 / 10%);
|
|
98
|
-
--input: oklch(1 0 0 / 15%);
|
|
99
|
-
--ring: oklch(0.556 0 0);
|
|
100
|
-
--chart-1: oklch(0.488 0.243 264.376);
|
|
101
|
-
--chart-2: oklch(0.696 0.17 162.48);
|
|
102
|
-
--chart-3: oklch(0.769 0.188 70.08);
|
|
103
|
-
--chart-4: oklch(0.627 0.265 303.9);
|
|
104
|
-
--chart-5: oklch(0.645 0.246 16.439);
|
|
105
|
-
--sidebar: oklch(0.205 0 0);
|
|
106
|
-
--sidebar-foreground: oklch(0.985 0 0);
|
|
107
|
-
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
108
|
-
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
109
|
-
--sidebar-accent: oklch(0.269 0 0);
|
|
110
|
-
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
111
|
-
--sidebar-border: oklch(1 0 0 / 10%);
|
|
112
|
-
--sidebar-ring: oklch(0.556 0 0);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
@layer base {
|
|
116
|
-
* {
|
|
117
|
-
@apply border-border outline-ring/50;
|
|
118
|
-
}
|
|
119
|
-
body {
|
|
120
|
-
@apply bg-background text-foreground;
|
|
121
|
-
}
|
|
122
|
-
}
|