From be901060a926b8966d7c9766b0721f27f726754a Mon Sep 17 00:00:00 2001 From: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com> Date: Mon, 27 Jul 2026 11:49:38 -0600 Subject: [PATCH 1/2] Pareto view file organization updates Signed-off-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com> --- .../MetricSelect.tsx | 51 ++++++++++ .../ParetoTooltip.tsx | 52 +++++++++++ .../ExperimentGroupParetoChart/index.tsx | 93 +------------------ .../useParetoEvaluations.ts | 7 +- .../{paretoMetrics.test.ts => utils.test.ts} | 2 +- .../{paretoMetrics.ts => utils.ts} | 0 6 files changed, 111 insertions(+), 94 deletions(-) create mode 100644 web/packages/studio/src/components/charts/ExperimentGroupParetoChart/MetricSelect.tsx create mode 100644 web/packages/studio/src/components/charts/ExperimentGroupParetoChart/ParetoTooltip.tsx rename web/packages/studio/src/components/charts/ExperimentGroupParetoChart/{paretoMetrics.test.ts => utils.test.ts} (98%) rename web/packages/studio/src/components/charts/ExperimentGroupParetoChart/{paretoMetrics.ts => utils.ts} (100%) diff --git a/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/MetricSelect.tsx b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/MetricSelect.tsx new file mode 100644 index 00000000000..3992443e009 --- /dev/null +++ b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/MetricSelect.tsx @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { + SelectContent, + SelectItem, + SelectListbox, + SelectRoot, + SelectTrigger, + Text, +} from '@nvidia/foundations-react-core'; +import { + metricLabel, + type ParetoMetric, +} from '@studio/components/charts/ExperimentGroupParetoChart/utils'; +import type { FC } from 'react'; + +interface MetricSelectProps { + label: string; + value: string; + metrics: readonly ParetoMetric[]; + onChange: (id: string) => void; +} + +/** A labeled dropdown for choosing the metric on one Pareto axis. */ +export const MetricSelect: FC = ({ label, value, metrics, onChange }) => ( + +); diff --git a/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/ParetoTooltip.tsx b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/ParetoTooltip.tsx new file mode 100644 index 00000000000..e9a1840a1ec --- /dev/null +++ b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/ParetoTooltip.tsx @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { Text } from '@nvidia/foundations-react-core'; +import type { + ParetoMetric, + ParetoPlotPoint, +} from '@studio/components/charts/ExperimentGroupParetoChart/utils'; +import type { FC } from 'react'; + +/** Format a metric value for tooltips: cost as USD, latency in ms, evaluator scores as-is. */ +const formatMetricValue = (metric: ParetoMetric, value: number): string => { + if (metric.id === 'cost_usd') { + return `$${value.toLocaleString(undefined, { maximumFractionDigits: 4 })}`; + } + if (metric.id === 'latency_ms') { + return `${Math.round(value).toLocaleString()} ms`; + } + return value.toLocaleString(undefined, { maximumFractionDigits: 3 }); +}; + +interface ParetoTooltipProps { + active?: boolean; + payload?: ReadonlyArray<{ payload: ParetoPlotPoint }>; + xMetric: ParetoMetric; + yMetric: ParetoMetric; +} + +/** Recharts tooltip for a Pareto point: the evaluation name, both plotted metric values, and a + * frontier badge when the point isn't dominated. */ +export const ParetoTooltip: FC = ({ active, payload, xMetric, yMetric }) => { + const point = payload?.[0]?.payload; + if (!active || !point) return null; + return ( +
+ {point.name} +
+ + {xMetric.label}: {formatMetricValue(xMetric, point.x)} + + + {yMetric.label}: {formatMetricValue(yMetric, point.y)} + + {point.onFrontier && ( + + On the Pareto frontier + + )} +
+
+ ); +}; diff --git a/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/index.tsx b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/index.tsx index 7cd2d3b6361..bf09fa8bb82 100644 --- a/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/index.tsx +++ b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/index.tsx @@ -7,23 +7,15 @@ import { useUpdateExperimentGroup, } from '@nemo/sdk/generated/platform/api'; import type { ExperimentGroupResponse } from '@nemo/sdk/generated/platform/schema'; -import { - Button, - SelectContent, - SelectItem, - SelectListbox, - SelectRoot, - SelectTrigger, - Text, -} from '@nvidia/foundations-react-core'; +import { Button, Text } from '@nvidia/foundations-react-core'; +import { MetricSelect } from '@studio/components/charts/ExperimentGroupParetoChart/MetricSelect'; +import { ParetoTooltip } from '@studio/components/charts/ExperimentGroupParetoChart/ParetoTooltip'; +import { useParetoEvaluations } from '@studio/components/charts/ExperimentGroupParetoChart/useParetoEvaluations'; import { buildParetoPoints, deriveParetoMetrics, metricLabel, - type ParetoMetric, - type ParetoPlotPoint, -} from '@studio/components/charts/ExperimentGroupParetoChart/paretoMetrics'; -import { useParetoEvaluations } from '@studio/components/charts/ExperimentGroupParetoChart/useParetoEvaluations'; +} from '@studio/components/charts/ExperimentGroupParetoChart/utils'; import type { EvaluationRow } from '@studio/components/dataViews/ExperimentGroupDataView/useExperimentGroupEvaluations'; import { useQueryClient } from '@tanstack/react-query'; import { Loader2, Save } from 'lucide-react'; @@ -67,81 +59,6 @@ const formatAxisTick = (value: number): string => ? value.toLocaleString(undefined, { notation: 'compact', maximumFractionDigits: 1 }) : value.toLocaleString(undefined, { maximumFractionDigits: 3 }); -/** Format a metric value for tooltips: cost as USD, latency in ms, evaluator scores as-is. */ -const formatMetricValue = (metric: ParetoMetric, value: number): string => { - if (metric.id === 'cost_usd') { - return `$${value.toLocaleString(undefined, { maximumFractionDigits: 4 })}`; - } - if (metric.id === 'latency_ms') { - return `${Math.round(value).toLocaleString()} ms`; - } - return value.toLocaleString(undefined, { maximumFractionDigits: 3 }); -}; - -interface ParetoTooltipProps { - active?: boolean; - payload?: ReadonlyArray<{ payload: ParetoPlotPoint }>; - xMetric: ParetoMetric; - yMetric: ParetoMetric; -} - -const ParetoTooltip: FC = ({ active, payload, xMetric, yMetric }) => { - const point = payload?.[0]?.payload; - if (!active || !point) return null; - return ( -
- {point.name} -
- - {xMetric.label}: {formatMetricValue(xMetric, point.x)} - - - {yMetric.label}: {formatMetricValue(yMetric, point.y)} - - {point.onFrontier && ( - - On the Pareto frontier - - )} -
-
- ); -}; - -interface MetricSelectProps { - label: string; - value: string; - metrics: readonly ParetoMetric[]; - onChange: (id: string) => void; -} - -const MetricSelect: FC = ({ label, value, metrics, onChange }) => ( - -); - /** * Cost-vs-accuracy Pareto view for an experiment group: one point per evaluation with the Pareto * frontier highlighted. Points come from the group's evaluations (the existing list endpoint, which diff --git a/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/useParetoEvaluations.ts b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/useParetoEvaluations.ts index 475aca56a93..7b076329558 100644 --- a/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/useParetoEvaluations.ts +++ b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/useParetoEvaluations.ts @@ -4,12 +4,9 @@ import { useListEvaluations } from '@nemo/sdk/generated/platform/api'; import type { EvaluationFilter } from '@nemo/sdk/generated/platform/schema'; import type { EvaluationRow } from '@studio/components/dataViews/ExperimentGroupDataView/useExperimentGroupEvaluations'; +import { DEFAULT_LARGE_PAGE_SIZE } from '@studio/constants/constants'; import { useMemo } from 'react'; -/** The list endpoint caps page_size at 1000; a group's evaluation set is far smaller, so one page - * covers every point the Pareto chart needs (the leaderboard, by contrast, is paginated). */ -const MAX_EVALUATIONS = 1000; - export interface ParetoEvaluations { rows: EvaluationRow[]; isLoading: boolean; @@ -34,7 +31,7 @@ export function useParetoEvaluations( workspace, { page: 1, - page_size: MAX_EVALUATIONS, + page_size: DEFAULT_LARGE_PAGE_SIZE, filter: { experiment_group_id: experimentGroupId } as EvaluationFilter, }, { query: { enabled } } diff --git a/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/paretoMetrics.test.ts b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/utils.test.ts similarity index 98% rename from web/packages/studio/src/components/charts/ExperimentGroupParetoChart/paretoMetrics.test.ts rename to web/packages/studio/src/components/charts/ExperimentGroupParetoChart/utils.test.ts index a01111b50ff..183fb96e1cc 100644 --- a/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/paretoMetrics.test.ts +++ b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/utils.test.ts @@ -5,7 +5,7 @@ import { buildParetoPoints, deriveParetoMetrics, type ParetoMetric, -} from '@studio/components/charts/ExperimentGroupParetoChart/paretoMetrics'; +} from '@studio/components/charts/ExperimentGroupParetoChart/utils'; import type { EvaluationRow } from '@studio/components/dataViews/ExperimentGroupDataView/useExperimentGroupEvaluations'; // Only the fields the Pareto accessors read (name + cost/latency/evaluator rollup means) are set; diff --git a/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/paretoMetrics.ts b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/utils.ts similarity index 100% rename from web/packages/studio/src/components/charts/ExperimentGroupParetoChart/paretoMetrics.ts rename to web/packages/studio/src/components/charts/ExperimentGroupParetoChart/utils.ts From 56e918f7e7565f68f1e4e4f1bedfe6129ada1d81 Mon Sep 17 00:00:00 2001 From: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com> Date: Mon, 27 Jul 2026 12:57:54 -0600 Subject: [PATCH 2/2] cleanup commemts Signed-off-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com> --- .../MetricSelect.tsx | 1 - .../ParetoTooltip.tsx | 2 - .../ExperimentGroupParetoChart/index.tsx | 40 +++++-------------- .../useParetoEvaluations.ts | 11 ++--- .../ExperimentGroupParetoChart/utils.ts | 20 +++------- .../ExperimentGroupDataView/index.tsx | 7 +--- 6 files changed, 20 insertions(+), 61 deletions(-) diff --git a/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/MetricSelect.tsx b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/MetricSelect.tsx index 3992443e009..62884bda6c0 100644 --- a/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/MetricSelect.tsx +++ b/web/packages/studio/src/components/charts/ExperimentGroupParetoChart/MetricSelect.tsx @@ -22,7 +22,6 @@ interface MetricSelectProps { onChange: (id: string) => void; } -/** A labeled dropdown for choosing the metric on one Pareto axis. */ export const MetricSelect: FC = ({ label, value, metrics, onChange }) => (