quivr/frontend/app/chat/page.tsx
!MAD! f69c64ead1
Toasts (Notification Component) (#163)
* feature: responsive navbar

* style: nav links hover animatiosn

* style: better Input Fields

* refactor: use form submit instead of button onclick

* feature: loading states

* feature: log out confirmation

* feature: basic toast

* feature: Toast variants

* fix: use global toast provider

* feature: use toast instead of alert for auth routes

* fix(mobile): nav menu close on route change

* fix: field dark mode

* feature: redirect when login and logout

* refactor: group auth routes

* refactor: use @/app imports

* style: use Field on /upload

* fix: forward ref

* feature: Multi toast

* feature: add toasts to /upload

* refactor: new login in auth group

* chore: quote

* chore(pnpm): removed

* feature: toasty animations

* fix: build errors and warnings

* chore: remove irrelevant comments

* fix: use unique ids for toasts

---------

Co-authored-by: Stan Girard <girard.stanislas@gmail.com>
2023-05-26 10:57:29 +02:00

144 lines
5.1 KiB
TypeScript

"use client";
import { useState } from "react";
import axios from "axios";
import Card from "../components/ui/Card";
import Button from "../components/ui/Button";
import Modal from "../components/ui/Modal";
import { MdSettings } from "react-icons/md";
import ChatMessages from "./ChatMessages";
import PageHeading from "../components/ui/PageHeading";
import { useSupabase } from "../supabase-provider";
import { redirect } from "next/navigation";
export default function ChatPage() {
const [question, setQuestion] = useState("");
const [history, setHistory] = useState<Array<[string, string]>>([]);
const [model, setModel] = useState("gpt-3.5-turbo");
const [temperature, setTemperature] = useState(0);
const [maxTokens, setMaxTokens] = useState(500);
const [isPending, setIsPending] = useState(false);
const { supabase, session } = useSupabase();
if (session === null) {
redirect("/login");
}
const askQuestion = async () => {
setHistory((hist) => [...hist, ["user", question]]);
setIsPending(true);
const response = await axios.post(
`${process.env.NEXT_PUBLIC_BACKEND_URL}/chat/`,
{
model,
question,
history,
temperature,
max_tokens: maxTokens,
},
{
headers: {
Authorization: `Bearer ${session.access_token}`,
},
}
);
setHistory(response.data.history);
console.log(response.data.history);
setQuestion("");
setIsPending(false);
};
return (
<main className="min-h-screen w-full flex flex-col pt-32">
<section className="flex flex-col justify-center items-center flex-1 gap-5 h-full">
<PageHeading
title="Chat with your brain"
subtitle="Talk to a language model about your uploaded data"
/>
{/* 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"
placeholder="Begin conversation here..."
/>
<Button type="submit" isLoading={isPending}>
{isPending ? "Thinking..." : "Chat"}
</Button>
{/* Settings Button */}
<Modal
Trigger={
<Button className="px-3" variant={"tertiary"}>
<MdSettings className="text-2xl" />
</Button>
}
title="Settings"
desc="Modify your brain"
>
<form className="flex flex-col gap-5 py-5">
<fieldset className="w-full flex">
<label className="flex-1" htmlFor="model">
Model:
</label>
<select
name="model"
id="model"
value={model}
className="px-5 py-2 dark:bg-gray-700 bg-gray-200 rounded-md"
onChange={(e) => setModel(e.target.value)}
>
<option value="gpt-3.5-turbo">gpt-3.5-turbo</option>
<option value="gpt-4">gpt-4</option>
</select>
</fieldset>
<fieldset className="w-full flex">
<label className="flex-1" htmlFor="temp">
Temperature: {temperature}
</label>
<input
name="temp"
id="temp"
type="range"
min="0"
max="1"
step="0.01"
value={temperature}
onChange={(e) => setTemperature(+e.target.value)}
/>
</fieldset>
<fieldset className="w-full flex">
<label className="flex-1" htmlFor="tokens">
Tokens: {maxTokens}
</label>
<input
name="tokens"
id="tokens"
type="range"
min="256"
max="3000"
step="1"
value={maxTokens}
onChange={(e) => setMaxTokens(+e.target.value)}
/>
</fieldset>
</form>
</Modal>
</form>
</Card>
</Card>
</section>
</main>
);
}