2023-05-21 02:20:55 +03:00
|
|
|
"use client";
|
2023-06-02 18:01:49 +03:00
|
|
|
import { useBrainConfig } from "@/lib/context/BrainConfigProvider/hooks/useBrainConfig";
|
|
|
|
import { useAxios } from "@/lib/useAxios";
|
|
|
|
import Link from "next/link";
|
2023-05-26 14:56:29 +03:00
|
|
|
import { redirect } from "next/navigation";
|
2023-05-29 01:45:48 +03:00
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
import { MdMic, MdMicOff, MdSettings } from "react-icons/md";
|
2023-05-21 02:20:55 +03:00
|
|
|
import Button from "../components/ui/Button";
|
2023-05-26 14:56:29 +03:00
|
|
|
import Card from "../components/ui/Card";
|
2023-05-23 11:06:58 +03:00
|
|
|
import PageHeading from "../components/ui/PageHeading";
|
2023-05-24 23:21:22 +03:00
|
|
|
import { useSupabase } from "../supabase-provider";
|
2023-05-26 14:56:29 +03:00
|
|
|
import ChatMessages from "./ChatMessages";
|
2023-06-02 17:01:24 +03:00
|
|
|
import { isSpeechRecognitionSupported } from "./helpers";
|
2023-05-18 02:22:13 +03:00
|
|
|
|
|
|
|
export default function ChatPage() {
|
2023-05-21 02:20:55 +03:00
|
|
|
const [question, setQuestion] = useState("");
|
2023-05-24 23:21:22 +03:00
|
|
|
const [history, setHistory] = useState<Array<[string, string]>>([]);
|
2023-05-21 02:20:55 +03:00
|
|
|
const [isPending, setIsPending] = useState(false);
|
2023-05-29 01:45:48 +03:00
|
|
|
const [isListening, setIsListening] = useState(false);
|
2023-05-26 14:56:29 +03:00
|
|
|
const { session } = useSupabase();
|
2023-06-02 18:01:49 +03:00
|
|
|
const { axiosInstance } = useAxios();
|
|
|
|
const {
|
|
|
|
config: { maxTokens, model, temperature },
|
|
|
|
} = useBrainConfig();
|
2023-05-24 23:21:22 +03:00
|
|
|
if (session === null) {
|
2023-05-26 11:57:29 +03:00
|
|
|
redirect("/login");
|
2023-05-24 23:21:22 +03:00
|
|
|
}
|
2023-05-18 02:22:13 +03:00
|
|
|
|
2023-05-29 01:45:48 +03:00
|
|
|
useEffect(() => {
|
2023-06-02 17:01:24 +03:00
|
|
|
if (isSpeechRecognitionSupported()) {
|
2023-05-29 01:45:48 +03:00
|
|
|
const SpeechRecognition =
|
|
|
|
window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
|
|
|
|
|
|
const mic = new SpeechRecognition();
|
|
|
|
|
|
|
|
mic.continuous = true;
|
|
|
|
mic.interimResults = false;
|
|
|
|
mic.lang = "en-US";
|
|
|
|
|
|
|
|
mic.onstart = () => {
|
|
|
|
console.log("Mics on");
|
|
|
|
};
|
|
|
|
|
|
|
|
mic.onend = () => {
|
|
|
|
console.log("Mics off");
|
|
|
|
};
|
|
|
|
|
|
|
|
mic.onerror = (event: SpeechRecognitionErrorEvent) => {
|
|
|
|
console.log(event.error);
|
|
|
|
setIsListening(false);
|
|
|
|
};
|
|
|
|
|
|
|
|
mic.onresult = (event: SpeechRecognitionEvent) => {
|
|
|
|
const interimTranscript =
|
|
|
|
event.results[event.results.length - 1][0].transcript;
|
|
|
|
setQuestion((prevQuestion) => prevQuestion + interimTranscript);
|
|
|
|
};
|
|
|
|
|
|
|
|
if (isListening) {
|
|
|
|
mic.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
if (mic) {
|
|
|
|
mic.stop();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}, [isListening]);
|
|
|
|
|
2023-05-18 02:22:13 +03:00
|
|
|
const askQuestion = async () => {
|
2023-05-21 02:20:55 +03:00
|
|
|
setHistory((hist) => [...hist, ["user", question]]);
|
|
|
|
setIsPending(true);
|
2023-05-29 01:45:48 +03:00
|
|
|
setIsListening(false);
|
2023-06-02 18:01:49 +03:00
|
|
|
|
|
|
|
const response = await axiosInstance.post(`/chat/`, {
|
|
|
|
model,
|
|
|
|
question,
|
|
|
|
history,
|
|
|
|
temperature,
|
|
|
|
max_tokens: maxTokens,
|
|
|
|
});
|
2023-05-18 02:22:13 +03:00
|
|
|
setHistory(response.data.history);
|
2023-05-21 02:20:55 +03:00
|
|
|
setQuestion("");
|
|
|
|
setIsPending(false);
|
2023-05-18 02:22:13 +03:00
|
|
|
};
|
|
|
|
|
2023-05-29 01:45:48 +03:00
|
|
|
const handleListen = () => {
|
|
|
|
setIsListening((prevIsListening) => !prevIsListening);
|
|
|
|
};
|
|
|
|
|
2023-05-18 02:22:13 +03:00
|
|
|
return (
|
2023-05-26 11:57:29 +03:00
|
|
|
<main className="min-h-screen w-full flex flex-col pt-32">
|
2023-05-23 11:06:58 +03:00
|
|
|
<section className="flex flex-col justify-center items-center flex-1 gap-5 h-full">
|
|
|
|
<PageHeading
|
|
|
|
title="Chat with your brain"
|
2023-05-25 11:10:35 +03:00
|
|
|
subtitle="Talk to a language model about your uploaded data"
|
2023-05-23 11:06:58 +03:00
|
|
|
/>
|
2023-05-21 02:20:55 +03:00
|
|
|
{/* Chat */}
|
|
|
|
<Card className="p-5 max-w-3xl w-full min-h-full flex-1 mb-24">
|
|
|
|
<ChatMessages history={history} />
|
|
|
|
<Card className="fixed left-1/2 w-full max-w-3xl bg-gray-100 dark:bg-gray-800 rounded-b-none -translate-x-1/2 bottom-0 px-5 py-5">
|
|
|
|
<form
|
|
|
|
onSubmit={(e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
if (!isPending) askQuestion();
|
|
|
|
}}
|
|
|
|
className="w-full flex items-center justify-center gap-2"
|
|
|
|
>
|
|
|
|
<input
|
|
|
|
autoFocus
|
|
|
|
type="text"
|
|
|
|
value={question}
|
|
|
|
onChange={(e) => setQuestion(e.target.value)}
|
|
|
|
className="w-full p-2 border border-gray-300 dark:border-gray-500 outline-none rounded dark:bg-gray-800"
|
2023-05-25 11:10:35 +03:00
|
|
|
placeholder="Begin conversation here..."
|
2023-05-21 02:20:55 +03:00
|
|
|
/>
|
|
|
|
<Button type="submit" isLoading={isPending}>
|
2023-05-25 11:10:35 +03:00
|
|
|
{isPending ? "Thinking..." : "Chat"}
|
2023-05-21 02:20:55 +03:00
|
|
|
</Button>
|
2023-05-29 01:45:48 +03:00
|
|
|
{/* Mic Button */}
|
|
|
|
<Button
|
|
|
|
className="px-3"
|
|
|
|
variant={"tertiary"}
|
|
|
|
type="button"
|
|
|
|
onClick={handleListen}
|
2023-06-02 17:01:24 +03:00
|
|
|
disabled={!isSpeechRecognitionSupported()}
|
2023-05-29 01:45:48 +03:00
|
|
|
>
|
|
|
|
{isListening ? (
|
|
|
|
<MdMicOff className="text-2xl" />
|
|
|
|
) : (
|
|
|
|
<MdMic className="text-2xl" />
|
|
|
|
)}
|
|
|
|
</Button>
|
2023-06-02 18:01:49 +03:00
|
|
|
<Link href={"/config"}>
|
|
|
|
<Button className="px-3" variant={"tertiary"}>
|
|
|
|
<MdSettings className="text-2xl" />
|
|
|
|
</Button>
|
|
|
|
</Link>
|
2023-05-21 02:20:55 +03:00
|
|
|
</form>
|
|
|
|
</Card>
|
|
|
|
</Card>
|
2023-05-23 11:06:58 +03:00
|
|
|
</section>
|
|
|
|
</main>
|
2023-05-18 02:22:13 +03:00
|
|
|
);
|
|
|
|
}
|