feat: grade exercise with AI (#296)

* working on the UI of the grading

* working on the grading function of the radio and checkboxes

* ai grading fully implemented with dummy functions for generating scores

* working on the openai response

* working on the openai response

* finished with the ai_grading

* finished with the ai_grading

* creating new migration file

* working on reviews

* updated the translations

* improvements

---------

Co-authored-by: Rotimi Best <[email protected]>
This commit is contained in:
Em_Dev
2024-05-13 19:35:06 +01:00
committed by GitHub
co-authored by Rotimi Best
parent fc8b8e1898
commit e243564113
37 changed files with 688 additions and 150 deletions
@@ -0,0 +1,51 @@
import { OPENAI_API_KEY } from '$env/static/private';
import { OpenAIStream, StreamingTextResponse } from 'ai';
import { Configuration, OpenAIApi } from 'openai-edge';
// Create an OpenAI API client (that's edge friendly!)
const openAIConfig = new Configuration({
apiKey: OPENAI_API_KEY
});
const openai = new OpenAIApi(openAIConfig);
// Set the runtime to edge for best performance
export const config = {
runtime: 'edge'
};
export async function POST({ request }) {
const { prompt } = await request.json();
const response = await openai.createChatCompletion({
model: 'gpt-3.5-turbo',
messages: [
{
role: 'system',
content:
'You are a teaching assistant, you only spit out JSON and nothing else, dont give any explanation.'
},
{
role: 'user',
content: `
Given this array of objects below, there are 4 keys , id, question, answer and points. You are required to come up with a score between 0 and the point for each answer provided to the question and a simple explanation for giving that score, you are to return an array of object in json with the following keys; id which is the id provided for that object in the initial array, score which is the value you gave for that question and then your explanation in this format below:
{
id,
score,
explanation,
}
IMPORTANT: DO NOT GIVE ANY OTHER TEXT EXCEPT THE JSON
The array you need to grade is below:
${prompt}
`
}
],
stream: true
});
const stream = OpenAIStream(response);
return new StreamingTextResponse(stream);
}
@@ -368,9 +368,8 @@
{/if}
</PageBody>
{/if}
<!-- Mobile Navigation -->
<div class="fixed bottom-5 w-[90%] flex items-center justify-center lg:hidden">
<div class="sticky bottom-5 flex items-center justify-center lg:hidden">
<div
class="flex items-center gap-2 w-fit rounded-full shadow-xl bg-gray-100 dark:bg-neutral-700 px-5 py-1"
>
@@ -61,6 +61,7 @@
let submissionIdData: { [key: number]: any } = {};
let submissionId: string | number | null;
let openExercise = false;
let isGradeWithAI = false;
const submissionStatus: { [key: number]: string } = {
1: $t('course.navItem.submissions.submission_status.submitted'),
@@ -176,6 +177,7 @@
}
function handleModalClose() {
isGradeWithAI = false;
goto($page.url.pathname);
}
@@ -230,8 +232,12 @@
}
}
async function handleSave(submission: { questionAnswerByPoint: any; questionAnswers: any }) {
const { questionAnswerByPoint, questionAnswers } = submission;
async function handleSave(submission: {
questionAnswerByPoint: any;
questionAnswers: any;
feedback: any;
}) {
const { questionAnswerByPoint, questionAnswers, feedback } = submission;
let totalPoints = 0;
@@ -249,7 +255,8 @@
updateSubmission({
id: submissionId,
total: totalPoints
total: totalPoints,
feedback: feedback
}).then((res) => console.log('Updated submission', res));
snackbar.success('snackbar.submissions.success.grading');
@@ -268,7 +275,8 @@
const sectionById: { [key: number]: sectionType[] } = {};
if (submissions) {
for (const submission of submissions) {
const { id, created_at, exercise, course, answers, groupmember, status_id } = submission;
const { id, created_at, exercise, course, answers, groupmember, status_id, feedback } =
submission;
const isEarly = isSubmissionEarly(created_at, exercise.due_by);
@@ -276,6 +284,7 @@
id,
statusId: status_id,
isEarly,
feedback,
submittedAt: formatDate(created_at),
exercise: {
id: exercise.id,
@@ -296,6 +305,7 @@
submissionIdData[id] = {
id,
status_id,
feedback,
isEarly,
title: exercise.title,
student: submissionItem.student,
@@ -334,6 +344,7 @@
{handleSave}
{updateStatus}
{submissionId}
bind:isGradeWithAI
/>
<RoleBasedSecurity allowedRoles={[1, 2]}>