Merge branch 'main' into 65-consistent-paths-plus-ui

This commit is contained in:
Keith Stevens
2022-12-28 07:56:42 +09:00
committed by GitHub
27 changed files with 718 additions and 33 deletions
+2 -2
View File
@@ -12,7 +12,7 @@ export function Avatar() {
return <></>;
}
if (session && session.user) {
const email = session.user.email;
const displayName = session.user.name || session.user.email;
const accountOptions = [
{
name: "Account Settings",
@@ -35,7 +35,7 @@ export function Avatar() {
height="40"
className="rounded-full"
></Image>
<p className="hidden lg:flex">{email}</p>
<p className="hidden lg:flex">{displayName}</p>
{/* Will be changed to username once it is implemented */}
</div>
</Popover.Button>
+19
View File
@@ -0,0 +1,19 @@
import clsx from "clsx";
export const Button = (
props: React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
) => {
const { className, children, ...rest } = props;
return (
<button
type="button"
className={clsx(
"inline-flex items-center rounded-md border border-transparent px-4 py-2 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2",
className
)}
{...rest}
>
{children}
</button>
);
};
+18
View File
@@ -0,0 +1,18 @@
export interface Message {
text: string;
is_assistant: boolean;
}
const getColor = (isAssistant: boolean) => (isAssistant ? "bg-slate-800" : "bg-sky-900");
export const Messages = ({ messages }: { messages: Message[] }) => {
const items = messages.map(({ text, is_assistant }: Message, i: number) => {
return (
<div key={i + text} className={`${getColor(is_assistant)} p-4 my-1 rounded-xl text-white whitespace-pre-wrap`}>
{text}
</div>
);
});
// Maybe also show a legend of the colors?
return <>{items}</>;
};
+12
View File
@@ -0,0 +1,12 @@
const RankItem = ({ username, score }) => {
return (
<div className="flex flex-row justify-between p-6 border-2 border-slate-100 text-left font-semibold hover:bg-sky-50">
<div>1</div>
<div>@username</div>
<div>20.5</div>
<div>gold</div>
</div>
);
};
export default RankItem;
@@ -0,0 +1,39 @@
import { Card, CardBody, Flex, Heading } from "@chakra-ui/react";
import Image from "next/image";
import Link from "next/link";
export type OptionProps = {
img: string;
alt: string;
title: string;
link: string;
};
export const TaskOption = (props: OptionProps) => {
const { alt, img, title, link } = props;
return (
<Link href={link}>
<Card
maxW="300"
minW="300"
minH="300"
maxH="300"
className="transition ease-in-out duration-500 sm:grayscale hover:grayscale-0"
>
<CardBody width="full" height="full">
<Flex direction="column" alignItems="center" justifyContent="center">
<Image src={img} alt={alt} width={200} height={200} />
<Heading
mt={-10}
className="bg-gradient-to-r from-indigo-600 via-sky-400 to-indigo-700 bg-clip-text tracking-tight text-transparent"
textAlign="center"
fontSize="3xl"
>
{title}
</Heading>
</Flex>
</CardBody>
</Card>
</Link>
);
};
@@ -0,0 +1,23 @@
import { Divider, Flex, Heading } from "@chakra-ui/react";
import React from "react";
export type TaskOptionsProps = {
title: string;
children: JSX.Element | JSX.Element[];
};
export const TaskOptions = (props: TaskOptionsProps) => {
const { title, children } = props;
return (
<Flex gap={10} wrap="wrap" justifyContent="center">
<Heading
className="bg-gradient-to-r from-indigo-600 via-sky-400 to-indigo-700 bg-clip-text tracking-tight text-transparent"
fontSize="5xl"
>
{title}
</Heading>
<Divider mt={-8} />
{children}
</Flex>
);
};
@@ -0,0 +1,29 @@
import React from "react";
import { TaskOptions } from "./TaskOptions";
import { Flex } from "@chakra-ui/react";
import { TaskOption } from "./TaskOption";
export const TaskSelection = () => {
return (
<Flex gap={10} wrap="wrap" justifyContent="space-evenly" width="full" height="full" alignItems={"center"}>
<TaskOptions key="create" title="Create">
<TaskOption
alt="Summarize Stories"
img="/images/logos/logo.svg"
title="Summarize stories"
link="/summarize/story"
/>
<TaskOption alt="Reply as User" img="/images/logos/logo.svg" title="Reply as User" link="/create/user_reply" />
<TaskOption
alt="Reply as Assistant"
img="/images/logos/logo.svg"
title="Reply as Assistant"
link="/create/assistant_reply"
/>
</TaskOptions>
<TaskOptions key="evaluate" title="Evaluate">
<TaskOption alt="Rate Prompts" img="/images/logos/logo.svg" title="Rate Prompts" link="/grading/grade-output" />
</TaskOptions>
</Flex>
);
};
@@ -0,0 +1,3 @@
export { TaskSelection } from "./TaskSelection";
export { TaskOptions } from "./TaskOptions";
export { TaskOption } from "./TaskOption";
+14
View File
@@ -0,0 +1,14 @@
export const TwoColumns = ({ children }: { children: React.ReactNode[] }) => {
if (!Array.isArray(children) || children.length !== 2) {
throw new Error("TwoColumns expects 2 children");
}
const [first, second] = children;
return (
<section className="mb-8 lt-lg:mb-12 grid lg:gap-x-12 lg:grid-cols-2">
<div className="rounded-lg shadow-lg h-full block bg-white p-6">{first}</div>
<div className="rounded-lg shadow-lg h-full block bg-white p-6 mt-6 lg:mt-0">{second}</div>
</section>
);
};
@@ -2,6 +2,7 @@ import type { AuthOptions } from "next-auth";
import NextAuth from "next-auth";
import DiscordProvider from "next-auth/providers/discord";
import EmailProvider from "next-auth/providers/email";
import CredentialsProvider from "next-auth/providers/credentials";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import prisma from "src/lib/prismadb";
@@ -32,6 +33,23 @@ if (process.env.DISCORD_CLIENT_ID) {
);
}
if (process.env.NODE_ENV === "development") {
providers.push(
CredentialsProvider({
name: "Debug Credentials",
credentials: {
username: { label: "Username", type: "text" },
},
async authorize(credentials) {
return {
id: credentials.username,
name: credentials.username,
};
},
})
);
}
export const authOptions: AuthOptions = {
// Ensure we can store user data in a database.
adapter: PrismaAdapter(prisma),
+31 -16
View File
@@ -1,6 +1,6 @@
import { Button, Input, Stack } from "@chakra-ui/react";
import Head from "next/head";
import { FaDiscord, FaEnvelope, FaGithub } from "react-icons/fa";
import { FaDiscord, FaEnvelope, FaBug, FaGithub } from "react-icons/fa";
import { getCsrfToken, getProviders, signIn } from "next-auth/react";
import { useRef } from "react";
import Link from "next/link";
@@ -8,12 +8,20 @@ import Link from "next/link";
import { AuthLayout } from "src/components/AuthLayout";
export default function Signin({ csrfToken, providers }) {
const { discord, email, github } = providers;
const { discord, email, github, credentials } = providers;
const emailEl = useRef(null);
const signinWithEmail = () => {
const debugUsernameEl = useRef(null);
const signinWithEmail = (ev: React.FormEvent) => {
ev.preventDefault();
signIn(email.id, { callbackUrl: "/", email: emailEl.current.value });
};
function signinWithDebugCredentials(ev: React.FormEvent) {
ev.preventDefault();
signIn(credentials.id, { callbackUrl: "/", username: debugUsernameEl.current.value });
}
return (
<>
<Head>
@@ -21,20 +29,27 @@ export default function Signin({ csrfToken, providers }) {
<meta name="Sign Up" content="Sign up to access Open Assistant" />
</Head>
<AuthLayout>
<Stack spacing="2">
<Stack spacing="6">
{credentials && (
<form onSubmit={signinWithDebugCredentials} className="border-2 border-orange-200 rounded-md p-4 relative">
<span className="text-orange-600 absolute -top-3 left-5 bg-white px-1">For Debugging Only</span>
<Stack>
<Input variant="outline" size="lg" placeholder="Username" ref={debugUsernameEl} />
<Button size={"lg"} leftIcon={<FaBug />} colorScheme="gray" type="submit">
Continue with Debug User
</Button>
</Stack>
</form>
)}
{email && (
<Stack>
<Input variant="outline" size="lg" placeholder="Email Address" ref={emailEl} />
<Button
size={"lg"}
leftIcon={<FaEnvelope />}
colorScheme="gray"
onClick={signinWithEmail}
// isDisabled="false"
>
Continue with Email
</Button>
</Stack>
<form onSubmit={signinWithEmail}>
<Stack>
<Input variant="outline" size="lg" placeholder="Email Address" ref={emailEl} />
<Button size={"lg"} leftIcon={<FaEnvelope />} colorScheme="gray">
Continue with Email
</Button>
</Stack>
</form>
)}
{discord && (
<Button
@@ -0,0 +1,83 @@
import { Textarea } from "@chakra-ui/react";
import { useRef, useState } from "react";
import useSWRMutation from "swr/mutation";
import useSWRImmutable from "swr/immutable";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import { Messages } from "src/components/Messages";
import { TwoColumns } from "src/components/TwoColumns";
import { Button } from "src/components/Button";
const AssistantReply = () => {
const [tasks, setTasks] = useState([]);
const inputRef = useRef<HTMLTextAreaElement>(null);
const { isLoading } = useSWRImmutable("/api/new_task/assistant_reply ", fetcher, {
onSuccess: (data) => {
console.log(data);
setTasks([data]);
},
});
const { trigger, isMutating } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
setTasks((oldTasks) => [...oldTasks, newTask]);
},
});
const submitResponse = (task: { id: string }) => {
const text = inputRef.current.value.trim();
trigger({
id: task.id,
update_type: "text_reply_to_post",
content: {
text,
},
});
};
/**
* TODO: Make this a nicer loading screen.
*/
if (tasks.length == 0) {
return <div className="p-6 h-full mx-auto bg-slate-100 text-gray-800">Loading...</div>;
}
const task = tasks[0].task;
return (
<div className="p-6 h-full mx-auto bg-slate-100 text-gray-800">
<TwoColumns>
<>
<h5 className="text-lg font-semibold">Reply as the assistant</h5>
<p className="text-lg py-1">Given the following conversation, provide an adequate reply</p>
<Messages messages={task.conversation.messages} />
</>
<Textarea name="reply" placeholder="Reply..." ref={inputRef} />
</TwoColumns>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<div className="grid grid-cols-[min-content_auto] gap-x-2 text-gray-700">
<b>Prompt</b>
<span>{tasks[0].id}</span>
<b>Output</b>
<span>Submit your answer</span>
</div>
<div className="flex justify-center ml-auto">
<Button className="mr-2 bg-indigo-100 text-indigo-700 hover:bg-indigo-200">Skip</Button>
<Button
onClick={() => submitResponse(tasks[0])}
className="bg-indigo-600 text-white shadow-sm hover:bg-indigo-700"
>
Submit
</Button>
</div>
</section>
</div>
);
};
export default AssistantReply;
+84
View File
@@ -0,0 +1,84 @@
import { Textarea } from "@chakra-ui/react";
import { useRef, useState } from "react";
import useSWRMutation from "swr/mutation";
import useSWRImmutable from "swr/immutable";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import { Messages } from "src/components/Messages";
import { TwoColumns } from "src/components/TwoColumns";
import { Button } from "src/components/Button";
const UserReply = () => {
const [tasks, setTasks] = useState([]);
const inputRef = useRef<HTMLTextAreaElement>(null);
const { isLoading } = useSWRImmutable("/api/new_task/user_reply", fetcher, {
onSuccess: (data) => {
console.log(data);
setTasks([data]);
},
});
const { trigger, isMutating } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
setTasks((oldTasks) => [...oldTasks, newTask]);
},
});
const submitResponse = (task: { id: string }) => {
const text = inputRef.current.value.trim();
trigger({
id: task.id,
update_type: "text_reply_to_post",
content: {
text,
},
});
};
/**
* TODO: Make this a nicer loading screen.
*/
if (tasks.length == 0) {
return <div className="p-6 h-full mx-auto bg-slate-100 text-gray-800">Loading...</div>;
}
const task = tasks[0].task;
return (
<div className="p-6 h-full mx-auto bg-slate-100 text-gray-800">
<TwoColumns>
<>
<h5 className="text-lg font-semibold">Reply as a user</h5>
<p className="text-lg py-1">Given the following conversation, provide an adequate reply</p>
<Messages messages={task.conversation.messages} />
{task.hint && <p className="text-lg py-1">Hint: {task.hint}</p>}
</>
<Textarea name="reply" placeholder="Reply..." ref={inputRef} />
</TwoColumns>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<div className="grid grid-cols-[min-content_auto] gap-x-2 text-gray-700">
<b>Prompt</b>
<span>{tasks[0].id}</span>
<b>Output</b>
<span>Submit your answer</span>
</div>
<div className="flex justify-center ml-auto">
<Button className="mr-2 bg-indigo-100 text-indigo-700 hover:bg-indigo-200">Skip</Button>
<Button
onClick={() => submitResponse(tasks[0])}
className="bg-indigo-600 text-white shadow-sm hover:bg-indigo-700"
>
Submit
</Button>
</div>
</section>
</div>
);
};
export default UserReply;
+3 -7
View File
@@ -8,6 +8,7 @@ import { Faq } from "src/components/Faq";
import { Footer } from "src/components/Footer";
import { Header } from "src/components/Header";
import { Hero } from "src/components/Hero";
import { TaskSelection } from "src/components/TaskSelection";
const Home = () => {
const { data: session } = useSession();
@@ -43,13 +44,8 @@ const Home = () => {
/>
</Head>
<Header />
<main className="h-3/4 z-0 bg-white flex flex-col items-center justify-center gap-2">
<Button size="lg" colorScheme="blue" className="drop-shadow">
<Link href="/evaluate/rate_summary">Rate a Summary</Link>
</Button>
<Button size="lg" colorScheme="blue" className="drop-shadow">
<Link href="/create/summarize_story">Summarize a story</Link>
</Button>
<main className="h-3/4 m-20 z-0 bg-white flex flex-col items-center justify-center gap-2">
<TaskSelection />
</main>
<Footer />
</>
@@ -0,0 +1,54 @@
import RankItem from "@/components/RankItem";
import { BarsArrowUpIcon, BarsArrowDownIcon } from "@heroicons/react/24/solid";
import Image from "next/image";
import { HiBarsArrowUp, HiBarsArrowDown } from "react-icons/hi2";
const LeaderBoard = () => {
const PlaceHolderProps = { username: "test_user", score: 10 };
return (
<div className=" p-6 h-full mx-auto bg-slate-100 text-gray-800">
<div className="flex flex-col">
<div className="rounded-lg shadow-lg h-full block bg-white">
<div className="p-8">
<h5 className="text-2xl font-bold">LeaderBoard</h5>
</div>
<div className="flex flex-row justify-between px-6 py-3 font-semibold text-md">
<div className="flex flex-row items-center justify-center space-x-2">
<div>
<p>Rank</p>
</div>
<div className="mt-2 text-slate-400 hover:text-sky-400 hover:cursor-pointer">
<HiBarsArrowDown className="w-6 h-6 text-inherit"></HiBarsArrowDown>
</div>
</div>
<div className="flex flex-row items-center justify-center space-x-2">
<div>
<p>User</p>
</div>
<div className="mt-2 text-slate-400 hover:text-sky-400 hover:cursor-pointer">
<HiBarsArrowDown className="w-6 h-6 text-inherit"></HiBarsArrowDown>
</div>
</div>
<div className="flex flex-row items-center justify-center space-x-2">
<div>
<p>Score</p>
</div>
<div className="mt-2 text-slate-400 hover:text-sky-400 hover:cursor-pointer">
<HiBarsArrowDown className="w-6 h-6 text-inherit"></HiBarsArrowDown>
</div>
</div>
<div className="flex flex-row items-center justify-center space-x-2">
<div>
<p>Medal</p>
</div>
</div>
</div>
{/* leaderboard items */}
<RankItem {...PlaceHolderProps}></RankItem>
</div>
</div>
</div>
);
};
export default LeaderBoard;