feat: add public prompts picker (#841)

* fix: update prompt_id logic in payload

* feat: add getPublicPrompts to sdk

* feat: add public prompt picker
This commit is contained in:
Mamadou DICKO 2023-08-03 17:00:05 +02:00 committed by GitHub
parent fdcdf581a8
commit b3fb8fc3bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 158 additions and 4 deletions

View File

@ -10,6 +10,7 @@ import { TextArea } from "@/lib/components/ui/TextArea";
import { models, paidModels } from "@/lib/context/BrainConfigProvider/types";
import { defineMaxTokens } from "@/lib/helpers/defineMexTokens";
import { PublicPrompts } from "./components/PublicPrompts";
import { useSettingsTab } from "./hooks/useSettingsTab";
type SettingsTabProps = {
@ -30,6 +31,7 @@ export const SettingsTab = ({ brainId }: SettingsTabProps): JSX.Element => {
isDefaultBrain,
formRef,
promptId,
pickPublicPrompt,
removeBrainPrompt,
} = useSettingsTab({ brainId });
@ -128,7 +130,8 @@ export const SettingsTab = ({ brainId }: SettingsTabProps): JSX.Element => {
{...register("maxTokens")}
/>
</fieldset>
<Divider text="prompt" />
<Divider text="Custom prompt" />
<PublicPrompts onSelect={pickPublicPrompt} />
<Field
label="Prompt title"
placeholder="My awesome prompt name"

View File

@ -0,0 +1,57 @@
import * as Accordion from "@radix-ui/react-accordion";
import { ChangeEvent, useEffect, useState } from "react";
import { usePromptApi } from "@/lib/api/prompt/usePromptApi";
import { Prompt } from "@/lib/types/Prompt";
type PublicPromptsProps = {
onSelect: ({ title, content }: { title: string; content: string }) => void;
};
export const PublicPrompts = ({
onSelect,
}: PublicPromptsProps): JSX.Element => {
const [publicPrompts, setPublicPrompts] = useState<Prompt[]>([]);
const { getPublicPrompts } = usePromptApi();
const fetchPublicPrompts = async () => {
setPublicPrompts(await getPublicPrompts());
};
const handleChange = (event: ChangeEvent<HTMLSelectElement>) => {
const selectedPrompt = publicPrompts.find(
(prompt) => prompt.id === event.target.value
);
if (selectedPrompt) {
onSelect({
title: selectedPrompt.title,
content: selectedPrompt.content,
});
}
};
useEffect(() => {
void fetchPublicPrompts();
}, []);
return (
<Accordion.Root className="AccordionRoot" type="single" collapsible>
<Accordion.Item className="AccordionItem" value="item-1">
<Accordion.Trigger>Pick in public prompts</Accordion.Trigger>
<Accordion.Content>
<select
onChange={handleChange}
className="px-5 w-full py-2 dark:bg-gray-700 bg-gray-200 rounded-md"
>
{publicPrompts.map((prompt) => (
<option value={prompt.id} key={prompt.id}>
{prompt.title}
</option>
))}
</select>
</Accordion.Content>
</Accordion.Item>
</Accordion.Root>
);
};

View File

@ -257,13 +257,15 @@ export const useSettingsTab = ({ brainId }: UseSettingsTabProps) => {
promptHandler(),
]);
}
return;
} else {
await updateBrain(brainId, {
...otherConfigs,
max_tokens,
openai_api_key,
prompt_id:
otherConfigs["prompt_id"] !== ""
? otherConfigs["prompt_id"]
: undefined,
});
}
@ -295,6 +297,21 @@ export const useSettingsTab = ({ brainId }: UseSettingsTabProps) => {
}
};
const pickPublicPrompt = ({
title,
content,
}: {
title: string;
content: string;
}): void => {
setValue("prompt.title", title, {
shouldDirty: true,
});
setValue("prompt.content", content, {
shouldDirty: true,
});
};
return {
handleSubmit,
register,
@ -309,5 +326,6 @@ export const useSettingsTab = ({ brainId }: UseSettingsTabProps) => {
formRef,
promptId,
removeBrainPrompt,
pickPublicPrompt,
};
};

View File

@ -1,5 +1,5 @@
import { renderHook } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, it, vi } from "vitest";
import { CreatePromptProps, PromptUpdatableProperties } from "../prompt";
import { usePromptApi } from "../usePromptApi";
@ -19,6 +19,10 @@ vi.mock("@/lib/hooks", () => ({
}));
describe("usePromptApi", () => {
afterEach(() => {
vi.resetAllMocks();
});
it("should call createPrompt with the correct parameters", async () => {
const prompt: CreatePromptProps = {
title: "Test Prompt",
@ -67,4 +71,17 @@ describe("usePromptApi", () => {
expect(axiosPutMock).toHaveBeenCalledTimes(1);
expect(axiosPutMock).toHaveBeenCalledWith(`/prompts/${promptId}`, prompt);
});
it("should call getPublicPrompts with the correct parameters", async () => {
axiosGetMock.mockReturnValue({ data: [] });
const {
result: {
current: { getPublicPrompts },
},
} = renderHook(() => usePromptApi());
await getPublicPrompts();
expect(axiosGetMock).toHaveBeenCalledTimes(1);
expect(axiosGetMock).toHaveBeenCalledWith("/prompts");
});
});

View File

@ -32,3 +32,9 @@ export const updatePrompt = async (
): Promise<Prompt> => {
return (await axiosInstance.put<Prompt>(`/prompts/${promptId}`, prompt)).data;
};
export const getPublicPrompts = async (
axiosInstance: AxiosInstance
): Promise<Prompt[]> => {
return (await axiosInstance.get<Prompt[]>("/prompts")).data;
};

View File

@ -4,6 +4,7 @@ import {
createPrompt,
CreatePromptProps,
getPrompt,
getPublicPrompts,
PromptUpdatableProperties,
updatePrompt,
} from "./prompt";
@ -18,5 +19,6 @@ export const usePromptApi = () => {
getPrompt: async (promptId: string) => getPrompt(promptId, axiosInstance),
updatePrompt: async (promptId: string, prompt: PromptUpdatableProperties) =>
updatePrompt(promptId, prompt, axiosInstance),
getPublicPrompts: async () => await getPublicPrompts(axiosInstance),
};
};

View File

@ -1,6 +1,7 @@
/* eslint-disable max-lines */
import { MdAdd } from "react-icons/md";
import { PublicPrompts } from "@/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/components/PublicPrompts";
import Button from "@/lib/components/ui/Button";
import Field from "@/lib/components/ui/Field";
import { Modal } from "@/lib/components/ui/Modal";
@ -22,6 +23,7 @@ export const AddBrainModal = (): JSX.Element => {
maxTokens,
model,
isPending,
pickPublicPrompt,
} = useAddBrainModal();
return (
@ -116,6 +118,7 @@ export const AddBrainModal = (): JSX.Element => {
/>
</fieldset>
<Divider text="Custom prompt" />
<PublicPrompts onSelect={pickPublicPrompt} />
<Field
label="Prompt title"
placeholder="My awesome prompt name"

View File

@ -123,6 +123,21 @@ export const useAddBrainModal = () => {
}
};
const pickPublicPrompt = ({
title,
content,
}: {
title: string;
content: string;
}): void => {
setValue("prompt.title", title, {
shouldDirty: true,
});
setValue("prompt.content", content, {
shouldDirty: true,
});
};
return {
isShareModalOpen,
setIsShareModalOpen,
@ -133,5 +148,6 @@ export const useAddBrainModal = () => {
temperature,
maxTokens,
isPending,
pickPublicPrompt,
};
};

View File

@ -20,6 +20,7 @@
"@emotion/styled": "^11.11.0",
"@growthbook/growthbook-react": "^0.17.0",
"@june-so/analytics-next": "^2.0.0",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-dialog": "^1.0.3",
"@radix-ui/react-popover": "^1.0.6",
"@radix-ui/react-select": "^1.2.2",

View File

@ -756,6 +756,22 @@
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-accordion@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-accordion/-/react-accordion-1.1.2.tgz#738441f7343e5142273cdef94d12054c3287966f"
integrity sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "1.0.1"
"@radix-ui/react-collapsible" "1.0.3"
"@radix-ui/react-collection" "1.0.3"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-context" "1.0.1"
"@radix-ui/react-direction" "1.0.1"
"@radix-ui/react-id" "1.0.1"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-use-controllable-state" "1.0.1"
"@radix-ui/react-arrow@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz#c24f7968996ed934d57fe6cde5d6ec7266e1d25d"
@ -764,6 +780,21 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-collapsible@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz#df0e22e7a025439f13f62d4e4a9e92c4a0df5b81"
integrity sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "1.0.1"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-context" "1.0.1"
"@radix-ui/react-id" "1.0.1"
"@radix-ui/react-presence" "1.0.1"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-use-controllable-state" "1.0.1"
"@radix-ui/react-use-layout-effect" "1.0.1"
"@radix-ui/react-collection@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.3.tgz#9595a66e09026187524a36c6e7e9c7d286469159"