Skip to content

Commit

Permalink
added input from prod in prompts
Browse files Browse the repository at this point in the history
  • Loading branch information
chitalian committed Jan 22, 2025
1 parent 2149f33 commit f6abb8a
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 49 deletions.
2 changes: 1 addition & 1 deletion valhalla/jawn/src/controllers/public/promptController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ export class PromptController extends Controller {
} else {
this.setStatus(200); // set return status 201
}
return resultMap(result, data => data?.[0]);
return resultMap(result, (data) => data?.[0]);
}

@Delete("version/{promptVersionId}")
Expand Down
94 changes: 94 additions & 0 deletions web/components/shared/prompts/VariablesPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,102 @@
import { Row } from "@/components/layout/common";
import { Button } from "@/components/ui/button";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { Variable } from "@/types/prompt-state";
import { isValidVariableName } from "@/utils/variables";
import { ImportIcon, ShuffleIcon } from "lucide-react";
import { populateVariables } from "./helpers";
import { usePromptInputs } from "./hooks";
import ExperimentInputSelector from "@/components/templates/prompts/experiments/experimentInputSelector";
import { useState } from "react";

interface VariablesPanelProps {
variables: Variable[];
onVariableChange: (index: number, value: string) => void;
promptVersionId: string;
}

export default function VariablesPanel({
variables,
onVariableChange,
promptVersionId,
}: VariablesPanelProps) {
// - Filter Valid Variables
const validVariablesWithIndices = variables
.map((v, i) => ({ variable: v, originalIndex: i }))
.filter(({ variable }) => isValidVariableName(variable.name));

const { getRandomInput, hasInputs } = usePromptInputs(promptVersionId);

const importRandom = async () => {
const res = await getRandomInput.mutateAsync();
populateVariables({
inputsFromBackend: res.data?.data?.[0]?.inputs ?? {},
validVariablesWithIndices,
onVariableChange,
});
};

const [openInputSelector, setOpenInputSelector] = useState(false);
return (
<div className="flex flex-col gap-2">
<div className="flex items-center justify-between">
<h2 className="text-lg font-semibold text-slate-700">Variables</h2>

<Row className="gap-2">
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<div>
<Button
variant={"secondary"}
size={"sm_sleek"}
asPill
disabled={!hasInputs}
onClick={() => setOpenInputSelector(true)}
>
<ImportIcon className="w-4 h-4" />
</Button>
</div>
</TooltipTrigger>
<TooltipContent>
<p>
{hasInputs
? "Import from Production"
: "No production data available"}
</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<div>
<Button
variant={"secondary"}
size={"sm_sleek"}
asPill
onClick={importRandom}
disabled={!hasInputs}
>
<ShuffleIcon className="w-4 h-4" />
</Button>
</div>
</TooltipTrigger>
<TooltipContent>
<p>
{hasInputs
? "Randomized from production data"
: "No production data available"}
</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</Row>
</div>

{/* No Variables */}
Expand Down Expand Up @@ -59,6 +137,22 @@ export default function VariablesPanel({
))}
</div>
)}
<ExperimentInputSelector
open={openInputSelector}
setOpen={setOpenInputSelector}
promptVersionId={promptVersionId}
onSuccess={() => {}}
handleAddRows={(rows) => {
const row = rows[0];

populateVariables({
inputsFromBackend: row.inputs,
validVariablesWithIndices,
onVariableChange,
});
}}
selectJustOne
/>
</div>
);
}
22 changes: 22 additions & 0 deletions web/components/shared/prompts/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Variable } from "@/types/prompt-state";

export const populateVariables = ({
inputsFromBackend,
validVariablesWithIndices,
onVariableChange,
}: {
inputsFromBackend: Record<string, string>;
validVariablesWithIndices: { variable: Variable; originalIndex: number }[];
onVariableChange: (index: number, value: string) => void;
}) => {
for (const [key, value] of Object.entries(inputsFromBackend ?? {})) {
const originalIndex = validVariablesWithIndices.find(
({ variable }) => variable.name === key
)?.originalIndex;

console.log(originalIndex, " ORIGINAL INDEX");
if (originalIndex !== undefined && originalIndex !== -1) {
onVariableChange(originalIndex, value);
}
}
};
55 changes: 55 additions & 0 deletions web/components/shared/prompts/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useJawnClient } from "@/lib/clients/jawnHook";
import { useMutation, useQuery } from "@tanstack/react-query";
import { useMemo } from "react";

export const usePromptInputs = (promptVersionId: string) => {
const jawn = useJawnClient();

const inputs = useQuery({
queryKey: ["promptInputs", promptVersionId],
queryFn: async () => {
return await jawn.POST(
"/v1/prompt/version/{promptVersionId}/inputs/query",
{
params: {
path: {
promptVersionId: promptVersionId ?? "unknown",
},
},
body: {
limit: 1,
},
}
);
},
});

const getRandomInput = useMutation({
mutationFn: async () => {
return await jawn.POST(
"/v1/prompt/version/{promptVersionId}/inputs/query",
{
params: {
path: {
promptVersionId: promptVersionId ?? "unknown",
},
},
body: {
limit: 1,
random: true,
},
}
);
},
});

const hasInputs = useMemo(() => {
return (inputs.data?.data?.data?.length ?? 0) > 0;
}, [inputs.data]);

return {
inputs,
getRandomInput,
hasInputs,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import useNotification from "../../../shared/notification/useNotification";
import PromptPropertyCard from "../id/promptPropertyCard";
import { Button } from "@/components/ui/button";
import { useQuery } from "@tanstack/react-query";
import clsx from "clsx";

interface ExperimentInputSelectorProps {
open: boolean;
Expand All @@ -18,10 +19,18 @@ interface ExperimentInputSelectorProps {
autoInputs: any[];
}[]
) => void;
selectJustOne?: boolean;
}

const ExperimentInputSelector = (props: ExperimentInputSelectorProps) => {
const { open, setOpen, promptVersionId, onSuccess, handleAddRows } = props;
const {
open,
setOpen,
promptVersionId,
onSuccess,
handleAddRows,
selectJustOne,
} = props;
const jawn = useJawnClient();
const { setNotification } = useNotification();

Expand Down Expand Up @@ -130,14 +139,16 @@ const ExperimentInputSelector = (props: ExperimentInputSelectorProps) => {
<h2 className="font-semibold text-xl">
Select Inputs ({inputRecords.length})
</h2>
<Button
variant="secondary"
size="sm"
title={isAllSelected ? "Deselect All" : "Select All"}
onClick={handleSelectAll}
>
{isAllSelected ? "Deselect All" : "Select All"}
</Button>
{!selectJustOne && (
<Button
variant="secondary"
size="sm"
title={isAllSelected ? "Deselect All" : "Select All"}
onClick={handleSelectAll}
>
{isAllSelected ? "Deselect All" : "Select All"}
</Button>
)}
</div>
<p className="text-gray-500 text-sm pb-4">
Select the inputs you want to include in the dataset.
Expand All @@ -149,7 +160,25 @@ const ExperimentInputSelector = (props: ExperimentInputSelectorProps) => {
{!isLoading &&
!isError &&
inputRecords.map((request) => (
<li key={request.id} className="w-full flex items-start">
<li
key={request.id}
className={clsx(
"w-full flex items-start",
selectJustOne && "cursor-pointer"
)}
onClick={() => {
if (selectJustOne) {
handleAddRows([
{
autoInputs: request.autoInputs,
inputs: request.inputs,
inputRecordId: request.id,
},
]);
setOpen(false);
}
}}
>
<input
type="checkbox"
className="mt-2 mr-2 rounded border-slate-300 dark:border-slate-700"
Expand All @@ -172,42 +201,44 @@ const ExperimentInputSelector = (props: ExperimentInputSelectorProps) => {
</ul>
</div>

<div className="flex justify-end space-x-4 sticky bottom-0 py-4 bg-white">
<Button
variant={"secondary"}
size={"sm"}
onClick={() => setOpen(false)}
>
Cancel
</Button>

<Button
size={"sm"}
onClick={async () => {
if (selectedRequests.length === 0) {
setNotification("Please select at least one input.", "error");
return;
}

await handleAddRows(
selectedRequests.map((request) => ({
inputRecordId: request.id,
inputs: request.inputs,
autoInputs: request.autoInputs,
}))
);

if (onSuccess) {
onSuccess(true);

setNotification("Added inputs to dataset", "success");
setOpen(false);
}
}}
>
Confirm
</Button>
</div>
{!selectJustOne && (
<div className="flex justify-end space-x-4 sticky bottom-0 py-4 bg-white">
<Button
variant={"secondary"}
size={"sm"}
onClick={() => setOpen(false)}
>
Cancel
</Button>

<Button
size={"sm"}
onClick={async () => {
if (selectedRequests.length === 0) {
setNotification("Please select at least one input.", "error");
return;
}

await handleAddRows(
selectedRequests.map((request) => ({
inputRecordId: request.id,
inputs: request.inputs,
autoInputs: request.autoInputs,
}))
);

if (onSuccess) {
onSuccess(true);

setNotification("Added inputs to dataset", "success");
setOpen(false);
}
}}
>
Confirm
</Button>
</div>
)}
</div>
</ThemedDrawer>
);
Expand Down
1 change: 1 addition & 0 deletions web/components/templates/prompts/id/promptIdPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,7 @@ export default function PromptIdPage(props: PromptIdPageProps) {
<VariablesPanel
variables={state.variables || []}
onVariableChange={handleVariableChange}
promptVersionId={state.versionId}
/>

<ParametersPanel
Expand Down
Loading

0 comments on commit f6abb8a

Please sign in to comment.