From d2aa0d9c68aad156538c3d27ee58476324d53ee5 Mon Sep 17 00:00:00 2001 From: "andrii.dudar" Date: Thu, 19 Dec 2024 14:06:53 +0100 Subject: [PATCH] [OPIK-579] [FR]: add output formats as it own fields for prompts (#932) * [OPIK-579] [FR]: add output formats as it own fields for prompts * - decrease edit prompt version popup for 50 pixels * - add max-h for popup content --- .../prompts/useCreatePromptVersionMutation.ts | 3 + .../api/prompts/usePromptCreateMutation.ts | 1 + .../AddEditDatasetItemDialog.tsx | 19 +- .../PromptPage/CommitsTab/CommitsTab.tsx | 11 ++ .../PromptPage/PromptTab/EditPromptDialog.tsx | 183 ++++++++++++------ .../pages/PromptPage/PromptTab/PromptTab.tsx | 24 ++- .../PromptTab/UseThisPromptDialog.tsx | 6 +- .../pages/PromptsPage/AddEditPromptDialog.tsx | 169 ++++++++++------ .../src/hooks/useBooleanTimeoutState.ts | 28 +++ apps/opik-frontend/src/types/prompts.ts | 3 +- 10 files changed, 305 insertions(+), 142 deletions(-) create mode 100644 apps/opik-frontend/src/hooks/useBooleanTimeoutState.ts diff --git a/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts b/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts index 9bc7017e6f..656efe2179 100644 --- a/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts +++ b/apps/opik-frontend/src/api/prompts/useCreatePromptVersionMutation.ts @@ -9,6 +9,7 @@ import { PromptVersion } from "@/types/prompts"; type UseCreatePromptVersionMutationParams = { name: string; template: string; + metadata?: object; onSetActiveVersionId: (versionId: string) => void; }; @@ -20,11 +21,13 @@ const useCreatePromptVersionMutation = () => { mutationFn: async ({ name, template, + metadata, }: UseCreatePromptVersionMutationParams) => { const { data } = await api.post(`${PROMPTS_REST_ENDPOINT}versions`, { name, version: { template, + ...(metadata && { metadata }), }, }); diff --git a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts index f953bae01f..aabcf517d1 100644 --- a/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts +++ b/apps/opik-frontend/src/api/prompts/usePromptCreateMutation.ts @@ -8,6 +8,7 @@ import { Prompt } from "@/types/prompts"; interface CreatePromptTemplate { template: string; + metadata?: object; } type UsePromptCreateMutationParams = { diff --git a/apps/opik-frontend/src/components/pages/DatasetItemsPage/AddEditDatasetItemDialog.tsx b/apps/opik-frontend/src/components/pages/DatasetItemsPage/AddEditDatasetItemDialog.tsx index 383b08b14f..ebbe262573 100644 --- a/apps/opik-frontend/src/components/pages/DatasetItemsPage/AddEditDatasetItemDialog.tsx +++ b/apps/opik-frontend/src/components/pages/DatasetItemsPage/AddEditDatasetItemDialog.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from "react"; +import React, { useCallback, useState } from "react"; import { EditorView } from "@codemirror/view"; import CodeMirror from "@uiw/react-codemirror"; import { jsonLanguage } from "@codemirror/lang-json"; @@ -19,8 +19,7 @@ import useDatasetItemBatchMutation from "@/api/datasets/useDatasetItemBatchMutat import { isValidJsonObject, safelyParseJSON } from "@/lib/utils"; import { Alert, AlertTitle } from "@/components/ui/alert"; import { useCodemirrorTheme } from "@/hooks/useCodemirrorTheme"; - -const ERROR_TIMEOUT = 3000; +import { useBooleanTimeoutState } from "@/hooks/useBooleanTimeoutState"; const DATA_PREFILLED_CONTENT = `{ "input": "", @@ -48,17 +47,7 @@ const AddEditDatasetItemDialog: React.FunctionComponent< ? JSON.stringify(datasetItem.data, null, 2) : DATA_PREFILLED_CONTENT, ); - const [showInvalidJSON, setShowInvalidJSON] = useState(false); - - useEffect(() => { - let timer: NodeJS.Timeout; - if (showInvalidJSON) { - timer = setTimeout(() => setShowInvalidJSON(false), ERROR_TIMEOUT); - } - return () => { - clearTimeout(timer); - }; - }, [showInvalidJSON]); + const [showInvalidJSON, setShowInvalidJSON] = useBooleanTimeoutState({}); const isValid = Boolean(data.length); const isEdit = Boolean(datasetItem); @@ -96,7 +85,7 @@ const AddEditDatasetItemDialog: React.FunctionComponent<
-
+
+ isObject(row.metadata) + ? JSON.stringify(row.metadata, null, 2) + : row.metadata, + cell: CodeCell as never, + }, { id: "created_at", label: "Created at", diff --git a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx index 9f2befdda9..a01cd7480d 100644 --- a/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx +++ b/apps/opik-frontend/src/components/pages/PromptPage/PromptTab/EditPromptDialog.tsx @@ -1,4 +1,7 @@ import React, { useState } from "react"; +import CodeMirror from "@uiw/react-codemirror"; +import { jsonLanguage } from "@codemirror/lang-json"; +import { EditorView } from "@codemirror/view"; import { Dialog, @@ -8,12 +11,17 @@ import { DialogHeader, DialogTitle, } from "@/components/ui/dialog"; +import { Alert, AlertTitle } from "@/components/ui/alert"; import { Textarea } from "@/components/ui/textarea"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; -import useCreatePromptVersionMutation from "@/api/prompts/useCreatePromptVersionMutation"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import TextDiff from "@/components/shared/CodeDiff/TextDiff"; +import useCreatePromptVersionMutation from "@/api/prompts/useCreatePromptVersionMutation"; +import { useBooleanTimeoutState } from "@/hooks/useBooleanTimeoutState"; +import { useCodemirrorTheme } from "@/hooks/useCodemirrorTheme"; +import { isValidJsonObject, safelyParseJSON } from "@/lib/utils"; enum PROMPT_PREVIEW_MODE { write = "write", @@ -23,8 +31,8 @@ enum PROMPT_PREVIEW_MODE { type EditPromptDialogProps = { open: boolean; setOpen: (open: boolean) => void; - - promptTemplate: string; + template: string; + metadata?: object; promptName: string; onSetActiveVersionId: (versionId: string) => void; }; @@ -32,27 +40,49 @@ type EditPromptDialogProps = { const EditPromptDialog: React.FunctionComponent = ({ open, setOpen, - promptTemplate: parentPromptTemplate, + template: promptTemplate, + metadata: promptMetadata, promptName, onSetActiveVersionId, }) => { + const [tab, setTab] = useState("template"); const [previewMode, setPreviewMode] = useState( PROMPT_PREVIEW_MODE.write, ); - const [promptTemplate, setPromptTemplate] = useState(parentPromptTemplate); + const metadataString = promptMetadata + ? JSON.stringify(promptMetadata, null, 2) + : ""; + const [template, setTemplate] = useState(promptTemplate); + const [metadata, setMetadata] = useState(metadataString); + + const [showInvalidJSON, setShowInvalidJSON] = useBooleanTimeoutState({}); + const theme = useCodemirrorTheme({ + editable: true, + }); - const createPromptVersionMutation = useCreatePromptVersionMutation(); + const { mutate } = useCreatePromptVersionMutation(); const handleClickEditPrompt = () => { - createPromptVersionMutation.mutate({ + const isMetadataValid = metadata === "" || isValidJsonObject(metadata); + + if (!isMetadataValid) { + return setShowInvalidJSON(true); + } + + mutate({ name: promptName, - template: promptTemplate, + template, + ...(metadata && { metadata: safelyParseJSON(metadata) }), onSetActiveVersionId, }); + + setOpen(false); }; - const templateHasChanges = promptTemplate !== parentPromptTemplate; - const isValid = promptTemplate?.length && templateHasChanges; + const templateHasChanges = template !== promptTemplate; + const metadataHasChanges = metadata !== metadataString; + const isValid = + template?.length && (templateHasChanges || metadataHasChanges); return ( @@ -60,72 +90,101 @@ const EditPromptDialog: React.FunctionComponent = ({ Edit prompt -
+

By editing a prompt, a new commit will be created automatically. You can access older versions of the prompt from the Commits tab.

-
-
- - - + + + Template + + + Metadata + + + +
+ + + value && setPreviewMode(value as PROMPT_PREVIEW_MODE) + } + size="sm" > - Write - - - Preview changes - - -
- {previewMode === PROMPT_PREVIEW_MODE.write ? ( -