Skip to content

Commit

Permalink
feat: Implement "Move Output" button on Playground Output (#5509)
Browse files Browse the repository at this point in the history
* feat: Implement "Move Output" button to Playground Output

This allows users to copy a desireable result from the playground back into their conversation,
to continue iteration

* Convert moved tool calls into the correct provider schema
  • Loading branch information
cephalization authored Nov 23, 2024
1 parent 38f8f56 commit aa8c283
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 4 deletions.
31 changes: 27 additions & 4 deletions app/src/pages/playground/PlaygroundOutput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
generateMessageId,
PlaygroundInstance,
} from "@phoenix/store";
import { isStringKeyedObject } from "@phoenix/typeUtils";
import { isStringKeyedObject, Mutable } from "@phoenix/typeUtils";
import {
getErrorMessagesFromRelayMutationError,
getErrorMessagesFromRelaySubscriptionError,
Expand All @@ -44,6 +44,7 @@ import {
} from "./__generated__/PlaygroundOutputSubscription.graphql";
import PlaygroundOutputSubscription from "./__generated__/PlaygroundOutputSubscription.graphql";
import { PlaygroundErrorWrap } from "./PlaygroundErrorWrap";
import { PlaygroundOutputMoveButton } from "./PlaygroundOutputMoveButton";
import {
PartialOutputToolCall,
PlaygroundToolCall,
Expand Down Expand Up @@ -316,14 +317,24 @@ export function PlaygroundOutput(props: PlaygroundOutputProps) {
]
);

const cleanup = useCallback(() => {
setOutputContent(undefined);
setToolCalls([]);
setOutputError(null);
updateInstance({
instanceId,
patch: {
spanId: null,
},
});
}, [instanceId, updateInstance]);

useEffect(() => {
if (!hasRunId) {
return;
}
setLoading(true);
setOutputContent(undefined);
setToolCalls([]);
setOutputError(null);
cleanup();
const input = getChatCompletionInput({
playgroundStore,
instanceId,
Expand Down Expand Up @@ -390,6 +401,7 @@ export function PlaygroundOutput(props: PlaygroundOutputProps) {
},
});
}, [
cleanup,
credentials,
environment,
generateChatCompletion,
Expand All @@ -408,6 +420,17 @@ export function PlaygroundOutput(props: PlaygroundOutputProps) {
return (
<Card
title={<TitleWithAlphabeticIndex index={index} title="Output" />}
titleExtra={
outputContent != null || toolCalls?.length > 0 ? (
<PlaygroundOutputMoveButton
outputContent={outputContent}
toolCalls={toolCalls as Mutable<typeof toolCalls>}
instance={instance}
cleanupOutput={cleanup}
/>
) : null
}
titleSeparator
collapsible
variant="compact"
bodyStyle={{ padding: 0 }}
Expand Down
93 changes: 93 additions & 0 deletions app/src/pages/playground/PlaygroundOutputMoveButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React from "react";

import {
Button,
Icon,
Icons,
Tooltip,
TooltipTrigger,
} from "@arizeai/components";

import { usePlaygroundContext } from "@phoenix/contexts/PlaygroundContext";
import {
ChatMessage,
generateMessageId,
PlaygroundInstance,
} from "@phoenix/store";
import { safelyParseJSON } from "@phoenix/utils/jsonUtils";

import { PartialOutputToolCall } from "./PlaygroundToolCall";
import {
convertMessageToolCallsToProvider,
getChatRole,
} from "./playgroundUtils";

export const PlaygroundOutputMoveButton = ({
instance,
outputContent,
toolCalls,
cleanupOutput,
}: {
instance: PlaygroundInstance;
outputContent?: string | ChatMessage[];
toolCalls: PartialOutputToolCall[];
cleanupOutput: () => void;
}) => {
const instanceId = instance.id;
const updateInstance = usePlaygroundContext((state) => state.updateInstance);
return (
<TooltipTrigger delay={500} offset={10}>
<Button
variant="default"
size="compact"
icon={<Icon svg={<Icons.PlusCircleOutline />} />}
onClick={(e) => {
e.stopPropagation();
if (instance.template.__type !== "chat") {
return;
}
const messages = Array.isArray(outputContent)
? outputContent
: outputContent
? [
{
id: generateMessageId(),
role: getChatRole("ai"),
content: outputContent,
},
]
: [];
if (toolCalls.length > 0) {
messages.push({
id: generateMessageId(),
role: getChatRole("ai"),
toolCalls: convertMessageToolCallsToProvider({
provider: instance.model.provider,
toolCalls: toolCalls.map((tc) => ({
...tc,
function: {
...tc.function,
arguments:
safelyParseJSON(tc.function.arguments)?.json ??
tc.function.arguments,
},
})),
}),
});
}
updateInstance({
instanceId,
patch: {
template: {
__type: "chat",
messages: [...instance.template.messages, ...messages],
},
},
});
cleanupOutput();
}}
/>
<Tooltip>Move Output message to the end of Prompt</Tooltip>
</TooltipTrigger>
);
};

0 comments on commit aa8c283

Please sign in to comment.