Skip to content

Commit

Permalink
feat(traces): evaluation summary on the header (#2000)
Browse files Browse the repository at this point in the history
* feat(traces): spanEvaluations summary

* wip

* Add a tooltip

* fall back value

* add streaming

* tsc

* explicit type

* fix comment
  • Loading branch information
mikeldking authored Dec 21, 2023
1 parent e6f6e7b commit 965beb0
Show file tree
Hide file tree
Showing 9 changed files with 553 additions and 10 deletions.
2 changes: 1 addition & 1 deletion app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
"dev:server:credit_card_fraud:single": "python3 -m phoenix.server.main fixture credit_card_fraud --primary-only true",
"dev:server:llm": "python3 -m phoenix.server.main fixture llm_summarization",
"dev:server:wiki": "python3 -m phoenix.server.main fixture wiki",
"dev:server:traces:llama_index_rag": "python3 -m phoenix.server.main trace-fixture llama_index_rag",
"dev:server:traces:llama_index_rag": "python3 -m phoenix.server.main trace-fixture llama_index_rag --simulate-streaming true",
"dev:server:traces:llama_index_calculator_agent": "python3 -m phoenix.server.main trace-fixture llama_index_calculator_agent",
"dev:server:traces:langchain_qa_with_sources": "python3 -m phoenix.server.main trace-fixture langchain_qa_with_sources",
"dev:server:traces:random": "python3 -m phoenix.server.main trace-fixture random --simulate-streaming true",
Expand Down
158 changes: 158 additions & 0 deletions app/src/pages/tracing/EvaluationSummary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import React, { startTransition, Suspense, useEffect } from "react";
import { graphql, useLazyLoadQuery, useRefetchableFragment } from "react-relay";
import { Cell, Pie, PieChart } from "recharts";

import {
Flex,
HelpTooltip,
Text,
TooltipTrigger,
TriggerWrap,
View,
} from "@arizeai/components";

import {
ChartTooltipDivider,
ChartTooltipItem,
useChartColors,
} from "@phoenix/components/chart";
import { useStreamState } from "@phoenix/contexts/StreamStateContext";
import { formatFloat, formatPercent } from "@phoenix/utils/numberFormatUtils";

import { EvaluationSummaryQuery } from "./__generated__/EvaluationSummaryQuery.graphql";
import { EvaluationSummaryValueFragment$key } from "./__generated__/EvaluationSummaryValueFragment.graphql";

type EvaluationSummaryProps = {
evaluationName: string;
};
export function EvaluationSummary({ evaluationName }: EvaluationSummaryProps) {
const data = useLazyLoadQuery<EvaluationSummaryQuery>(
graphql`
query EvaluationSummaryQuery($evaluationName: String!) {
...EvaluationSummaryValueFragment
@arguments(evaluationName: $evaluationName)
}
`,
{
evaluationName,
}
);
return (
<Flex direction="column">
<Text elementType="h3" textSize="medium" color="text-700">
{evaluationName}
</Text>
<Suspense fallback={<Text textSize="xlarge">--</Text>}>
<EvaluationSummaryValue evaluationName={evaluationName} query={data} />
</Suspense>
</Flex>
);
}

function EvaluationSummaryValue(props: {
evaluationName: string;
query: EvaluationSummaryValueFragment$key;
}) {
const { query } = props;
const { fetchKey } = useStreamState();
const [data, refetch] = useRefetchableFragment<
EvaluationSummaryQuery,
EvaluationSummaryValueFragment$key
>(
graphql`
fragment EvaluationSummaryValueFragment on Query
@refetchable(queryName: "EvaluationSummaryValueQuery")
@argumentDefinitions(evaluationName: { type: "String!" }) {
spanEvaluationSummary(evaluationName: $evaluationName) {
labelFractions {
label
fraction
}
meanScore
}
}
`,
query
);

// Refetch the evaluation summary if the fetchKey changes
useEffect(() => {
startTransition(() => {
refetch({}, { fetchPolicy: "store-and-network" });
});
}, [fetchKey, refetch]);

const chartColors = useChartColors();
const colors = [
chartColors.default,
chartColors.gray600,
chartColors.gray400,
chartColors.gray200,
];
const meanScore = data?.spanEvaluationSummary?.meanScore;
const labelFractions = data?.spanEvaluationSummary?.labelFractions;
const hasMeanScore = typeof meanScore === "number";
const hasLabelFractions =
Array.isArray(labelFractions) && labelFractions.length > 0;

return (
<TooltipTrigger delay={0} placement="bottom">
<TriggerWrap>
<Flex direction="row" alignItems="center" gap="size-50">
{hasLabelFractions ? (
<PieChart width={24} height={24}>
<Pie
data={labelFractions}
dataKey="fraction"
nameKey="label"
cx="50%"
cy="50%"
innerRadius={8}
outerRadius={11}
strokeWidth={0}
stroke="transparent"
>
{labelFractions.map((entry, index) => (
<Cell
key={`cell-${index}`}
fill={colors[index % colors.length]}
/>
))}
</Pie>
</PieChart>
) : null}
<Text textSize="xlarge">
{hasMeanScore ? formatFloat(meanScore) : "--"}
</Text>
</Flex>
</TriggerWrap>
<HelpTooltip>
<View width="size-2400">
<Flex direction="column" gap="size-50">
{hasLabelFractions && (
<ul>
{labelFractions.map((entry, index) => (
<li key={entry.label}>
<ChartTooltipItem
color={colors[index % colors.length]}
name={entry.label}
shape="square"
value={formatPercent(entry.fraction * 100)}
/>
</li>
))}
</ul>
)}
{hasLabelFractions && hasMeanScore ? <ChartTooltipDivider /> : null}
{hasMeanScore ? (
<Flex direction="row" justifyContent="space-between">
<Text>mean</Text>
<Text>{formatFloat(meanScore)}</Text>
</Flex>
) : null}
</Flex>
</View>
</HelpTooltip>
</TooltipTrigger>
);
}
8 changes: 8 additions & 0 deletions app/src/pages/tracing/TracingHomePageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { intFormatter } from "@phoenix/utils/numberFormatUtils";

import { TracingHomePageHeader_stats$key } from "./__generated__/TracingHomePageHeader_stats.graphql";
import { TracingHomePageHeaderQuery } from "./__generated__/TracingHomePageHeaderQuery.graphql";
import { EvaluationSummary } from "./EvaluationSummary";

export function TracingHomePageHeader(props: {
query: TracingHomePageHeader_stats$key;
Expand Down Expand Up @@ -38,6 +39,8 @@ export function TracingHomePageHeader(props: {
latencyMsP50
latencyMsP99
}
spanEvaluationNames
documentEvaluationNames
}
`,
props.query
Expand All @@ -53,6 +56,8 @@ export function TracingHomePageHeader(props: {
const latencyMsP50 = data?.traceDatasetInfo?.latencyMsP50;
const latencyMsP99 = data?.traceDatasetInfo?.latencyMsP99;
const tokenCountTotal = data?.traceDatasetInfo?.tokenCountTotal;
const spanEvaluationNames = data?.spanEvaluationNames;

return (
<View
paddingStart="size-200"
Expand Down Expand Up @@ -98,6 +103,9 @@ export function TracingHomePageHeader(props: {
<Text textSize="xlarge">--</Text>
)}
</Flex>
{spanEvaluationNames.map((name) => (
<EvaluationSummary key={name} evaluationName={name} />
))}
</Flex>
<>{extra}</>
</Flex>
Expand Down
119 changes: 119 additions & 0 deletions app/src/pages/tracing/__generated__/EvaluationSummaryQuery.graphql.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 965beb0

Please sign in to comment.