diff --git a/packages/stats/app/src/routes/index.css b/packages/stats/app/src/routes/index.css index 39877378a435..b3f25eff01dc 100644 --- a/packages/stats/app/src/routes/index.css +++ b/packages/stats/app/src/routes/index.css @@ -2170,6 +2170,7 @@ body { font: inherit; font-size: 11px; line-height: 1; + text-align: left; cursor: pointer; outline: none; text-decoration: none; diff --git a/packages/stats/core/src/domain/home.ts b/packages/stats/core/src/domain/home.ts index 8a541430d7a2..e0fd2be37bd6 100644 --- a/packages/stats/core/src/domain/home.ts +++ b/packages/stats/core/src/domain/home.ts @@ -4,7 +4,7 @@ import { Resource } from "sst/resource" import { DatabaseError } from "../database" import type { GeoStatMetric } from "./geo" import { ModelStatRepo, type ModelStatMetric } from "./model" -import type { ProviderStatMetric } from "./provider" +import { statProvider } from "./model-normalization" import { DATA_SITE_TIERS, normalizeTier } from "./stat" export type UsageProduct = "All Users" | "Zen" | "Go" | "Enterprise" @@ -140,10 +140,6 @@ type StatMetricRow = Omit & { periodStart: number updatedAt: number } -type ProviderMetricRow = Omit & { - periodStart: number - updatedAt: number -} type GeoMetricRow = Omit & { periodStart: number updatedAt: number @@ -171,12 +167,8 @@ type RawRow = Record export function getStatsHomeData(): Effect.Effect { return Effect.tryPromise({ try: async () => { - const [modelRows, providerRows, geoRows] = await Promise.all([ - listModelDaily(), - listProviderDaily(), - listGeoDaily(), - ]) - return buildStatsHomeData(modelRows, providerRows, geoRows) + const [modelRows, geoRows] = await Promise.all([listModelDaily(), listGeoDaily()]) + return buildStatsHomeData(modelRows, geoRows) }, catch: (cause) => new StatsDataError(cause), }) @@ -241,23 +233,6 @@ async function listModelDaily(): Promise { })) } -async function listProviderDaily(): Promise { - return ( - await queryRows( - `select period_key, updated_at, tier, provider, total_tokens from provider_stat - where grain = 'day' and client = 'all' and source = 'all' - and tier in (${SITE_TIER_PLACEHOLDERS}) order by period_key`, - DATA_SITE_TIERS, - ) - ).map((row) => ({ - periodKey: stringValue(row.period_key), - updatedAt: dateValue(row.updated_at), - tier: stringValue(row.tier), - provider: stringValue(row.provider), - totalTokens: numberValue(row.total_tokens), - })) -} - async function listGeoDaily(opts?: { provider?: string; model?: string }): Promise { const scope = opts?.model && opts.provider @@ -334,15 +309,10 @@ export const getStatsModelComparisonData = ( { provider: secondProvider, model: secondModel }, ]) -function buildStatsHomeData( - modelRows: ModelStatMetric[], - providerRows: ProviderStatMetric[], - geoRows: GeoStatMetric[], -): StatsHomeData { +function buildStatsHomeData(modelRows: ModelStatMetric[], geoRows: GeoStatMetric[]): StatsHomeData { const normalized = modelRows.flatMap(normalizeStatRow) - const providers = providerRows.flatMap(normalizeProviderRow) const geo = geoRows.flatMap(normalizeGeoRow) - const periods = [...normalized, ...providers, ...geo] + const periods = [...normalized, ...geo] if (periods.length === 0) return emptyStatsHomeData() const earliest = Math.min(...periods.map((row) => row.periodStart)) @@ -377,7 +347,7 @@ function buildStatsHomeData( leaderboard: createUsageProductRecord((product) => createRangeRecord((range) => buildLeaderboard(normalized, product, getWindow("1W", earliest, latest))), ), - market: createRangeRecord((range) => buildMarketShare(providers, "Go", range, getWindow(range, earliest, latest))), + market: createRangeRecord((range) => buildMarketShare(normalized, "Go", range, getWindow(range, earliest, latest))), tokenCost: createTokenProductRecord((product) => buildTokenCost(normalized, product, getWindow("1W", earliest, latest)), ), @@ -602,15 +572,20 @@ function buildLeaderboard(rows: StatMetricRow[], product: UsageProduct, rankWind })) } -function buildMarketShare(rows: ProviderMetricRow[], product: UsageProduct, range: UsageRange, window: DateWindow) { +function buildMarketShare(rows: StatMetricRow[], product: UsageProduct, range: UsageRange, window: DateWindow) { + const providerOrder = aggregateByProvider(rowsForProduct(rows, product, window.start, window.end)) + .filter((item) => item.provider !== "unknown") + .toSorted((a, b) => b.tokens - a.tokens || a.provider.localeCompare(b.provider)) + .slice(0, 8) + .map((item) => item.provider) + return createBuckets(window, range).flatMap((bucket) => { - const total = aggregateByProvider(rowsForProduct(rows, product, bucket.start, bucket.end)).toSorted( - (a, b) => b.tokens - a.tokens, - ) + const total = aggregateByProvider(rowsForProduct(rows, product, bucket.start, bucket.end)) const totalTokens = total.reduce((sum, item) => sum + item.tokens, 0) if (totalTokens === 0) return [] - const authors = total.slice(0, 8) + const byProvider = new Map(total.map((item) => [item.provider, item.tokens])) + const authors = providerOrder.map((provider) => ({ provider, tokens: byProvider.get(provider) ?? 0 })) const knownTokens = authors.reduce((sum, item) => sum + item.tokens, 0) const withOther = [...authors, { provider: "Other", tokens: Math.max(totalTokens - knownTokens, 0) }].filter( (item) => item.tokens > 0, @@ -773,7 +748,7 @@ function aggregateByModelName(rows: StatMetricRow[]) { ) } -function aggregateByProvider(rows: ProviderMetricRow[]) { +function aggregateByProvider(rows: { provider: string; totalTokens: number }[]) { return Object.values( rows.reduce>((result, row) => { result[row.provider] = { @@ -917,27 +892,12 @@ function normalizeStatRow(row: ModelStatMetric): StatMetricRow[] { periodStart, updatedAt, tier: normalizeTier(row.tier), - provider: row.provider || "unknown", + provider: statProvider(row.model, undefined, row.provider) || "unknown", model: row.model || "unknown", }, ] } -function normalizeProviderRow(row: ProviderStatMetric): ProviderMetricRow[] { - const periodStart = periodKeyTime(row.periodKey) - const updatedAt = dateTime(row.updatedAt) - if (!Number.isFinite(periodStart) || !Number.isFinite(updatedAt)) return [] - return [ - { - ...row, - periodStart, - updatedAt, - tier: normalizeTier(row.tier), - provider: row.provider || "unknown", - }, - ] -} - function normalizeGeoRow(row: GeoStatMetric): GeoMetricRow[] { const periodStart = periodKeyTime(row.periodKey) const updatedAt = dateTime(row.updatedAt) @@ -948,7 +908,7 @@ function normalizeGeoRow(row: GeoStatMetric): GeoMetricRow[] { periodStart, updatedAt, tier: normalizeTier(row.tier), - provider: row.provider || "all", + provider: row.provider === "all" ? "all" : statProvider(row.model, undefined, row.provider) || "unknown", model: row.model || "all", country: row.country || "ZZ", continent: row.continent || "", @@ -987,6 +947,7 @@ function formatProvider(provider: string) { deepseek: "DeepSeek", google: "Google", minimax: "MiniMax", + meta: "Meta", moonshot: "Moonshot", moonshotai: "Moonshot", nvidia: "NVIDIA", diff --git a/packages/stats/core/src/domain/inference.test.ts b/packages/stats/core/src/domain/inference.test.ts index b4a7f394d3ec..0f8248ad1568 100644 --- a/packages/stats/core/src/domain/inference.test.ts +++ b/packages/stats/core/src/domain/inference.test.ts @@ -24,6 +24,7 @@ describe("inference stat normalization", () => { expect(modelAuthor("kimi-k2.6")).toBe("moonshot") expect(modelAuthor("mimo-v2-omni")).toBe("xiaomi") expect(modelAuthor("minimax-m2.7")).toBe("minimax") + expect(modelAuthor("muse-spark-1.2-contributor")).toBe("meta") expect(modelAuthor("nemotron-3-super-free")).toBe("nvidia") expect(modelAuthor("qwen3.7-max")).toBe("qwen") expect(modelAuthor("alpha-gpt-next")).toBeUndefined() @@ -67,6 +68,9 @@ describe("inference stat normalization", () => { { provider: "openai" }, ]) expect(toProviderAggregate(aggregate("big-pickle", "opencode"))).toMatchObject([{ provider: "unknown" }]) + expect(toProviderAggregate(aggregate("muse-spark-1.2-contributor", "unknown"))).toMatchObject([ + { provider: "meta" }, + ]) }) test("geo aggregates never keep opencode or big-pickle dimensions", () => { diff --git a/packages/stats/core/src/domain/model-normalization.ts b/packages/stats/core/src/domain/model-normalization.ts index 973184fb7f5e..4b6f474062fd 100644 --- a/packages/stats/core/src/domain/model-normalization.ts +++ b/packages/stats/core/src/domain/model-normalization.ts @@ -9,6 +9,7 @@ export const MODEL_AUTHOR_RULES = [ { match: "kimi", author: "moonshot" }, { match: "mimo", author: "xiaomi" }, { match: "minimax", author: "minimax" }, + { match: "muse-spark", author: "meta" }, { match: "nemotron", author: "nvidia" }, { match: "qwen", author: "qwen" }, ] as const