Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(prompts): unify template format and language #6403

Merged
merged 20 commits into from
Feb 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/typescript-packages-CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Typescript Packages CI

on:
push:
branches: [main, js]
branches: [main, prompts]
pull_request:
paths:
- "js/**"
Expand Down
22 changes: 8 additions & 14 deletions app/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ input ChatCompletionInput {
invocationParameters: [InvocationParameterInput!]! = []
tools: [JSON!]
apiKey: String = null
template: TemplateOptions
template: PromptTemplateOptions
promptName: Identifier = null
}

Expand Down Expand Up @@ -154,7 +154,7 @@ input ChatCompletionOverDatasetInput {
invocationParameters: [InvocationParameterInput!]! = []
tools: [JSON!]
apiKey: String = null
templateLanguage: TemplateLanguage!
templateFormat: PromptTemplateFormat! = MUSTACHE
datasetId: GlobalID!
datasetVersionId: GlobalID = null
experimentName: String = null
Expand Down Expand Up @@ -1573,10 +1573,15 @@ union PromptTemplate = PromptStringTemplate | PromptChatTemplate

enum PromptTemplateFormat {
MUSTACHE
FSTRING
F_STRING
NONE
}

input PromptTemplateOptions {
variables: JSON!
format: PromptTemplateFormat!
}

enum PromptTemplateType {
STRING
CHAT
Expand Down Expand Up @@ -1979,17 +1984,6 @@ type SystemApiKey implements ApiKey & Node {
id: GlobalID!
}

enum TemplateLanguage {
NONE
MUSTACHE
F_STRING
}

input TemplateOptions {
variables: JSON!
language: TemplateLanguage!
}

type TextChunk implements ChatCompletionSubscriptionPayload {
datasetExampleId: GlobalID
content: String!
Expand Down
20 changes: 10 additions & 10 deletions app/src/components/templateEditor/TemplateEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import { assertUnreachable } from "@phoenix/typeUtils";

import { FStringTemplating } from "./language/fString";
import { MustacheLikeTemplating } from "./language/mustacheLike";
import { TemplateLanguages } from "./constants";
import { TemplateLanguage } from "./types";
import { TemplateFormats } from "./constants";
import { TemplateFormat } from "./types";

type TemplateEditorProps = Omit<ReactCodeMirrorProps, "value"> & {
templateLanguage: TemplateLanguage;
templateFormat: TemplateFormat;
defaultValue: string;
};

Expand Down Expand Up @@ -49,7 +49,7 @@ const baseExtensions = [
* cursor position when value is updated.
*/
export const TemplateEditor = ({
templateLanguage,
templateFormat,
defaultValue,
readOnly,
...props
Expand All @@ -59,20 +59,20 @@ export const TemplateEditor = ({
const codeMirrorTheme = theme === "light" ? githubLight : nord;
const extensions = useMemo(() => {
const ext: TemplateEditorProps["extensions"] = [...baseExtensions];
switch (templateLanguage) {
case TemplateLanguages.FString:
switch (templateFormat) {
case TemplateFormats.FString:
ext.push(FStringTemplating());
break;
case TemplateLanguages.Mustache:
case TemplateFormats.Mustache:
ext.push(MustacheLikeTemplating());
break;
case TemplateLanguages.NONE:
case TemplateFormats.NONE:
break;
default:
assertUnreachable(templateLanguage);
assertUnreachable(templateFormat);
}
return ext;
}, [templateLanguage]);
}, [templateFormat]);

useEffect(() => {
if (readOnly) {
Expand Down
6 changes: 3 additions & 3 deletions app/src/components/templateEditor/constants.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/**
* Enum for the different template languages supported by the template editor
* Enum for the different template formats supported by the template editor
*
* - FString: `variables look like {variable}`
* - Mustache: `variables look like {{variable}}`
*
* @example
* ```tsx
* <TemplateEditor language={TemplateLanguages.Mustache} />
* <TemplateEditor format={TemplateFormats.Mustache} />
* ```
*/
export const TemplateLanguages = {
export const TemplateFormats = {
NONE: "NONE", // No templating
FString: "F_STRING", // {variable}
Mustache: "MUSTACHE", // {{variable}}
Expand Down
20 changes: 10 additions & 10 deletions app/src/components/templateEditor/templateEditorUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import {
extractVariablesFromMustacheLike,
formatMustacheLike,
} from "./language/mustacheLike";
import { TemplateLanguages } from "./constants";
import { TemplateLanguage } from "./types";
import { TemplateFormats } from "./constants";
import { TemplateFormat } from "./types";

/**
* A function that formats a template with the given variables
Expand All @@ -24,35 +24,35 @@ export type ExtractVariablesFn = (template: string) => string[];
/**
* Get an object of isomorphic functions for processing templates of the given language
*
* @param templateLanguage - The language of the template to process
* @param templateFormat - The format of the template to process
*
* @returns An object containing the `format` and `extractVariables` functions.
* These functions share the same signature despite the different underlying
* templating languages.
*/
export const getTemplateLanguageUtils = (
templateLanguage: TemplateLanguage
export const getTemplateFormatUtils = (
templateFormat: TemplateFormat
): {
format: FormatFn;
extractVariables: ExtractVariablesFn;
} => {
switch (templateLanguage) {
case TemplateLanguages.FString:
switch (templateFormat) {
case TemplateFormats.FString:
return {
format: formatFString,
extractVariables: extractVariablesFromFString,
};
case TemplateLanguages.Mustache:
case TemplateFormats.Mustache:
return {
format: formatMustacheLike,
extractVariables: extractVariablesFromMustacheLike,
};
case TemplateLanguages.NONE:
case TemplateFormats.NONE:
return {
format: ({ text }) => text,
extractVariables: () => [],
};
default:
assertUnreachable(templateLanguage);
assertUnreachable(templateFormat);
}
};
12 changes: 6 additions & 6 deletions app/src/components/templateEditor/types.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { TemplateLanguages } from "./constants";
import { TemplateFormats } from "./constants";

export type TemplateLanguage =
(typeof TemplateLanguages)[keyof typeof TemplateLanguages];
export type TemplateFormat =
(typeof TemplateFormats)[keyof typeof TemplateFormats];

/**
* Type guard for the TemplateLanguage type
* Type guard for the TemplateFormat type
*/
export function isTemplateLanguage(v: string): v is TemplateLanguage {
return Object.values(TemplateLanguages).includes(v as TemplateLanguage);
export function isTemplateFormat(v: string): v is TemplateFormat {
return Object.values(TemplateFormats).includes(v as TemplateFormat);
}
12 changes: 5 additions & 7 deletions app/src/pages/playground/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import { ConfirmNavigationDialog } from "@phoenix/components/ConfirmNavigation";
import { resizeHandleCSS } from "@phoenix/components/resize";
import { StopPropagation } from "@phoenix/components/StopPropagation";
import { TemplateLanguages } from "@phoenix/components/templateEditor/constants";
import { TemplateFormats } from "@phoenix/components/templateEditor/constants";
import {
PlaygroundProvider,
usePlaygroundContext,
Expand All @@ -40,7 +40,7 @@ import { PlaygroundOutput } from "./PlaygroundOutput";
import { PlaygroundRunButton } from "./PlaygroundRunButton";
import { PlaygroundStreamToggle } from "./PlaygroundStreamToggle";
import { PlaygroundTemplate } from "./PlaygroundTemplate";
import { TemplateLanguageRadioGroup } from "./TemplateLanguageRadioGroup";
import { TemplateFormatRadioGroup } from "./TemplateFormatRadioGroup";

const playgroundWrapCSS = css`
display: flex;
Expand Down Expand Up @@ -209,9 +209,7 @@ const DEFAULT_EXPANDED_PARAMS = ["input", "output"];

function PlaygroundContent() {
const instances = usePlaygroundContext((state) => state.instances);
const templateLanguage = usePlaygroundContext(
(state) => state.templateLanguage
);
const templateFormat = usePlaygroundContext((state) => state.templateFormat);
const [searchParams] = useSearchParams();
const datasetId = searchParams.get("datasetId");
const isDatasetMode = datasetId != null;
Expand Down Expand Up @@ -272,7 +270,7 @@ function PlaygroundContent() {
Prompts
<StopPropagation>
<Flex direction="row" gap="size-100" alignItems="center">
<TemplateLanguageRadioGroup size="M" />
<TemplateFormatRadioGroup size="M" />
<AddPromptButton />
</Flex>
</StopPropagation>
Expand Down Expand Up @@ -307,7 +305,7 @@ function PlaygroundContent() {
) : (
<div css={playgroundInputOutputPanelContentCSS}>
<DisclosureGroup defaultExpandedKeys={DEFAULT_EXPANDED_PARAMS}>
{templateLanguage !== TemplateLanguages.NONE ? (
{templateFormat !== TemplateFormats.NONE ? (
<Disclosure id="input" size="L">
<DisclosureTrigger arrowPosition="start">
Inputs
Expand Down
20 changes: 9 additions & 11 deletions app/src/pages/playground/PlaygroundChatTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import {
TemplateEditor,
TemplateEditorWrap,
} from "@phoenix/components/templateEditor";
import { TemplateLanguage } from "@phoenix/components/templateEditor/types";
import { TemplateFormat } from "@phoenix/components/templateEditor/types";
import { usePlaygroundContext } from "@phoenix/contexts/PlaygroundContext";
import { useChatMessageStyles } from "@phoenix/hooks/useChatMessageStyles";
import { ChatMessage, PlaygroundState } from "@phoenix/store";
Expand Down Expand Up @@ -85,9 +85,7 @@ interface PlaygroundChatTemplateProps extends PlaygroundInstanceProps {}
export function PlaygroundChatTemplate(props: PlaygroundChatTemplateProps) {
const id = props.playgroundInstanceId;

const templateLanguage = usePlaygroundContext(
(state) => state.templateLanguage
);
const templateFormat = usePlaygroundContext((state) => state.templateFormat);
const updateInstance = usePlaygroundContext((state) => state.updateInstance);
const instanceSelector = useMemo(() => selectPlaygroundInstance(id), [id]);
const playgroundInstance = usePlaygroundContext(instanceSelector);
Expand Down Expand Up @@ -156,7 +154,7 @@ export function PlaygroundChatTemplate(props: PlaygroundChatTemplateProps) {
return (
<SortableMessageItem
playgroundInstanceId={id}
templateLanguage={templateLanguage}
templateFormat={templateFormat}
key={messageId}
messageId={messageId}
/>
Expand Down Expand Up @@ -191,13 +189,13 @@ export function PlaygroundChatTemplate(props: PlaygroundChatTemplateProps) {
function MessageEditor({
message,
updateMessage,
templateLanguage,
templateFormat,
playgroundInstanceId,
messageMode,
}: {
playgroundInstanceId: number;
message: ChatMessage;
templateLanguage: TemplateLanguage;
templateFormat: TemplateFormat;
updateMessage: (patch: Partial<ChatMessage>) => void;
messageMode: MessageMode;
}) {
Expand Down Expand Up @@ -277,7 +275,7 @@ function MessageEditor({
height="100%"
defaultValue={message.content || ""}
aria-label="Message content"
templateLanguage={templateLanguage}
templateFormat={templateFormat}
onChange={onChange}
placeholder={
message.role === "system"
Expand All @@ -293,12 +291,12 @@ function MessageEditor({

function SortableMessageItem({
playgroundInstanceId,
templateLanguage,
templateFormat,
messageId,
}: PropsWithChildren<{
playgroundInstanceId: number;
messageId: number;
templateLanguage: TemplateLanguage;
templateFormat: TemplateFormat;
}>) {
const updateMessage = usePlaygroundContext((state) => state.updateMessage);
const deleteMessage = usePlaygroundContext((state) => state.deleteMessage);
Expand Down Expand Up @@ -482,7 +480,7 @@ function SortableMessageItem({
message={message}
messageMode={aiMessageMode}
playgroundInstanceId={playgroundInstanceId}
templateLanguage={templateLanguage}
templateFormat={templateFormat}
updateMessage={onMessageUpdate}
/>
</div>
Expand Down
8 changes: 3 additions & 5 deletions app/src/pages/playground/PlaygroundDatasetExamplesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,7 @@ export function PlaygroundDatasetExamplesTable({
const allInstanceMessages = usePlaygroundContext(
(state) => state.allInstanceMessages
);
const templateLanguage = usePlaygroundContext(
(state) => state.templateLanguage
);
const templateFormat = usePlaygroundContext((state) => state.templateFormat);

const updateInstance = usePlaygroundContext((state) => state.updateInstance);
const updateExampleData = usePlaygroundDatasetExamplesTableContext(
Expand Down Expand Up @@ -766,7 +764,7 @@ export function PlaygroundDatasetExamplesTable({
);
const instanceVariables = extractVariablesFromInstance({
instance: enrichedInstance,
templateLanguage,
templateFormat,
});
return {
id: `instance-${instance.id}`,
Expand All @@ -792,7 +790,7 @@ export function PlaygroundDatasetExamplesTable({
size: 500,
};
});
}, [hasSomeRunIds, instances, templateLanguage, allInstanceMessages]);
}, [hasSomeRunIds, instances, templateFormat, allInstanceMessages]);

const columns: ColumnDef<TableRow>[] = [
{
Expand Down
15 changes: 7 additions & 8 deletions app/src/pages/playground/PlaygroundInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";

import { Flex, Text, View } from "@phoenix/components";
import { TemplateFormats } from "@phoenix/components/templateEditor/constants";
import { usePlaygroundContext } from "@phoenix/contexts/PlaygroundContext";
import { assertUnreachable } from "@phoenix/typeUtils";

Expand All @@ -12,25 +13,23 @@ export function PlaygroundInput() {
const setVariableValue = usePlaygroundContext(
(state) => state.setVariableValue
);
const templateLanguage = usePlaygroundContext(
(state) => state.templateLanguage
);
const templateFormat = usePlaygroundContext((state) => state.templateFormat);
if (variableKeys.length === 0) {
let templateSyntax = "";
switch (templateLanguage) {
case "F_STRING": {
switch (templateFormat) {
case TemplateFormats.FString: {
templateSyntax = "{input name}";
break;
}
case "MUSTACHE": {
case TemplateFormats.Mustache: {
templateSyntax = "{{input name}}";
break;
}
case "NONE": {
case TemplateFormats.NONE: {
return null;
}
default:
assertUnreachable(templateLanguage);
assertUnreachable(templateFormat);
}
return (
<View padding="size-100">
Expand Down
Loading
Loading