mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 02:24:10 +08:00
feat(stats): add daily model rankings (#51774)
This commit is contained in:
@@ -1545,6 +1545,25 @@ body {
|
||||
background: var(--stats-layer-2);
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="leaderboard-period"] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 24px;
|
||||
color: var(--stats-muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="leaderboard-period"] [data-component="usage-filter"] button {
|
||||
width: auto;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-slot="leaderboard-period"] + [data-component="leaderboard"] {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
[data-page="stats"] [data-component="chart-tooltip"] {
|
||||
position: absolute;
|
||||
right: auto;
|
||||
|
||||
@@ -65,7 +65,7 @@ type StatsHomePageData = {
|
||||
updatedAt: string | null
|
||||
usage: UsagePoint[]
|
||||
users: UsagePoint[]
|
||||
leaderboard: LeaderboardEntry[]
|
||||
leaderboard: { daily: LeaderboardEntry[]; weekly: LeaderboardEntry[] }
|
||||
market: MarketDay[]
|
||||
tokenCost: TokenCostEntry[]
|
||||
cacheRatio: CacheRatioEntry[]
|
||||
@@ -86,7 +86,7 @@ const getData = query(async () => {
|
||||
updatedAt: stats.updatedAt,
|
||||
usage: stats.usage.Go["2M"],
|
||||
users: stats.users.Go["2M"],
|
||||
leaderboard: stats.leaderboard.Go["2M"],
|
||||
leaderboard: { daily: stats.leaderboard.Go["1D"], weekly: stats.leaderboard.Go["1W"] },
|
||||
market: stats.market["2M"],
|
||||
tokenCost: priceTokenCostFromCatalog(stats.tokenCost.Go, catalog),
|
||||
cacheRatio: stats.cacheRatio.Go,
|
||||
@@ -162,7 +162,7 @@ export default function StatsHome() {
|
||||
<MarketShareSection data={stats().market} />
|
||||
<GeoBreakdownSection data={stats().country} />
|
||||
<ComparisonCardsSection
|
||||
pairs={homeComparisonPairs(stats().leaderboard, stats().catalogLabs)}
|
||||
pairs={homeComparisonPairs(stats().leaderboard.weekly, stats().catalogLabs)}
|
||||
title="Model Comparisons"
|
||||
description="Popular model pairs from the leaderboard."
|
||||
variant="featured"
|
||||
@@ -376,11 +376,13 @@ function formatUpdatedAtLabel(value: { date: string; time: string }) {
|
||||
|
||||
function TopModelsSection(props: {
|
||||
data: UsagePoint[]
|
||||
leaderboard: LeaderboardEntry[]
|
||||
leaderboard: StatsHomePageData["leaderboard"]
|
||||
catalogLabs: readonly string[]
|
||||
}) {
|
||||
const i18n = useI18n()
|
||||
const [activeModel, setActiveModel] = createSignal<string>()
|
||||
const [period, setPeriod] = createSignal<"weekly" | "daily">("weekly")
|
||||
const leaderboard = createMemo(() => props.leaderboard[period()])
|
||||
|
||||
return (
|
||||
<section id="top-models" data-section="top-models">
|
||||
@@ -397,14 +399,40 @@ function TopModelsSection(props: {
|
||||
>
|
||||
<TopModelsChart data={props.data} range="2M" activeModel={activeModel()} onActiveModelChange={setActiveModel} />
|
||||
</Show>
|
||||
<div data-slot="leaderboard-period" role="group" aria-label={i18n.t("nav.leaderboard")}>
|
||||
<div data-component="usage-filter" data-variant="range">
|
||||
<button
|
||||
type="button"
|
||||
data-active={period() === "weekly" ? "true" : undefined}
|
||||
aria-pressed={period() === "weekly"}
|
||||
onClick={() => {
|
||||
setPeriod("weekly")
|
||||
setActiveModel(undefined)
|
||||
}}
|
||||
>
|
||||
Weekly
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-active={period() === "daily" ? "true" : undefined}
|
||||
aria-pressed={period() === "daily"}
|
||||
onClick={() => {
|
||||
setPeriod("daily")
|
||||
setActiveModel(undefined)
|
||||
}}
|
||||
>
|
||||
{i18n.t("chart.daily")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<Show
|
||||
when={props.leaderboard.length > 0}
|
||||
when={leaderboard().length > 0}
|
||||
fallback={
|
||||
<EmptyState title={i18n.t("home.noLeaderboardTitle")} description={i18n.t("home.noLeaderboardDescription")} />
|
||||
}
|
||||
>
|
||||
<Leaderboard
|
||||
data={props.leaderboard}
|
||||
data={leaderboard()}
|
||||
activeModel={activeModel()}
|
||||
onActiveModelChange={setActiveModel}
|
||||
catalogLabs={props.catalogLabs}
|
||||
@@ -882,6 +910,7 @@ function LeaderboardCard(props: {
|
||||
const i18n = useI18n()
|
||||
const language = useLanguage()
|
||||
const hasProvider = () => isKnownCatalogLab(props.entry.provider, props.catalogLabs)
|
||||
const icon = () => (hasProvider() ? getProviderIconId(props.entry.author) : "synthetic")
|
||||
return (
|
||||
<a
|
||||
data-component="leader-card"
|
||||
@@ -900,13 +929,9 @@ function LeaderboardCard(props: {
|
||||
onClick={() => props.onActiveModelChange(props.entry.model)}
|
||||
>
|
||||
<span data-slot="rank">{String(props.entry.rank).padStart(2, "0")}</span>
|
||||
<Show when={hasProvider()}>
|
||||
<ProviderIcon data-slot="leader-watermark" aria-hidden="true" id={getProviderIconId(props.entry.author)} />
|
||||
</Show>
|
||||
<ProviderIcon data-slot="leader-watermark" aria-hidden="true" id={icon()} />
|
||||
<div data-slot="leader-body">
|
||||
<Show when={hasProvider()}>
|
||||
<ProviderIcon data-slot="leader-avatar" aria-hidden="true" id={getProviderIconId(props.entry.author)} />
|
||||
</Show>
|
||||
<ProviderIcon data-slot="leader-avatar" aria-hidden="true" id={icon()} />
|
||||
<div data-slot="leader-copy">
|
||||
<div>
|
||||
<strong>{props.entry.model}</strong>
|
||||
|
||||
@@ -1,10 +1,50 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import type { ModelStatMetric } from "./model"
|
||||
import type { RetentionMetricRow } from "./home"
|
||||
|
||||
process.env.SST_RESOURCE_App = JSON.stringify({ name: "opencode", stage: "test" })
|
||||
process.env.SST_RESOURCE_StatsDatabase = JSON.stringify({ url: "mysql://localhost/stats" })
|
||||
|
||||
const { buildRetentionEntries } = await import("./home")
|
||||
const { buildRetentionEntries, buildStatsHomeData } = await import("./home")
|
||||
|
||||
test("daily rankings use the latest day while weekly rankings retain seven days and their previous-period change", () => {
|
||||
const rows = Array.from({ length: 14 }, (_, index) =>
|
||||
[
|
||||
{ model: "model-a", totalTokens: index === 13 ? 3_000_000_000 : 1_000_000_000 },
|
||||
{ model: "model-b", totalTokens: index === 13 ? 2_000_000_000 : 4_000_000_000 },
|
||||
].map(
|
||||
(item) =>
|
||||
({
|
||||
periodKey: `2026-09-${String(index + 1).padStart(2, "0")}`,
|
||||
updatedAt: new Date(Date.UTC(2026, 8, index + 1)),
|
||||
tier: "Go",
|
||||
provider: "test",
|
||||
model: item.model,
|
||||
sessions: 1,
|
||||
uniqueUsers: 1,
|
||||
inputTokens: item.totalTokens,
|
||||
outputTokens: 0,
|
||||
reasoningTokens: 0,
|
||||
cacheReadTokens: 0,
|
||||
totalTokens: item.totalTokens,
|
||||
inputCostMicrocents: 0,
|
||||
outputCostMicrocents: 0,
|
||||
totalCostMicrocents: 0,
|
||||
}) satisfies ModelStatMetric,
|
||||
),
|
||||
).flat()
|
||||
const rankings = buildStatsHomeData(rows, [], []).leaderboard.Go
|
||||
|
||||
expect(rankings["1D"].map((item) => [item.model, item.tokens, item.change])).toEqual([
|
||||
["model-a", 3, 200],
|
||||
["model-b", 2, -50],
|
||||
])
|
||||
expect(rankings["1W"].map((item) => [item.model, item.tokens])).toEqual([
|
||||
["model-b", 26],
|
||||
["model-a", 9],
|
||||
])
|
||||
expect(rankings["2M"]).toEqual(rankings["1W"])
|
||||
})
|
||||
|
||||
describe("retention aggregates", () => {
|
||||
test("pools the latest seven weekly cohorts and ranks models above the sample floor", () => {
|
||||
|
||||
@@ -378,7 +378,7 @@ export const getStatsModelComparisonData = (
|
||||
{ provider: secondProvider, model: secondModel },
|
||||
])
|
||||
|
||||
function buildStatsHomeData(
|
||||
export function buildStatsHomeData(
|
||||
modelRows: ModelStatMetric[],
|
||||
countryRows: CountryTotalRow[],
|
||||
retentionRows: RetentionMetricRow[],
|
||||
@@ -416,7 +416,9 @@ function buildStatsHomeData(
|
||||
),
|
||||
),
|
||||
leaderboard: createUsageProductRecord((product) =>
|
||||
createRangeRecord((_range) => buildLeaderboard(normalized, product, getWindow("1W", earliest, latest))),
|
||||
createRangeRecord((range) =>
|
||||
buildLeaderboard(normalized, product, getWindow(range === "1D" ? "1D" : "1W", earliest, latest)),
|
||||
),
|
||||
),
|
||||
market: createRangeRecord((range) => buildMarketShare(normalized, "Go", range, getWindow(range, earliest, latest))),
|
||||
tokenCost: createTokenProductRecord((product) =>
|
||||
|
||||
Reference in New Issue
Block a user