diff --git a/app/package.json b/app/package.json
index c2ca08266c..1cb7645a2f 100644
--- a/app/package.json
+++ b/app/package.json
@@ -6,7 +6,7 @@
"license": "None",
"private": true,
"dependencies": {
- "@arizeai/components": "^1.8.3",
+ "@arizeai/components": "^1.8.4",
"@arizeai/openinference-semantic-conventions": "^0.10.0",
"@arizeai/point-cloud": "^3.0.6",
"@codemirror/autocomplete": "6.12.0",
diff --git a/app/pnpm-lock.yaml b/app/pnpm-lock.yaml
index e1115998d7..f31c4990ba 100644
--- a/app/pnpm-lock.yaml
+++ b/app/pnpm-lock.yaml
@@ -12,8 +12,8 @@ importers:
.:
dependencies:
'@arizeai/components':
- specifier: ^1.8.3
- version: 1.8.3(@types/react@18.3.10)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ specifier: ^1.8.4
+ version: 1.8.4(@types/react@18.3.10)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@arizeai/openinference-semantic-conventions':
specifier: ^0.10.0
version: 0.10.0
@@ -274,8 +274,8 @@ packages:
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
- '@arizeai/components@1.8.3':
- resolution: {integrity: sha512-U+EV8+GDm0yLNh+xXcEiKY4v7cJgepHMVLRD9pmtYYYdCgiBOLZ7TNQv6gxcRRvlxuqUgLIcP//nwY/roI6MdQ==}
+ '@arizeai/components@1.8.4':
+ resolution: {integrity: sha512-pq7J01TPXpLRJJjRZSWpZX4XtlO/41zKEZv1l7un8Nv6Ol4RG7mf5i4h+QMDUmg5m2JXVNAb8GaRLRqESFM5tA==}
engines: {node: '>=14'}
peerDependencies:
react: '>=18'
@@ -3804,7 +3804,7 @@ snapshots:
'@jridgewell/gen-mapping': 0.3.5
'@jridgewell/trace-mapping': 0.3.25
- '@arizeai/components@1.8.3(@types/react@18.3.10)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ '@arizeai/components@1.8.4(@types/react@18.3.10)(eslint@8.57.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@emotion/react': 11.11.4(@types/react@18.3.10)(react@18.3.1)
'@react-aria/breadcrumbs': 3.5.13(react@18.3.1)
diff --git a/app/src/pages/playground/Playground.tsx b/app/src/pages/playground/Playground.tsx
index f25d6548e7..e15fe4f220 100644
--- a/app/src/pages/playground/Playground.tsx
+++ b/app/src/pages/playground/Playground.tsx
@@ -1,7 +1,17 @@
-import React, { Fragment } from "react";
+import React from "react";
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
+import { css } from "@emotion/react";
-import { Button, Flex, Heading, Icon, Icons, View } from "@arizeai/components";
+import {
+ Accordion,
+ AccordionItem,
+ Button,
+ Flex,
+ Heading,
+ Icon,
+ Icons,
+ View,
+} from "@arizeai/components";
import { resizeHandleCSS } from "@phoenix/components/resize";
import {
@@ -13,8 +23,9 @@ 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 { PlaygroundOutput } from "./PlaygroundOutput";
import { PlaygroundRunButton } from "./PlaygroundRunButton";
+import { PlaygroundTemplate } from "./PlaygroundTemplate";
export function Playground(props: InitialPlaygroundState) {
return (
@@ -35,12 +46,11 @@ export function Playground(props: InitialPlaygroundState) {
-
-
+
);
@@ -50,35 +60,132 @@ function AddPromptButton() {
const addInstance = usePlaygroundContext((state) => state.addInstance);
const numInstances = usePlaygroundContext((state) => state.instances.length);
return (
- } />}
- disabled={numInstances >= NUM_MAX_PLAYGROUND_INSTANCES}
- onClick={() => {
- addInstance();
+
{
+ // Stop propagation to prevent the accordion from closing
+ e.stopPropagation();
}}
>
- Prompt
-
+ } />}
+ disabled={numInstances >= NUM_MAX_PLAYGROUND_INSTANCES}
+ onClick={() => {
+ addInstance();
+ }}
+ >
+ Prompt
+
+
);
}
-function PlaygroundInstances() {
+const playgroundPromptPanelContentCSS = css`
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ overflow: hidden;
+ .ac-accordion {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ overflow: hidden;
+ flex: 1 1 auto;
+ .ac-accordion-item {
+ height: 100%;
+ overflow: hidden;
+ flex: 1 1 auto;
+ .ac-accordion-itemContent {
+ height: 100%;
+ overflow: hidden;
+ flex: 1 1 auto;
+ & > * {
+ height: 100%;
+ flex: 1 1 auto;
+ overflow: auto;
+ box-sizing: border-box;
+ // Fix padding issue with flexbox
+ padding-bottom: 57px !important;
+ }
+ }
+ }
+ }
+`;
+
+const playgroundInputOutputPanelContentCSS = css`
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ overflow: auto;
+`;
+
+function PlaygroundContent() {
const instances = usePlaygroundContext((state) => state.instances);
+ const numInstances = instances.length;
+ const isSingleInstance = numInstances === 1;
+
return (
-
-
- {instances.map((instance, i) => (
-
- {i !== 0 && }
-
-
-
-
- ))}
-
-
+
+
+
+
+ }
+ >
+
+
+ {instances.map((instance, i) => (
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+ Inputs go here
+
+
+
+
+ {instances.map((instance, i) => (
+
+
+
+ ))}
+
+
+
+
+
+
+
);
}
diff --git a/app/src/pages/playground/PlaygroundCredentialsDropdown.tsx b/app/src/pages/playground/PlaygroundCredentialsDropdown.tsx
index 4023bed5b0..3887c19ed5 100644
--- a/app/src/pages/playground/PlaygroundCredentialsDropdown.tsx
+++ b/app/src/pages/playground/PlaygroundCredentialsDropdown.tsx
@@ -1,4 +1,5 @@
import React from "react";
+import { css } from "@emotion/react";
import {
DropdownButton,
@@ -32,38 +33,46 @@ export function PlaygroundCredentialsDropdown() {
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.
-
-
-
-
-
-
+
+
+ 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/PlaygroundInstance.tsx b/app/src/pages/playground/PlaygroundInstance.tsx
deleted file mode 100644
index 8e6bf27de8..0000000000
--- a/app/src/pages/playground/PlaygroundInstance.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import React, { PropsWithChildren } from "react";
-import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
-import { css } from "@emotion/react";
-
-import {
- compactResizeHandleCSS,
- resizeHandleCSS,
-} from "@phoenix/components/resize";
-import { usePlaygroundContext } from "@phoenix/contexts/PlaygroundContext";
-
-import { PlaygroundInput } from "./PlaygroundInput";
-import { PlaygroundOutput } from "./PlaygroundOutput";
-import { PlaygroundTemplate } from "./PlaygroundTemplate";
-import { PlaygroundTools } from "./PlaygroundTools";
-import { PlaygroundInstanceProps } from "./types";
-
-export function PlaygroundInstance(props: PlaygroundInstanceProps) {
- const numInstances = usePlaygroundContext((state) => state.instances.length);
- const isSingleInstance = numInstances == 1;
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-const PanelContent = (props: PropsWithChildren) => (
-
-);
diff --git a/app/src/pages/playground/PlaygroundTools.tsx b/app/src/pages/playground/PlaygroundTools.tsx
deleted file mode 100644
index 805f4e1823..0000000000
--- a/app/src/pages/playground/PlaygroundTools.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from "react";
-
-import { Card } from "@arizeai/components";
-
-import { usePlaygroundContext } from "@phoenix/contexts/PlaygroundContext";
-
-import { TitleWithAlphabeticIndex } from "./TitleWithAlphabeticIndex";
-import { PlaygroundInstanceProps } from "./types";
-
-interface PlaygroundToolsProps extends PlaygroundInstanceProps {}
-export function PlaygroundTools(props: PlaygroundToolsProps) {
- const index = usePlaygroundContext((state) =>
- state.instances.findIndex(
- (instance) => instance.id === props.playgroundInstanceId
- )
- );
- return (
- }
- collapsible
- variant="compact"
- >
- Tools go here
-
- );
-}
diff --git a/app/src/pages/playground/__tests__/playgroundUtils.test.ts b/app/src/pages/playground/__tests__/playgroundUtils.test.ts
index cd012c62f8..0f36ba1090 100644
--- a/app/src/pages/playground/__tests__/playgroundUtils.test.ts
+++ b/app/src/pages/playground/__tests__/playgroundUtils.test.ts
@@ -22,9 +22,6 @@ const expectedPlaygroundInstanceWithIO: PlaygroundInstance = {
id: 0,
activeRunId: null,
isRunning: false,
- input: {
- variables: {},
- },
model: {
provider: "OPENAI",
modelName: "gpt-4o",
diff --git a/app/src/store/playground/playgroundStore.tsx b/app/src/store/playground/playgroundStore.tsx
index fe3a1292c8..7011dc41c0 100644
--- a/app/src/store/playground/playgroundStore.tsx
+++ b/app/src/store/playground/playgroundStore.tsx
@@ -71,7 +71,6 @@ export function createPlaygroundInstance(): PlaygroundInstance {
template: generateChatCompletionTemplate(),
model: { provider: "OPENAI", modelName: "gpt-4o" },
tools: {},
- input: { variables: {} },
output: undefined,
activeRunId: null,
isRunning: false,
@@ -84,6 +83,7 @@ export const createPlaygroundStore = (
const playgroundStore: StateCreator = (set, get) => ({
operationType: "chat",
inputMode: "manual",
+ input: { variables: {} },
setInputMode: (inputMode: PlaygroundInputMode) => set({ inputMode }),
instances: [createPlaygroundInstance()],
setOperationType: (operationType: GenAIOperationType) => {
diff --git a/app/src/store/playground/types.ts b/app/src/store/playground/types.ts
index 043007f485..1b36d2f5be 100644
--- a/app/src/store/playground/types.ts
+++ b/app/src/store/playground/types.ts
@@ -70,7 +70,6 @@ export interface PlaygroundInstance {
id: number;
template: PlaygroundTemplate;
tools: unknown;
- input: PlaygroundInput;
model: ModelConfig;
output: ChatMessage[] | undefined | string;
activeRunId: number | null;
@@ -102,6 +101,10 @@ export interface PlaygroundProps {
* @default "manual"
*/
inputMode: PlaygroundInputMode;
+ /**
+ * The input to all the playground instances
+ */
+ input: PlaygroundInput;
/**
* The current playground instances(s)
* Defaults to a single instance until a second instance is added