Skip to main content
Glama

@arizeai/phoenix-mcp

Official
by Arize-ai
DatasetPage.tsx10.5 kB
import { Suspense, useCallback, useMemo } from "react"; import { graphql, usePreloadedQuery } from "react-relay"; import { Outlet, useLoaderData, useLocation, useNavigate } from "react-router"; import invariant from "tiny-invariant"; import { css } from "@emotion/react"; import { Button, Counter, Flex, Icon, Icons, LazyTabPanel, Loading, Menu, MenuItem, MenuTrigger, Popover, Tab, TabList, Tabs, Text, Token, View, } from "@phoenix/components"; import { DatasetLabelConfigButton } from "@phoenix/components/dataset"; import { Truncate } from "@phoenix/components/utility/Truncate"; import { useNotifySuccess } from "@phoenix/contexts"; import { DatasetProvider, useDatasetContext, } from "@phoenix/contexts/DatasetContext"; import { useFeatureFlag } from "@phoenix/contexts/FeatureFlagsContext"; import { datasetLoader } from "@phoenix/pages/dataset/datasetLoader"; import { prependBasename } from "@phoenix/utils/routingUtils"; import type { datasetLoaderQuery$data } from "./__generated__/datasetLoaderQuery.graphql"; import { DatasetPageQuery } from "./__generated__/DatasetPageQuery.graphql"; import { AddDatasetExampleButton } from "./AddDatasetExampleButton"; import { DatasetCodeButton } from "./DatasetCodeButton"; import { RunExperimentButton } from "./RunExperimentButton"; export const DatasetPageQueryNode = graphql` query DatasetPageQuery($id: ID!) { dataset: node(id: $id) { id ... on Dataset { id name description exampleCount experimentCount labels { id name color } latestVersions: versions( first: 1 sort: { col: createdAt, dir: desc } ) { edges { version: node { id description createdAt } } } } } } `; export function DatasetPage() { const loaderData = useLoaderData<typeof datasetLoader>(); invariant(loaderData, "loaderData is required"); const data = usePreloadedQuery<DatasetPageQuery>( DatasetPageQueryNode, loaderData.queryRef ); const latestVersion = useMemo(() => { const versions = data.dataset.latestVersions; if (versions?.edges && versions.edges.length) { return versions.edges[0].version; } return null; }, [data]); return ( <DatasetProvider datasetId={data.dataset.id} datasetName={data.dataset.name as string} latestVersion={latestVersion} > <Suspense fallback={<Loading />}> <DatasetPageContent dataset={data.dataset} /> </Suspense> </DatasetProvider> ); } const mainCSS = css` flex: 1 1 auto; display: flex; flex-direction: column; overflow: hidden; .ac-tabs { flex: 1 1 auto; overflow: hidden; display: flex; flex-direction: column; div[role="tablist"] { flex: none; } .ac-tabs__pane-container { flex: 1 1 auto; display: flex; flex-direction: column; overflow: hidden; div[role="tabpanel"]:not([hidden]) { flex: 1 1 auto; display: flex; flex-direction: column; overflow: hidden; } } } `; const TABS_CONFIG = { 0: "experiments", 1: "examples", 2: "versions", 3: "evaluators", } as const; const TABS_LIST = Object.values(TABS_CONFIG); type TabName = (typeof TABS_LIST)[number]; function isTabName(name: unknown): name is TabName { return typeof name === "string" && (TABS_LIST as string[]).includes(name); } function getTabIndexFromPathname(pathname: string): number { // We only need the last part of the path const path = pathname.split("/").at(-1); if (isTabName(path)) { return TABS_LIST.indexOf(path); } return 0; } function DatasetPageContent({ dataset, }: { dataset: datasetLoaderQuery$data["dataset"]; }) { const isEvaluatorsEnabled = useFeatureFlag("evaluators"); const isDatasetLabelEnabled = useFeatureFlag("datasetLabel"); const datasetId = dataset.id; const refreshLatestVersion = useDatasetContext( (state) => state.refreshLatestVersion ); const notifySuccess = useNotifySuccess(); const navigate = useNavigate(); const onTabChange = useCallback( (tabIndex: number) => { if (TABS_CONFIG[tabIndex as keyof typeof TABS_CONFIG]) { const path = TABS_CONFIG[tabIndex as keyof typeof TABS_CONFIG]; navigate(`/datasets/${datasetId}/${path}`); } }, [navigate, datasetId] ); // Set the initial tab const location = useLocation(); const initialIndex = getTabIndexFromPathname(location.pathname); return ( <main css={mainCSS}> <View paddingStart="size-200" paddingEnd="size-200" paddingTop="size-200" paddingBottom="size-50" flex="none" > <Flex direction="row" justifyContent="space-between" alignItems="start"> <Flex direction="column" justifyContent="space-between" alignItems="start" > <Flex direction="row" gap="size-200" alignItems="center"> {/* TODO(datasets): Add an icon here to make the UI cohesive */} {/* <Icon svg={<Icons.DatabaseOutline />} /> */} <Flex direction="column" gap="size-50"> <Text elementType="h1" size="L" weight="heavy"> {dataset.name} </Text> <Text color="text-700">{dataset.description || "--"}</Text> {dataset.labels && dataset.labels.length > 0 && ( <ul css={css` display: flex; flex-direction: row; gap: var(--ac-global-dimension-size-100); min-width: 0; flex-wrap: wrap; padding-top: var(--ac-global-dimension-size-50); `} > {dataset.labels.map((label) => ( <li key={label.id}> <Token color={label.color}> <Truncate maxWidth={200} title={label.name}> {label.name} </Truncate> </Token> </li> ))} </ul> )} </Flex> </Flex> </Flex> <Flex direction="row" gap="size-100" alignItems="center"> <MenuTrigger> <Button size="S" leadingVisual={<Icon svg={<Icons.MoreHorizontalOutline />} />} /> <Popover> <Menu aria-label="Dataset action menu" onAction={(action) => { switch (action) { case "csv": window.open( prependBasename(`/v1/datasets/${dataset.id}/csv`), "_blank" ); break; case "openai-ft": window.open( prependBasename( `/v1/datasets/${dataset.id}/jsonl/openai_ft` ), "_blank" ); break; case "openai-evals": window.open( prependBasename( `/v1/datasets/${dataset.id}/jsonl/openai_evals` ), "_blank" ); break; } }} > <MenuItem id="csv">Download CSV</MenuItem> <MenuItem id="openai-ft"> Download OpenAI Fine-Tuning JSONL </MenuItem> <MenuItem id="openai-evals"> Download OpenAI Evals JSONL </MenuItem> </Menu> </Popover> </MenuTrigger> <DatasetCodeButton /> <RunExperimentButton /> <AddDatasetExampleButton datasetId={dataset.id} onAddExampleCompleted={() => { notifySuccess({ title: "Example added", message: "The example has been added successfully and the version has been updated.", }); refreshLatestVersion(); }} /> {isDatasetLabelEnabled && ( <DatasetLabelConfigButton datasetId={dataset.id} /> )} <Button size="S" variant="primary" leadingVisual={<Icon svg={<Icons.PlayCircleOutline />} />} onPress={() => { navigate(`/playground?datasetId=${dataset.id}`); }} > Playground </Button> </Flex> </Flex> </View> <Tabs defaultSelectedKey={ initialIndex === 0 ? "experiments" : initialIndex === 1 ? "examples" : "versions" } onSelectionChange={(key) => { if (isTabName(key)) { onTabChange(TABS_LIST.indexOf(key)); } }} > <TabList> <Tab id="experiments"> Experiments <Counter>{dataset.experimentCount}</Counter> </Tab> <Tab id="examples"> Examples <Counter>{dataset.exampleCount}</Counter> </Tab> <Tab id="versions">Versions</Tab> {isEvaluatorsEnabled ? ( <Tab id="evaluators" isDisabled={!isEvaluatorsEnabled}> Evaluators </Tab> ) : null} </TabList> <LazyTabPanel id="experiments"> <Suspense> <Outlet /> </Suspense> </LazyTabPanel> <LazyTabPanel id="examples"> <Suspense> <Outlet /> </Suspense> </LazyTabPanel> <LazyTabPanel id="versions"> <Suspense> <Outlet /> </Suspense> </LazyTabPanel> <LazyTabPanel id="evaluators"> <Suspense> <Outlet /> </Suspense> </LazyTabPanel> </Tabs> </main> ); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Arize-ai/phoenix'

If you have feedback or need assistance with the MCP directory API, please join our Discord server