feat(data): redesign model efficiency

This commit is contained in:
Adam 2026-07-07 06:52:57 -05:00
parent 516f0266b8
commit ea9fffce2e
No known key found for this signature in database
GPG key ID: 9CB48779AF150E75
20 changed files with 171 additions and 35 deletions

View file

@ -218,17 +218,22 @@ const en = {
"model.noUsersTitle": "No user data",
"model.noUsersDescription": "No user-bearing rows landed in the current window.",
"model.dailyUserChart": "Daily unique user chart",
"model.efficiencyDescription": "Cost, cache behavior, and average OpenCode Go session shape.",
"model.efficiencyDescription": "Cost, cache behavior, and average session shape.",
"model.noEfficiencyTitle": "No efficiency data",
"model.noEfficiencyDescription": "Efficiency data appears after usage lands.",
"model.totalSpendLabel": "Total spend",
"model.cost": "Cost",
"model.totalSpend": "total spend",
"model.costPerMillion": "Cost / 1M",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.inputOutput": "input / output",
"model.observedTokens": "observed all tokens",
"model.costSession": "Cost / Session",
"model.averageCostSession": "Average cost / Session",
"model.average": "average",
"model.tokensSession": "Tokens / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cacheRatio": "Cache Ratio",
"model.inputTokens": "input tokens",
"model.geoDescription": "OpenCode Go model tokens used by country.",

View file

@ -202,6 +202,11 @@ export const dict = {
"model.efficiencyDescription": "التكلفة، وسلوك التخزين المؤقت، ومتوسط شكل جلسة OpenCode Go.",
"model.noEfficiencyTitle": "لا توجد بيانات كفاءة",
"model.noEfficiencyDescription": "تظهر بيانات الكفاءة بعد وصول الاستخدام.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "التكلفة",
"model.totalSpend": "إجمالي الإنفاق",
"model.costPerMillion": "التكلفة / 1M",

View file

@ -204,6 +204,11 @@ export const dict = {
"model.efficiencyDescription": "Custo, comportamento de cache e formato médio da sessão do OpenCode Go.",
"model.noEfficiencyTitle": "Sem dados de eficiência",
"model.noEfficiencyDescription": "Os dados de eficiência aparecem depois que o uso chega.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "Custo",
"model.totalSpend": "gasto total",
"model.costPerMillion": "Custo / 1M",

View file

@ -203,6 +203,11 @@ export const dict = {
"model.efficiencyDescription": "Omkostning, cacheadfærd og gennemsnitlig OpenCode Go-sessionsform.",
"model.noEfficiencyTitle": "Ingen effektivitetsdata",
"model.noEfficiencyDescription": "Effektivitetsdata vises, når brug lander.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "Omkostning",
"model.totalSpend": "samlet forbrug",
"model.costPerMillion": "Omkostning / 1 mio.",

View file

@ -204,6 +204,11 @@ export const dict = {
"model.efficiencyDescription": "Kosten, Cache-Verhalten und durchschnittliche OpenCode Go-Sitzungsform.",
"model.noEfficiencyTitle": "Keine Effizienzdaten",
"model.noEfficiencyDescription": "Effizienzdaten erscheinen, nachdem Nutzung eingegangen ist.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "Kosten",
"model.totalSpend": "Gesamtausgaben",
"model.costPerMillion": "Kosten / 1 Mio.",

View file

@ -203,6 +203,11 @@ export const dict = {
"model.efficiencyDescription": "Coste, comportamiento de caché y forma media de sesión de OpenCode Go.",
"model.noEfficiencyTitle": "Sin datos de eficiencia",
"model.noEfficiencyDescription": "Los datos de eficiencia aparecen después de que llegue uso.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "Coste",
"model.totalSpend": "gasto total",
"model.costPerMillion": "Coste / 1 M",

View file

@ -205,6 +205,11 @@ export const dict = {
"model.efficiencyDescription": "Coût, comportement du cache et forme moyenne des sessions OpenCode Go.",
"model.noEfficiencyTitle": "Aucune donnée d'efficacité",
"model.noEfficiencyDescription": "Les données d'efficacité apparaissent après l'arrivée de l'utilisation.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "Coût",
"model.totalSpend": "dépense totale",
"model.costPerMillion": "Coût / 1 M",

View file

@ -204,6 +204,11 @@ export const dict = {
"model.efficiencyDescription": "Costi, comportamento della cache e forma media della sessione OpenCode Go.",
"model.noEfficiencyTitle": "Nessun dato di efficienza",
"model.noEfficiencyDescription": "I dati di efficienza appaiono dopo l'arrivo dell'utilizzo.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "Costo",
"model.totalSpend": "spesa totale",
"model.costPerMillion": "Costo / 1 M",

View file

@ -205,6 +205,11 @@ export const dict = {
"model.efficiencyDescription": "コスト、キャッシュ動作、平均的なOpenCode Goセッションの形。",
"model.noEfficiencyTitle": "効率データがありません",
"model.noEfficiencyDescription": "使用量が届くと効率データが表示されます。",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "コスト",
"model.totalSpend": "総支出",
"model.costPerMillion": "100万あたりのコスト",

View file

@ -205,6 +205,11 @@ export const dict = {
"model.efficiencyDescription": "비용, 캐시 동작, 평균 OpenCode Go 세션 형태입니다.",
"model.noEfficiencyTitle": "효율 데이터 없음",
"model.noEfficiencyDescription": "사용량이 들어오면 효율 데이터가 표시됩니다.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "비용",
"model.totalSpend": "총 지출",
"model.costPerMillion": "100만당 비용",

View file

@ -203,6 +203,11 @@ export const dict = {
"model.efficiencyDescription": "Kostnad, cacheatferd og gjennomsnittlig OpenCode Go-øktform.",
"model.noEfficiencyTitle": "Ingen effektivitetsdata",
"model.noEfficiencyDescription": "Effektivitetsdata vises etter at bruk lander.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "Kostnad",
"model.totalSpend": "totalt forbruk",
"model.costPerMillion": "Kostnad / 1 mill.",

View file

@ -202,6 +202,11 @@ export const dict = {
"model.efficiencyDescription": "Koszt, zachowanie cache i średni kształt sesji OpenCode Go.",
"model.noEfficiencyTitle": "Brak danych wydajności",
"model.noEfficiencyDescription": "Dane wydajności pojawią się po nadejściu użycia.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "Koszt",
"model.totalSpend": "łączne wydatki",
"model.costPerMillion": "Koszt / 1 mln",

View file

@ -204,6 +204,11 @@ export const dict = {
"model.efficiencyDescription": "Стоимость, поведение кэша и средняя форма сеанса OpenCode Go.",
"model.noEfficiencyTitle": "Нет данных эффективности",
"model.noEfficiencyDescription": "Данные эффективности появятся после использования.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "Стоимость",
"model.totalSpend": "общие расходы",
"model.costPerMillion": "Стоимость / 1 млн",

View file

@ -204,6 +204,11 @@ export const dict = {
"model.efficiencyDescription": "ต้นทุน พฤติกรรมแคช และรูปแบบเซสชัน OpenCode Go โดยเฉลี่ย",
"model.noEfficiencyTitle": "ไม่มีข้อมูลประสิทธิภาพ",
"model.noEfficiencyDescription": "ข้อมูลประสิทธิภาพจะแสดงหลังจากมีการใช้งานเข้ามา",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "ต้นทุน",
"model.totalSpend": "ยอดใช้จ่ายรวม",
"model.costPerMillion": "ต้นทุน / 1 ล้าน",

View file

@ -204,6 +204,11 @@ export const dict = {
"model.efficiencyDescription": "Maliyet, önbellek davranışı ve ortalama OpenCode Go oturum yapısı.",
"model.noEfficiencyTitle": "Verimlilik verisi yok",
"model.noEfficiencyDescription": "Verimlilik verileri kullanım geldikten sonra görünür.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "Maliyet",
"model.totalSpend": "toplam harcama",
"model.costPerMillion": "Maliyet / 1M",

View file

@ -204,6 +204,11 @@ export const dict = {
"model.efficiencyDescription": "Вартість, поведінка кешу та середня форма сеансу OpenCode Go.",
"model.noEfficiencyTitle": "Немає даних ефективності",
"model.noEfficiencyDescription": "Дані ефективності з'являться після використання.",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "Вартість",
"model.totalSpend": "загальні витрати",
"model.costPerMillion": "Вартість / 1 млн",

View file

@ -203,6 +203,11 @@ export const dict = {
"model.efficiencyDescription": "成本、缓存行为和平均 OpenCode Go 会话形态。",
"model.noEfficiencyTitle": "无效率数据",
"model.noEfficiencyDescription": "使用量到达后会显示效率数据。",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "成本",
"model.totalSpend": "总支出",
"model.costPerMillion": "每 100 万成本",

View file

@ -203,6 +203,11 @@ export const dict = {
"model.efficiencyDescription": "成本、快取行為和平均 OpenCode Go 工作階段形態。",
"model.noEfficiencyTitle": "無效率數據",
"model.noEfficiencyDescription": "使用量到達後會顯示效率數據。",
"model.totalSpendLabel": "Total spend",
"model.costInput": "Cost input",
"model.costOutput": "Cost output",
"model.averageCostSession": "Average cost / Session",
"model.averageTokensSession": "Average tokens / session",
"model.cost": "成本",
"model.totalSpend": "總支出",
"model.costPerMillion": "每 100 萬成本",

View file

@ -28,7 +28,6 @@ import {
formatCatalogLabName,
getModelCatalog,
type ModelCatalog,
type ModelCatalogCost,
type ModelCatalogEntry,
} from "../model-catalog"
import { SectionHeading } from "../section-heading"
@ -881,35 +880,26 @@ function ModelEfficiencySection(props: { data: StatsModelData | null; catalog: M
}
>
{(data) => (
<div data-component="model-metric-grid" data-variant="dense">
<MetricCard
label={i18n.t("model.cost")}
value={formatMoney(data().totals.cost)}
detail={i18n.t("model.totalSpend")}
/>
<MetricCard
label={i18n.t("model.costPerMillion")}
value={
props.catalog?.cost ? formatCatalogPrice(props.catalog.cost) : formatMoney(data().totals.costPerMillion)
}
detail={props.catalog?.cost ? i18n.t("model.inputOutput") : i18n.t("model.observedTokens")}
/>
<MetricCard
label={i18n.t("model.costSession")}
value={formatSessionCost(data().totals.costPerSession)}
detail={i18n.t("model.average")}
/>
<MetricCard
label={i18n.t("model.tokensSession")}
value={formatTokens(data().totals.tokensPerSession)}
detail={i18n.t("model.average")}
/>
<MetricCard
label={i18n.t("model.cacheRatio")}
value={formatPercent(data().totals.cacheRatio)}
detail={i18n.t("model.inputTokens")}
/>
</div>
<>
<div data-slot="model-efficiency-pattern" aria-hidden="true" />
<div data-component="model-efficiency-grid">
<MetricCard label={i18n.t("model.totalSpendLabel")} value={formatMoney(data().totals.cost)} />
<MetricCard label={i18n.t("model.costInput")} value={formatCatalogUnitPrice(props.catalog?.cost?.input)} />
<MetricCard label={i18n.t("model.costOutput")} value={formatCatalogUnitPrice(props.catalog?.cost?.output)} />
<MetricCard
label={i18n.t("model.averageCostSession")}
value={formatSessionCost(data().totals.costPerSession)}
/>
<MetricCard
label={i18n.t("model.averageTokensSession")}
value={formatTokens(data().totals.tokensPerSession)}
/>
<MetricCard
label={i18n.t("model.cacheRatio")}
value={`${formatPercent(data().totals.cacheRatio)} ${i18n.t("model.inputTokens")}`}
/>
</div>
</>
)}
</Show>
</section>
@ -1129,12 +1119,12 @@ function ModelPeersSection(props: { data: StatsModelData | null }) {
)
}
function MetricCard(props: { label: string; value: string; detail: string; state?: "positive" | "negative" }) {
function MetricCard(props: { label: string; value: string; detail?: string; state?: "positive" | "negative" }) {
return (
<article data-component="model-metric" data-state={props.state}>
<span>{props.label}</span>
<strong>{props.value}</strong>
<p>{props.detail}</p>
<Show when={props.detail}>{(detail) => <p>{detail()}</p>}</Show>
</article>
)
}
@ -1517,8 +1507,9 @@ function formatMoney(value: number) {
return `$${value.toFixed(value >= 10 ? 0 : 2)}`
}
function formatCatalogPrice(value: ModelCatalogCost) {
return `${formatModelPrice(value.input)} / ${formatModelPrice(value.output)}`
function formatCatalogUnitPrice(value: number | undefined) {
if (value === undefined) return "-"
return `${formatModelPrice(value)} / 1M`
}
function formatModelPrice(value: number) {

View file

@ -3913,6 +3913,50 @@
color: #b82d35;
}
[data-page="stats"] [data-slot="model-efficiency-pattern"] {
width: 100%;
height: 16px;
margin-bottom: 40px;
overflow: hidden;
background: color-mix(in srgb, var(--stats-text) 10%, transparent);
mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0H2V2H0V0Z' fill='black'/%3E%3C/svg%3E");
mask-position: center top;
mask-repeat: repeat;
mask-size: 6px 6px;
-webkit-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0H2V2H0V0Z' fill='black'/%3E%3C/svg%3E");
-webkit-mask-position: center top;
-webkit-mask-repeat: repeat;
-webkit-mask-size: 6px 6px;
}
[data-page="stats"] [data-component="model-efficiency-grid"] {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
}
[data-page="stats"] [data-component="model-efficiency-grid"] [data-component="model-metric"] {
display: flex;
align-items: flex-start;
flex-direction: column;
box-sizing: border-box;
gap: 0;
height: 120px;
min-height: 120px;
padding: 16px;
background: var(--stats-layer);
}
[data-page="stats"] [data-component="model-efficiency-grid"] [data-component="model-metric"] span {
line-height: 14px;
}
[data-page="stats"] [data-component="model-efficiency-grid"] [data-component="model-metric"] strong {
margin-top: 32px;
font-size: 28px;
line-height: 42px;
}
[data-page="stats"] [data-section="model-panel"][data-variant="lab-models"] {
overflow: hidden;
}
@ -5699,6 +5743,7 @@
[data-page="stats"] [data-component="model-metric-grid"],
[data-page="stats"] [data-component="model-metric-grid"][data-variant="dense"],
[data-page="stats"] [data-component="model-efficiency-grid"],
[data-page="stats"] [data-component="lab-model-grid"] {
grid-template-columns: 1fr 1fr;
}
@ -6125,6 +6170,7 @@
[data-page="stats"] [data-component="model-metric-grid"],
[data-page="stats"] [data-component="model-metric-grid"][data-variant="dense"],
[data-page="stats"] [data-component="model-efficiency-grid"],
[data-page="stats"] [data-component="lab-model-grid"] {
grid-template-columns: 1fr;
}
@ -6133,6 +6179,15 @@
min-height: 112px;
}
[data-page="stats"] [data-component="model-efficiency-grid"] [data-component="model-metric"] {
height: 112px;
min-height: 112px;
}
[data-page="stats"] [data-component="model-efficiency-grid"] [data-component="model-metric"] strong {
margin-top: 24px;
}
[data-page="stats"] [data-component="model-usage-chart"] {
--model-usage-mobile-bar-width: 16px;
--model-usage-mobile-edge-space: 48px;