diff --git a/app/src/pages/trace/SpanDetails.tsx b/app/src/pages/trace/SpanDetails.tsx
index 8d27f54e06..05ad77e7be 100644
--- a/app/src/pages/trace/SpanDetails.tsx
+++ b/app/src/pages/trace/SpanDetails.tsx
@@ -86,7 +86,7 @@ import {
} from "./__generated__/SpanDetailsQuery.graphql";
import { EditSpanAnnotationsButton } from "./EditSpanAnnotationsButton";
import { SpanCodeDropdown } from "./SpanCodeDropdown";
-import { SpanEvaluationsTable } from "./SpanEvaluationsTable";
+import { SpanFeedback } from "./SpanFeedback";
import { SpanToDatasetExampleDialog } from "./SpanToDatasetExampleDialog";
/**
@@ -178,11 +178,6 @@ export function SpanDetails({
message
timestamp
}
- spanEvaluations {
- name
- label
- score
- }
documentRetrievalMetrics {
evaluationName
ndcg
@@ -196,7 +191,10 @@ export function SpanDetails({
score
explanation
}
- ...SpanEvaluationsTable_evals
+ spanAnnotations {
+ name
+ }
+ ...SpanFeedback_annotations
}
}
}
@@ -252,13 +250,13 @@ export function SpanDetails({
{span.spanEvaluations.length}
+ {span.spanAnnotations.length}
}
>
{(selected) => {
- return selected ? : null;
+ return selected ? : null;
}}
@@ -1637,10 +1635,6 @@ function SpanEventsList({ events }: { events: Span["events"] }) {
);
}
-function SpanEvaluations(props: { span: Span }) {
- return ;
-}
-
const attributesContextualHelp = (
diff --git a/app/src/pages/trace/SpanEvaluationsTable.tsx b/app/src/pages/trace/SpanFeedback.tsx
similarity index 62%
rename from app/src/pages/trace/SpanEvaluationsTable.tsx
rename to app/src/pages/trace/SpanFeedback.tsx
index 29ddce6220..bd6b4bf668 100644
--- a/app/src/pages/trace/SpanEvaluationsTable.tsx
+++ b/app/src/pages/trace/SpanFeedback.tsx
@@ -6,11 +6,16 @@ import {
useReactTable,
} from "@tanstack/react-table";
+import { Accordion, AccordionItem } from "@arizeai/components";
+
import { PreformattedTextCell } from "@phoenix/components/table";
import { tableCSS } from "@phoenix/components/table/styles";
import { TableEmpty } from "@phoenix/components/table/TableEmpty";
-import { SpanEvaluationsTable_evals$key } from "./__generated__/SpanEvaluationsTable_evals.graphql";
+import {
+ SpanFeedback_annotations$data,
+ SpanFeedback_annotations$key,
+} from "./__generated__/SpanFeedback_annotations.graphql";
const columns = [
{
@@ -36,29 +41,15 @@ const columns = [
},
];
-export function SpanEvaluationsTable(props: {
- span: SpanEvaluationsTable_evals$key;
+function SpanAnnotationsTable({
+ annotations,
+}: {
+ annotations: SpanFeedback_annotations$data["spanAnnotations"];
}) {
- const data = useFragment(
- graphql`
- fragment SpanEvaluationsTable_evals on Span {
- spanEvaluations {
- name
- label
- score
- explanation
- }
- }
- `,
- props.span
- );
- const evaluations = useMemo(() => {
- return [...data.spanEvaluations];
- }, [data.spanEvaluations]);
-
+ const tableData = useMemo(() => [...annotations], [annotations]);
const table = useReactTable({
columns,
- data: evaluations,
+ data: tableData,
getCoreRowModel: getCoreRowModel(),
});
const rows = table.getRowModel().rows;
@@ -107,3 +98,41 @@ export function SpanEvaluationsTable(props: {
);
}
+
+export function SpanFeedback({ span }: { span: SpanFeedback_annotations$key }) {
+ const data = useFragment(
+ graphql`
+ fragment SpanFeedback_annotations on Span {
+ spanAnnotations {
+ name
+ label
+ score
+ explanation
+ annotatorKind
+ }
+ }
+ `,
+ span
+ );
+
+ const humanAnnotations = useMemo(() => {
+ return data.spanAnnotations.filter(
+ (annotation) => annotation.annotatorKind === "HUMAN"
+ );
+ }, [data.spanAnnotations]);
+ const llmAnnotations = useMemo(() => {
+ return data.spanAnnotations.filter(
+ (annotation) => annotation.annotatorKind === "LLM"
+ );
+ }, [data.spanAnnotations]);
+ return (
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/app/src/pages/trace/__generated__/SpanDetailsQuery.graphql.ts b/app/src/pages/trace/__generated__/SpanDetailsQuery.graphql.ts
index 8cdaf57d28..f9992e3df6 100644
--- a/app/src/pages/trace/__generated__/SpanDetailsQuery.graphql.ts
+++ b/app/src/pages/trace/__generated__/SpanDetailsQuery.graphql.ts
@@ -1,5 +1,5 @@
/**
- * @generated SignedSource<<353a86207783c9525898f58f87984ece>>
+ * @generated SignedSource<>
* @lightSyntaxTransform
* @nogrep
*/
@@ -54,10 +54,8 @@ export type SpanDetailsQuery$data = {
readonly value: string;
} | null;
readonly parentId: string | null;
- readonly spanEvaluations: ReadonlyArray<{
- readonly label: string | null;
+ readonly spanAnnotations: ReadonlyArray<{
readonly name: string;
- readonly score: number | null;
}>;
readonly spanKind: SpanKind;
readonly startTime: string;
@@ -66,7 +64,7 @@ export type SpanDetailsQuery$data = {
readonly tokenCountCompletion: number | null;
readonly tokenCountPrompt: number | null;
readonly tokenCountTotal: number | null;
- readonly " $fragmentSpreads": FragmentRefs<"SpanEvaluationsTable_evals">;
+ readonly " $fragmentSpreads": FragmentRefs<"SpanFeedback_annotations">;
} | {
// This will never be '%other', but we need some
// value in case none of the concrete values match.
@@ -272,20 +270,6 @@ v19 = {
"storageKey": null
},
v20 = {
- "alias": null,
- "args": null,
- "kind": "ScalarField",
- "name": "label",
- "storageKey": null
-},
-v21 = {
- "alias": null,
- "args": null,
- "kind": "ScalarField",
- "name": "score",
- "storageKey": null
-},
-v22 = {
"alias": null,
"args": null,
"concreteType": "DocumentRetrievalMetrics",
@@ -324,6 +308,20 @@ v22 = {
],
"storageKey": null
},
+v21 = {
+ "alias": null,
+ "args": null,
+ "kind": "ScalarField",
+ "name": "label",
+ "storageKey": null
+},
+v22 = {
+ "alias": null,
+ "args": null,
+ "kind": "ScalarField",
+ "name": "score",
+ "storageKey": null
+},
v23 = {
"alias": null,
"args": null,
@@ -347,8 +345,8 @@ v24 = {
"storageKey": null
},
(v5/*: any*/),
- (v20/*: any*/),
(v21/*: any*/),
+ (v22/*: any*/),
(v23/*: any*/)
],
"storageKey": null
@@ -393,26 +391,24 @@ return {
"action": "THROW",
"path": "span.events"
},
+ (v20/*: any*/),
+ (v24/*: any*/),
{
"alias": null,
"args": null,
- "concreteType": "SpanEvaluation",
+ "concreteType": "SpanAnnotation",
"kind": "LinkedField",
- "name": "spanEvaluations",
+ "name": "spanAnnotations",
"plural": true,
"selections": [
- (v5/*: any*/),
- (v20/*: any*/),
- (v21/*: any*/)
+ (v5/*: any*/)
],
"storageKey": null
},
- (v22/*: any*/),
- (v24/*: any*/),
{
"args": null,
"kind": "FragmentSpread",
- "name": "SpanEvaluationsTable_evals"
+ "name": "SpanFeedback_annotations"
}
],
"type": "Span",
@@ -463,23 +459,30 @@ return {
(v17/*: any*/),
(v18/*: any*/),
(v19/*: any*/),
+ (v20/*: any*/),
+ (v24/*: any*/),
{
"alias": null,
"args": null,
- "concreteType": "SpanEvaluation",
+ "concreteType": "SpanAnnotation",
"kind": "LinkedField",
- "name": "spanEvaluations",
+ "name": "spanAnnotations",
"plural": true,
"selections": [
(v5/*: any*/),
- (v20/*: any*/),
(v21/*: any*/),
- (v23/*: any*/)
+ (v22/*: any*/),
+ (v23/*: any*/),
+ {
+ "alias": null,
+ "args": null,
+ "kind": "ScalarField",
+ "name": "annotatorKind",
+ "storageKey": null
+ }
],
"storageKey": null
- },
- (v22/*: any*/),
- (v24/*: any*/)
+ }
],
"type": "Span",
"abstractKey": null
@@ -490,16 +493,16 @@ return {
]
},
"params": {
- "cacheID": "994295103990e4b8fbff3b1422e1647f",
+ "cacheID": "1a2fd0a554755d7a72f92f71ca891a76",
"id": null,
"metadata": {},
"name": "SpanDetailsQuery",
"operationKind": "query",
- "text": "query SpanDetailsQuery(\n $spanId: GlobalID!\n) {\n span: node(id: $spanId) {\n __typename\n ... on Span {\n id\n context {\n spanId\n traceId\n }\n name\n spanKind\n statusCode: propagatedStatusCode\n statusMessage\n startTime\n parentId\n latencyMs\n tokenCountTotal\n tokenCountPrompt\n tokenCountCompletion\n input {\n value\n mimeType\n }\n output {\n value\n mimeType\n }\n attributes\n events {\n name\n message\n timestamp\n }\n spanEvaluations {\n name\n label\n score\n }\n documentRetrievalMetrics {\n evaluationName\n ndcg\n precision\n hit\n }\n documentEvaluations {\n documentPosition\n name\n label\n score\n explanation\n }\n ...SpanEvaluationsTable_evals\n }\n __isNode: __typename\n id\n }\n}\n\nfragment SpanEvaluationsTable_evals on Span {\n spanEvaluations {\n name\n label\n score\n explanation\n }\n}\n"
+ "text": "query SpanDetailsQuery(\n $spanId: GlobalID!\n) {\n span: node(id: $spanId) {\n __typename\n ... on Span {\n id\n context {\n spanId\n traceId\n }\n name\n spanKind\n statusCode: propagatedStatusCode\n statusMessage\n startTime\n parentId\n latencyMs\n tokenCountTotal\n tokenCountPrompt\n tokenCountCompletion\n input {\n value\n mimeType\n }\n output {\n value\n mimeType\n }\n attributes\n events {\n name\n message\n timestamp\n }\n documentRetrievalMetrics {\n evaluationName\n ndcg\n precision\n hit\n }\n documentEvaluations {\n documentPosition\n name\n label\n score\n explanation\n }\n spanAnnotations {\n name\n }\n ...SpanFeedback_annotations\n }\n __isNode: __typename\n id\n }\n}\n\nfragment SpanFeedback_annotations on Span {\n spanAnnotations {\n name\n label\n score\n explanation\n annotatorKind\n }\n}\n"
}
};
})();
-(node as any).hash = "39420c6270d451eca0528e7bb90fd065";
+(node as any).hash = "b2cb5f7c63f463b9b0e3b6f86724132f";
export default node;
diff --git a/app/src/pages/trace/__generated__/SpanEvaluationsTable_evals.graphql.ts b/app/src/pages/trace/__generated__/SpanFeedback_annotations.graphql.ts
similarity index 62%
rename from app/src/pages/trace/__generated__/SpanEvaluationsTable_evals.graphql.ts
rename to app/src/pages/trace/__generated__/SpanFeedback_annotations.graphql.ts
index 629814be03..15d3f25d10 100644
--- a/app/src/pages/trace/__generated__/SpanEvaluationsTable_evals.graphql.ts
+++ b/app/src/pages/trace/__generated__/SpanFeedback_annotations.graphql.ts
@@ -1,5 +1,5 @@
/**
- * @generated SignedSource<>
+ * @generated SignedSource<<9c51d189ef5a77e30b1e811d5272a33e>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,33 +9,35 @@
// @ts-nocheck
import { Fragment, ReaderFragment } from 'relay-runtime';
+export type AnnotatorKind = "HUMAN" | "LLM";
import { FragmentRefs } from "relay-runtime";
-export type SpanEvaluationsTable_evals$data = {
- readonly spanEvaluations: ReadonlyArray<{
+export type SpanFeedback_annotations$data = {
+ readonly spanAnnotations: ReadonlyArray<{
+ readonly annotatorKind: AnnotatorKind;
readonly explanation: string | null;
readonly label: string | null;
readonly name: string;
readonly score: number | null;
}>;
- readonly " $fragmentType": "SpanEvaluationsTable_evals";
+ readonly " $fragmentType": "SpanFeedback_annotations";
};
-export type SpanEvaluationsTable_evals$key = {
- readonly " $data"?: SpanEvaluationsTable_evals$data;
- readonly " $fragmentSpreads": FragmentRefs<"SpanEvaluationsTable_evals">;
+export type SpanFeedback_annotations$key = {
+ readonly " $data"?: SpanFeedback_annotations$data;
+ readonly " $fragmentSpreads": FragmentRefs<"SpanFeedback_annotations">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
- "name": "SpanEvaluationsTable_evals",
+ "name": "SpanFeedback_annotations",
"selections": [
{
"alias": null,
"args": null,
- "concreteType": "SpanEvaluation",
+ "concreteType": "SpanAnnotation",
"kind": "LinkedField",
- "name": "spanEvaluations",
+ "name": "spanAnnotations",
"plural": true,
"selections": [
{
@@ -65,6 +67,13 @@ const node: ReaderFragment = {
"kind": "ScalarField",
"name": "explanation",
"storageKey": null
+ },
+ {
+ "alias": null,
+ "args": null,
+ "kind": "ScalarField",
+ "name": "annotatorKind",
+ "storageKey": null
}
],
"storageKey": null
@@ -74,6 +83,6 @@ const node: ReaderFragment = {
"abstractKey": null
};
-(node as any).hash = "0604d02236eeb7e73817a68e2e6f12e2";
+(node as any).hash = "6199ecd4f0143cffbaa2fe5e19a8739c";
export default node;
diff --git a/app/src/typeUtils.ts b/app/src/typeUtils.ts
index d4fc0a3ef9..936a698c57 100644
--- a/app/src/typeUtils.ts
+++ b/app/src/typeUtils.ts
@@ -38,3 +38,10 @@ export function isStringArray(value: unknown): value is string[] {
export function isObject(value: unknown): value is object {
return typeof value === "object" && value !== null;
}
+
+/**
+ * Makes a type mutable
+ */
+export type Mutable = {
+ -readonly [P in keyof T]: T[P];
+};