diff --git a/app/src/@types/generative.d.ts b/app/src/@types/generative.d.ts
index 08309ffeb6..326b6a4160 100644
--- a/app/src/@types/generative.d.ts
+++ b/app/src/@types/generative.d.ts
@@ -1 +1,6 @@
declare type ModelProvider = "OPENAI" | "AZURE_OPENAI" | "ANTHROPIC";
+
+/**
+ * The role of a chat message
+ */
+declare type ChatMessageRole = "user" | "system" | "ai" | "tool";
diff --git a/app/src/App.tsx b/app/src/App.tsx
index 6f462abba4..2c98a09883 100644
--- a/app/src/App.tsx
+++ b/app/src/App.tsx
@@ -4,6 +4,7 @@ import { ThemeProvider as EmotionThemeProvider } from "@emotion/react";
import { Provider, theme } from "@arizeai/components";
+import { CredentialsProvider } from "./contexts/CredentialsContext";
import { FeatureFlagsProvider } from "./contexts/FeatureFlagsContext";
import { FunctionalityProvider } from "./contexts/FunctionalityContext";
import { PreferencesProvider } from "./contexts/PreferencesContext";
@@ -33,11 +34,13 @@ export function AppContent() {
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/app/src/contexts/CredentialsContext.tsx b/app/src/contexts/CredentialsContext.tsx
new file mode 100644
index 0000000000..ad26b4ede1
--- /dev/null
+++ b/app/src/contexts/CredentialsContext.tsx
@@ -0,0 +1,35 @@
+import React, { createContext, PropsWithChildren, useState } from "react";
+import { useZustand } from "use-zustand";
+
+import {
+ createCredentialsStore,
+ CredentialsProps,
+ CredentialsState,
+ CredentialsStore,
+} from "@phoenix/store";
+
+export const CredentialsContext = createContext(null);
+
+export function CredentialsProvider({
+ children,
+ ...props
+}: PropsWithChildren>) {
+ const [store] = useState(() =>
+ createCredentialsStore(props)
+ );
+ return (
+
+ {children}
+
+ );
+}
+
+export function useCredentialsContext(
+ selector: (state: CredentialsState) => T,
+ equalityFn?: (left: T, right: T) => boolean
+): T {
+ const store = React.useContext(CredentialsContext);
+ if (!store)
+ throw new Error("Missing CredentialsContext.Provider in the tree");
+ return useZustand(store, selector, equalityFn);
+}
diff --git a/app/src/contexts/PlaygroundContext.tsx b/app/src/contexts/PlaygroundContext.tsx
index e6a353f9c2..e3c115e5d9 100644
--- a/app/src/contexts/PlaygroundContext.tsx
+++ b/app/src/contexts/PlaygroundContext.tsx
@@ -6,7 +6,7 @@ import {
PlaygroundProps,
PlaygroundState,
PlaygroundStore,
-} from "@phoenix/store/playgroundStore";
+} from "@phoenix/store";
export const PlaygroundContext = createContext(null);
diff --git a/app/src/pages/playground/MessageRolePicker.tsx b/app/src/pages/playground/MessageRolePicker.tsx
index d10e46fbc2..6d0c26131b 100644
--- a/app/src/pages/playground/MessageRolePicker.tsx
+++ b/app/src/pages/playground/MessageRolePicker.tsx
@@ -3,8 +3,6 @@ import { css } from "@emotion/react";
import { Item, Picker } from "@arizeai/components";
-import { ChatMessageRole } from "@phoenix/store";
-
import { isChatMessageRole } from "./playgroundUtils";
const hiddenLabelCSS = css`
diff --git a/app/src/pages/playground/Playground.tsx b/app/src/pages/playground/Playground.tsx
index 14adc0962e..f25d6548e7 100644
--- a/app/src/pages/playground/Playground.tsx
+++ b/app/src/pages/playground/Playground.tsx
@@ -11,6 +11,7 @@ import {
import { InitialPlaygroundState } from "@phoenix/store";
import { NUM_MAX_PLAYGROUND_INSTANCES } from "./constants";
+import { PlaygroundCredentialsDropdown } from "./PlaygroundCredentialsDropdown";
import { PlaygroundInputTypeTypeRadioGroup } from "./PlaygroundInputModeRadioGroup";
import { PlaygroundInstance } from "./PlaygroundInstance";
import { PlaygroundRunButton } from "./PlaygroundRunButton";
@@ -33,9 +34,7 @@ export function Playground(props: InitialPlaygroundState) {
Playground
-
+
diff --git a/app/src/pages/playground/PlaygroundChatTemplate.tsx b/app/src/pages/playground/PlaygroundChatTemplate.tsx
index 0c1caf850a..39755e7e94 100644
--- a/app/src/pages/playground/PlaygroundChatTemplate.tsx
+++ b/app/src/pages/playground/PlaygroundChatTemplate.tsx
@@ -26,7 +26,6 @@ import { usePlaygroundContext } from "@phoenix/contexts/PlaygroundContext";
import { useChatMessageStyles } from "@phoenix/hooks/useChatMessageStyles";
import {
ChatMessage,
- ChatMessageRole,
generateMessageId,
PlaygroundChatTemplate as PlaygroundChatTemplateType,
} from "@phoenix/store";
@@ -140,7 +139,7 @@ export function PlaygroundChatTemplate(props: PlaygroundChatTemplateProps) {
...template.messages,
{
id: generateMessageId(),
- role: ChatMessageRole.user,
+ role: "user",
content: "",
},
],
diff --git a/app/src/pages/playground/PlaygroundCredentialsDropdown.tsx b/app/src/pages/playground/PlaygroundCredentialsDropdown.tsx
new file mode 100644
index 0000000000..4023bed5b0
--- /dev/null
+++ b/app/src/pages/playground/PlaygroundCredentialsDropdown.tsx
@@ -0,0 +1,69 @@
+import React from "react";
+
+import {
+ DropdownButton,
+ DropdownMenu,
+ DropdownTrigger,
+ Flex,
+ Form,
+ Heading,
+ Text,
+ TextField,
+ View,
+} from "@arizeai/components";
+
+import { useCredentialsContext } from "@phoenix/contexts/CredentialsContext";
+import { usePlaygroundContext } from "@phoenix/contexts/PlaygroundContext";
+import { CredentialKey } from "@phoenix/store";
+
+export const ProviderToCredentialKeyMap: Record =
+ {
+ OPENAI: "OPENAI_API_KEY",
+ ANTHROPIC: "ANTHROPIC_API_KEY",
+ AZURE_OPENAI: "AZURE_OPENAI_API_KEY",
+ };
+
+export function PlaygroundCredentialsDropdown() {
+ const currentProviders = usePlaygroundContext((state) =>
+ Array.from(
+ new Set(state.instances.map((instance) => instance.model.provider))
+ )
+ );
+ const setCredential = useCredentialsContext((state) => state.setCredential);
+ const credentials = useCredentialsContext((state) => state);
+ return (
+
+ API Keys
+
+
+
+
+ API Keys
+
+
+ API keys are stored in your browser and used to communicate with
+ their respective API's.
+
+
+
+
+
+
+ );
+}
diff --git a/app/src/pages/playground/PlaygroundOutput.tsx b/app/src/pages/playground/PlaygroundOutput.tsx
index 2ac91203d7..e5c41c42c8 100644
--- a/app/src/pages/playground/PlaygroundOutput.tsx
+++ b/app/src/pages/playground/PlaygroundOutput.tsx
@@ -6,11 +6,7 @@ import { Card, Flex, Icon, Icons } from "@arizeai/components";
import { usePlaygroundContext } from "@phoenix/contexts/PlaygroundContext";
import { useChatMessageStyles } from "@phoenix/hooks/useChatMessageStyles";
-import {
- ChatMessage,
- ChatMessageRole,
- generateMessageId,
-} from "@phoenix/store";
+import { ChatMessage, generateMessageId } from "@phoenix/store";
import { assertUnreachable } from "@phoenix/typeUtils";
import {
@@ -70,7 +66,7 @@ export function PlaygroundOutput(props: PlaygroundOutputProps) {
message={{
id: generateMessageId(),
content: instance.output,
- role: ChatMessageRole.ai,
+ role: "ai",
}}
/>
);
@@ -144,13 +140,13 @@ function toGqlChatCompletionRole(
role: ChatMessageRole
): ChatCompletionMessageRole {
switch (role) {
- case ChatMessageRole.system:
+ case "system":
return "SYSTEM";
- case ChatMessageRole.user:
+ case "user":
return "USER";
- case ChatMessageRole.tool:
+ case "tool":
return "TOOL";
- case ChatMessageRole.ai:
+ case "ai":
return "AI";
default:
assertUnreachable(role);
@@ -204,7 +200,7 @@ function PlaygroundOutputText(props: PlaygroundInstanceProps) {
message={{
id: generateMessageId(),
content: output,
- role: ChatMessageRole.ai,
+ role: "ai",
}}
/>
);
diff --git a/app/src/pages/playground/__tests__/playgroundUtils.test.ts b/app/src/pages/playground/__tests__/playgroundUtils.test.ts
index 7ec0b816b4..cd012c62f8 100644
--- a/app/src/pages/playground/__tests__/playgroundUtils.test.ts
+++ b/app/src/pages/playground/__tests__/playgroundUtils.test.ts
@@ -1,7 +1,6 @@
import {
_resetInstanceId,
_resetMessageId,
- ChatMessageRole,
PlaygroundInstance,
} from "@phoenix/store";
@@ -36,13 +35,11 @@ const expectedPlaygroundInstanceWithIO: PlaygroundInstance = {
// These id's are not 0, 1, 2, because we create a playground instance (including messages) at the top of the transformSpanAttributesToPlaygroundInstance function
// Doing so increments the message id counter
messages: [
- { id: 2, content: "You are a chatbot", role: ChatMessageRole.system },
- { id: 3, content: "hello?", role: ChatMessageRole.user },
+ { id: 2, content: "You are a chatbot", role: "system" },
+ { id: 3, content: "hello?", role: "user" },
],
},
- output: [
- { id: 4, content: "This is an AI Answer", role: ChatMessageRole.ai },
- ],
+ output: [{ id: 4, content: "This is an AI Answer", role: "ai" }],
};
const defaultTemplate = {
@@ -50,12 +47,12 @@ const defaultTemplate = {
messages: [
{
id: 0,
- role: ChatMessageRole.system,
+ role: "system",
content: "You are a chatbot",
},
{
id: 1,
- role: ChatMessageRole.user,
+ role: "user",
content: "{{question}}",
},
],
diff --git a/app/src/pages/playground/constants.tsx b/app/src/pages/playground/constants.tsx
index 8f34607c82..624e0e1ca5 100644
--- a/app/src/pages/playground/constants.tsx
+++ b/app/src/pages/playground/constants.tsx
@@ -1,8 +1,6 @@
-import { ChatMessageRole } from "@phoenix/store";
-
export const NUM_MAX_PLAYGROUND_INSTANCES = 4;
-export const DEFAULT_CHAT_ROLE = ChatMessageRole.user;
+export const DEFAULT_CHAT_ROLE = "user";
/**
* Map of {@link ChatMessageRole} to potential role values.
diff --git a/app/src/pages/playground/playgroundUtils.ts b/app/src/pages/playground/playgroundUtils.ts
index ffe15aa51c..66d8290f53 100644
--- a/app/src/pages/playground/playgroundUtils.ts
+++ b/app/src/pages/playground/playgroundUtils.ts
@@ -1,7 +1,6 @@
import { PlaygroundInstance } from "@phoenix/store";
import {
ChatMessage,
- ChatMessageRole,
createPlaygroundInstance,
generateMessageId,
} from "@phoenix/store";
diff --git a/app/src/pages/playground/schemas.ts b/app/src/pages/playground/schemas.ts
index f572e20bf0..11bdde6c35 100644
--- a/app/src/pages/playground/schemas.ts
+++ b/app/src/pages/playground/schemas.ts
@@ -6,7 +6,7 @@ import {
SemanticAttributePrefixes,
} from "@arizeai/openinference-semantic-conventions";
-import { ChatMessage, ChatMessageRole } from "@phoenix/store";
+import { ChatMessage } from "@phoenix/store";
import { schemaForType } from "@phoenix/typeUtils";
/**
@@ -76,7 +76,9 @@ export const outputSchema = z.object({
/**
* The zod schema for {@link chatMessageRoles}
*/
-export const chatMessageRolesSchema = z.nativeEnum(ChatMessageRole);
+export const chatMessageRolesSchema = schemaForType()(
+ z.enum(["user", "ai", "system", "tool"])
+);
const chatMessageSchema = schemaForType()(
z.object({
diff --git a/app/src/store/credentialsStore.tsx b/app/src/store/credentialsStore.tsx
new file mode 100644
index 0000000000..ab854a6c5c
--- /dev/null
+++ b/app/src/store/credentialsStore.tsx
@@ -0,0 +1,49 @@
+import { create, StateCreator } from "zustand";
+import { devtools, persist } from "zustand/middleware";
+
+export interface CredentialsProps {
+ /**
+ * The API key for the OpenAI API.
+ */
+ OPENAI_API_KEY?: string;
+ /**
+ * The API key for the Azure OpenAI API.
+ */
+ AZURE_OPENAI_API_KEY?: string;
+ /**
+ * The API key for the Anthropic API.
+ */
+ ANTHROPIC_API_KEY?: string;
+}
+
+export type CredentialKey = keyof CredentialsProps;
+
+export interface CredentialsState extends CredentialsProps {
+ /**
+ * Setter for a given credential
+ * @param credential the name of the credential to set
+ * @param value the value of the credential
+ */
+ setCredential: (params: {
+ credential: keyof CredentialsProps;
+ value: string;
+ }) => void;
+}
+
+export const createCredentialsStore = (
+ initialProps: Partial
+) => {
+ const credentialsStore: StateCreator = (set) => ({
+ setCredential: ({ credential, value }) => {
+ set({ [credential]: value });
+ },
+ ...initialProps,
+ });
+ return create()(
+ persist(devtools(credentialsStore), {
+ name: "arize-phoenix-credentials",
+ })
+ );
+};
+
+export type CredentialsStore = ReturnType;
diff --git a/app/src/store/index.tsx b/app/src/store/index.tsx
index 98fbe30497..13b6d059a0 100644
--- a/app/src/store/index.tsx
+++ b/app/src/store/index.tsx
@@ -1,3 +1,4 @@
export * from "./pointCloudStore";
export * from "./tracingStore";
-export * from "./playgroundStore";
+export * from "./playground";
+export * from "./credentialsStore";
diff --git a/app/src/store/playground/index.ts b/app/src/store/playground/index.ts
new file mode 100644
index 0000000000..a26b3b3411
--- /dev/null
+++ b/app/src/store/playground/index.ts
@@ -0,0 +1,2 @@
+export * from "./playgroundStore";
+export * from "./types";
diff --git a/app/src/store/playgroundStore.tsx b/app/src/store/playground/playgroundStore.tsx
similarity index 53%
rename from app/src/store/playgroundStore.tsx
rename to app/src/store/playground/playgroundStore.tsx
index b6fb0d25fc..fe3a1292c8 100644
--- a/app/src/store/playgroundStore.tsx
+++ b/app/src/store/playground/playgroundStore.tsx
@@ -1,7 +1,15 @@
import { create, StateCreator } from "zustand";
import { devtools } from "zustand/middleware";
-export type GenAIOperationType = "chat" | "text_completion";
+import {
+ GenAIOperationType,
+ InitialPlaygroundState,
+ PlaygroundChatTemplate,
+ PlaygroundInputMode,
+ PlaygroundInstance,
+ PlaygroundState,
+ PlaygroundTextCompletionTemplate,
+} from "./types";
let playgroundInstanceIdIndex = 0;
let playgroundRunIdIndex = 0;
@@ -36,184 +44,17 @@ export const _resetMessageId = () => {
playgroundMessageIdIndex = 0;
};
-/**
- * The input mode for the playground
- * @example "manual" or "dataset"
- */
-export type PlaygroundInputMode = "manual" | "dataset";
-
-/**
- * A playground template can be a chat completion or text completion (legacy)
- */
-export type PlaygroundTemplate =
- | PlaygroundChatTemplate
- | PlaygroundTextCompletionTemplate;
-
-/**
- * Array of roles for a chat message with a LLM
- */
-export enum ChatMessageRole {
- system = "system",
- user = "user",
- tool = "tool",
- ai = "ai",
-}
-
-/**
- * A chat message with a role and content
- * @example { role: "user", content: "What is the meaning of life?" }
- */
-export type ChatMessage = {
- id: number;
- role: ChatMessageRole;
- content: string;
-};
-
-/**
- * A template for a chat completion playground
- * Takes a list of messages for multi-turn
- * @see https://platform.openai.com/docs/guides/chat-completions
- */
-export type PlaygroundChatTemplate = {
- __type: "chat";
- messages: ChatMessage[];
-};
-
-export type PlaygroundTextCompletionTemplate = {
- __type: "text_completion";
- prompt: string;
-};
-
-export interface PlaygroundProps {
- /**
- * How the LLM API should be invoked. Distinguishes between chat and text_completion.
- * @see https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/
- * @default "chat"
- */
- operationType: GenAIOperationType;
- /**
- * The input mode for the playground(s)
- * NB: the input mode for all instances is synchronized
- * @default "manual"
- */
- inputMode: PlaygroundInputMode;
- /**
- * The current playground instances(s)
- * Defaults to a single instance until a second instance is added
- */
- instances: Array;
-}
-
-export type InitialPlaygroundState = Partial;
-
-type DatasetInput = {
- datasetId: string;
-};
-
-type ManualInput = {
- variables: Record;
-};
-
-type PlaygroundInput = DatasetInput | ManualInput;
-
-type ModelConfig = {
- provider: ModelProvider;
- modelName: string | null;
-};
-/**
- * A single instance of the playground that has
- * - a template
- * - tools
- * - input (dataset or manual)
- * - output (experiment or spans)
- */
-export interface PlaygroundInstance {
- /**
- * An ID to uniquely identify the instance
- */
- id: number;
- template: PlaygroundTemplate;
- tools: unknown;
- input: PlaygroundInput;
- model: ModelConfig;
- output: ChatMessage[] | undefined | string;
- activeRunId: number | null;
- /**
- * Whether or not the playground instance is actively running or not
- **/
- isRunning: boolean;
-}
-
-/**
- * All actions for a playground instance must contain the index of the playground
- */
-interface PlaygroundInstanceActionParams {
- playgroundInstanceId: number;
-}
-interface AddMessageParams extends PlaygroundInstanceActionParams {}
-
-export interface PlaygroundState extends PlaygroundProps {
- /**
- * Setter for the invocation mode
- * @param operationType
- */
- setOperationType: (operationType: GenAIOperationType) => void;
- /**
- * Setter for the input mode.
- */
- setInputMode: (inputMode: PlaygroundInputMode) => void;
- /**
- * Add a comparison instance to the playground
- */
- addInstance: () => void;
- /**
- * Delete a specific instance of the playground
- * @param instanceId the instance to delete
- */
- deleteInstance: (instanceId: number) => void;
- /**
- * Add a message to a playground instance
- */
- addMessage: (params: AddMessageParams) => void;
- /**
- * Update an instance of the playground
- */
- updateInstance: (params: {
- instanceId: number;
- patch: Partial;
- }) => void;
- /**
- * Update an instance's model configuration
- */
- updateModel: (params: {
- instanceId: number;
- model: Partial;
- }) => void;
- /**
- * Run all the active playground Instances
- */
- runPlaygroundInstances: () => void;
- /**
- * Run a specific playground instance
- */
- runPlaygroundInstance: (instanceId: number) => void;
- /**
- * Mark a given playground instance as completed
- */
- markPlaygroundInstanceComplete: (instanceId: number) => void;
-}
-
const generateChatCompletionTemplate = (): PlaygroundChatTemplate => ({
__type: "chat",
messages: [
{
id: generateMessageId(),
- role: ChatMessageRole.system,
+ role: "system",
content: "You are a chatbot",
},
{
id: generateMessageId(),
- role: ChatMessageRole.user,
+ role: "user",
content: "{{question}}",
},
],
@@ -247,35 +88,18 @@ export const createPlaygroundStore = (
instances: [createPlaygroundInstance()],
setOperationType: (operationType: GenAIOperationType) => {
if (operationType === "chat") {
- // TODO: this is incorrect, it should only change the template
set({
- instances: [
- {
- id: generateInstanceId(),
- model: { provider: "OPENAI", modelName: "gpt-4o" },
- template: generateChatCompletionTemplate(),
- tools: {},
- input: { variables: {} },
- output: undefined,
- activeRunId: null,
- isRunning: false,
- },
- ],
+ instances: get().instances.map((instance) => ({
+ ...instance,
+ template: generateChatCompletionTemplate(),
+ })),
});
} else {
set({
- instances: [
- {
- id: generateInstanceId(),
- model: { provider: "OPENAI", modelName: "gpt-4o" },
- template: DEFAULT_TEXT_COMPLETION_TEMPLATE,
- tools: {},
- input: { variables: {} },
- output: undefined,
- activeRunId: null,
- isRunning: false,
- },
- ],
+ instances: get().instances.map((instance) => ({
+ ...instance,
+ template: DEFAULT_TEXT_COMPLETION_TEMPLATE,
+ })),
});
}
set({ operationType });
diff --git a/app/src/store/playground/types.ts b/app/src/store/playground/types.ts
new file mode 100644
index 0000000000..043007f485
--- /dev/null
+++ b/app/src/store/playground/types.ts
@@ -0,0 +1,163 @@
+export type GenAIOperationType = "chat" | "text_completion";
+/**
+ * The input mode for the playground
+ * @example "manual" or "dataset"
+ */
+export type PlaygroundInputMode = "manual" | "dataset";
+
+/**
+ * A chat message with a role and content
+ * @example { role: "user", content: "What is the meaning of life?" }
+ */
+export type ChatMessage = {
+ id: number;
+ role: ChatMessageRole;
+ content: string;
+};
+
+/**
+ * A template for a chat completion playground
+ * Takes a list of messages for multi-turn
+ * @see https://platform.openai.com/docs/guides/chat-completions
+ */
+export type PlaygroundChatTemplate = {
+ __type: "chat";
+ messages: ChatMessage[];
+};
+
+/**
+ * A template for a text completion playground
+ * A single prompt for text completion
+ */
+export type PlaygroundTextCompletionTemplate = {
+ __type: "text_completion";
+ prompt: string;
+};
+
+/**
+ * A playground template can be a chat completion or text completion (legacy)
+ */
+export type PlaygroundTemplate =
+ | PlaygroundChatTemplate
+ | PlaygroundTextCompletionTemplate;
+
+type DatasetInput = {
+ datasetId: string;
+};
+
+type ManualInput = {
+ variables: Record;
+};
+
+type PlaygroundInput = DatasetInput | ManualInput;
+
+type ModelConfig = {
+ provider: ModelProvider;
+ modelName: string | null;
+};
+
+/**
+ * A single instance of the playground that has
+ * - a template
+ * - tools
+ * - input (dataset or manual)
+ * - output (experiment or spans)
+ */
+export interface PlaygroundInstance {
+ /**
+ * An ID to uniquely identify the instance
+ */
+ id: number;
+ template: PlaygroundTemplate;
+ tools: unknown;
+ input: PlaygroundInput;
+ model: ModelConfig;
+ output: ChatMessage[] | undefined | string;
+ activeRunId: number | null;
+ /**
+ * Whether or not the playground instance is actively running or not
+ **/
+ isRunning: boolean;
+}
+
+/**
+ * All actions for a playground instance must contain the id of the instance
+ */
+interface PlaygroundInstanceActionParams {
+ playgroundInstanceId: number;
+}
+
+export interface AddMessageParams extends PlaygroundInstanceActionParams {}
+
+export interface PlaygroundProps {
+ /**
+ * How the LLM API should be invoked. Distinguishes between chat and text_completion.
+ * @see https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/
+ * @default "chat"
+ */
+ operationType: GenAIOperationType;
+ /**
+ * The input mode for the playground(s)
+ * NB: the input mode for all instances is synchronized
+ * @default "manual"
+ */
+ inputMode: PlaygroundInputMode;
+ /**
+ * The current playground instances(s)
+ * Defaults to a single instance until a second instance is added
+ */
+ instances: Array;
+}
+
+export type InitialPlaygroundState = Partial;
+
+export interface PlaygroundState extends PlaygroundProps {
+ /**
+ * Setter for the invocation mode
+ * @param operationType
+ */
+ setOperationType: (operationType: GenAIOperationType) => void;
+ /**
+ * Setter for the input mode.
+ */
+ setInputMode: (inputMode: PlaygroundInputMode) => void;
+ /**
+ * Add a comparison instance to the playground
+ */
+ addInstance: () => void;
+ /**
+ * Delete a specific instance of the playground
+ * @param instanceId the instance to delete
+ */
+ deleteInstance: (instanceId: number) => void;
+ /**
+ * Add a message to a playground instance
+ */
+ addMessage: (params: AddMessageParams) => void;
+ /**
+ * Update an instance of the playground
+ */
+ updateInstance: (params: {
+ instanceId: number;
+ patch: Partial;
+ }) => void;
+ /**
+ * Update an instance's model configuration
+ */
+ updateModel: (params: {
+ instanceId: number;
+ model: Partial;
+ }) => void;
+ /**
+ * Run all the active playground Instances
+ */
+ runPlaygroundInstances: () => void;
+ /**
+ * Run a specific playground instance
+ */
+ runPlaygroundInstance: (instanceId: number) => void;
+ /**
+ * Mark a given playground instance as completed
+ */
+ markPlaygroundInstanceComplete: (instanceId: number) => void;
+}