fix(stats): clarify market share providers (#43647)
This commit is contained in:
@@ -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<ModelStatMetric, "updatedAt"> & {
|
||||
periodStart: number
|
||||
updatedAt: number
|
||||
}
|
||||
type ProviderMetricRow = Omit<ProviderStatMetric, "updatedAt"> & {
|
||||
periodStart: number
|
||||
updatedAt: number
|
||||
}
|
||||
type GeoMetricRow = Omit<GeoStatMetric, "updatedAt"> & {
|
||||
periodStart: number
|
||||
updatedAt: number
|
||||
@@ -171,12 +167,8 @@ type RawRow = Record<string, unknown>
|
||||
export function getStatsHomeData(): Effect.Effect<StatsHomeData, StatsDataError> {
|
||||
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<ModelStatMetric[]> {
|
||||
}))
|
||||
}
|
||||
|
||||
async function listProviderDaily(): Promise<ProviderStatMetric[]> {
|
||||
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<GeoStatMetric[]> {
|
||||
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<Record<string, { provider: string; tokens: number }>>((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",
|
||||
|
||||
@@ -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", () => {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user