New Chat
Ctrl
K
Plugins Scheduled Tasks
Kimi Work Kimi Code
  • Get App
  • About Us
  • Language
  • Get Help

模型比价网站

制作一个模型比价网站,按照models.dev公布的价格进行计算。 1.用户可以调整输入缓存率/输入token/输出token。 2.根据用户输入,展示各个模型的价格对比表 3.可以筛选指定多个或单个模型。 响应式布局,现代化,适配亮色和夜间主题,自动根据系统颜色切换。
响应式模型价格对比表主题切换
The user is asking to build a model price comparison website based on models.dev pricing. This appears to be a continuation of a previous task (from the conversation history: "0716T23:45 模型比价网站进度" - "制作一个模型比价网站,按照models.dev公布的价格进行计算...").
Let me check the current state:
  1. First, check if there's existing work in /mnt/agents/output
  2. The task requirements:
    • Users can adjust input cache rate / input tokens / output tokens
    • Show price comparison table for models based on user input
    • Filter specific multiple or single models
    • Responsive layout, modern, light/dark theme adapting to system
This is a website building task, so I need to load the webapp-building skill and the website_version_manager tool.
Let me start by:
  1. Checking existing work
  2. Reading the webapp-building skill
  3. Fetching models.dev pricing data (they have an API: https://models.dev/api.json)
  4. Building the site
Let me first check the existing state and read the skill.
Read Todo
Execute Terminal
Check existing output and app directory
构建模型价格比较网站
The output directory is empty, so this is a fresh start (the previous conversation's work isn't in this sandbox). I need to build the model price comparison website from scratch.
Let me:
  1. Read the webapp-building skill
  2. Load the website_version_manager tool
  3. Fetch models.dev API data
  4. Build the app
Let me start.
输出目录是空的,需要从零开始构建。先读取建站技能并加载版本管理工具,同时获取 models.dev 的价格数据。
Read
SKILL.md
Execute Terminal
Download models.dev API pricing data
分析模型.dev结构与定价,规划应用
The models.dev API data is available. Let me analyze its structure to understand the pricing format, then plan the app.
Let me examine the data structure more, particularly the cost field.
数据拿到了(约3.2MB)。先分析数据结构,特别是价格字段。
Execute Python code
构建供应商数据集并启动Web应用
The data structure is clear. Now let me understand the pricing model:
  • input: price per 1M input tokens (USD)
  • output: price per 1M output tokens
  • cache_read: price per 1M cached input tokens
  • cache_write: price per 1M cache write tokens
  • reasoning: price per 1M reasoning tokens
  • tiers: tiered pricing based on input size
The user wants:
  1. Adjustable: 输入缓存率 (input cache rate) / 输入token (input tokens) / 输出token (output tokens)
  2. Price comparison table based on user input
  3. Filter specific multiple or single models
  4. Responsive, modern, light/dark theme auto-switching
From previous context (memory): the user wanted 人民币计价 (RMB pricing) and mobile adaptation — "构建AI模型比价网站(人民币计价、移动端适配)". The previous conversation summary said "1.用户可以调整输入缓存率/输入[TL;DR]" — so it was truncated, but the memory says RMB pricing. Let me include a currency toggle (USD/CNY) to be safe, defaulting to CNY maybe? The current request doesn't mention RMB, but past context suggests 人民币计价. I'll add a currency switcher with USD/CNY, with exchange rate. That covers both.
There are 167 providers and 5686 models — too many to show all. A good approach:
  • Embed a curated dataset: pick well-known providers (openai, anthropic, google, deepseek, moonshotai, zhipuai, alibaba, qwen, xai, mistral, meta, minimax, kimi, stepfun, etc.) and their models with cost data.
  • Actually, better: embed ALL models with cost data but organize by provider, and let users filter. 5285 models is a lot but as JSON it's maybe 2-3MB. That might be too heavy for initial load but could be fine if gzipped... Actually let me think about bundle size. A 2-3MB JSON is heavy. Better to curate a reasonable subset: major providers' models. Or dedupe by model family.
Actually, a cleaner approach: include all providers but let the data load be manageable. Let me estimate the size of the trimmed dataset (id, name, provider, cost fields, context limit, modalities). 5285 models × ~200 bytes = ~1MB. That's acceptable-ish, but many providers are junk/duplicates (e.g., "opencode", "zenmux", aggregators like openrouter with hundreds of models duplicating others).
Better UX: focus on first-party providers (the model's creator), plus maybe popular aggregators. Let me define a whitelist of quality providers:
  • openai, anthropic, google, google-vertex, xai, deepseek, moonshotai, moonshotai-cn, zhipuai, alibaba, alibaba-cn, minimax, minimax-cn, stepfun, mistral, meta, cohere, perplexity, amazon-bedrock, azure, fireworks-ai, groq, togetherai, deepinfra, cerebras, openrouter, siliconflow, siliconflow-cn, huggingface, nvidia, tencent-, xiaomi-, longcat, qiniu-ai, iflowcn, modelscope...
Hmm, that's still a lot. Let me check how many models are in the big-name providers.
Also note some "providers" in the list are actually plans (e.g., "kimi-for-coding", "zhipuai-coding-plan", "opencode") which may have zero/subscription pricing. Those probably have cost 0 — should filter out models where input+output are both 0 or missing.
Let me analyze: count models per provider with valid cost, then decide the whitelist.
Pricing calculation with cache rate:
  • User inputs: total input tokens (I), output tokens (O), cache hit rate (r, 0-100%)
  • Uncached input = I × (1-r), cached input = I × r
  • Cost = uncached_input/1M × input_price + cached_input/1M × cache_read_price + O/1M × output_price
  • If model has no cache_read price, cached tokens charged at full input price (or we note that cache is unsupported — common approach: fall back to input price).
  • cache_write: models with cache_write (e.g., Anthropic 5m ephemeral writes cost 1.25× input). Should we include cache write? The user's requirement says "输入缓存率" — input cache rate. Simplest: cache_read for hit portion. Could optionally include a cache write assumption. I'll keep it simple: cached portion billed at cache_read price; if no cache_read price, billed at input price. Maybe add an option for cache write? Keep it simple per requirements.
  • Reasoning tokens: some models (o1 etc.) charge output tokens including reasoning at output price — models.dev has a separate reasoning price field for some. If reasoning price exists, output tokens might be charged at reasoning price? Actually on models.dev, reasoning is the price for reasoning tokens. For simplicity, charge output at output price (standard interpretation).
  • tiers / context_over_200k: some models have tiered pricing when input > 200k. Could handle: if total input > 200k and tiers exist, use the higher tier price. Let me check the tiers structure.
Let me look at a tiers example (Gemini).
Plan for the app:
Data prep (Python):
  • Parse api.json
  • Whitelist major providers (first-party + major aggregators)
  • Extract: provider id, provider name, model id, model name, cost {input, output, cache_read, cache_write, reasoning}, context limit, release_date, modalities (text/image/audio/video input), reasoning flag
  • Filter out models with no cost or zero cost
  • Output a compact JSON to src/data/models.json
  • Also fetch USD→CNY rate (or hardcode ~7.2 with a note; better to search for current rate)
App structure (React + Tailwind + shadcn):
  • Header: title, theme auto (prefers-color-scheme), currency toggle (USD/CNY)
  • Control panel:
    • Input tokens (slider + number input, maybe in K/M units)
    • Output tokens
    • Cache hit rate slider (0-100%)
    • Sort options (by total price asc/desc, input price, output price)
    • Provider filter (multi-select chips)
    • Model search box
    • Model multi-select filter (the requirement #3: filter specific multiple or single models)
  • Results table/cards:
    • Desktop: table with columns: Model, Provider, Input /1M,Cached /1M, Output $/1M, Your cost (total), breakdown
    • Highlight cheapest
    • Mobile: cards
    • Bar chart comparison? Could add a simple bar visualization for top N. Nice touch: horizontal bars showing cost proportions.
  • Theme: auto system theme with manual override toggle (light/dark/auto)
The requirement says "自动根据系统颜色切换" — auto switch by system. I'll implement auto with manual override buttons.
Tech: Use the webapp-building init script. React + TS + Tailwind + shadcn components.
Let me now:
  1. Analyze providers & build dataset
  2. Get current USD/CNY rate (search)
  3. Init the webapp
  4. Build the UI
Let me check model counts per major provider and the tiers structure first.
Execute Python code
中文AI服务商列表计数
Good. Now let me define a curated whitelist of first-party and popular providers, then build the dataset. I'll include:
First-party / official providers:
  • openai, anthropic, google, xai, deepseek, moonshotai, moonshotai-cn, zhipuai, alibaba, alibaba-cn, minimax, minimax-cn, stepfun, mistral, meta, cohere, perplexity, groq, cerebras, togetherai, fireworks-ai, deepinfra, novita-ai, siliconflow, siliconflow-cn, amazon-bedrock, azure, google-vertex, openrouter, huggingface, nvidia, inception, longcat, qiniu-ai, iflowcn, modelscope, xiaomi...
Wait, let me check what providers exist for Chinese labs: 'moonshotai-cn', 'zhipuai', 'minimax-cn', 'stepfun', 'longcat' (Meituan), 'xiaomi'... also 'bailing' (?), 'qiniu-ai', 'tencent-tokenhub'. Let me check anthropic, xai, deepseek counts.
Let me just check counts for the key ones and then decide. The table shows top40 by count but anthropic/openai/google/xai may be lower. openai: 52, google-vertex: 39. Let me get specific counts.
Execute Python code
Gemini价格计算按缓存未缓存与上下文阈值全量计费策略实现细节说明
Good picture. Plan: curated whitelist of first-party providers plus major aggregators, keep it manageable (~600-800 models). Include both international and China-region variants.
Whitelist (first-party official + popular aggregators):
  • openai, anthropic, google, google-vertex, azure, amazon-bedrock (big cloud, though bedrock has 110 — mostly dupes of anthropic/meta etc., but useful for comparison)
  • xai, deepseek, mistral, meta, cohere, perplexity, inception
  • moonshotai, moonshotai-cn, zhipuai, alibaba, alibaba-cn, minimax, minimax-cn, stepfun, longcat, xiaomi, bailing
  • groq, cerebras, togetherai, fireworks-ai, deepinfra, novita-ai, siliconflow, siliconflow-cn, openrouter, huggingface, aihubmix
That's roughly: 52+14+21+39+113+110+6+4+29+1+9+4+2+9+9+11+51+82+7+7+5+1+6+2+9+3+32+16+40+105+49+44+315+50+62 ≈ 920. Hmm, ~900 models is fine for a JSON (~250KB minified). That's acceptable. Actually maybe trim: exclude azure/bedrock/google-vertex duplicates? No — users may want to compare cloud pricing vs official. Keep them. 900 models is OK for client-side filtering.
Actually, let me reconsider: the user asked "可以筛选指定多个或单个模型" — filter specific models. With ~900 models, a searchable multi-select is needed. Fine.
Also the data should show provider display names. Provider objects have "name" field.
Fields per model:
  • pid (provider id), pname (provider name), id, name
  • cost: i (input), o (output), cr (cache_read), cw (cache_write), r (reasoning)
  • tiers: for >200k context: keep context_over_200k {i, o, cr}
  • ctx (context limit)
  • mod: input modalities beyond text: 'img', 'audio', 'video' flags
  • reasoning flag
  • release_date
Compact keys to keep JSON small.
Price calculation:
  • uncached = input_tokens × (1 - cache_rate), cached = input_tokens × cache_rate
  • input cost = uncached/1M × price.i + cached/1M × (price.cr ?? price.i)
  • output cost = output_tokens/1M × price.o
  • If context_over_200k exists and input_tokens > 200000: use the over-200k rates for the portion? models.dev semantics: for Gemini, when total context > 200k, ALL tokens are charged at the higher rate (that's how Google bills: if prompt > 200k, entire prompt uses higher tier). I'll implement: if input_tokens > 200k and context_over_200k exists, use those rates for everything. Add a note in UI.
Currency: user memory said 人民币计价. I'll default to CNY with USD toggle, and show exchange rate. Need current USD/CNY rate — I should search for it since it's time-sensitive. Let me do a quick search.
Now, exchange rate: let me search quickly. Then init the project.
Let me now:
  1. Search USD/CNY rate
  2. Init webapp in parallel? The init script is independent of the rate search. Run both in parallel.
Search
USD CNY exchange rate today July 2026
50 results
Execute Terminal
Initialize React webapp project
准备数据集并构建应用界面流程
Current USD/CNY rate is about 6.77-6.78 (as of July 16, 2026). I'll use 6.78 as the default rate, and make it adjustable in the UI.
Project initialized. Now let me:
  1. Prepare the dataset (Python → JSON into src/data/)
  2. Build the app UI
Let me create the todo list and proceed.
项目初始化完成,汇率约 6.78(2026-07-16)。现在制定任务计划并生成数据集。
Write Todo
Execute Python code
查看项目结构了解数据集
Dataset ready: 35 providers, 1319 models, 182KB JSON.
Now let me look at the project structure to understand what's there.
数据集完成:35 个提供商、1319 个模型、182KB。查看项目结构后开始写代码。
Execute Terminal
Inspect project structure and dependencies
编写定价库与主题钩子代码
The project has all shadcn components. Now let me build the app. I'll write the main App.tsx with all components. Plan:
Files:
  • src/lib/calc.ts — types + price calculation + formatting
  • src/hooks/useTheme.ts — theme management (auto/light/dark)
  • src/components/ControlsPanel.tsx — input params (tokens, cache rate, currency, exchange rate)
  • src/components/ModelFilter.tsx — search + provider filter + model multi-select
  • src/components/PriceTable.tsx — comparison table (desktop) + cards (mobile)
  • src/App.tsx — composition
Actually, to keep it manageable, I'll write fewer files but well organized. Let me design the UI:
Layout:
  • Sticky header: logo/title "AI 模型比价" + subtitle "基于 models.dev 价格", theme toggle (auto/light/dark icons), currency toggle (¥/$)
  • Controls card (top):
    • 输入 tokens (number input + quick presets: 10K/100K/1M/10M)
    • 输出 tokens (same presets)
    • 缓存命中率 slider 0-100%
    • 汇率 input (when CNY)
    • Sort by select
  • Filter area:
    • Search input (model name)
    • Provider chips (multi-select toggle) — collapsible
    • Selected models shown as removable badges; "模型自选" mode: a command palette style multi-select (use cmdk or simple popover with checkbox list)
  • Results:
    • Summary bar: 共 N 个模型, cheapest highlight
    • Desktop: table. Columns: # / 模型 (name + provider + tags) / 输入价 / 缓存价 / 输出价 / 本次费用 (total, with mini bar) / 费用构成 (input part + output part)
    • Mobile: cards with same info
    • Pagination or "show more" (limit initial to 50, load more button)
Pricing logic:
TypeScript
Copy
function calcCost(m, inputTokens, outputTokens, cacheRate) {
  // cacheRate: 0..1
  let pi = m.i, po = m.o, pcr = m.cr ?? m.i;
  let note200 = false;
  if (inputTokens > 200_000 && m.o200) {
    pi = m.o200.i; po = m.o200.o; pcr = m.o200.cr ?? pi;
    note200 = true;
  }
  const cachedTokens = inputTokens * cacheRate;
  const freshTokens = inputTokens - cachedTokens;
  const inputCost = freshTokens/1e6*pi + cachedTokens/1e6*pcr;
  const outputCost = outputTokens/1e6*po;
  return { total: inputCost+outputCost, inputCost, outputCost, note200 };
}
Formatting:
  • Price per 1M: show with appropriate precision (2-4 decimals)
  • Total cost: adaptive precision — if < 0.01 show 4-6 decimals; if large show thousands separators
Theme:
  • useTheme: 'auto' | 'light' | 'dark', default auto; listen to matchMedia('(prefers-color-scheme: dark)'), toggle .dark class on documentElement.
Currency:
  • 'CNY' | 'USD', default CNY (per user preference). Rate state default 6.78, editable. USD values from models.dev; display = usd * rate when CNY.
Model selection:
  • Two filter modes: "全部" (all models passing provider/search filters) vs "自选" (user picks specific models via multi-select). Requirement: "可以筛选指定多个或单个模型" — a multi-select combobox. I'll implement a popover with search + checkboxes (using cmdk style manually). Selected models appear as badges with x to remove.
  • Behavior: if user has selected specific models (selection list non-empty), show only those; else show all filtered by provider+search. Plus quick actions: "仅看选中" toggle? Simpler: tabs "全部模型" / 已选 (n). And in the all view, each row has a "+" button to add to selection? That might be overkill. Let me do: a dedicated "自选模型" combobox where you search and check models; once any checked, a filter switch appears: 全部 / 已选对比. Also provider multi-select chips and text search apply to the full list.
Default selection: to make first paint nice, preselect a handful of flagship models? Default view = all models sorted by total price asc. That's fine.
Also add "常用组合" preset buttons? E.g., "国产旗舰", "国际旗舰" — nice-to-have; skip to keep scope tight but maybe add quick provider group chips (全部/国际/国产/云平台/聚合). Provider chips with counts are already good. I'll group providers into categories for chip coloring: 官方(国际), 官方(中国), 云平台, 聚合平台. Actually simpler: just list provider chips sorted alphabetically with counts.
Let me also add a comparison bar chart at top for the visible top-N (horizontal bars proportional to cost) — pure CSS bars inside table rows is enough (mini bar under total). Plus a "Top 10 cheapest" bar section? Keep it in-table: a relative bar behind the cost cell. That's clean.
Additional features for polish:
  • Sticky table header
  • 费用构成 tooltip/hover breakdown
  • 每百万 tokens 单价 columns toggle display currency accordingly
  • "缓存价" column shows cr or "—" (falls back to input price, show "不支持")
  • Note for 200k tier models when input > 200k
  • Show context window in model cell (e.g., 200K, 1M)
  • Badges: 思考 (reasoning), modality icons
  • Empty state
  • Footer: data source models.dev, update date, disclaimer
Let me now write the code. I'll structure:
  1. src/lib/pricing.ts — types, calc, format
  2. src/hooks/useTheme.ts
  3. src/components/NumberField.tsx — token input with presets
  4. src/components/ModelPicker.tsx — multi-select combobox
  5. src/components/ResultsTable.tsx — table + mobile cards
  6. src/App.tsx
Let me check what App.tsx and main.tsx look like first, then write. Also check slider component exists (yes, @radix-ui/react-slider in deps; check ui/slider.tsx exists). Let me list ui components fully — earlier list was cut at sidebar/skeleton. Slider, select, popover, checkbox, badge, button, input, card, tooltip, command exist per deps. Good.
Let me write the files now.
Design language: modern, clean. Use CSS variables from shadcn. Accent color: I'll use a violet/indigo accent for highlights. Custom scrollbar. Font: system + maybe add Inter via index.css? Keep system fonts for speed. Chinese UI text.
Number formatting decisions:
  • per-1M price display: if >= 100 → 1 decimal? Use formatPricePerM: value < 1 → up to 4 sig decimals (e.g., 0.0028); 1-100 → 2 decimals; >100 → 1 decimal.
  • total cost: < 0.01 → 4 decimals (or 6 if < 0.0001); < 1 → 4 decimals; < 100 → 2 decimals; else thousands separators + 2 decimals. In CNY, similar.
Token input: allow K/M suffix? Number input + unit select (K/M)? I'll do plain number with thousand separators and preset buttons (1万/10万/100万/1000万). Also a slider for log scale? Presets + manual input is enough, plus cache rate slider 0-100%.
Sort options: 总价从低到高 / 总价从高到低 / 输入价 / 输出价 / 模型名称. Default: total asc.
Let me now also think about "输入缓存率" meaning: the user said "输入缓存率/输入token/输出token" — cache hit rate of input. Yes, my interpretation is right.
One more consideration: reasoning models — output tokens include reasoning; some models have separate reasoning price. When r exists and differs from o... e.g., some models charge reasoning tokens at different rate. I'll ignore r for the main calc (output price covers it in most cases on models.dev where reasoning usually equals output price). Fine.
Now write the code. Start with pricing lib and theme hook.
项目结构完整。开始编写核心代码——先是价格计算库和主题 Hook:
File created
pricing.ts
File created
useTheme.ts
构建控制面板模型选择器结果表格与主应用
Now the control panel component (token inputs + cache slider), then the model picker (multi-select combobox), then results table, then App.
File created
ControlsPanel.tsx
File created
ModelPicker.tsx
ResultsTable分页显示前50条并加载更多
Now the results table component. Key design:
  • Desktop (md+): full table with sticky header
  • Mobile: cards
  • Each row: rank, model (name, provider, badges: ctx, think, modalities), input price, cache price, output price, total cost (with proportional bar), cheapest highlighted
  • Expandable row for cost breakdown? Show breakdown on hover via tooltip, or expandable detail row on click. Let me add click-to-expand showing 输入费用/缓存节省/输出费用 breakdown. Nice.
Pagination: show first 50, "加载更多" button.
Let me write ResultsTable.tsx.
File created
ResultsTable.tsx
Vite React TS 项目暗黑模式与货币切换
Now the main App.tsx that ties everything together:
  • Header with title, theme toggle, currency toggle
  • Controls panel
  • Filter section: search box, provider chips (collapsible with categories), model picker, scope tabs (全部/已选)
  • Sort select
  • Results table
  • Footer
Also handle: default currency CNY, rate 6.78 editable.
Provider categories for chip display — let me categorize:
  • intl official: openai, anthropic, google, xai, mistral, meta, cohere, perplexity, inception
  • cn official: deepseek, moonshotai, moonshotai-cn, zhipuai, alibaba, alibaba-cn, minimax, minimax-cn, stepfun, longcat, xiaomi, bailing
  • cloud: azure, amazon-bedrock, google-vertex
  • platforms: groq, cerebras, togetherai, fireworks-ai, deepinfra, novita-ai, siliconflow, siliconflow-cn, openrouter, huggingface, aihubmix
I'll show provider chips in a collapsible area, grouped by category. Single-click toggles. "全选/清空" quick buttons.
Scope: when user selected models in picker, a Tabs appears: "全部结果" vs 仅自选 (n). Default to showing selected when selection changes? Let's keep tab state; when user adds first selection, auto-switch to '已选'? I'll auto-switch to 已选 when selected goes 0→1+. And switching back to 全部 keeps selections.
State:
  • inputTokens (default 1,000,000)
  • outputTokens (default 100,000? For a typical chat scenario. Hmm, for comparison maybe 1M/1M? The user asked adjustable. Default: input 1M, output 200K, cache 0%. Let me pick 1M input / 100K output / 0% cache.)
  • Actually reasonable default: 输入 1M,输出 200K,缓存 0%。
  • currency CNY, rate 6.78
  • sort: 'total-asc' default
  • provider filter: empty set = all
  • search text
  • selected model keys
  • scope: 'all' | 'picked'
  • visible count: 50
Compute rows = useMemo over models * filters * scope, map to RowData with calcCost, sort.
Search applies to model name/id.
Sort options: total asc/desc, input asc, output asc, name.
Reset button for filters.
Also add a small summary stat strip: cheapest model name + cost, median? Keep: cheapest highlight card? The table already highlights. Add stats row: "最便宜: X ¥y · 最贵: X ¥y · 中位数 ¥y". Nice touch, compact.
Header: use Monitor/Sun/Moon icons for theme modes (auto/light/dark cycle). Currency toggle: ¥ / $ button.
Data import: import dataJson from './data/models.json'. TS needs resolveJsonModule — Vite template usually has it enabled. I'll cast.
Let me write App.tsx now. Also need to update index.html title and add font smoothing. And App.css can be emptied (or leave default — check what App.css has; it might contain default Vite styles that conflict; I'll empty it).
Also index.css — keep the shadcn vars. Maybe add small custom scrollbar styles.
Write App.tsx:
File created
App.tsx
检查样式组件tsconfig后构建
Now let me check:
  1. App.css — might have default styles; check and clean
  2. index.html title
  3. Slider component exists?
  4. tsconfig has resolveJsonModule?
Then build.
Execute Terminal
Check App.css, UI components, tsconfig, main.tsx
Vite JSON 导入 tsconfig
Issues to fix:
  1. App.css has default Vite styles with max-width 1280px and padding 2rem on #root — this will break my layout. But is App.css imported? main.tsx imports './index.css' and App.tsx — my App.tsx doesn't import App.css. Good, App.css is unused. I'll empty it anyway to be safe... Actually it's not imported anywhere, so it's fine. But let me just clear it to avoid confusion.
  2. resolveJsonModule: grep found nothing. Vite supports JSON imports natively at build time via its own handling — yes, Vite handles JSON imports regardless of tsconfig, but tsc (if build runs tsc) needs resolveJsonModule. Let me check the build script and tsconfig.
  3. Title already "AI 模型比价" — good (init script set it).
Let me check package.json build script and tsconfig.app.json.
Execute Terminal
Check build script and tsconfig, clear App.css
代码审查格式化依赖与未使用属性
Build runs tsc -b && vite build, and tsconfig doesn't have resolveJsonModule. I need to add it. Let me add "resolveJsonModule": true to tsconfig.app.json compilerOptions.
Also verbatimModuleSyntax is on — my imports use type imports properly. And noUnusedLocals/noUnusedParameters — need to make sure no unused imports. Let me check my files:
App.tsx imports: ArrowDownUp, Monitor, Moon, RotateCcw, Search, Sun — all used. Badge, Button, Card, CardContent, Input, Label, Select..., Tabs..., ControlsPanel, ModelPicker, modelKey, ResultsTable, RowData, useTheme, ThemeMode, calcCost, convert, currencySymbol, fmtCost, CalcInput, Currency, ModelEntry, ProviderEntry — CalcInput used in query type; ModelEntry/ProviderEntry used in DATA cast; fmtCost used in stats; ok.
ResultsTable.tsx: imports Fragment, useMemo, useState — useMemo used for maxTotal; ChevronDown, Crown used; Badge, Button, Card, CardContent used; calcCost (type usage in RowData), convert, currencySymbol, fmtCost, fmtCtx, fmtPerM used; CalcInput, Currency, ModelEntry, ProviderEntry used; modelKey used. total prop used in footer text. OK.
ControlsPanel: imports Card, CardContent, Input, Label, Button, Slider, fmtTokens — all used. accent prop used.
ModelPicker: Check, ChevronsUpDown, Search, X used; Button, Badge, Input, Popover..., ScrollArea used; ModelEntry, ProviderEntry used. OK.
One concern: h-4.5 class in ResultsTable — Tailwind 3.4 supports arbitrary... 4.5 is not a default spacing value. Tailwind 3.4 does NOT include h-4.5 by default... Actually Tailwind v3.4 added size-* but h-4.5 isn't standard. It will just be ignored (class won't exist) → badges will have no height constraint, fine but text might make them taller. Let me change to py-0 instead. I'll fix: replace h-4.5 with py-0 ... Actually Badge default has px-2.5 py-0.5 text-xs. My overrides set text-[10px], px-1. Height auto is fine. Remove h-4.5.
Also Breakdown in ResultsTable unused import? No, it's defined and used.
In ModelPicker, modelKey exported — used by App and ResultsTable. Good.
tsconfig: need resolveJsonModule. Also check tsconfig.node.json maybe not needed.
Potential TS strict issue in App.tsx: const PROVIDERS = new Map(DATA.providers.map((p) => [p.id, p])) — Map<string, ProviderEntry> inference: new Map(DATA.providers.map(p => [p.id, p])) infers Map<string, ProviderEntry>? The array literal [p.id, p] infers as (string | ProviderEntry)[] not tuple → error under strict. Need as [string, ProviderEntry] or map(p => [p.id, p] as const). Hmm, actually Map constructor accepts Iterable<readonly [K, V]>, and Array<(string | ProviderEntry)[]> is not assignable → TS error. Fix: new Map(DATA.providers.map((p) => [p.id, p] as [string, ProviderEntry])).
Same pattern in ModelPicker: new Map(models.map((m) => [modelKey(m), m])) — same issue. Fix with as [string, ModelEntry].
In ResultsTable Breakdown: fine.
Slider onValueChange: ([v]) => onChange(v) — v could be undefined? Radix gives number[]. Destructuring gives number; TS: number[] destructure → v: number (could be undefined with noUncheckedIndexedAccess — not enabled by default; template didn't show it; fine).
fmtTokens: uses trimZeros on e.g. (10000/1e3).toFixed(1) = "10.0" → "10K". Good. 100000 → "100K", 1e6 → "1M". Good.
In App.tsx, query object recreated each render → rows useMemo deps include inputTokens etc. individually — but query used inside; fine.
unused: in ResultsTable, query prop used in footer line. Good.
Also in App.tsx I use type ThemeMode import — used in ThemeIcon props. Good.
index.css: maybe add scrollbar styling + font. Let me add small additions: tabular-nums utility exists in Tailwind (font-variant-numeric). Good.
Dark mode: shadcn theme uses .dark class — tailwind.config darkMode probably 'class'. Check quickly. The init template presumably configured. Let me check tailwind.config darkMode setting while building.
Fix the Map inference issues and h-4.5, add resolveJsonModule, then build.
构建脚本含 tsc -b,需补充 resolveJsonModule 并修正几处严格类型问题:
Edit
tsconfig.app.json
Edit
App.tsx
Edit
ModelPicker.tsx
Execute Terminal
Fix h-4.5 classes and check darkMode config
检查 Tailwind darkMode 构建
The sed worked (grep count returned 0 for h-4.5), exit code 1 came from grep finding 0 matches and tailwind darkMode grep maybe. Let me check tailwind.config.js darkMode separately, then build.
Execute Terminal
Check darkMode config and build project
删除未用modelKey导入
One unused import: modelKey in ResultsTable.tsx — indeed, I don't use modelKey there since rows come pre-keyed from App. Remove it.
Edit
ResultsTable.tsx
Execute Terminal
Rebuild project
在浏览器中测试构建预览并截图
Build succeeded. Now let me test it in the browser to verify everything renders correctly — light/dark, table, interactions. Let me start a preview server and take screenshots.
构建成功。启动预览并用浏览器验证页面效果:
Execute Terminal
Start preview server on port 4173
Browse
http://localhost:4173/
在App.tsx实现Embedding/专用标签过滤并默认排除m.o===0的项目,提升筛选效率与用户体验
The page renders well. But I notice an issue: embedding models (输出价 ¥0) rank at the top — these aren't chat models, so "cheapest" is an embedding model. That's expected given data, but for a better default experience, I could add a filter option to exclude embedding/audio-only models, e.g. "隐藏 embedding/专用模型" toggle. Models with output price 0 are embedding models. Let me add a switch: "包含 Embedding / 专用模型" — default off (hidden). That would make the default view chat models.
How to detect: output price === 0 → embedding or non-generative. Also moderation models etc. Let me add a toggle "含 Embedding 等专用模型" default off: filter out models where o === 0.
Also verify dark theme and interactions. Let me:
  1. Add the embedding toggle
  2. Test dark mode screenshot
  3. Test model picker & selection flow
  4. Test cache slider effect
Also the "仅自选" tab is disabled when nothing picked — good.
One more improvement: The theme button cycles auto→light→dark; initial state auto → shows Monitor icon. Good.
Let me add the embedding toggle in the filter card next to the 提供商 button. Use shadcn Switch or a simple toggle button. I'll add a small labeled checkbox-style button: "Embedding" badge toggle. Simple: a Button variant outline with check state: 专用模型 — better as a Switch with Label "含 Embedding/专用".
Implementation: state includeSpecial default false. Filter: if !includeSpecial, exclude m.o === 0.
Let me edit App.tsx.
Edit
App.tsx
Edit
App.tsx
Edit
App.tsx
Edit
App.tsx
Edit
App.tsx
Execute Terminal
Rebuild with special-model toggle
排查React组件未使用Switch错误
Odd — I added the Switch usage... let me check: the last edit added the Label+Switch block after the 提供商 Button. But the error says Switch is never read. Maybe my edit placed it but... wait, the error line says App.tsx(9,1) unused. Perhaps the build ran before file sync? Or my JSX edit failed to apply? No, it said success. Let me check the file.
Execute Terminal
Check Switch usage in App.tsx
检查代码编辑未应用的Switch使用块
The Switch import was added but the usage block didn't get applied?? The edit said "edited successfully" but grep shows no usage. Wait — the last edit's old_string was the 提供商 Button block. Let me check if the button block got the new Label. grep shows only line 9. So the edit replaced... hmm, maybe the old_string appeared and was replaced, but my new_string's Label+Switch part... Let me look at the actual section in the file.
Execute Terminal
Inspect provider button section
验证 includeSpecial 是否存在
The Label+Switch edit didn't apply — the old_string matched and it says success... but the content isn't there. Possibly the last edit was applied to a different occurrence... no wait, it must have been overwritten. Ah, I see — I made 5 edits in one message, all to the same file App.tsx. They likely applied sequentially, but perhaps one edit overwrote another because they were applied against the same original snapshot? The import edit (line 9) applied, the state edits applied (let me verify includeSpecial exists), the deps edit, and the button edit... Let me check includeSpecial.
Execute Terminal
Check includeSpecial state edits
按顺序逐个应用文件编辑以避免冲突
So all the middle edits got lost — only the import edit (first one) survived. The parallel edits to the same file raced each other: each edit was computed against the original and the last write won. Lesson: don't batch multiple edits to the same file in one block.
Let me re-apply the remaining four edits sequentially now.
并行编辑同一文件导致后几处修改丢失,逐个重新应用:
Edit
App.tsx
Edit
App.tsx
Edit
App.tsx
Edit
App.tsx
Execute Terminal
Verify edits and rebuild
构建完成后浏览器交互测试
Build succeeded. Now test interactions in the browser:
  1. Dark mode
  2. Cache rate change
  3. Model picker / 自选 flow
  4. Mobile viewport
Let me reload the page and test. First visit fresh, then click theme toggle twice (auto→light→dark), take screenshot.
构建成功。现在验证深色模式与交互流程:
Browse
http://localhost:4173/
测试暗黑主题:点击主题切换两次
The default view now excludes output-price-0 models (1304 vs 1319). Cheapest is now Ling-2.6-flash. Good.
Now test dark theme — click theme toggle (index 3) twice to get to dark mode (auto→light→dark), then screenshot.
默认列表已排除专用模型(1304 个)。测试深色主题:
Click element
Think
That click set theme from auto→light. Click again for dark mode, then screenshot.
Click element
测试模型选择器并验证仅自选标签激活
Dark mode looks great. Now test the model picker (自选对比): click the picker button, search "Kimi", select a couple models, verify the 仅自选 tab activates. Also test cache slider behavior via input? The slider is a Radix component — hard to drag via automation, but I can test the calculation logic separately. Let me test the picker first.
深色模式正常。测试自选模型功能:
Click element
Think
The picker popover opened. Now let me type in the search input (index 31) "Kimi" and select a model.
选择器已打开。搜索并选择模型:
Type
Kimi K2.5
选中首个Kimi K2.5
The search filtered the list — shows "Kimi K2.5" across providers. Now click the first one (index 33 "Kimi K2.5 Moonshot AI") to select it.
Click element
Radix 滑块点击设置值并添加模型
自选模式 works — selected Kimi K2.5, scope auto-switched to 仅自选, showing 1 model: input ¥4.07/M, cache ¥0.678/M, output ¥20.34/M, total ¥8.14 for 1M in + 200K out.
Verify calculation: input $0.60/M? Let me check: 4.07/6.78 = 0.60. Output 20.34/6.78 = 3.0. Total = 1M×0.6/1M + 200K×3/1M = 0.6 + 0.6 = 1.2 USD = 8.136 CNY ≈ 8.14. ✓ Correct.
Let me also select the China variant to test multi-select, then test cache slider effect by... the slider is Radix, clicking on track should set value. Let me click element 35 (Moonshot AI China) to add second model.
计算验证正确($0.6 输入 + $0.6 输出 = $1.2 ≈ ¥8.14)。再选一个测试多选对比:
Click element
测试行展开与供应商过滤功能
Multi-select works. Now test the cache slider — click on it (element 18 is the slider input). Radix sliders respond to clicking on the track. Let me click element 17 (span, the slider thumb/track container) — clicking should set a value. Actually clicking on a Radix slider track sets value based on position. Element 18 is input type? Let me try clicking element 17 (the span wrapper).
Actually, a simpler and more deterministic verification of the cache calculation: I trust the calc (verified formula above with cache at 0). Let me verify cache math manually via the unit logic in pricing.ts — the formula is straightforward. But an end-to-end check of the slider is valuable. Clicking the slider track at some position sets approximate value — fine for verification purposes.
Let me close the popover first (press Escape or click elsewhere), then click the slider track. Element 17 is the span (slider thumb), 18 is input (hidden input?). Radix slider: clicking anywhere on track moves thumb. The clickable element listed as [17]<span />
Alternative: keyboard. Focus thumb and press ArrowRight/End. browser tools don't have keypress.
I could verify the cache calc via a quick screenshot after clicking at a track position: click element 17 — the click lands at center of the thumb which is at 0%, so value stays 0. Not useful.
OK, different approach: verify the calc logic in Node directly. The formula: total = fresh×pi + cached×pcr + out×po. I already verified cache=0 case numerically against UI output. The cache path uses the same arithmetic. I'm confident. But let me at least sanity-test calcCost via node quickly with the built bundle? Simpler: replicate in python — no, better to test the actual TS via node with a tiny script using the source... ts isn't directly runnable; use npx tsx? tsx isn't installed. I'll do a quick vite-node? Not installed either.
Pragmatic: trust formula (it's trivially verifiable), and visually confirmed cache=0 case matches. Also the row expansion breakdown shows cached part. Let me test row expansion instead — click a table row (element 27) to see breakdown panel.
Actually — wait, one more thing to verify: mobile responsiveness. I can't easily resize viewport with these tools; but the layout uses md: breakpoints, Tailwind standard. The mobile card layout is hidden on desktop. I could take a screenshot at mobile width — the browser tool doesn't expose viewport control. I'll trust the responsive classes (they're standard patterns: hidden md:block / md:hidden).
Let me test row expand (breakdown) and the provider filter. First click row 27.
多选对比正常。测试行展开的费用明细:
Click element
Kimi与Gemini模型成本计算与缓存评估
The expanded breakdown works beautifully: 未命中 ¥4.07, 缓存命中 ¥0, 输出 ¥4.07. The dark theme UI looks polished with the selected-model badges, tabs, and the exchange-rate editor at the bottom right.
Now verify cache calculation end-to-end. I'll verify with a quick numeric check by changing the cache slider via clicking at ~50% position of the track. The slider thumb (element 17) is at 0%. Clicking on the track itself should work — but the track isn't a listed element. Alternatively use the hidden input 18? It's a number input? Actually Radix slider renders a hidden input for form value. browser_input on it may not work.
Let me instead validate calcCost directly: compile pricing.ts quickly with esbuild (vite has esbuild) and run in node. npx esbuild src/lib/pricing.ts --format=esm then node eval. Let me do that to be rigorous about the cache + 200k tier math.
Test cases:
  1. Kimi K2.5 (i=0.6, o=3.0, cr=0.1): 1M in, 200K out, cache 80% → fresh 200K×0.6/1M=0.12, cached 800K×0.1/1M=0.08, out 200K×3/1M=0.6 → total 0.80 USD → ×6.78 = ¥5.424.
  2. Gemini 3 Pro (o200): 300K input → all at tier i=4,o=18,cr=0.4: no cache → 300K×4/1M=1.2 + out.
  3. Model without cache_read: cached part at full price.
Let me run these.
明细展开正常。用 Node 直接验证计算函数(缓存命中、200K 阶梯、无缓存价回退):
Execute Terminal
Unit-test pricing calculation logic
headless捕获390px截图交付
All calculation cases pass:
  1. Cache hit at 80%: $0.80 ✓
  2. 200K input triggers high tier ✓
  3. Base price under 200K ✓
  4. No-cache model falls back to full price ✓
Now check mobile responsiveness. The browser tool doesn't support viewport resize directly... Actually let me try a mobile-width screenshot via a different approach — I can use the shell with a headless chromium screenshot at mobile size. There's Chromium in the sandbox. Let me capture a 390px-wide screenshot with chromium headless.
Then final: build version, update todos, deliver.
Execute Terminal
Capture mobile-width screenshot
Read
mobile.png
移动端验证:垂直控件,价格卡,最低价加冠
Mobile layout works well — controls stack vertically, stats are 3 columns, cards display with per-1M prices in a 3-col grid, cheapest highlighted with crown.
One minor thing: in mobile header, the title subtitle is hidden (by design). Stats truncate nicely.
Everything verified: ✓ Adjustable input tokens / output tokens / cache rate ✓ Price comparison table recalculated from inputs ✓ Multi/single model filter (picker + search + provider filter) ✓ Responsive (desktop table / mobile cards) ✓ Light/dark theme with auto system follow ✓ CNY/USD toggle with editable rate ✓ Calculations unit-tested
Final build is already done. Update todos and save version. The version manager: type "static" (Vite build with dist). project_dir /mnt/agents/output/app.
移动端布局完美。收尾:保存版本。
Write Todo
Version saved
commit 27bba5f
Write Todo
Think
Version saved (ID: 27bba5f, no URL returned, so I just say the version was saved with the ID). Now summarize for the user.
模型比价网站已完成,版本已保存(ID:27bba5f)。
数据基础:按 models.dev 官方 API 实时价格构建,收录 35 个提供商、1319 个模型(OpenAI、Anthropic、Google、xAI、DeepSeek、月之暗面、智谱、阿里、MiniMax 及 Azure/Bedrock/OpenRouter/SiliconFlow 等云平台与聚合平台)。
核心功能:
  1. 可调计费参数 — 输入 tokens、输出 tokens(数字输入 + 10K/100K/1M/10M 快捷预设)、输入缓存命中率滑杆(0–100%)。费用 = 未命中输入 × 输入价 + 命中输入 × 缓存价 + 输出 × 输出价;不支持缓存的模型自动按输入全价计,Gemini 类模型输入超 200K 时自动切换高阶梯价,这些规则都在页脚注明。
  2. 价格对比表 — 实时按参数重算,含输入/缓存/输出单价与本次总费用,最便宜模型皇冠高亮 + 比例条,点击任意行展开三段费用明细;顶部还有"最便宜 / 中位数 / 最贵"统计卡;支持总价、输入价、输出价、名称五种排序。
  3. 模型筛选 — 关键词搜索、按分组(国际官方/中国官方/云平台/聚合平台)的提供商多选、以及可搜索的多选选择器(勾选指定单个或多个模型后自动切到"仅自选"对比视图,选中模型以标签展示可单独移除);默认隐藏 Embedding/OCR 等专用模型,可通过开关加回。
体验细节:默认人民币计价(汇率 6.78,页脚可自行修改),一键切美元;主题默认跟随系统亮/暗自动切换,也可手动锁定;移动端自动变为卡片式布局,已实测桌面与手机宽度。计算逻辑经过缓存命中、200K 阶梯、无缓存回退三组用例验证,结果全部精确吻合。
AI 模型比价 V1
Website