Merge pull request #625 from othrayte/purge-summary-task-pages

website: Remove summarization pages
This commit is contained in:
Keith Stevens
2023-01-11 21:33:03 +09:00
committed by GitHub
4 changed files with 2 additions and 354 deletions
+2 -2
View File
@@ -188,10 +188,10 @@ new tasks:
1. For any task that involves writing a free-form response, put the page under
`website/src/pages/create` with a page name matching the task type, such as
`summarize_story.tsx`.
`initial_prompt.tsx`.
1. For any task that evaluates, rates, or ranks content, put the page under
`website/src/pages/evaluate` with a page name matching the task type such as
`rate_summary.tsx`.
`rank_initial_prompts.tsx`.
With this we'll be able to ensure these contribution pages are hidden from
logged out users but accessible to logged in users.
@@ -1,60 +0,0 @@
import { Box, HStack, useRadio, useRadioGroup } from "@chakra-ui/react";
const RatingRadioButton = (props) => {
const { getInputProps, getCheckboxProps } = useRadio(props);
const input = getInputProps();
const checkbox = getCheckboxProps();
return (
<Box as="label">
<input {...input} />
<Box
{...checkbox}
cursor="pointer"
borderWidth="1px"
borderRadius="md"
boxShadow="md"
_checked={{
bg: "blue.200",
color: "white",
borderColor: "blue.200",
}}
_focus={{
boxShadow: "outline",
}}
px={5}
py={3}
>
{props.children}
</Box>
</Box>
);
};
const RatingRadioGroup = (props) => {
const { min, max, onChange } = props;
const { getRadioProps, getRootProps } = useRadioGroup({
name: "rating",
defaultValue: `${min}`,
onChange: onChange,
});
const group = getRootProps();
const options = Array.from(new Array(1 + max - min), (x, i) => `${i + min}`);
return (
<HStack {...group}>
{options.map((option) => {
const radio = getRadioProps({ value: option });
return (
<RatingRadioButton key={option} {...radio}>
{option}
</RatingRadioButton>
);
})}
</HStack>
);
};
export default RatingRadioGroup;
@@ -1,102 +0,0 @@
import { useColorMode } from "@chakra-ui/react";
import { useState } from "react";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { TaskControls } from "src/components/Survey/TaskControls";
import { TrackedTextarea } from "src/components/Survey/TrackedTextarea";
import { TwoColumnsWithCards } from "src/components/Survey/TwoColumnsWithCards";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
const SummarizeStory = () => {
// Use an array of tasks that record the sequence of steps until a task is
// deemed complete.
const [tasks, setTasks] = useState([]);
const [inputText, setInputText] = useState("");
// Fetch the very fist task. We can ignore everything except isLoading
// because the onSuccess handler will update `tasks` when ready.
const { isLoading, mutate } = useSWRImmutable("/api/new_task/summarize_story", fetcher, {
onSuccess: (data) => {
setTasks([data]);
},
});
// Every time we submit an answer to the latest task, let the backend handle
// all the interactions then add the resulting task to the queue. This ends
// when we hit the done task.
const { trigger } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
// This is the more efficient way to update a react state array.
setTasks((oldTasks) => [...oldTasks, newTask]);
},
});
// Trigger a mutation that updates the current task. We should probably
// signal somewhere that this interaction is being processed.
const submitResponse = () => {
const text = inputText.trim();
trigger({
id: tasks[0].id,
update_type: "text_reply_to_message",
content: {
text,
},
});
};
const fetchNextTask = () => {
setInputText("");
mutate();
};
const textChangeHandler = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
setInputText(event.target.value);
};
const { colorMode } = useColorMode();
const mainBgClasses = colorMode === "light" ? "bg-slate-300 text-gray-800" : "bg-slate-900 text-white";
if (isLoading) {
return <LoadingScreen text="Loading..." />;
}
if (tasks.length === 0) {
return <div className="p-6 bg-slate-100 text-gray-800">No tasks found...</div>;
}
return (
<div className={`p-12 ${mainBgClasses}`}>
<main className="p-6 h-full mx-auto bg-slate-100 text-gray-800">
<TwoColumnsWithCards>
<>
<h5 className="text-lg font-semibold">Instruction</h5>
<p className="text-lg py-1">Summarize the following story</p>
<div className="bg-slate-800 p-6 rounded-xl text-white whitespace-pre-wrap">{tasks[0].task.story}</div>
</>
<>
<h5 className="text-lg font-semibold">Provide the assistant`s reply</h5>
<TrackedTextarea
text={inputText}
onTextChange={textChangeHandler}
thresholds={{ low: 20, medium: 40, goal: 50 }}
textareaProps={{ placeholder: "Summary" }}
/>
</>
</TwoColumnsWithCards>
<TaskControls
task={tasks[0].task}
taskStatus={"NOT_SUBMITTABLE"}
onSubmit={submitResponse}
onSkip={fetchNextTask}
onNextTask={fetchNextTask}
/>
</main>
</div>
);
};
export default SummarizeStory;
-190
View File
@@ -1,190 +0,0 @@
import { Textarea } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
import { QuestionMarkCircleIcon } from "@heroicons/react/20/solid";
import Head from "next/head";
import { useState } from "react";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import RatingRadioGroup from "src/components/RatingRadioGroup";
import { TaskControls } from "src/components/Survey/TaskControls";
import { TwoColumnsWithCards } from "src/components/Survey/TwoColumnsWithCards";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
const RateSummary = () => {
// Use an array of tasks that record the sequence of steps until a task is
// deemed complete.
const [tasks, setTasks] = useState([]);
const [rating, setRating] = useState(0);
// Fetch the very fist task. We can ignore everything except isLoading
// because the onSuccess handler will update `tasks` when ready.
const { isLoading, mutate } = useSWRImmutable("/api/new_task/rate_summary", fetcher, {
onSuccess: (data) => {
setTasks([data]);
},
});
// Every time we submit an answer to the latest task, let the backend handle
// all the interactions then add the resulting task to the queue. This ends
// when we hit the done task.
const { trigger } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
// This is the more efficient way to update a react state array.
setTasks((oldTasks) => [...oldTasks, newTask]);
},
});
// Trigger a mutation that updates the current task. We should probably
// signal somewhere that this interaction is being processed.
const submitResponse = () => {
trigger({
id: tasks[0].task.id,
update_type: "message_rating",
content: {
rating: rating,
},
});
};
const fetchNextTask = () => {
mutate();
};
const { colorMode } = useColorMode();
const mainBgClasses = colorMode === "light" ? "bg-slate-300 text-gray-800" : "bg-slate-900 text-white";
if (isLoading) {
return <LoadingScreen text="Loading..." />;
}
if (tasks.length === 0) {
return (
<div className={`p-12 ${mainBgClasses}`}>
<div className="flex h-full">
<div className="text-xl font-bold mx-auto my-auto">No tasks found...</div>
</div>
</div>
);
}
return (
<>
<Head>
<title>Rate A Summary</title>
<meta name="description" content="Rate a proposed story summary." />
</Head>
<main className="p-6 bg-slate-100 text-gray-800">
<TwoColumnsWithCards>
<>
<h5 className="text-lg font-semibold mb-4">Instruction</h5>
<div className="bg-slate-800 p-6 rounded-xl text-white whitespace-pre-wrap">{tasks[0].task.full_text}</div>
</>
<section className="grid grid-row-[auto] gap-3">
<h5 className="text-lg font-semibold">Output</h5>
<p className="bg-slate-800 p-6 rounded-xl text-white whitespace-pre-wrap">{tasks[0].task.summary}</p>
<h3 className="text-lg text-center font-medium leading-6 text-gray-900">Rating</h3>
<p className="text-center text-sm text-gray-500">
({tasks[0].task.scale.min} = worst, {tasks[0].task.scale.max} = best)
</p>
<div className="m-auto">
<RatingRadioGroup min={tasks[0].task.scale.min} max={tasks[0].task.scale.max} onChange={setRating} />
</div>
<ul>
{ANNOTATION_FLAGS.map((option, i) => (
<AnnotationCheckboxLi option={option} key={i} />
))}
</ul>
<Textarea name="notes" placeholder="Optional notes" />
</section>
</TwoColumnsWithCards>
<TaskControls
task={tasks[0].task}
taskStatus={"NOT_SUBMITTABLE"}
onSubmit={submitResponse}
onSkip={fetchNextTask}
onNextTask={fetchNextTask}
/>
</main>
</>
);
};
export default RateSummary;
function AnnotationCheckboxLi(props: { option: annotationBool }): JSX.Element {
let AdditionalExplanation = null;
if (props.option.additionalExplanation) {
AdditionalExplanation = (
<a href="#" className="group flex items-center space-x-2.5 text-sm ">
<QuestionMarkCircleIcon className="h-5 w-5 ml-3 text-gray-400 group-hover:text-gray-500" aria-hidden="true" />
</a>
);
}
return (
<li className="form-check flex mb-1">
<input
className="form-check-input appearance-none h-4 w-4 border border-gray-300 rounded-sm bg-white checked:bg-blue-600 checked:border-blue-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer"
type="checkbox"
value=""
id={props.option.attributeName}
/>
<label className="flex ml-1 form-check-label hover:cursor-pointer" htmlFor={props.option.attributeName}>
<span className="text-gray-800 hover:text-blue-700">{props.option.labelText}</span>
{AdditionalExplanation}
</label>
</li>
);
}
interface annotationBool {
attributeName: string;
labelText: string;
additionalExplanation?: string;
}
const ANNOTATION_FLAGS: annotationBool[] = [
// For the time being this list is configured on the FE.
// In the future it may be provided by the API.
{
attributeName: "fails_task",
labelText: "Fails to follow the correct instruction / task",
additionalExplanation: "__TODO__",
},
{
attributeName: "not_customer_assistant_appropriate",
labelText: "Inappropriate for customer assistant",
additionalExplanation: "__TODO__",
},
{
attributeName: "contains_sexual_content",
labelText: "Contains sexual content",
},
{
attributeName: "contains_violent_content",
labelText: "Contains violent content",
},
{
attributeName: "encourages_violence",
labelText: "Encourages or fails to discourage violence/abuse/terrorism/self-harm",
},
{
attributeName: "denigrates_a_protected_class",
labelText: "Denigrates a protected class",
},
{
attributeName: "gives_harmful_advice",
labelText: "Fails to follow the correct instruction / task",
additionalExplanation:
"The advice given in the output is harmful or counter-productive. This may be in addition to, but is distinct from the question about encouraging violence/abuse/terrorism/self-harm.",
},
{
attributeName: "expresses_moral_judgement",
labelText: "Expresses moral judgement",
},
];