fix(stats): hide stealth model providers
This commit is contained in:
parent
3f31139064
commit
4178fd74f1
7 changed files with 176 additions and 83 deletions
|
|
@ -24,6 +24,8 @@ import {
|
|||
findModelCatalogEntry,
|
||||
formatCatalogLabName,
|
||||
getModelCatalog,
|
||||
isKnownCatalogLab,
|
||||
isProviderlessLab,
|
||||
type ModelCatalog,
|
||||
type ModelCatalogEntry,
|
||||
} from "../routes/model-catalog"
|
||||
|
|
@ -71,7 +73,7 @@ const comparisonModelLimit = 6
|
|||
type ComparisonModel = {
|
||||
name: string
|
||||
lab: string
|
||||
labName: string
|
||||
labName?: string
|
||||
slug: string
|
||||
catalog: ModelCatalogEntry | null
|
||||
stats: StatsModelComparisonEntry | null
|
||||
|
|
@ -159,13 +161,19 @@ export default function ModelCompareDetailPage(props: ModelCompareDetailPageProp
|
|||
let comparisonBodyScroll: HTMLDivElement | undefined
|
||||
const models = createMemo(() =>
|
||||
modelSelections().map((model, index) =>
|
||||
buildComparisonModel(model.lab, model.slug, model.catalog ?? null, stats()?.models[index] ?? null),
|
||||
buildComparisonModel(
|
||||
model.lab,
|
||||
model.slug,
|
||||
model.catalog ?? null,
|
||||
stats()?.models[index] ?? null,
|
||||
catalog()?.labs.map((lab) => lab.id) ?? [],
|
||||
),
|
||||
),
|
||||
)
|
||||
const title = createMemo(() => `${models()[0].name} vs ${models()[1].name} - AI Model Comparison`)
|
||||
const description = createMemo(
|
||||
() =>
|
||||
`Compare ${models()[0].name} from ${models()[0].labName} and ${models()[1].name} from ${models()[1].labName} on key metrics including benchmarks, price, context length, usage, and model features.`,
|
||||
`Compare ${comparisonModelLabel(models()[0])} and ${comparisonModelLabel(models()[1])} on key metrics including benchmarks, price, context length, usage, and model features.`,
|
||||
)
|
||||
const canonicalPath = createMemo(() => {
|
||||
if (props.family) return canonicalFamilyComparisonPath(props.family.first, props.family.second)
|
||||
|
|
@ -206,7 +214,7 @@ export default function ModelCompareDetailPage(props: ModelCompareDetailPageProp
|
|||
"@type": "SoftwareApplication",
|
||||
name: model.name,
|
||||
applicationCategory: "AI model",
|
||||
provider: model.labName,
|
||||
...(model.labName ? { provider: model.labName } : {}),
|
||||
})),
|
||||
}),
|
||||
)
|
||||
|
|
@ -459,7 +467,9 @@ function CompareDetailSelectButton(props: {
|
|||
aria-expanded={props.expanded}
|
||||
onClick={props.onOpen}
|
||||
>
|
||||
<LabLogo lab={props.model.lab} label={props.model.labName} size="small" />
|
||||
<Show when={props.model.labName}>
|
||||
{(labName) => <LabLogo lab={props.model.lab} label={labName()} size="small" />}
|
||||
</Show>
|
||||
<span data-slot="compare-detail-select-name">{props.model.name}</span>
|
||||
<ChevronDownIcon />
|
||||
</button>
|
||||
|
|
@ -581,8 +591,7 @@ function CompareModelDetail(props: { model: ModelCatalogEntry }) {
|
|||
</header>
|
||||
<div data-slot="compare-model-modal-description">
|
||||
<p>
|
||||
{props.model.description ??
|
||||
`${props.model.name} is an AI model from ${formatCatalogLabName(props.model.lab)}.`}
|
||||
{props.model.description ?? `${props.model.name} is an AI model.`}
|
||||
</p>
|
||||
<span aria-hidden="true" />
|
||||
</div>
|
||||
|
|
@ -789,9 +798,11 @@ function LabLogo(props: { lab: string; label: string; size: "large" | "small" |
|
|||
const iconId = () => getProviderIconId(props.lab)
|
||||
|
||||
return (
|
||||
<span data-slot="compare-home-avatar" data-lab={iconId()} data-size={props.size} aria-label={props.label}>
|
||||
<ProviderIcon aria-hidden="true" id={iconId()} />
|
||||
</span>
|
||||
<Show when={!isProviderlessLab(props.lab)}>
|
||||
<span data-slot="compare-home-avatar" data-lab={iconId()} data-size={props.size} aria-label={props.label}>
|
||||
<ProviderIcon aria-hidden="true" id={iconId()} />
|
||||
</span>
|
||||
</Show>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -832,11 +843,13 @@ function buildComparisonModel(
|
|||
modelParam: string,
|
||||
catalog: ModelCatalogEntry | null,
|
||||
stats: StatsModelComparisonEntry | null,
|
||||
catalogLabs: readonly string[],
|
||||
): ComparisonModel {
|
||||
const lab = catalog?.lab ?? stats?.provider ?? catalogSlug(labParam)
|
||||
return {
|
||||
name: catalog?.name ?? stats?.model ?? formatParamName(modelParam),
|
||||
lab: catalog?.lab ?? stats?.provider ?? catalogSlug(labParam),
|
||||
labName: formatCatalogLabName(catalog?.lab ?? stats?.provider ?? labParam),
|
||||
lab,
|
||||
labName: isKnownCatalogLab(lab, catalogLabs) ? formatCatalogLabName(lab) : undefined,
|
||||
slug: catalog?.slug ?? stats?.slug ?? catalogSlug(modelParam),
|
||||
catalog,
|
||||
stats,
|
||||
|
|
@ -877,7 +890,7 @@ function buildComparisonDetailSections(models: readonly ComparisonModel[]): Comp
|
|||
rows: [
|
||||
comparisonDetailRow(
|
||||
"Author",
|
||||
models.map((model) => linkedTextCell(model.stats?.author ?? model.labName, labHref(model.lab))),
|
||||
models.map(providerDetailCell),
|
||||
),
|
||||
comparisonDetailRow(
|
||||
"Context length",
|
||||
|
|
@ -899,7 +912,7 @@ function buildComparisonDetailSections(models: readonly ComparisonModel[]): Comp
|
|||
),
|
||||
comparisonDetailRow(
|
||||
"Providers",
|
||||
models.map((model) => linkedTextCell(model.labName, labHref(model.lab))),
|
||||
models.map(providerDetailCell),
|
||||
),
|
||||
],
|
||||
},
|
||||
|
|
@ -1013,6 +1026,15 @@ function comparisonRef(model: ComparisonModel): ComparisonModelRef {
|
|||
}
|
||||
}
|
||||
|
||||
function comparisonModelLabel(model: ComparisonModel) {
|
||||
return model.labName ? `${model.name} from ${model.labName}` : model.name
|
||||
}
|
||||
|
||||
function providerDetailCell(model: ComparisonModel): ComparisonDetailCell {
|
||||
if (!model.labName) return textCell("")
|
||||
return linkedTextCell(model.stats?.author ?? model.labName ?? "", labHref(model.lab))
|
||||
}
|
||||
|
||||
function textCell(value: string): ComparisonDetailCell {
|
||||
return { value }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,13 @@ import { LocaleLinks } from "../../component/locale-links"
|
|||
import { useI18n } from "../../context/i18n"
|
||||
import { useLanguage } from "../../context/language"
|
||||
import { localizedUrl } from "../../lib/language"
|
||||
import { findModelCatalogEntry, formatCatalogLabName, loadModelCatalog, type ModelCatalogEntry } from "../model-catalog"
|
||||
import {
|
||||
findModelCatalogEntry,
|
||||
formatCatalogLabName,
|
||||
isKnownCatalogLab,
|
||||
loadModelCatalog,
|
||||
type ModelCatalogEntry,
|
||||
} from "../model-catalog"
|
||||
import { SectionHeading } from "../section-heading"
|
||||
import { runStatsEffect } from "../../stats-runtime"
|
||||
import { setStatsPageCacheHeaders } from "../stats-cache"
|
||||
|
|
@ -96,7 +102,9 @@ export default function StatsModel() {
|
|||
const modelName = createMemo(
|
||||
() => catalogEntry()?.name ?? publicModelName(canonicalModel()) ?? i18n.t("model.fallback"),
|
||||
)
|
||||
const labName = createMemo(() => formatCatalogLabName(catalogEntry()?.lab ?? stats()?.provider ?? labParam()))
|
||||
const lab = createMemo(() => catalogEntry()?.lab ?? stats()?.provider ?? labParam())
|
||||
const catalogLabs = createMemo(() => page()?.catalog.labs.map((item) => item.id) ?? [])
|
||||
const labName = createMemo(() => (isKnownCatalogLab(lab(), catalogLabs()) ? formatCatalogLabName(lab()) : undefined))
|
||||
const formerName = createMemo(() => formerModelName(canonicalModel()))
|
||||
const searchModelName = createMemo(() => (formerName() ? `${modelName()} (formerly ${formerName()})` : modelName()))
|
||||
const modelTitle = createMemo(() => i18n.t("model.title", { model: searchModelName() }))
|
||||
|
|
@ -185,9 +193,14 @@ export default function StatsModel() {
|
|||
<ModelUniqueUsersSection data={stats() ?? null} />
|
||||
<ModelEfficiencySection data={stats() ?? null} catalog={catalogEntry() ?? null} />
|
||||
<ModelGeoBreakdownSection data={stats()?.country ?? []} />
|
||||
<ModelPeersSection data={stats() ?? null} />
|
||||
<ModelPeersSection data={stats() ?? null} catalogLabs={catalogLabs()} />
|
||||
<ComparisonCardsSection
|
||||
pairs={modelComparisonPairs(page()?.catalog.labModels, catalogEntry() ?? null, stats() ?? null)}
|
||||
pairs={modelComparisonPairs(
|
||||
page()?.catalog.labModels,
|
||||
catalogLabs(),
|
||||
catalogEntry() ?? null,
|
||||
stats() ?? null,
|
||||
)}
|
||||
title="Compare This Model"
|
||||
description="Other models to compare with this one."
|
||||
variant="featured"
|
||||
|
|
@ -265,12 +278,13 @@ function ModelHero(props: {
|
|||
data: StatsModelPageData | null
|
||||
catalog: ModelCatalogEntry | null
|
||||
catalogData: ModelPageCatalog | null
|
||||
labName: string
|
||||
labName?: string
|
||||
formerName?: string
|
||||
}) {
|
||||
const i18n = useI18n()
|
||||
const language = useLanguage()
|
||||
const labId = () => props.catalog?.lab ?? props.data?.provider ?? props.labName
|
||||
const labId = () => props.catalog?.lab ?? props.data?.provider
|
||||
const hasLab = () => props.labName !== undefined
|
||||
const modelName = () => props.catalog?.name ?? props.data?.model ?? i18n.t("model.fallback")
|
||||
const weights = () => props.catalog?.weights[0]
|
||||
const labs = () => props.catalogData?.labs ?? []
|
||||
|
|
@ -281,35 +295,31 @@ function ModelHero(props: {
|
|||
<a data-slot="model-hero-crumb" href={language.route(import.meta.env.BASE_URL)}>
|
||||
Data
|
||||
</a>
|
||||
<span data-slot="model-hero-separator">/</span>
|
||||
<Show
|
||||
when={labs().length > 0}
|
||||
fallback={
|
||||
<span data-slot="model-hero-crumb" data-menu="true">
|
||||
<span>{props.labName}</span>
|
||||
<ChevronDownIcon />
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<BreadcrumbSelect
|
||||
ariaLabel="Choose a lab"
|
||||
label={props.labName}
|
||||
options={labs().map((lab) => ({
|
||||
href: language.route(`${import.meta.env.BASE_URL}${lab.id}`),
|
||||
label: lab.name,
|
||||
value: lab.id,
|
||||
}))}
|
||||
value={providerSlug(labId())}
|
||||
variant="model"
|
||||
/>
|
||||
<Show when={hasLab()}>
|
||||
<span data-slot="model-hero-separator">/</span>
|
||||
<Show
|
||||
when={labs().length > 0}
|
||||
fallback={<span data-slot="model-hero-crumb">{props.labName}</span>}
|
||||
>
|
||||
<BreadcrumbSelect
|
||||
ariaLabel="Choose a lab"
|
||||
label={props.labName ?? ""}
|
||||
options={labs().map((lab) => ({
|
||||
href: language.route(`${import.meta.env.BASE_URL}${lab.id}`),
|
||||
label: lab.name,
|
||||
value: lab.id,
|
||||
}))}
|
||||
value={providerSlug(labId() ?? "")}
|
||||
variant="model"
|
||||
/>
|
||||
</Show>
|
||||
</Show>
|
||||
<span data-slot="model-hero-separator">/</span>
|
||||
<Show
|
||||
when={labModels().length > 0}
|
||||
fallback={
|
||||
<span data-slot="model-hero-crumb" data-menu="true" data-current="true" aria-current="page">
|
||||
<span>{modelName()}</span>
|
||||
<ChevronDownIcon />
|
||||
<span data-slot="model-hero-crumb" data-current="true" aria-current="page">
|
||||
{modelName()}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
|
|
@ -328,9 +338,11 @@ function ModelHero(props: {
|
|||
</Show>
|
||||
</nav>
|
||||
<div data-slot="model-hero-title-row">
|
||||
<span data-slot="model-hero-avatar">
|
||||
<ProviderIcon aria-hidden="true" id={getProviderIconId(labId())} />
|
||||
</span>
|
||||
<Show when={hasLab()}>
|
||||
<span data-slot="model-hero-avatar">
|
||||
<ProviderIcon aria-hidden="true" id={getProviderIconId(labId() ?? "")} />
|
||||
</span>
|
||||
</Show>
|
||||
<h1>{modelName()}</h1>
|
||||
<div data-slot="model-hero-actions">
|
||||
<Show when={props.catalog?.openWeights && weights()}>
|
||||
|
|
@ -980,7 +992,7 @@ function GeoCountryList(props: {
|
|||
)
|
||||
}
|
||||
|
||||
function ModelPeersSection(props: { data: StatsModelPageData | null }) {
|
||||
function ModelPeersSection(props: { data: StatsModelPageData | null; catalogLabs: readonly string[] }) {
|
||||
const i18n = useI18n()
|
||||
return (
|
||||
<section id="peers" data-section="model-panel">
|
||||
|
|
@ -993,7 +1005,7 @@ function ModelPeersSection(props: { data: StatsModelPageData | null }) {
|
|||
>
|
||||
<ol data-component="model-peer-list">
|
||||
<For each={props.data?.peers ?? []}>
|
||||
{(peer) => <PeerRow peer={peer} active={peer.model === props.data?.model} />}
|
||||
{(peer) => <PeerRow peer={peer} active={peer.model === props.data?.model} catalogLabs={props.catalogLabs} />}
|
||||
</For>
|
||||
</ol>
|
||||
</Show>
|
||||
|
|
@ -1011,23 +1023,29 @@ function MetricCard(props: { label: string; value: string; detail?: string; stat
|
|||
)
|
||||
}
|
||||
|
||||
function PeerRow(props: { peer: ModelPeerEntry; active: boolean }) {
|
||||
function PeerRow(props: { peer: ModelPeerEntry; active: boolean; catalogLabs: readonly string[] }) {
|
||||
const language = useLanguage()
|
||||
const hasProvider = () => isKnownCatalogLab(props.peer.provider, props.catalogLabs)
|
||||
return (
|
||||
<li>
|
||||
<a
|
||||
href={language.route(`${import.meta.env.BASE_URL}${providerSlug(props.peer.provider)}/${props.peer.slug}`)}
|
||||
data-active={props.active ? "true" : undefined}
|
||||
data-providerless={!hasProvider() ? "true" : undefined}
|
||||
>
|
||||
<span data-slot="model-peer-rank" aria-label={props.active ? `Rank ${props.peer.rank}` : undefined}>
|
||||
<Show when={!props.active}>{String(props.peer.rank).padStart(2, "0")}</Show>
|
||||
</span>
|
||||
<span data-slot="model-peer-avatar">
|
||||
<ProviderIcon aria-hidden="true" id={getProviderIconId(props.peer.author)} />
|
||||
</span>
|
||||
<Show when={hasProvider()}>
|
||||
<span data-slot="model-peer-avatar">
|
||||
<ProviderIcon aria-hidden="true" id={getProviderIconId(props.peer.author)} />
|
||||
</span>
|
||||
</Show>
|
||||
<span data-slot="model-peer-copy">
|
||||
<strong>{props.peer.model}</strong>
|
||||
<em>{props.peer.author}</em>
|
||||
<Show when={hasProvider()}>
|
||||
<em>{props.peer.author}</em>
|
||||
</Show>
|
||||
</span>
|
||||
<b>{formatTokens(props.peer.tokens)}</b>
|
||||
</a>
|
||||
|
|
@ -1050,6 +1068,7 @@ function ModelEmptyState(props: { title: string; description: string; compact?:
|
|||
|
||||
function modelComparisonPairs(
|
||||
catalogModels: ModelCatalogOption[] | undefined,
|
||||
catalogLabs: readonly string[],
|
||||
catalogEntry: ModelCatalogEntry | null,
|
||||
data: StatsModelPageData | null,
|
||||
) {
|
||||
|
|
@ -1064,7 +1083,7 @@ function modelComparisonPairs(
|
|||
name: peer.model,
|
||||
lab: peer.provider,
|
||||
slug: peer.slug,
|
||||
labName: peer.author,
|
||||
labName: isKnownCatalogLab(peer.provider, catalogLabs) ? peer.author : undefined,
|
||||
metric: `#${peer.rank} / ${formatTokens(peer.tokens)}`,
|
||||
},
|
||||
detail: "Usage peer",
|
||||
|
|
@ -1090,7 +1109,7 @@ function modelComparisonRef(
|
|||
name: data.model,
|
||||
lab: data.provider,
|
||||
slug: data.slug,
|
||||
labName: data.author,
|
||||
labName: undefined,
|
||||
metric: `#${data.rank}`,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,17 +119,24 @@ function ComparisonCardIcon() {
|
|||
}
|
||||
|
||||
function ComparisonPanelCard(props: { pair: ComparisonPair }) {
|
||||
const firstLabName = () => props.pair.first.labName
|
||||
const secondLabName = () => props.pair.second.labName
|
||||
|
||||
return (
|
||||
<a data-component="comparison-card" href={canonicalComparisonHref(props.pair.first, props.pair.second)}>
|
||||
<span>{props.pair.detail}</span>
|
||||
<strong>
|
||||
{props.pair.first.name} <em>vs</em> {props.pair.second.name}
|
||||
</strong>
|
||||
<p>
|
||||
<b>{props.pair.first.labName ?? formatCatalogLabName(props.pair.first.lab)}</b>
|
||||
<i />
|
||||
<b>{props.pair.second.labName ?? formatCatalogLabName(props.pair.second.lab)}</b>
|
||||
</p>
|
||||
<Show when={firstLabName() || secondLabName()}>
|
||||
<p>
|
||||
<Show when={firstLabName()}>{(name) => <b>{name()}</b>}</Show>
|
||||
<Show when={firstLabName() && secondLabName()}>
|
||||
<i />
|
||||
</Show>
|
||||
<Show when={secondLabName()}>{(name) => <b>{name()}</b>}</Show>
|
||||
</p>
|
||||
</Show>
|
||||
<Show when={props.pair.first.metric || props.pair.second.metric}>
|
||||
<small>
|
||||
{props.pair.first.metric ?? "Listed"} / {props.pair.second.metric ?? "Listed"}
|
||||
|
|
@ -143,14 +150,16 @@ function ComparisonLabLogo(props: { model: ComparisonModelRef }) {
|
|||
const iconId = () => providerIconId(props.model.lab)
|
||||
|
||||
return (
|
||||
<span
|
||||
data-slot="compare-home-avatar"
|
||||
data-lab={iconId()}
|
||||
data-size="small"
|
||||
aria-label={props.model.labName ?? formatCatalogLabName(props.model.lab)}
|
||||
>
|
||||
<ProviderIcon aria-hidden="true" id={iconId()} />
|
||||
</span>
|
||||
<Show when={props.model.labName}>
|
||||
<span
|
||||
data-slot="compare-home-avatar"
|
||||
data-lab={iconId()}
|
||||
data-size="small"
|
||||
aria-label={props.model.labName}
|
||||
>
|
||||
<ProviderIcon aria-hidden="true" id={iconId()} />
|
||||
</span>
|
||||
</Show>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const toolUseBenchmarkPattern = /(terminal bench|claw eval|tau ?(?:bench|2|3))/
|
|||
|
||||
export type ComparisonRadarModel = {
|
||||
name: string
|
||||
labName: string
|
||||
labName?: string
|
||||
catalog: ModelCatalogEntry | null
|
||||
}
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ export function ComparisonRadar(props: ComparisonRadarProps) {
|
|||
<i style={{ background: model.color }} aria-hidden="true" />
|
||||
<span>
|
||||
<strong>{model.name}</strong>
|
||||
<small>{model.labName}</small>
|
||||
<Show when={model.labName}>{(name) => <small>{name()}</small>}</Show>
|
||||
</span>
|
||||
</li>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -5320,6 +5320,10 @@ body {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-component="model-peer-list"] a[data-providerless="true"] {
|
||||
grid-template-columns: 32px minmax(0, 1fr) minmax(64px, auto);
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-component="model-peer-list"] a:hover,
|
||||
[data-page="stats"] [data-component="model-peer-list"] a[data-active="true"] {
|
||||
border-color: var(--stats-text);
|
||||
|
|
@ -8483,6 +8487,10 @@ body {
|
|||
gap: 12px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-component="model-peer-list"] a[data-providerless="true"] {
|
||||
grid-template-columns: 28px minmax(0, 1fr) minmax(56px, auto);
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="model-peer-rank"] {
|
||||
width: 28px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import { LocaleLinks } from "../component/locale-links"
|
|||
import { useI18n } from "../context/i18n"
|
||||
import { useLanguage } from "../context/language"
|
||||
import { localizedUrl } from "../lib/language"
|
||||
import { findModelCatalogEntry, loadModelCatalog, type ModelCatalog } from "./model-catalog"
|
||||
import { findModelCatalogEntry, isKnownCatalogLab, loadModelCatalog, type ModelCatalog } from "./model-catalog"
|
||||
import { SectionHeading } from "./section-heading"
|
||||
import { setStatsPageCacheHeaders } from "./stats-cache"
|
||||
import { ComparisonCardsSection, uniqueComparisonPairs, type ComparisonModelRef } from "./compare-cards"
|
||||
|
|
@ -72,6 +72,7 @@ type StatsHomePageData = {
|
|||
sessionCost: SessionCostEntry[]
|
||||
retention: RetentionEntry[]
|
||||
country: CountryEntry[]
|
||||
catalogLabs: string[]
|
||||
}
|
||||
|
||||
const countryNumericIds = new Map(
|
||||
|
|
@ -92,6 +93,7 @@ const getData = query(async () => {
|
|||
sessionCost: stats.sessionCost.Go,
|
||||
retention: stats.retention,
|
||||
country: stats.country,
|
||||
catalogLabs: catalog.labs.map((lab) => lab.id),
|
||||
} satisfies StatsHomePageData
|
||||
}, "getStatsHomeData")
|
||||
|
||||
|
|
@ -147,7 +149,11 @@ export default function StatsHome() {
|
|||
{(stats) => (
|
||||
<>
|
||||
<Hero updatedAt={stats().updatedAt} />
|
||||
<TopModelsSection data={stats().usage} leaderboard={stats().leaderboard} />
|
||||
<TopModelsSection
|
||||
data={stats().usage}
|
||||
leaderboard={stats().leaderboard}
|
||||
catalogLabs={stats().catalogLabs}
|
||||
/>
|
||||
<UniqueUsersSection data={stats().users} />
|
||||
<RetentionSection data={stats().retention} />
|
||||
<SessionCostSection data={stats().sessionCost} />
|
||||
|
|
@ -156,7 +162,7 @@ export default function StatsHome() {
|
|||
<MarketShareSection data={stats().market} />
|
||||
<GeoBreakdownSection data={stats().country} />
|
||||
<ComparisonCardsSection
|
||||
pairs={homeComparisonPairs(stats().leaderboard)}
|
||||
pairs={homeComparisonPairs(stats().leaderboard, stats().catalogLabs)}
|
||||
title="Model Comparisons"
|
||||
description="Popular model pairs from the leaderboard."
|
||||
variant="featured"
|
||||
|
|
@ -368,7 +374,7 @@ function formatUpdatedAtLabel(value: { date: string; time: string }) {
|
|||
return `${value.date}, ${value.time}`
|
||||
}
|
||||
|
||||
function TopModelsSection(props: { data: UsagePoint[]; leaderboard: LeaderboardEntry[] }) {
|
||||
function TopModelsSection(props: { data: UsagePoint[]; leaderboard: LeaderboardEntry[]; catalogLabs: readonly string[] }) {
|
||||
const i18n = useI18n()
|
||||
const [activeModel, setActiveModel] = createSignal<string>()
|
||||
|
||||
|
|
@ -393,7 +399,12 @@ function TopModelsSection(props: { data: UsagePoint[]; leaderboard: LeaderboardE
|
|||
<EmptyState title={i18n.t("home.noLeaderboardTitle")} description={i18n.t("home.noLeaderboardDescription")} />
|
||||
}
|
||||
>
|
||||
<Leaderboard data={props.leaderboard} activeModel={activeModel()} onActiveModelChange={setActiveModel} />
|
||||
<Leaderboard
|
||||
data={props.leaderboard}
|
||||
activeModel={activeModel()}
|
||||
onActiveModelChange={setActiveModel}
|
||||
catalogLabs={props.catalogLabs}
|
||||
/>
|
||||
</Show>
|
||||
</section>
|
||||
)
|
||||
|
|
@ -806,6 +817,7 @@ function Leaderboard(props: {
|
|||
data: LeaderboardEntry[]
|
||||
activeModel: string | undefined
|
||||
onActiveModelChange: (model: string | undefined) => void
|
||||
catalogLabs: readonly string[]
|
||||
}) {
|
||||
const featured = createMemo(() => props.data.slice(0, 3))
|
||||
const compact = createMemo(() => props.data.slice(3))
|
||||
|
|
@ -820,6 +832,7 @@ function Leaderboard(props: {
|
|||
size="featured"
|
||||
active={props.activeModel === entry.model}
|
||||
onActiveModelChange={props.onActiveModelChange}
|
||||
catalogLabs={props.catalogLabs}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
|
|
@ -833,6 +846,7 @@ function Leaderboard(props: {
|
|||
size="compact"
|
||||
active={props.activeModel === entry.model}
|
||||
onActiveModelChange={props.onActiveModelChange}
|
||||
catalogLabs={props.catalogLabs}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
|
|
@ -845,6 +859,7 @@ function Leaderboard(props: {
|
|||
size="featured"
|
||||
active={props.activeModel === entry.model}
|
||||
onActiveModelChange={props.onActiveModelChange}
|
||||
catalogLabs={props.catalogLabs}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
|
|
@ -858,9 +873,11 @@ function LeaderboardCard(props: {
|
|||
size: "featured" | "compact"
|
||||
active: boolean
|
||||
onActiveModelChange: (model: string | undefined) => void
|
||||
catalogLabs: readonly string[]
|
||||
}) {
|
||||
const i18n = useI18n()
|
||||
const language = useLanguage()
|
||||
const hasProvider = () => isKnownCatalogLab(props.entry.provider, props.catalogLabs)
|
||||
return (
|
||||
<a
|
||||
data-component="leader-card"
|
||||
|
|
@ -879,16 +896,22 @@ function LeaderboardCard(props: {
|
|||
onClick={() => props.onActiveModelChange(props.entry.model)}
|
||||
>
|
||||
<span data-slot="rank">{String(props.entry.rank).padStart(2, "0")}</span>
|
||||
<ProviderIcon data-slot="leader-watermark" aria-hidden="true" id={getProviderIconId(props.entry.author)} />
|
||||
<Show when={hasProvider()}>
|
||||
<ProviderIcon data-slot="leader-watermark" aria-hidden="true" id={getProviderIconId(props.entry.author)} />
|
||||
</Show>
|
||||
<div data-slot="leader-body">
|
||||
<ProviderIcon data-slot="leader-avatar" aria-hidden="true" id={getProviderIconId(props.entry.author)} />
|
||||
<Show when={hasProvider()}>
|
||||
<ProviderIcon data-slot="leader-avatar" aria-hidden="true" id={getProviderIconId(props.entry.author)} />
|
||||
</Show>
|
||||
<div data-slot="leader-copy">
|
||||
<div>
|
||||
<strong>{props.entry.model}</strong>
|
||||
<span>{formatBillions(props.entry.tokens)}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>{props.entry.author}</span>
|
||||
<Show when={hasProvider()} fallback={<span />}>
|
||||
<span>{props.entry.author}</span>
|
||||
</Show>
|
||||
<span
|
||||
data-slot="delta"
|
||||
data-new={props.entry.change === null ? "true" : undefined}
|
||||
|
|
@ -1669,22 +1692,24 @@ function formatSessionCost(value: number) {
|
|||
return `$${value.toFixed(4)}`
|
||||
}
|
||||
|
||||
function homeComparisonPairs(leaderboard: LeaderboardEntry[]) {
|
||||
function homeComparisonPairs(leaderboard: LeaderboardEntry[], catalogLabs: readonly string[]) {
|
||||
return uniqueComparisonPairs(
|
||||
comparisonPairIndexes.flatMap(([firstIndex, secondIndex, detail]) => {
|
||||
const first = leaderboard[firstIndex]
|
||||
const second = leaderboard[secondIndex]
|
||||
return first && second ? [{ first: leaderboardRef(first), second: leaderboardRef(second), detail }] : []
|
||||
return first && second
|
||||
? [{ first: leaderboardRef(first, catalogLabs), second: leaderboardRef(second, catalogLabs), detail }]
|
||||
: []
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
function leaderboardRef(entry: LeaderboardEntry): ComparisonModelRef {
|
||||
function leaderboardRef(entry: LeaderboardEntry, catalogLabs: readonly string[]): ComparisonModelRef {
|
||||
return {
|
||||
name: entry.model,
|
||||
lab: entry.provider,
|
||||
slug: modelSlug(entry.model),
|
||||
labName: entry.author,
|
||||
labName: isKnownCatalogLab(entry.provider, catalogLabs) ? entry.author : undefined,
|
||||
metric: `#${entry.rank} / ${formatBillions(entry.tokens)}`,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,6 +114,16 @@ export function formatCatalogLabName(lab: string) {
|
|||
return known[catalogSlug(lab)] ?? lab.replace(/[-_]/g, " ").replace(/\b\w/g, (letter) => letter.toUpperCase())
|
||||
}
|
||||
|
||||
export function isProviderlessLab(lab: string | undefined) {
|
||||
return !lab || catalogSlug(lab) === "unknown"
|
||||
}
|
||||
|
||||
export function isKnownCatalogLab(lab: string | undefined, catalogLabs: readonly string[]) {
|
||||
if (!lab || isProviderlessLab(lab)) return false
|
||||
const key = catalogSlug(formatCatalogLabName(lab))
|
||||
return catalogLabs.some((candidate) => catalogSlug(formatCatalogLabName(candidate)) === key)
|
||||
}
|
||||
|
||||
export function catalogSlug(value: string) {
|
||||
return value
|
||||
.trim()
|
||||
|
|
|
|||
Loading…
Reference in a new issue