Skip to content

Commit

Permalink
feat(playground): parse span input messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Parker-Stafford committed Oct 7, 2024
1 parent a9bd2d2 commit 182c053
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 88 deletions.
5 changes: 3 additions & 2 deletions app/src/pages/playground/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import {
PlaygroundProvider,
usePlaygroundContext,
} from "@phoenix/contexts/PlaygroundContext";
import { PlaygroundProps } from "@phoenix/store";

import { PlaygroundInstance } from "./PlaygroundInstance";
import { PlaygroundOperationTypeRadioGroup } from "./PlaygroundOperationTypeRadioGroup";

export function Playground() {
export function Playground(props: Partial<PlaygroundProps>) {
return (
<PlaygroundProvider>
<PlaygroundProvider {...props}>
<View
borderBottomColor="dark"
borderBottomWidth="thin"
Expand Down
83 changes: 24 additions & 59 deletions app/src/pages/playground/SpanPlaygroundPage.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,18 @@
import React, { useMemo } from "react";
import { useLoaderData } from "react-router";
import { z } from "zod";

import { PlaygroundInstance } from "@phoenix/store";
import { safelyParseJSON } from "@phoenix/utils/jsonUtils";

import { spanPlaygroundPageLoaderQuery$data } from "./__generated__/spanPlaygroundPageLoaderQuery.graphql";
import { Playground } from "./Playground";
import { llmAttributesSchema } from "./schemas";

type PlaygroundSpan = Extract<
spanPlaygroundPageLoaderQuery$data["span"],
{ __typename: "Span" }
>;

const toolCallSchema = z
.object({
function: z
.object({
name: z.string(),
arguments: z.string(),
})
.partial(),
})
.partial();

const messageSchema = z
.object({
role: z.string(),
content: z.string(),
name: z.string(),
tool_calls: z.array(toolCallSchema),
})
.partial();

const llmAttributesSchema = z
.object({
model_name: z.string(),
prompts: z.array(z.string()),
prompt_template: z
.object({
template: z.string(),
variables: z.record(z.string()),
})
.partial(),
})
.partial();

export function SpanPlaygroundPage() {
const data = useLoaderData() as spanPlaygroundPageLoaderQuery$data;
const span = useMemo(() => {
Expand All @@ -58,37 +26,34 @@ export function SpanPlaygroundPage() {
throw new Error("Invalid span");
}

const PlaygroundInstance = z.object({
template: z.string(),
});
const playgroundInstance = transformSpanAttributesToPlaygroundInstance(span);

return <Playground />;
return <Playground instances={[playgroundInstance]} />;
}

type MessageTemplate = {
messages: { role: string; message: string }[];
};

const a = z.object({
messages: z.array(
z.object({
role: z.string(),
message: z.string(),
})
),
});
function transformSpanAttributesToPlaygroundInstance(
span: PlaygroundSpan
): PlaygroundInstance {
const result = ZMessageTemplate.safeParse(span);
if (!result.success) {
const { json: parsedAttributes, parseError } = safelyParseJSON(
span.attributes
);
if (parseError) {
throw new Error("Invalid attributes");
}
const { data, success } = llmAttributesSchema.safeParse(parsedAttributes);
if (!success) {
throw new Error("Invalid data");
}
return result.data;
// return {
// messages: data.messages.map(message => ({
// role: message.role,
// message: message.message
// }))
// };
return {
id: 1,
input: {
variables: {},
},
template: {
__type: "chat",
messages: data["llm.input_messages"],
},
output: data["llm.output_messages"],
tools: undefined,
};
}
2 changes: 2 additions & 0 deletions app/src/pages/playground/constants.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export const NUM_MAX_PLAYGROUND_INSTANCES = 2;

export const DEFAULT_CHAT_ROLE = "system";
45 changes: 23 additions & 22 deletions app/src/pages/playground/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { z } from "zod";

import {
ImageAttributesPostfixes,
LLMAttributePostfixes,
MessageAttributePostfixes,
MessageContentsAttributePostfixes,
SemanticAttributePrefixes,
SemanticConventions,
} from "@arizeai/openinference-semantic-conventions";

/**
Expand All @@ -22,6 +22,7 @@ const toolCallSchema = z
.partial(),
})
.partial();

/**
* The zod schema for llm message contents
* @see {@link https://github.com/Arize-ai/openinference/blob/main/spec/semantic_conventions.md|Semantic Conventions}
Expand All @@ -43,25 +44,25 @@ const messageContentSchema = z.object({
})
.partial(),
});
const messageSchema = z
.object({
[MessageAttributePostfixes.role]: z.string(),
[MessageAttributePostfixes.content]: z.string(),
[MessageAttributePostfixes.name]: z.string(),
[MessageAttributePostfixes.tool_calls]: z.array(toolCallSchema),
[MessageAttributePostfixes.contents]: z.array(messageContentSchema),
})
.partial();
/**
* The zod schema for llm messages
* @see {@link https://github.com/Arize-ai/openinference/blob/main/spec/semantic_conventions.md|Semantic Conventions}
*/
const messageSchema = z.object({
[MessageAttributePostfixes.role]: z.string(),
[MessageAttributePostfixes.content]: z.string(),
[MessageAttributePostfixes.name]: z.string().optional(),
[MessageAttributePostfixes.tool_calls]: z.array(toolCallSchema).optional(),
[MessageAttributePostfixes.contents]: z
.array(messageContentSchema)
.optional(),
});

const llmAttributesSchema = z
.object({
[LLMAttributePostfixes.model_name]: z.string(),
[LLMAttributePostfixes.prompts]: z.array(z.string()),
prompt_template: z
.object({
template: z.string(),
variables: z.record(z.string()),
})
.partial(),
})
.partial();
/**
* The zod schema for llm attributes
* @see {@link https://github.com/Arize-ai/openinference/blob/main/spec/semantic_conventions.md|Semantic Conventions}
*/
export const llmAttributesSchema = z.object({
[SemanticConventions.LLM_INPUT_MESSAGES]: z.array(messageSchema),
[SemanticConventions.LLM_OUTPUT_MESSAGES]: z.optional(z.array(messageSchema)),
});
7 changes: 2 additions & 5 deletions app/src/pages/trace/SpanDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ import {
AttributeTool,
} from "@phoenix/openInference/tracing/types";
import { assertUnreachable, isStringArray } from "@phoenix/typeUtils";
import { safelyParseJSON } from "@phoenix/utils/jsonUtils";
import { formatFloat, numberFormatter } from "@phoenix/utils/numberFormatUtils";

import { RetrievalEvaluationLabel } from "../project/RetrievalEvaluationLabel";
Expand Down Expand Up @@ -117,11 +118,7 @@ const useSafelyParsedJSON = (
jsonStr: string
): { json: { [key: string]: unknown } | null; parseError?: unknown } => {
return useMemo(() => {
try {
return { json: JSON.parse(jsonStr) };
} catch (e) {
return { json: null, parseError: e };
}
return safelyParseJSON(jsonStr);
}, [jsonStr]);
};

Expand Down
8 changes: 8 additions & 0 deletions app/src/utils/jsonUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,11 @@ export function isJSONString({
export function isJSONObjectString(str: string) {
return isJSONString({ str, excludeArray: true, excludePrimitives: true });
}

export function safelyParseJSON(str: string) {
try {
return { json: JSON.parse(str) };
} catch (e) {
return { json: null, parseError: e };
}
}

0 comments on commit 182c053

Please sign in to comment.