mirror of
https://github.com/StanGirard/quivr.git
synced 2024-12-26 04:42:31 +03:00
feat: add onboarding step 3 (#1324)
* feat: add OnboardingContext * feat: add Step3 boilerplate * feat: activate step3 * feat: add <Step3/> content * feat: add shouldStream guard on useStreamText
This commit is contained in:
parent
945178de39
commit
85eba3da70
@ -16,7 +16,7 @@ export const ActionsBar = (): JSX.Element => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{hasPendingRequests && (
|
{hasPendingRequests && (
|
||||||
<div className="flex mt-1 flex-col md:flex-row w-full shadow-md dark:shadow-primary/25 hover:shadow-xl transition-shadow rounded-xl bg-white dark:bg-black border border-black/10 dark:border-white/25 p-2 md:p-6 pl-6">
|
<div className="flex mt-1 flex-col md:flex-row w-full shadow-md dark:shadow-primary/25 hover:shadow-xl transition-shadow rounded-xl bg-white dark:bg-black border border-black/10 dark:border-white/25 p-2 md:p-6 pl-6 mb-3">
|
||||||
<div className="flex flex-1 items-center mb-2 md:mb-0">
|
<div className="flex flex-1 items-center mb-2 md:mb-0">
|
||||||
<span className="text-sm md:text-1xl">{t("feedingBrain")}</span>
|
<span className="text-sm md:text-1xl">{t("feedingBrain")}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
/*eslint max-lines: ["error", 200 ]*/
|
||||||
|
|
||||||
import { UUID } from "crypto";
|
import { UUID } from "crypto";
|
||||||
import { useParams, useRouter } from "next/navigation";
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
@ -10,6 +12,7 @@ import { useChatContext } from "@/lib/context";
|
|||||||
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
|
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
|
||||||
import { useKnowledgeToFeedContext } from "@/lib/context/KnowledgeToFeedProvider/hooks/useKnowledgeToFeedContext";
|
import { useKnowledgeToFeedContext } from "@/lib/context/KnowledgeToFeedProvider/hooks/useKnowledgeToFeedContext";
|
||||||
import { useToast } from "@/lib/hooks";
|
import { useToast } from "@/lib/hooks";
|
||||||
|
import { useOnboardingContext } from "@/lib/hooks/useOnboardingContext";
|
||||||
|
|
||||||
import { FeedItemCrawlType, FeedItemUploadType } from "../../../types";
|
import { FeedItemCrawlType, FeedItemUploadType } from "../../../types";
|
||||||
|
|
||||||
@ -23,7 +26,7 @@ export const useFeedBrainInChat = ({
|
|||||||
const { t } = useTranslation(["upload"]);
|
const { t } = useTranslation(["upload"]);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { setShouldDisplayFeedCard } = useKnowledgeToFeedContext();
|
const { setShouldDisplayFeedCard } = useKnowledgeToFeedContext();
|
||||||
|
const { setCurrentStep } = useOnboardingContext();
|
||||||
const { currentBrainId } = useBrainContext();
|
const { currentBrainId } = useBrainContext();
|
||||||
const { setKnowledgeToFeed, knowledgeToFeed } = useKnowledgeToFeedContext();
|
const { setKnowledgeToFeed, knowledgeToFeed } = useKnowledgeToFeedContext();
|
||||||
const [hasPendingRequests, setHasPendingRequests] = useState(false);
|
const [hasPendingRequests, setHasPendingRequests] = useState(false);
|
||||||
@ -61,6 +64,7 @@ export const useFeedBrainInChat = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
setCurrentStep("UPLOADED");
|
||||||
dispatchHasPendingRequests();
|
dispatchHasPendingRequests();
|
||||||
setShouldDisplayFeedCard(false);
|
setShouldDisplayFeedCard(false);
|
||||||
setHasPendingRequests(true);
|
setHasPendingRequests(true);
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
import { Step1 } from "./components";
|
import { Step1 } from "./components";
|
||||||
import { Step2 } from "./components/Step2";
|
import { Step2 } from "./components/Step2";
|
||||||
import { OnboardingState } from "../types";
|
import { Step3 } from "./components/Step3";
|
||||||
|
|
||||||
export const Onboarding = (): JSX.Element => {
|
export const Onboarding = (): JSX.Element => {
|
||||||
const [currentStep, setCurrentStep] = useState<OnboardingState>("DOWNLOAD");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2 mb-3">
|
||||||
<Step1 changeStateTo={setCurrentStep} currentStep={currentStep} />
|
<Step1 />
|
||||||
<Step2 currentStep={currentStep} />
|
<Step2 />
|
||||||
|
<Step3 />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4,27 +4,25 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { RiDownloadLine } from "react-icons/ri";
|
import { RiDownloadLine } from "react-icons/ri";
|
||||||
|
|
||||||
import Button from "@/lib/components/ui/Button";
|
import Button from "@/lib/components/ui/Button";
|
||||||
|
import { OnboardingState } from "@/lib/context/OnboardingContext/types";
|
||||||
|
import { useOnboardingContext } from "@/lib/hooks/useOnboardingContext";
|
||||||
|
|
||||||
import { MessageRow } from "../../QADisplay";
|
import { MessageRow } from "../../QADisplay";
|
||||||
import { OnboardingState } from "../../types";
|
|
||||||
import { checkIfShouldDisplayStep } from "../helpers/checkIfShouldDisplayStep";
|
import { checkIfShouldDisplayStep } from "../helpers/checkIfShouldDisplayStep";
|
||||||
import { useStreamText } from "../hooks/useStreamText";
|
import { useStreamText } from "../hooks/useStreamText";
|
||||||
import { stepsContainerStyle } from "../styles";
|
import { stepsContainerStyle } from "../styles";
|
||||||
|
|
||||||
type Step1Props = {
|
const stepId: OnboardingState = "DOWNLOAD";
|
||||||
currentStep: OnboardingState;
|
|
||||||
changeStateTo: (state: OnboardingState) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Step1 = ({
|
export const Step1 = (): JSX.Element => {
|
||||||
currentStep,
|
const { currentStep, setCurrentStep } = useOnboardingContext();
|
||||||
changeStateTo,
|
|
||||||
}: Step1Props): JSX.Element => {
|
|
||||||
const shouldStepBeDisplayed = checkIfShouldDisplayStep({
|
const shouldStepBeDisplayed = checkIfShouldDisplayStep({
|
||||||
currentStep,
|
currentStep,
|
||||||
step: "DOWNLOAD",
|
step: stepId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const shouldStreamMessage = currentStep === stepId;
|
||||||
|
|
||||||
const { t } = useTranslation(["chat"]);
|
const { t } = useTranslation(["chat"]);
|
||||||
const firstMessage = t("onboarding.download_message_1");
|
const firstMessage = t("onboarding.download_message_1");
|
||||||
const secondMessageStream = t("onboarding.download_message_2");
|
const secondMessageStream = t("onboarding.download_message_2");
|
||||||
@ -33,11 +31,13 @@ export const Step1 = ({
|
|||||||
useStreamText({
|
useStreamText({
|
||||||
text: firstMessage,
|
text: firstMessage,
|
||||||
enabled: shouldStepBeDisplayed,
|
enabled: shouldStepBeDisplayed,
|
||||||
|
shouldStream: shouldStreamMessage,
|
||||||
});
|
});
|
||||||
const { streamingText: firstMessageStrem, isDone: isStep1Done } =
|
const { streamingText: firstMessageStrem, isDone: isStep1Done } =
|
||||||
useStreamText({
|
useStreamText({
|
||||||
text: secondMessageStream,
|
text: secondMessageStream,
|
||||||
enabled: isAssistantDone && shouldStepBeDisplayed,
|
enabled: isAssistantDone && shouldStepBeDisplayed,
|
||||||
|
shouldStream: shouldStreamMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!shouldStepBeDisplayed) {
|
if (!shouldStepBeDisplayed) {
|
||||||
@ -56,7 +56,7 @@ export const Step1 = ({
|
|||||||
download
|
download
|
||||||
target="_blank"
|
target="_blank"
|
||||||
referrerPolicy="no-referrer"
|
referrerPolicy="no-referrer"
|
||||||
onClick={() => changeStateTo("UPLOAD")}
|
onClick={() => setCurrentStep("UPLOAD")}
|
||||||
>
|
>
|
||||||
<Button className="bg-black p-2 ml-2 rounded-full inline-flex">
|
<Button className="bg-black p-2 ml-2 rounded-full inline-flex">
|
||||||
<RiDownloadLine />
|
<RiDownloadLine />
|
||||||
|
@ -1,35 +1,40 @@
|
|||||||
import { Fragment } from "react";
|
import { Fragment } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
import { OnboardingState } from "@/lib/context/OnboardingContext/types";
|
||||||
|
import { useOnboardingContext } from "@/lib/hooks/useOnboardingContext";
|
||||||
|
|
||||||
import { MessageRow } from "../../QADisplay";
|
import { MessageRow } from "../../QADisplay";
|
||||||
import { OnboardingState } from "../../types";
|
|
||||||
import { checkIfShouldDisplayStep } from "../helpers/checkIfShouldDisplayStep";
|
import { checkIfShouldDisplayStep } from "../helpers/checkIfShouldDisplayStep";
|
||||||
import { useStreamText } from "../hooks/useStreamText";
|
import { useStreamText } from "../hooks/useStreamText";
|
||||||
import { stepsContainerStyle } from "../styles";
|
import { stepsContainerStyle } from "../styles";
|
||||||
|
|
||||||
type Step1Props = {
|
const stepId: OnboardingState = "UPLOAD";
|
||||||
currentStep: OnboardingState;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Step2 = ({ currentStep }: Step1Props): JSX.Element => {
|
export const Step2 = (): JSX.Element => {
|
||||||
|
const { currentStep } = useOnboardingContext();
|
||||||
const shouldStepBeDisplayed = checkIfShouldDisplayStep({
|
const shouldStepBeDisplayed = checkIfShouldDisplayStep({
|
||||||
currentStep,
|
currentStep,
|
||||||
step: "UPLOAD",
|
step: stepId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { t } = useTranslation(["chat"]);
|
const { t } = useTranslation(["chat"]);
|
||||||
const firstMessage = t("onboarding.upload_message_1");
|
const firstMessage = t("onboarding.upload_message_1");
|
||||||
const secondMessageStream = t("onboarding.upload_message_2");
|
const secondMessageStream = t("onboarding.upload_message_2");
|
||||||
|
|
||||||
|
const shouldStreamMessage = currentStep === stepId;
|
||||||
|
|
||||||
const { streamingText: streamingAssistantMessage, isDone: isAssistantDone } =
|
const { streamingText: streamingAssistantMessage, isDone: isAssistantDone } =
|
||||||
useStreamText({
|
useStreamText({
|
||||||
text: firstMessage,
|
text: firstMessage,
|
||||||
enabled: shouldStepBeDisplayed,
|
enabled: shouldStepBeDisplayed,
|
||||||
|
shouldStream: shouldStreamMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { streamingText: firstMessageStream } = useStreamText({
|
const { streamingText: firstMessageStream } = useStreamText({
|
||||||
text: secondMessageStream,
|
text: secondMessageStream,
|
||||||
enabled: isAssistantDone && shouldStepBeDisplayed,
|
enabled: isAssistantDone && shouldStepBeDisplayed,
|
||||||
|
shouldStream: shouldStreamMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!shouldStepBeDisplayed) {
|
if (!shouldStepBeDisplayed) {
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
import { Fragment } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
import { OnboardingState } from "@/lib/context/OnboardingContext/types";
|
||||||
|
import { useOnboardingContext } from "@/lib/hooks/useOnboardingContext";
|
||||||
|
|
||||||
|
import { MessageRow } from "../../QADisplay";
|
||||||
|
import { checkIfShouldDisplayStep } from "../helpers/checkIfShouldDisplayStep";
|
||||||
|
import { useStreamText } from "../hooks/useStreamText";
|
||||||
|
import { stepsContainerStyle } from "../styles";
|
||||||
|
|
||||||
|
const stepId: OnboardingState = "UPLOADED";
|
||||||
|
|
||||||
|
export const Step3 = (): JSX.Element => {
|
||||||
|
const { currentStep } = useOnboardingContext();
|
||||||
|
const shouldStepBeDisplayed = checkIfShouldDisplayStep({
|
||||||
|
currentStep,
|
||||||
|
step: stepId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { t } = useTranslation(["chat"]);
|
||||||
|
const firstMessage = t("onboarding.last_step");
|
||||||
|
const secondMessageStream = t("onboarding.ask_question_to_file");
|
||||||
|
const shouldStreamMessage = currentStep === stepId;
|
||||||
|
|
||||||
|
const { streamingText: streamingAssistantMessage, isDone: isAssistantDone } =
|
||||||
|
useStreamText({
|
||||||
|
text: firstMessage,
|
||||||
|
enabled: shouldStepBeDisplayed,
|
||||||
|
shouldStream: shouldStreamMessage,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { streamingText: firstMessageStream } = useStreamText({
|
||||||
|
text: secondMessageStream,
|
||||||
|
enabled: isAssistantDone && shouldStepBeDisplayed,
|
||||||
|
shouldStream: shouldStreamMessage,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!shouldStepBeDisplayed) {
|
||||||
|
return <Fragment />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MessageRow speaker={"assistant"} brainName={"Quivr"}>
|
||||||
|
<div className={stepsContainerStyle}>
|
||||||
|
<p>{streamingAssistantMessage}</p>
|
||||||
|
<p>{firstMessageStream}</p>
|
||||||
|
</div>
|
||||||
|
</MessageRow>
|
||||||
|
);
|
||||||
|
};
|
@ -1,8 +1,9 @@
|
|||||||
import { OnboardingState } from "../../types";
|
import { OnboardingState } from "@/lib/context/OnboardingContext/types";
|
||||||
|
|
||||||
const onboardingStepToState: Record<OnboardingState, OnboardingState[]> = {
|
const requiredStateForDisplaying: Record<OnboardingState, OnboardingState[]> = {
|
||||||
DOWNLOAD: ["DOWNLOAD", "UPLOAD"],
|
DOWNLOAD: ["DOWNLOAD", "UPLOAD", "UPLOADED"],
|
||||||
UPLOAD: ["UPLOAD"],
|
UPLOAD: ["UPLOAD", "UPLOADED"],
|
||||||
|
UPLOADED: ["UPLOADED"],
|
||||||
};
|
};
|
||||||
|
|
||||||
type CheckIfShouldDisplayStepProps = {
|
type CheckIfShouldDisplayStepProps = {
|
||||||
@ -14,5 +15,5 @@ export const checkIfShouldDisplayStep = ({
|
|||||||
currentStep,
|
currentStep,
|
||||||
step,
|
step,
|
||||||
}: CheckIfShouldDisplayStepProps): boolean => {
|
}: CheckIfShouldDisplayStepProps): boolean => {
|
||||||
return onboardingStepToState[step].includes(currentStep);
|
return requiredStateForDisplaying[step].includes(currentStep);
|
||||||
};
|
};
|
||||||
|
@ -3,9 +3,14 @@ import { useEffect, useState } from "react";
|
|||||||
type UseStreamTextProps = {
|
type UseStreamTextProps = {
|
||||||
text: string;
|
text: string;
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
|
shouldStream?: boolean;
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
export const useStreamText = ({ text, enabled = true }: UseStreamTextProps) => {
|
export const useStreamText = ({
|
||||||
|
text,
|
||||||
|
enabled = true,
|
||||||
|
shouldStream = true,
|
||||||
|
}: UseStreamTextProps) => {
|
||||||
const [streamingText, setStreamingText] = useState<string>("");
|
const [streamingText, setStreamingText] = useState<string>("");
|
||||||
const [currentIndex, setCurrentIndex] = useState(0);
|
const [currentIndex, setCurrentIndex] = useState(0);
|
||||||
|
|
||||||
@ -18,6 +23,13 @@ export const useStreamText = ({ text, enabled = true }: UseStreamTextProps) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!shouldStream) {
|
||||||
|
setStreamingText(text);
|
||||||
|
setCurrentIndex(text.length);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const messageInterval = setInterval(() => {
|
const messageInterval = setInterval(() => {
|
||||||
if (currentIndex < text.length) {
|
if (currentIndex < text.length) {
|
||||||
setStreamingText((prevText) => prevText + (text[currentIndex] ?? ""));
|
setStreamingText((prevText) => prevText + (text[currentIndex] ?? ""));
|
||||||
@ -30,7 +42,7 @@ export const useStreamText = ({ text, enabled = true }: UseStreamTextProps) => {
|
|||||||
return () => {
|
return () => {
|
||||||
clearInterval(messageInterval);
|
clearInterval(messageInterval);
|
||||||
};
|
};
|
||||||
}, [text, currentIndex, enabled]);
|
}, [text, currentIndex, enabled, shouldStream]);
|
||||||
|
|
||||||
return { streamingText, isDone };
|
return { streamingText, isDone };
|
||||||
};
|
};
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export type OnboardingState = "DOWNLOAD" | "UPLOAD";
|
|
@ -18,7 +18,8 @@ export const useChatsList = () => {
|
|||||||
const fetchAllChats = async () => {
|
const fetchAllChats = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await getChats();
|
const response = await getChats();
|
||||||
setAllChats(response.reverse());
|
|
||||||
|
return response.reverse();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
publish({
|
publish({
|
||||||
|
@ -3,6 +3,7 @@ import { ReactNode } from "react";
|
|||||||
|
|
||||||
import { ChatProvider, KnowledgeToFeedProvider } from "@/lib/context";
|
import { ChatProvider, KnowledgeToFeedProvider } from "@/lib/context";
|
||||||
import { ChatsProvider } from "@/lib/context/ChatsProvider/chats-provider";
|
import { ChatsProvider } from "@/lib/context/ChatsProvider/chats-provider";
|
||||||
|
import { OnboardingContextProvider } from "@/lib/context/OnboardingContext/knowledgeToFeed-provider";
|
||||||
import { useSupabase } from "@/lib/context/SupabaseProvider";
|
import { useSupabase } from "@/lib/context/SupabaseProvider";
|
||||||
import { redirectToLogin } from "@/lib/router/redirectToLogin";
|
import { redirectToLogin } from "@/lib/router/redirectToLogin";
|
||||||
|
|
||||||
@ -23,10 +24,12 @@ const Layout = ({ children }: LayoutProps): JSX.Element => {
|
|||||||
<KnowledgeToFeedProvider>
|
<KnowledgeToFeedProvider>
|
||||||
<ChatsProvider>
|
<ChatsProvider>
|
||||||
<ChatProvider>
|
<ChatProvider>
|
||||||
<div className="relative h-full w-full flex justify-stretch items-stretch">
|
<OnboardingContextProvider>
|
||||||
<ChatsList />
|
<div className="relative h-full w-full flex justify-stretch items-stretch">
|
||||||
{children}
|
<ChatsList />
|
||||||
</div>
|
{children}
|
||||||
|
</div>
|
||||||
|
</OnboardingContextProvider>
|
||||||
</ChatProvider>
|
</ChatProvider>
|
||||||
</ChatsProvider>
|
</ChatsProvider>
|
||||||
</KnowledgeToFeedProvider>
|
</KnowledgeToFeedProvider>
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { createContext, useState } from "react";
|
||||||
|
|
||||||
|
import { OnboardingState } from "./types";
|
||||||
|
|
||||||
|
type OnboardingContextType = {
|
||||||
|
currentStep: OnboardingState;
|
||||||
|
setCurrentStep: React.Dispatch<React.SetStateAction<OnboardingState>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const OnboardingContext = createContext<
|
||||||
|
OnboardingContextType | undefined
|
||||||
|
>(undefined);
|
||||||
|
|
||||||
|
export const OnboardingContextProvider = ({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}): JSX.Element => {
|
||||||
|
const [currentStep, setCurrentStep] = useState<OnboardingState>("DOWNLOAD");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<OnboardingContext.Provider
|
||||||
|
value={{
|
||||||
|
currentStep,
|
||||||
|
setCurrentStep,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</OnboardingContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
1
frontend/lib/context/OnboardingContext/types.ts
Normal file
1
frontend/lib/context/OnboardingContext/types.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type OnboardingState = "DOWNLOAD" | "UPLOAD" | "UPLOADED";
|
15
frontend/lib/hooks/useOnboardingContext.ts
Normal file
15
frontend/lib/hooks/useOnboardingContext.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { useContext } from "react";
|
||||||
|
|
||||||
|
import { OnboardingContext } from "../context/OnboardingContext/knowledgeToFeed-provider";
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
|
export const useOnboardingContext = () => {
|
||||||
|
const context = useContext(OnboardingContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error(
|
||||||
|
"useOnboardingContext must be used within a OnboardingContextProvider"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
};
|
@ -41,6 +41,8 @@
|
|||||||
"upload_message_2":"Step 2: Now Drag and drop it on the chat or in the 📎",
|
"upload_message_2":"Step 2: Now Drag and drop it on the chat or in the 📎",
|
||||||
"how_to_use_quivr": "How to user Quivr",
|
"how_to_use_quivr": "How to user Quivr",
|
||||||
"what_is_quivr":"What is Quivr ?",
|
"what_is_quivr":"What is Quivr ?",
|
||||||
"what_is_brain": "What is a brain ?"
|
"what_is_brain": "What is a brain ?",
|
||||||
|
"last_step":"Last step 🥳",
|
||||||
|
"ask_question_to_file":"Ask a question to your file. Ex : 'What are you talking about ?'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
"upload_message_2": "Paso 2: Ahora, arrástralo y suéltalo en el chat o en el 📎",
|
"upload_message_2": "Paso 2: Ahora, arrástralo y suéltalo en el chat o en el 📎",
|
||||||
"how_to_use_quivr": "Cómo usar Quivr",
|
"how_to_use_quivr": "Cómo usar Quivr",
|
||||||
"what_is_quivr": "¿Qué es Quivr?",
|
"what_is_quivr": "¿Qué es Quivr?",
|
||||||
"what_is_brain": "¿Qué es un cerebro?"
|
"what_is_brain": "¿Qué es un cerebro?",
|
||||||
|
"last_step":"Último paso 🥳",
|
||||||
|
"ask_question_to_file":"Haz una pregunta a tu archivo. Ej: '¿De qué estás hablando?'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
"upload_message_2": "Étape 2 : Maintenant, faites glisser et déposez-le dans le chat ou dans 📎",
|
"upload_message_2": "Étape 2 : Maintenant, faites glisser et déposez-le dans le chat ou dans 📎",
|
||||||
"how_to_use_quivr": "Comment utiliser Quivr",
|
"how_to_use_quivr": "Comment utiliser Quivr",
|
||||||
"what_is_quivr": "Qu'est-ce que Quivr ?",
|
"what_is_quivr": "Qu'est-ce que Quivr ?",
|
||||||
"what_is_brain": "Qu'est-ce qu'un cerveau ?"
|
"what_is_brain": "Qu'est-ce qu'un cerveau ?",
|
||||||
|
"last_step":"Dernière étape 🥳",
|
||||||
|
"ask_question_to_file":"Posez une question à votre fichier. Ex : 'De quoi parlez-vous ?'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
"upload_message_2": "Passo 2: Agora, arraste e solte no chat ou na 📎",
|
"upload_message_2": "Passo 2: Agora, arraste e solte no chat ou na 📎",
|
||||||
"how_to_use_quivr": "Como usar o Quivr",
|
"how_to_use_quivr": "Como usar o Quivr",
|
||||||
"what_is_quivr": "O que é o Quivr?",
|
"what_is_quivr": "O que é o Quivr?",
|
||||||
"what_is_brain": "O que é um cérebro?"
|
"what_is_brain": "O que é um cérebro?",
|
||||||
|
"last_step":"Dernière étape 🥳",
|
||||||
|
"ask_question_to_file":"Posez une question à votre fichier. Ex : 'De quoi parlez-vous ?'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
"upload_message_2": "Шаг 2: Теперь перетащите его в чат или в 📎",
|
"upload_message_2": "Шаг 2: Теперь перетащите его в чат или в 📎",
|
||||||
"how_to_use_quivr": "Как использовать Quivr",
|
"how_to_use_quivr": "Как использовать Quivr",
|
||||||
"what_is_quivr": "Что такое Quivr?",
|
"what_is_quivr": "Что такое Quivr?",
|
||||||
"what_is_brain": "Что такое мозг?"
|
"what_is_brain": "Что такое мозг?",
|
||||||
|
"last_step":"Последний шаг 🥳",
|
||||||
|
"ask_question_to_file":"Задайте вопрос своему файлу. Например: 'О чем вы говорите?'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,8 @@
|
|||||||
"upload_message_2": "第2步:现在,将其拖放到聊天框或 📎 中",
|
"upload_message_2": "第2步:现在,将其拖放到聊天框或 📎 中",
|
||||||
"how_to_use_quivr": "如何使用Quivr",
|
"how_to_use_quivr": "如何使用Quivr",
|
||||||
"what_is_quivr": "什么是Quivr?",
|
"what_is_quivr": "什么是Quivr?",
|
||||||
"what_is_brain": "什么是大脑?"
|
"what_is_brain": "什么是大脑?",
|
||||||
|
"last_step":"最后一步 🥳",
|
||||||
|
"ask_question_to_file":"向您的文件提问。例如:'你在谈论什么?'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user