feat(chatSettings): set last config as default

This commit is contained in:
mamadoudicko 2023-09-26 15:01:09 +02:00
parent a89a9c0f6b
commit 0ffb8f036f
8 changed files with 81 additions and 84 deletions

View File

@ -42,6 +42,22 @@ vi.mock("@/lib/api/chat/useChatApi", () => ({
getHistory: () => [],
}),
}));
vi.mock("@/lib/hooks", async () => {
const actual = await vi.importActual<typeof import("@/lib/hooks")>(
"@/lib/hooks"
);
return {
...actual,
useAxios: () => ({
axiosInstance: {
get: vi.fn(() => ({ data: [] })),
},
}),
};
});
vi.mock("@tanstack/react-query", async () => {
const actual = await vi.importActual<typeof import("@tanstack/react-query")>(
"@tanstack/react-query"

View File

@ -7,7 +7,7 @@ import { defineMaxTokens } from "@/lib/helpers/defineMaxTokens";
import { useConfigModal } from "./hooks/useConfigModal";
export const ConfigModal = ({ chatId }: { chatId?: string }): JSX.Element => {
export const ConfigModal = (): JSX.Element => {
const {
handleSubmit,
isConfigModalOpen,
@ -17,11 +17,7 @@ export const ConfigModal = ({ chatId }: { chatId?: string }): JSX.Element => {
maxTokens,
model,
accessibleModels,
} = useConfigModal(chatId);
if (chatId === undefined) {
return <div />;
}
} = useConfigModal();
return (
<Modal
@ -79,7 +75,7 @@ export const ConfigModal = ({ chatId }: { chatId?: string }): JSX.Element => {
<input
type="range"
min="10"
max={defineMaxTokens(model ?? "gpt-3.5-turbo")}
max={defineMaxTokens(model)}
value={maxTokens}
{...register("maxTokens")}
/>

View File

@ -1,28 +1,27 @@
/* eslint-disable max-lines */
import { useQuery } from "@tanstack/react-query";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { useBrainApi } from "@/lib/api/brain/useBrainApi";
import {
getChatConfigFromLocalStorage,
saveChatConfigInLocalStorage,
getChatsConfigFromLocalStorage,
saveChatsConfigInLocalStorage,
} from "@/lib/api/chat/chat.local";
import { USER_DATA_KEY, USER_IDENTITY_DATA_KEY } from "@/lib/api/user/config";
import { useUserApi } from "@/lib/api/user/useUserApi";
import { defaultBrainConfig } from "@/lib/config/defaultBrainConfig";
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
import { ChatConfig } from "@/lib/context/ChatProvider/types";
import { defineMaxTokens } from "@/lib/helpers/defineMaxTokens";
import { getAccessibleModels } from "@/lib/helpers/getAccessibleModels";
import { useToast } from "@/lib/hooks";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const useConfigModal = (chatId?: string) => {
export const useConfigModal = () => {
const { publish } = useToast();
const [isConfigModalOpen, setIsConfigModalOpen] = useState(false);
const { getBrain } = useBrainApi();
const { currentBrain } = useBrainContext();
const { currentBrainId } = useBrainContext();
const { getUser, getUserIdentity } = useUserApi();
const { data: userData } = useQuery({
@ -34,10 +33,12 @@ export const useConfigModal = (chatId?: string) => {
queryFn: getUserIdentity,
});
const defaultValues: ChatConfig = {};
const { register, watch, setValue } = useForm({
defaultValues,
const { register, watch, setValue } = useForm<ChatConfig>({
defaultValues: {
model: defaultBrainConfig.model,
temperature: defaultBrainConfig.temperature,
maxTokens: defaultBrainConfig.maxTokens,
},
});
const model = watch("model");
@ -49,54 +50,40 @@ export const useConfigModal = (chatId?: string) => {
userData,
});
useEffect(() => {
const fetchChatConfig = async () => {
if (chatId === undefined) {
const fetchChatConfig = useCallback(async () => {
const chatConfig = getChatsConfigFromLocalStorage();
if (chatConfig !== undefined) {
setValue("model", chatConfig.model);
setValue("temperature", chatConfig.temperature);
setValue("maxTokens", chatConfig.maxTokens);
} else {
if (currentBrainId === null) {
return;
}
const relatedBrainConfig = await getBrain(currentBrainId);
const chatConfig = getChatConfigFromLocalStorage(chatId);
if (chatConfig !== undefined) {
setValue("model", chatConfig.model);
setValue("temperature", chatConfig.temperature);
setValue("maxTokens", chatConfig.maxTokens);
} else {
if (currentBrain === undefined) {
return;
}
const relatedBrainConfig = await getBrain(currentBrain.id);
if (relatedBrainConfig === undefined) {
return;
}
setValue("model", relatedBrainConfig.model ?? defaultBrainConfig.model);
setValue(
"temperature",
relatedBrainConfig.temperature ?? defaultBrainConfig.temperature
);
setValue(
"maxTokens",
relatedBrainConfig.max_tokens ?? defaultBrainConfig.maxTokens
);
if (relatedBrainConfig === undefined) {
return;
}
};
void fetchChatConfig();
setValue("model", relatedBrainConfig.model ?? defaultBrainConfig.model);
setValue(
"temperature",
relatedBrainConfig.temperature ?? defaultBrainConfig.temperature
);
setValue(
"maxTokens",
relatedBrainConfig.max_tokens ?? defaultBrainConfig.maxTokens
);
}
}, []);
useEffect(() => {
if (maxTokens === undefined || model === undefined) {
return;
}
void fetchChatConfig();
}, [fetchChatConfig]);
setValue("maxTokens", Math.min(maxTokens, defineMaxTokens(model)));
}, [maxTokens, model, setValue]);
const handleSubmit = () => {
if (chatId === undefined) {
return;
}
const handleSubmit = useCallback(() => {
try {
saveChatConfigInLocalStorage(chatId, {
saveChatsConfigInLocalStorage({
maxTokens,
model,
temperature,
@ -112,7 +99,7 @@ export const useConfigModal = (chatId?: string) => {
text: "An error occurred while updating chat config",
});
}
};
}, [maxTokens, model, publish, temperature]);
return {
isConfigModalOpen,

View File

@ -25,7 +25,7 @@ export const ChatInput = ({
setShouldDisplayUploadCard,
hasContentToFeedBrain,
}: ChatInputProps): JSX.Element => {
const { setMessage, submitQuestion, chatId, generatingAnswer, message } =
const { setMessage, submitQuestion, generatingAnswer, message } =
useChatInput();
const { t } = useTranslation(["chat"]);
const { currentBrainId } = useBrainContext();
@ -80,7 +80,7 @@ export const ChatInput = ({
<>
{isEmptyMessage ? (
<div className="md:hidden flex items-center">
<ConfigModal chatId={chatId} />
<ConfigModal />
</div>
) : (
<Button
@ -95,7 +95,7 @@ export const ChatInput = ({
</Button>
)}
<div className="hidden md:flex items-center">
<ConfigModal chatId={chatId} />
<ConfigModal />
</div>
</>
)}

View File

@ -4,7 +4,7 @@ import { useParams, useRouter } from "next/navigation";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { getChatConfigFromLocalStorage } from "@/lib/api/chat/chat.local";
import { getChatsConfigFromLocalStorage } from "@/lib/api/chat/chat.local";
import { useChatApi } from "@/lib/api/chat/useChatApi";
import { useChatContext } from "@/lib/context";
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
@ -64,7 +64,7 @@ export const useChat = () => {
promptId: currentPromptId,
});
const chatConfig = getChatConfigFromLocalStorage(currentChatId);
const chatConfig = getChatsConfigFromLocalStorage();
const chatQuestion: ChatQuestion = {
model: chatConfig?.model,

View File

@ -6,17 +6,20 @@ import { ChatHeader } from "./components/ChatHeader";
const SelectedChatPage = (): JSX.Element => {
return (
<main className="flex flex-col w-full h-[calc(100vh-61px)] overflow-hidden" data-testid="chat-page">
<section className="flex flex-col flex-1 items-center w-full h-full overflow-y-auto">
<ChatHeader /> {/* Added margin-bottom */}
<main
className="flex flex-col w-full h-[calc(100vh-61px)] overflow-hidden"
data-testid="chat-page"
>
<section className="flex flex-col flex-1 items-center w-full h-full overflow-y-auto">
<ChatHeader />
<div className="flex-1 flex flex-col mt-4 md:mt-8 w-full shadow-md dark:shadow-primary/25 hover:shadow-xl transition-shadow rounded-xl overflow-hidden bg-white dark:bg-black border border-black/10 dark:border-white/25 p-2 md:p-12 pt-4 md:pt-10">
<div className="flex flex-1 flex-col overflow-y-auto">
<ChatDialogueArea />
</div>
<ActionsBar/> {/* Added margin-top */}
<div className="flex flex-1 flex-col overflow-y-auto">
<ChatDialogueArea />
</div>
<ActionsBar />
</div>
</section>
</main>
</section>
</main>
);
};

View File

@ -1,16 +1,11 @@
import { ChatConfig } from "@/lib/context/ChatProvider/types";
export const saveChatConfigInLocalStorage = (
chatId: string,
chatConfig: ChatConfig
): void => {
localStorage.setItem(`chat-config-${chatId}`, JSON.stringify(chatConfig));
const chatConfigLocalStorageKey = "chat-config";
export const saveChatsConfigInLocalStorage = (chatConfig: ChatConfig): void => {
localStorage.setItem(chatConfigLocalStorageKey, JSON.stringify(chatConfig));
};
export const getChatConfigFromLocalStorage = (
chatId: string
): ChatConfig | undefined => {
const config = localStorage.getItem(`chat-config-${chatId}`);
export const getChatsConfigFromLocalStorage = (): ChatConfig | undefined => {
const config = localStorage.getItem(chatConfigLocalStorageKey);
if (config === null) {
return undefined;

View File

@ -3,9 +3,9 @@ import { ChatMessage, Notification } from "@/app/chat/[chatId]/types";
import { Model } from "../../types/brainConfig";
export type ChatConfig = {
model?: Model;
temperature?: number;
maxTokens?: number;
model: Model;
temperature: number;
maxTokens: number;
};
export type ChatContextProps = {