autogen scenarios

This commit is contained in:
Kyle Corbitt
2023-06-27 13:00:23 -07:00
parent ab32995eb9
commit 0a675cd7f7
8 changed files with 472 additions and 50 deletions

View File

@@ -1,12 +1,27 @@
import { Button } from "@chakra-ui/react";
import { Button, type ButtonProps, Fade, HStack } from "@chakra-ui/react";
import { useState } from "react";
import { BsPlus } from "react-icons/bs";
import { api } from "~/utils/api";
import { useExperiment, useHandledAsyncCallback } from "~/utils/hooks";
// Extracted Button styling into reusable component
const StyledButton = ({ children, onClick }: ButtonProps) => (
<Button
fontWeight="normal"
bgColor="transparent"
_hover={{ bgColor: "gray.100" }}
px={2}
onClick={onClick}
>
{children}
</Button>
);
export default function NewScenarioButton() {
const experiment = useExperiment();
const mutation = api.scenarios.create.useMutation();
const utils = api.useContext();
const [hovering, setHovering] = useState(false);
const [onClick] = useHandledAsyncCallback(async () => {
if (!experiment.data) return;
@@ -16,19 +31,31 @@ export default function NewScenarioButton() {
await utils.scenarios.list.invalidate();
}, [mutation]);
const [onAutogenerate] = useHandledAsyncCallback(async () => {
if (!experiment.data) return;
await mutation.mutateAsync({
experimentId: experiment.data.id,
autogenerate: true,
});
await utils.scenarios.list.invalidate();
}, [mutation]);
return (
<Button
w="100%"
alignItems="center"
justifyContent="flex-start"
fontWeight="normal"
bgColor="transparent"
_hover={{ bgColor: "gray.100" }}
px={2}
onClick={onClick}
<HStack
spacing={2}
onMouseEnter={() => setHovering(true)}
onMouseLeave={() => setHovering(false)}
>
<BsPlus size={24} />
Add Scenario
</Button>
<StyledButton onClick={onClick}>
<BsPlus size={24} />
Add Scenario
</StyledButton>
<Fade in={hovering}>
<StyledButton onClick={onAutogenerate}>
<BsPlus size={24} />
Autogenerate Scenario
</StyledButton>
</Fade>
</HStack>
);
}

View File

@@ -1,14 +1,12 @@
import { api } from "~/utils/api";
import { type PromptVariant, type Scenario } from "./types";
import { Center, Spinner, Text } from "@chakra-ui/react";
import { Spinner, Text, Box } from "@chakra-ui/react";
import { useExperiment } from "~/utils/hooks";
import { cellPadding } from "../constants";
const CellShell = ({ children }: { children: React.ReactNode }) => (
<Center h="100%" w="100%" px={cellPadding.x} py={cellPadding.y}>
{children}
</Center>
);
import { type CreateChatCompletionResponse } from "openai";
import SyntaxHighlighter from "react-syntax-highlighter";
import { docco } from "react-syntax-highlighter/dist/cjs/styles/hljs";
import stringify from "json-stringify-pretty-compact";
import { type ReactElement } from "react";
export default function OutputCell({
scenario,
@@ -16,7 +14,7 @@ export default function OutputCell({
}: {
scenario: Scenario;
variant: PromptVariant;
}) {
}): ReactElement | null {
const experiment = useExperiment();
const vars = api.templateVars.list.useQuery({ experimentId: experiment.data?.id ?? "" }).data;
@@ -41,37 +39,34 @@ export default function OutputCell({
if (!vars) return null;
if (disabledReason)
return (
<CellShell>
<Text color="gray.500">{disabledReason}</Text>
</CellShell>
);
if (disabledReason) return <Text color="gray.500">{disabledReason}</Text>;
if (output.isLoading)
return (
<CellShell>
<Spinner />
</CellShell>
);
if (output.isLoading) return <Spinner />;
if (!output.data)
return (
<CellShell>
<Text color="gray.500">Error retrieving output</Text>
</CellShell>
);
if (!output.data) return <Text color="gray.500">Error retrieving output</Text>;
if (output.data.errorMessage) {
return <Text color="red.600">Error: {output.data.errorMessage}</Text>;
}
const response = output.data?.output as unknown as CreateChatCompletionResponse;
const message = response?.choices?.[0]?.message;
if (message?.function_call) {
return (
<CellShell>
<Text color="red.600">Error: {output.data.errorMessage}</Text>
</CellShell>
<Box fontSize="xs">
<SyntaxHighlighter language="json" style={docco}>
{stringify(
{
function: message.function_call.name,
args: JSON.parse(message.function_call.arguments ?? "null"),
},
{ maxLength: 40 }
)}
</SyntaxHighlighter>
</Box>
);
}
return (
// @ts-expect-error TODO proper typing and error checks
<CellShell>{output.data.output.choices[0].message.content}</CellShell>
);
return <Box>{message?.content ?? JSON.stringify(output.data.output)}</Box>;
}

View File

@@ -1,4 +1,4 @@
import { Grid, GridItem, type SystemStyleObject } from "@chakra-ui/react";
import { Center, Grid, GridItem, type SystemStyleObject } from "@chakra-ui/react";
import React, { useState } from "react";
import { api } from "~/utils/api";
import NewScenarioButton from "./NewScenarioButton";
@@ -9,6 +9,7 @@ import VariantConfigEditor from "./VariantConfigEditor";
import VariantHeader from "./VariantHeader";
import type { Scenario, PromptVariant } from "./types";
import ScenarioHeader from "~/server/ScenarioHeader";
import { cellPadding } from "../constants";
const stickyHeaderStyle: SystemStyleObject = {
position: "sticky",
@@ -41,7 +42,9 @@ const ScenarioRow = (props: { scenario: Scenario; variants: PromptVariant[] }) =
onMouseLeave={() => setIsHovered(false)}
sx={isHovered ? highlightStyle : undefined}
>
<OutputCell key={variant.id} scenario={props.scenario} variant={variant} />
<Center h="100%" w="100%" px={cellPadding.x} py={cellPadding.y}>
<OutputCell key={variant.id} scenario={props.scenario} variant={variant} />
</Center>
</GridItem>
))}
</React.Fragment>