Skip to content

Commit 375d9b8

Browse files
committed
Side panel data layout improvements
1 parent 597f965 commit 375d9b8

1 file changed

Lines changed: 154 additions & 128 deletions

File tree

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.models._index

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.models._index/route.tsx

Lines changed: 154 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -323,13 +323,7 @@ function FiltersBar({
323323

324324
// --- Models Table ---
325325

326-
function BooleanCell({
327-
value,
328-
onClick,
329-
}: {
330-
value: boolean;
331-
onClick: () => void;
332-
}) {
326+
function BooleanCell({ value, onClick }: { value: boolean; onClick: () => void }) {
333327
return (
334328
<TableCell onClick={onClick} alignment="center">
335329
{value ? (
@@ -393,10 +387,7 @@ function ModelsList({
393387
const popular = popularMap.get(model.modelName);
394388
const select = () => onSelectModel(model);
395389
return (
396-
<TableRow
397-
key={model.friendlyId}
398-
isSelected={selectedModelId === model.friendlyId}
399-
>
390+
<TableRow key={model.friendlyId} isSelected={selectedModelId === model.friendlyId}>
400391
<TableCell>
401392
<Checkbox
402393
checked={compareSet.has(model.modelName)}
@@ -759,7 +750,7 @@ function ModelDetailPanel({
759750
return (
760751
<div className="grid h-full max-h-full grid-rows-[2.5rem_2rem_1fr] overflow-hidden bg-background-bright">
761752
<div className="flex items-center justify-between gap-2 overflow-x-hidden px-3 pr-2">
762-
<Header2 className="truncate text-blue-500">{model.displayId}</Header2>
753+
<Header2 className="truncate text-text-bright">{model.displayId}</Header2>
763754
<Button
764755
onClick={onClose}
765756
variant="minimal/small"
@@ -894,33 +885,26 @@ function DetailOverviewTab({ model }: { model: ModelCatalogItem }) {
894885

895886
<Property.Table>
896887
<Property.Item>
897-
<Property.Label>Structured output</Property.Label>
888+
<Property.Label>Features</Property.Label>
898889
<Property.Value>
899-
{model.supportsStructuredOutput ? (
900-
<CheckIcon className="size-4 text-success" />
901-
) : (
902-
"Not supported"
903-
)}
904-
</Property.Value>
905-
</Property.Item>
906-
<Property.Item>
907-
<Property.Label>Parallel tool calls</Property.Label>
908-
<Property.Value>
909-
{model.supportsParallelToolCalls ? (
910-
<CheckIcon className="size-4 text-success" />
911-
) : (
912-
"Not supported"
913-
)}
914-
</Property.Value>
915-
</Property.Item>
916-
<Property.Item>
917-
<Property.Label>Streaming tool calls</Property.Label>
918-
<Property.Value>
919-
{model.supportsStreamingToolCalls ? (
920-
<CheckIcon className="size-4 text-success" />
921-
) : (
922-
"Not supported"
923-
)}
890+
<div className="flex flex-col gap-0.5">
891+
{(
892+
[
893+
["Structured output", model.supportsStructuredOutput],
894+
["Parallel tool calls", model.supportsParallelToolCalls],
895+
["Streaming tool calls", model.supportsStreamingToolCalls],
896+
] as const
897+
).map(([label, supported]) => (
898+
<div key={label} className="mt-1 flex items-center gap-1">
899+
{supported ? (
900+
<CheckIcon className="size-4 text-text-dimmed" />
901+
) : (
902+
<XMarkIcon className="-mx-0.5 size-4 text-text-dimmed" />
903+
)}
904+
<span className="text-text-dimmed">{label}</span>
905+
</div>
906+
))}
907+
</div>
924908
</Property.Value>
925909
</Property.Item>
926910
</Property.Table>
@@ -933,11 +917,7 @@ function DetailOverviewTab({ model }: { model: ModelCatalogItem }) {
933917
<Property.Item key={v.friendlyId}>
934918
<Property.Label>{v.displayId}</Property.Label>
935919
<Property.Value>
936-
{v.releaseDate ? (
937-
<DateTime date={v.releaseDate} includeTime={false} />
938-
) : (
939-
"—"
940-
)}
920+
{v.releaseDate ? <DateTime date={v.releaseDate} includeTime={false} /> : "—"}
941921
</Property.Value>
942922
</Property.Item>
943923
))}
@@ -971,60 +951,79 @@ function DetailGlobalMetricsTab({
971951

972952
return (
973953
<div className="flex flex-col gap-3 py-3">
974-
<div className="grid grid-cols-2 gap-3">
975-
<div className="h-24">
976-
<MetricWidget
977-
widgetKey={`${modelName}-calls`}
978-
title="Total calls"
979-
query={`SELECT sum(call_count) AS total_calls FROM llm_models WHERE response_model = '${escapeTSQL(modelName)}'`}
980-
config={bignumberConfig("total_calls", { abbreviate: true })}
981-
{...widgetProps}
982-
/>
983-
</div>
984-
<div className="h-24">
985-
<MetricWidget
986-
widgetKey={`${modelName}-ttfc-p50`}
987-
title="p50 TTFC"
988-
query={`SELECT round(quantilesMerge(0.5)(ttfc_quantiles)[1], 0) AS ttfc_p50 FROM llm_models WHERE response_model = '${escapeTSQL(modelName)}'`}
989-
config={bignumberConfig("ttfc_p50", { aggregation: "avg", suffix: "ms" })}
990-
{...widgetProps}
991-
/>
992-
</div>
993-
<div className="h-24">
994-
<MetricWidget
995-
widgetKey={`${modelName}-ttfc-p90`}
996-
title="p90 TTFC"
997-
query={`SELECT round(quantilesMerge(0.9)(ttfc_quantiles)[1], 0) AS ttfc_p90 FROM llm_models WHERE response_model = '${escapeTSQL(modelName)}'`}
998-
config={bignumberConfig("ttfc_p90", { aggregation: "avg", suffix: "ms" })}
999-
{...widgetProps}
1000-
/>
1001-
</div>
1002-
<div className="h-24">
1003-
<MetricWidget
1004-
widgetKey={`${modelName}-tps`}
1005-
title="Tokens/sec (p50)"
1006-
query={`SELECT round(quantilesMerge(0.5)(tps_quantiles)[1], 0) AS tps_p50 FROM llm_models WHERE response_model = '${escapeTSQL(modelName)}'`}
1007-
config={bignumberConfig("tps_p50", { aggregation: "avg" })}
1008-
{...widgetProps}
1009-
/>
1010-
</div>
954+
<div className="h-[250px]">
955+
<MetricWidget
956+
widgetKey={`${modelName}-calls`}
957+
title="Total calls"
958+
query={`SELECT sum(call_count) AS total_calls FROM llm_models WHERE response_model = '${escapeTSQL(
959+
modelName
960+
)}'`}
961+
config={bignumberConfig("total_calls", { abbreviate: true })}
962+
{...widgetProps}
963+
/>
964+
</div>
965+
<div className="h-[250px]">
966+
<MetricWidget
967+
widgetKey={`${modelName}-ttfc-p50`}
968+
title="p50 TTFC"
969+
query={`SELECT round(quantilesMerge(0.5)(ttfc_quantiles)[1], 0) AS ttfc_p50 FROM llm_models WHERE response_model = '${escapeTSQL(
970+
modelName
971+
)}'`}
972+
config={bignumberConfig("ttfc_p50", { aggregation: "avg", suffix: "ms" })}
973+
{...widgetProps}
974+
/>
975+
</div>
976+
<div className="h-[250px]">
977+
<MetricWidget
978+
widgetKey={`${modelName}-ttfc-p90`}
979+
title="p90 TTFC"
980+
query={`SELECT round(quantilesMerge(0.9)(ttfc_quantiles)[1], 0) AS ttfc_p90 FROM llm_models WHERE response_model = '${escapeTSQL(
981+
modelName
982+
)}'`}
983+
config={bignumberConfig("ttfc_p90", { aggregation: "avg", suffix: "ms" })}
984+
{...widgetProps}
985+
/>
986+
</div>
987+
<div className="h-[250px]">
988+
<MetricWidget
989+
widgetKey={`${modelName}-tps`}
990+
title="Tokens/sec (p50)"
991+
query={`SELECT round(quantilesMerge(0.5)(tps_quantiles)[1], 0) AS tps_p50 FROM llm_models WHERE response_model = '${escapeTSQL(
992+
modelName
993+
)}'`}
994+
config={bignumberConfig("tps_p50", { aggregation: "avg" })}
995+
{...widgetProps}
996+
/>
1011997
</div>
1012998

1013999
<div className="h-[250px]">
10141000
<MetricWidget
10151001
widgetKey={`${modelName}-calls-time`}
10161002
title="Calls over time"
1017-
query={`SELECT timeBucket(), sum(call_count) AS calls FROM llm_models WHERE response_model = '${escapeTSQL(modelName)}' GROUP BY timeBucket ORDER BY timeBucket`}
1018-
config={chartConfig({ chartType: "bar", xAxisColumn: "timebucket", yAxisColumns: ["calls"] })}
1003+
query={`SELECT timeBucket(), sum(call_count) AS calls FROM llm_models WHERE response_model = '${escapeTSQL(
1004+
modelName
1005+
)}' GROUP BY timeBucket ORDER BY timeBucket`}
1006+
config={chartConfig({
1007+
chartType: "bar",
1008+
xAxisColumn: "timebucket",
1009+
yAxisColumns: ["calls"],
1010+
})}
10191011
{...widgetProps}
10201012
/>
10211013
</div>
10221014
<div className="h-[250px]">
10231015
<MetricWidget
10241016
widgetKey={`${modelName}-ttfc-time`}
10251017
title="TTFC over time"
1026-
query={`SELECT timeBucket(), round(quantilesMerge(0.5)(ttfc_quantiles)[1], 0) AS ttfc_p50, round(quantilesMerge(0.9)(ttfc_quantiles)[1], 0) AS ttfc_p90 FROM llm_models WHERE response_model = '${escapeTSQL(modelName)}' GROUP BY timeBucket ORDER BY timeBucket`}
1027-
config={chartConfig({ chartType: "line", xAxisColumn: "timebucket", yAxisColumns: ["ttfc_p50", "ttfc_p90"], aggregation: "avg" })}
1018+
query={`SELECT timeBucket(), round(quantilesMerge(0.5)(ttfc_quantiles)[1], 0) AS ttfc_p50, round(quantilesMerge(0.9)(ttfc_quantiles)[1], 0) AS ttfc_p90 FROM llm_models WHERE response_model = '${escapeTSQL(
1019+
modelName
1020+
)}' GROUP BY timeBucket ORDER BY timeBucket`}
1021+
config={chartConfig({
1022+
chartType: "line",
1023+
xAxisColumn: "timebucket",
1024+
yAxisColumns: ["ttfc_p50", "ttfc_p90"],
1025+
aggregation: "avg",
1026+
})}
10281027
{...widgetProps}
10291028
/>
10301029
</div>
@@ -1059,68 +1058,88 @@ function DetailYourUsageTab({
10591058

10601059
return (
10611060
<div className="flex flex-col gap-3 py-3">
1062-
<div className="grid grid-cols-2 gap-3">
1063-
<div className="h-24">
1064-
<MetricWidget
1065-
widgetKey={`${modelName}-user-calls`}
1066-
title="Your calls"
1067-
query={`SELECT count() AS total_calls FROM llm_metrics WHERE response_model = '${escapeTSQL(modelName)}'`}
1068-
config={bignumberConfig("total_calls", { abbreviate: true })}
1069-
{...widgetProps}
1070-
/>
1071-
</div>
1072-
<div className="h-24">
1073-
<MetricWidget
1074-
widgetKey={`${modelName}-user-cost`}
1075-
title="Your cost"
1076-
query={`SELECT sum(total_cost) AS total_cost FROM llm_metrics WHERE response_model = '${escapeTSQL(modelName)}'`}
1077-
config={bignumberConfig("total_cost", { aggregation: "sum" })}
1078-
{...widgetProps}
1079-
/>
1080-
</div>
1081-
<div className="h-24">
1082-
<MetricWidget
1083-
widgetKey={`${modelName}-user-ttfc`}
1084-
title="Avg TTFC"
1085-
query={`SELECT round(avg(ms_to_first_chunk), 0) AS avg_ttfc FROM llm_metrics WHERE response_model = '${escapeTSQL(modelName)}' AND ms_to_first_chunk > 0`}
1086-
config={bignumberConfig("avg_ttfc", { aggregation: "avg", suffix: "ms" })}
1087-
{...widgetProps}
1088-
/>
1089-
</div>
1090-
<div className="h-24">
1091-
<MetricWidget
1092-
widgetKey={`${modelName}-user-tps`}
1093-
title="Avg tokens/sec"
1094-
query={`SELECT round(avg(tokens_per_second), 0) AS avg_tps FROM llm_metrics WHERE response_model = '${escapeTSQL(modelName)}' AND tokens_per_second > 0`}
1095-
config={bignumberConfig("avg_tps", { aggregation: "avg" })}
1096-
{...widgetProps}
1097-
/>
1098-
</div>
1061+
<div className="h-[250px]">
1062+
<MetricWidget
1063+
widgetKey={`${modelName}-user-calls`}
1064+
title="Your calls"
1065+
query={`SELECT count() AS total_calls FROM llm_metrics WHERE response_model = '${escapeTSQL(
1066+
modelName
1067+
)}'`}
1068+
config={bignumberConfig("total_calls", { abbreviate: true })}
1069+
{...widgetProps}
1070+
/>
1071+
</div>
1072+
<div className="h-[250px]">
1073+
<MetricWidget
1074+
widgetKey={`${modelName}-user-cost`}
1075+
title="Your cost"
1076+
query={`SELECT sum(total_cost) AS total_cost FROM llm_metrics WHERE response_model = '${escapeTSQL(
1077+
modelName
1078+
)}'`}
1079+
config={bignumberConfig("total_cost", { aggregation: "sum" })}
1080+
{...widgetProps}
1081+
/>
1082+
</div>
1083+
<div className="h-[250px]">
1084+
<MetricWidget
1085+
widgetKey={`${modelName}-user-ttfc`}
1086+
title="Avg TTFC"
1087+
query={`SELECT round(avg(ms_to_first_chunk), 0) AS avg_ttfc FROM llm_metrics WHERE response_model = '${escapeTSQL(
1088+
modelName
1089+
)}' AND ms_to_first_chunk > 0`}
1090+
config={bignumberConfig("avg_ttfc", { aggregation: "avg", suffix: "ms" })}
1091+
{...widgetProps}
1092+
/>
1093+
</div>
1094+
<div className="h-[250px]">
1095+
<MetricWidget
1096+
widgetKey={`${modelName}-user-tps`}
1097+
title="Avg tokens/sec"
1098+
query={`SELECT round(avg(tokens_per_second), 0) AS avg_tps FROM llm_metrics WHERE response_model = '${escapeTSQL(
1099+
modelName
1100+
)}' AND tokens_per_second > 0`}
1101+
config={bignumberConfig("avg_tps", { aggregation: "avg" })}
1102+
{...widgetProps}
1103+
/>
10991104
</div>
11001105

11011106
<div className="h-[250px]">
11021107
<MetricWidget
11031108
widgetKey={`${modelName}-user-cost-time`}
11041109
title="Cost over time"
1105-
query={`SELECT timeBucket(), sum(total_cost) AS cost FROM llm_metrics WHERE response_model = '${escapeTSQL(modelName)}' GROUP BY timeBucket ORDER BY timeBucket`}
1106-
config={chartConfig({ chartType: "bar", xAxisColumn: "timebucket", yAxisColumns: ["cost"] })}
1110+
query={`SELECT timeBucket(), sum(total_cost) AS cost FROM llm_metrics WHERE response_model = '${escapeTSQL(
1111+
modelName
1112+
)}' GROUP BY timeBucket ORDER BY timeBucket`}
1113+
config={chartConfig({
1114+
chartType: "bar",
1115+
xAxisColumn: "timebucket",
1116+
yAxisColumns: ["cost"],
1117+
})}
11071118
{...widgetProps}
11081119
/>
11091120
</div>
11101121
<div className="h-[250px]">
11111122
<MetricWidget
11121123
widgetKey={`${modelName}-user-tokens-time`}
11131124
title="Tokens over time"
1114-
query={`SELECT timeBucket(), sum(input_tokens) AS input_tokens, sum(output_tokens) AS output_tokens FROM llm_metrics WHERE response_model = '${escapeTSQL(modelName)}' GROUP BY timeBucket ORDER BY timeBucket`}
1115-
config={chartConfig({ chartType: "bar", xAxisColumn: "timebucket", yAxisColumns: ["input_tokens", "output_tokens"] })}
1125+
query={`SELECT timeBucket(), sum(input_tokens) AS input_tokens, sum(output_tokens) AS output_tokens FROM llm_metrics WHERE response_model = '${escapeTSQL(
1126+
modelName
1127+
)}' GROUP BY timeBucket ORDER BY timeBucket`}
1128+
config={chartConfig({
1129+
chartType: "bar",
1130+
xAxisColumn: "timebucket",
1131+
yAxisColumns: ["input_tokens", "output_tokens"],
1132+
})}
11161133
{...widgetProps}
11171134
/>
11181135
</div>
11191136
<div className="h-[250px]">
11201137
<MetricWidget
11211138
widgetKey={`${modelName}-user-tasks`}
11221139
title="Cost by task"
1123-
query={`SELECT task_identifier, count() AS calls, sum(total_cost) AS cost FROM llm_metrics WHERE response_model = '${escapeTSQL(modelName)}' GROUP BY task_identifier ORDER BY cost DESC LIMIT 20`}
1140+
query={`SELECT task_identifier, count() AS calls, sum(total_cost) AS cost FROM llm_metrics WHERE response_model = '${escapeTSQL(
1141+
modelName
1142+
)}' GROUP BY task_identifier ORDER BY cost DESC LIMIT 20`}
11241143
config={{ type: "table", prettyFormatting: true, sorting: [] }}
11251144
{...widgetProps}
11261145
/>
@@ -1132,8 +1151,15 @@ function DetailYourUsageTab({
11321151
// --- Main Page ---
11331152

11341153
export default function ModelsPage() {
1135-
const { catalog, popularModels, allProviders, allCapabilities, organizationId, projectId, environmentId } =
1136-
useTypedLoaderData<typeof loader>();
1154+
const {
1155+
catalog,
1156+
popularModels,
1157+
allProviders,
1158+
allCapabilities,
1159+
organizationId,
1160+
projectId,
1161+
environmentId,
1162+
} = useTypedLoaderData<typeof loader>();
11371163
const { values: searchValues, value: searchValue } = useSearchParams();
11381164

11391165
const search = searchValue("search") ?? "";

0 commit comments

Comments
 (0)