diff --git a/web/packages/studio/src/api/evaluation/details/useEvaluationDownloadResultsById.tsx b/web/packages/studio/src/api/evaluation/details/useEvaluationDownloadResultsById.tsx deleted file mode 100644 index 9129ac79d7..0000000000 --- a/web/packages/studio/src/api/evaluation/details/useEvaluationDownloadResultsById.tsx +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import type { ExcludedChatCompletionMessageParam } from '@nemo/common/src/types/chat'; -import { evaluatorDownloadEvaluateJobResult } from '@nemo/sdk/generated/evaluator/api'; -import { useQuery } from '@tanstack/react-query'; - -export interface EvaluationMetrics { - bleu?: { - scores?: { - sentence?: { - value: number; - }; - }; - }; - [key: string]: unknown; -} - -export type EvaluationItem = - | { - prompt: string; - ideal_response: string; - } - | { - messages: ExcludedChatCompletionMessageParam[]; - }; - -export interface EvaluationSample { - output_text: string; -} -export interface EvaluationResultItem { - item: EvaluationItem; - sample: EvaluationSample; - metrics: EvaluationMetrics; -} - -interface RowScore { - index: number; - row: Record; - scores?: Record; - error?: string; -} - -function mapRowScores(rows: RowScore[]): EvaluationResultItem[] { - return rows.map((row) => ({ - item: { - prompt: String(row.row?.prompt ?? row.row?.input ?? ''), - ideal_response: String(row.row?.ideal_response ?? row.row?.reference ?? ''), - ...(row.row?.messages - ? { messages: row.row.messages as ExcludedChatCompletionMessageParam[] } - : {}), - } as EvaluationItem, - sample: { - output_text: String(row.row?.output ?? row.row?.output_text ?? ''), - }, - metrics: mapScores(row.scores), - })); -} - -function mapScores(scores?: Record): EvaluationMetrics { - if (!scores) return {}; - - const result: EvaluationMetrics = {}; - - for (const [key, value] of Object.entries(scores)) { - if (key === 'sentence' || key === 'corpus') { - if (!result.bleu) { - result.bleu = { scores: {} }; - } - if (!result.bleu!.scores) { - result.bleu!.scores = {}; - } - (result.bleu!.scores as Record)[key] = { value }; - } else { - result[key] = value; - } - } - - return result; -} - -async function fetchEvaluationResults( - workspace: string, - jobName: string, - name: string -): Promise { - const blob = await evaluatorDownloadEvaluateJobResult(workspace, jobName, name); - - const text = await blob.text(); - const parsed = JSON.parse(text); - - const rows: RowScore[] = Array.isArray(parsed) - ? parsed - : (parsed.data ?? parsed.row_scores ?? []); - - return mapRowScores(rows); -} - -export const useEvaluationDownloadResultsById = ( - workspace: string, - jobName: string, - name = 'row_scores' -) => { - return useQuery({ - queryKey: ['evaluationDownloadResults', workspace, jobName, name], - queryFn: () => fetchEvaluationResults(workspace, jobName, name), - enabled: !!workspace && !!jobName, - }); -}; diff --git a/web/packages/studio/src/components/common/Loader.tsx b/web/packages/studio/src/components/common/Loader.tsx deleted file mode 100644 index 4d59b5086b..0000000000 --- a/web/packages/studio/src/components/common/Loader.tsx +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { Spinner, Stack } from '@nvidia/foundations-react-core'; -import { FC } from 'react'; - -/** Compact loading spinner used in forms and inline contexts. */ -export const Loader: FC = () => ( - - - -); diff --git a/web/packages/studio/src/components/dataViews/SafeSynthesizerJobsDataView/Empty.tsx b/web/packages/studio/src/components/dataViews/SafeSynthesizerJobsDataView/Empty.tsx deleted file mode 100644 index 4e5e183533..0000000000 --- a/web/packages/studio/src/components/dataViews/SafeSynthesizerJobsDataView/Empty.tsx +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { TableEmptyState } from '@nemo/common/src/components/TableEmptyState'; -import { removeEmptyValues } from '@nemo/common/src/utils/removeEmptyValues'; -import { Button, Stack } from '@nvidia/foundations-react-core'; -import { SafeSynthesizerJobsFilterState } from '@studio/components/dataViews/SafeSynthesizerJobsDataView/types'; -import { DocumentationButton } from '@studio/components/DocumentationButton'; -import { LINK_DOCS_PROJECT } from '@studio/constants/links'; -import { getNewSafeSynthesizerRoute } from '@studio/routes/utils'; -import { Link } from 'react-router-dom'; - -export const Empty = ({ - filterState, - workspace, -}: { - filterState: SafeSynthesizerJobsFilterState; - workspace: string; -}) => ( - - - - - - } - /> - -); diff --git a/web/packages/studio/src/components/evaluation/AvatarColorText.tsx b/web/packages/studio/src/components/evaluation/AvatarColorText.tsx deleted file mode 100644 index 79accc9223..0000000000 --- a/web/packages/studio/src/components/evaluation/AvatarColorText.tsx +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { Avatar, Flex } from '@nvidia/foundations-react-core'; -import { FC, PropsWithChildren } from 'react'; - -interface AvatarColorTextProps { - color?: string; - className?: string; - title?: string; - onClick?: () => void; -} - -/** - * A component that displays an avatar with a color indicator next to text content. - * Used in evaluation comparisons to visually distinguish between different models. - */ -export const AvatarColorText: FC> = ({ - className, - color, - children, - title, - onClick, -}) => { - return ( - - - {children} - - ); -}; diff --git a/web/packages/studio/src/components/evaluation/Configurations/ActionMenu.tsx b/web/packages/studio/src/components/evaluation/Configurations/ActionMenu.tsx deleted file mode 100644 index ca2d065127..0000000000 --- a/web/packages/studio/src/components/evaluation/Configurations/ActionMenu.tsx +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { - DropdownRoot, - DropdownTrigger, - DropdownContent, - DropdownItem, - Flex, -} from '@nvidia/foundations-react-core'; -import { FC } from 'react'; - -export interface QuickActionItem { - slotLabel: string; - slotIcon?: React.ReactNode; - onSelect: () => void; -} - -interface ActionMenuProps { - slotTrigger: React.ReactNode; - actions: QuickActionItem[]; -} - -/** - * Dropdown menu for evaluation configuration actions. - * Supports actions like "View Details" and "Create Evaluation". - */ -export const ActionMenu: FC = ({ actions, slotTrigger }) => { - const handleItemClicked = - (action: QuickActionItem): React.MouseEventHandler => - (e) => { - e.stopPropagation(); - action.onSelect(); - }; - - return ( - - e.stopPropagation()}> - {slotTrigger} - - - {actions.map((action, key) => ( - - - {action.slotIcon} - {action.slotLabel} - - - ))} - - - ); -}; diff --git a/web/packages/studio/src/components/evaluation/Jobs/TestMetric/ResultsLog.tsx b/web/packages/studio/src/components/evaluation/Jobs/TestMetric/ResultsLog.tsx deleted file mode 100644 index 59f4f75450..0000000000 --- a/web/packages/studio/src/components/evaluation/Jobs/TestMetric/ResultsLog.tsx +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { useToast } from '@nemo/common/src/providers/toast/useToast'; -import { Badge, CodeSnippet, Flex, Stack, Text } from '@nvidia/foundations-react-core'; -import type { FC } from 'react'; - -interface AggregateScore { - name: string; - count: number; - mean?: number | null; - min?: number | null; - max?: number | null; -} - -interface RowScore { - index: number; - scores?: Record; - error?: string | null; -} - -interface EvaluateJobResults { - aggregate_scores: AggregateScore[]; - row_scores: RowScore[]; -} - -function formatScoreValue(value: number): string { - return String(value); -} - -function buildRowResultLines(rowScores: RowScore[], scoreOrder: string[]): string[] { - const lines: string[] = []; - const sorted = [...rowScores].sort((a, b) => a.index - b.index); - - for (const row of sorted) { - if (row.scores) { - const seen = new Set(); - for (const name of scoreOrder) { - if (name in row.scores) { - seen.add(name); - lines.push(`Row ${row.index}: ${name} = ${formatScoreValue(row.scores[name])}`); - } - } - for (const [name, value] of Object.entries(row.scores)) { - if (seen.has(name)) continue; - lines.push(`Row ${row.index}: ${name} = ${formatScoreValue(value)}`); - } - } else { - lines.push(`Row ${row.index}: error = ${row.error ?? 'Unknown error'}`); - } - } - - return lines; -} - -export const ResultsLog: FC<{ results: EvaluateJobResults }> = ({ results }) => { - const toast = useToast(); - const { aggregate_scores, row_scores } = results; - const scoreNames = aggregate_scores.map((s) => s.name); - const resultLines = buildRowResultLines(row_scores, scoreNames); - const resultText = resultLines.join('\n'); - - return ( - - - Aggregate Scores - - {aggregate_scores.map((agg) => ( - - {agg.name}: mean={agg.mean != null ? agg.mean.toFixed(2) : 'N/A'} min= - {agg.min != null ? agg.min : 'N/A'} max= - {agg.max != null ? agg.max : 'N/A'} (n={agg.count}) - - ))} - - - - - Results - - } - onCopySuccess={() => toast.success('Results copied to clipboard')} - attributes={{ - CodeSnippetCode: { className: 'max-h-[min(40vh,360px)]' }, - }} - /> - - ); -}; diff --git a/web/packages/studio/src/constants/tools.tsx b/web/packages/studio/src/constants/tools.tsx deleted file mode 100644 index 990644d0cb..0000000000 --- a/web/packages/studio/src/constants/tools.tsx +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -import { Button, PageHeader } from '@nvidia/foundations-react-core'; -import { ReactNode } from 'react'; - -/** - * A collection of functions that can be used in a chat completion. - * These are allowlisted tools that are avaiable for the Studio App to use. - * The return type is a ReactNode because the tool call is rendered in the UI. - */ -export const tools: Record ReactNode> = { - get_weather: (): string => { - return "I don't know the weather, what do I look like?"; - }, - rich_content: (parameters: unknown): ReactNode => { - const props = parameters as { name: string; props: Record }; - if (props.name === 'Button') { - return