Skip to content

Commit

Permalink
feat/itp-324
Browse files Browse the repository at this point in the history
this should work at some point
  • Loading branch information
RickyRAV committed May 13, 2024
1 parent e1633cc commit 4347ed9
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 15 deletions.
45 changes: 36 additions & 9 deletions controllers/quizController.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import {generateQuizQuestions, generateQuizVideo} from "../services/quizService.js";
import {generateBlanksQuiz, generateQuizQuestions, generateQuizVideo} from "../services/quizService.js";
import {prisma} from "../config/prismaClient.js";

const welcome = async (req, res) => {
res.send('Welcome to the IntelliQ-BE API! For Documentation please visit: intelliq-be.azurewebsites.net/api-docs/');
};

const getQuiz = async (req, res) => {
const { user: { id: user_id } } = req.user;
const {user: {id: user_id}} = req.user;
const startTime = process.hrtime();

try {
const {interests, numberOfQuestions} = req.query;
const rawQuestions = await generateQuizQuestions(interests, numberOfQuestions);
const endTime = process.hrtime(startTime);
const timeTaken = (endTime[0] * 1000 + endTime[1] / 1000000)/1000;
const timeTaken = (endTime[0] * 1000 + endTime[1] / 1000000) / 1000;
res.json({rawQuestions: rawQuestions.rawQuestions, seed: rawQuestions.quiz_seed});
const usage = await prisma.user_usage_data.create({
data: {
Expand All @@ -34,13 +34,13 @@ const getQuiz = async (req, res) => {
};

const getQuizVideo = async (req, res) => {
const { user: { id: user_id } } = req.user;
const {user: {id: user_id}} = req.user;
const startTime = process.hrtime();
try {
const {summary, topic, numberOfQuestions} = req.body;
const rawQuestions = await generateQuizVideo(summary, topic, numberOfQuestions);
const endTime = process.hrtime(startTime);
const timeTaken = (endTime[0] * 1000 + endTime[1] / 1000000)/1000;
const timeTaken = (endTime[0] * 1000 + endTime[1] / 1000000) / 1000;
res.json({rawQuestions: rawQuestions.rawQuestions, seed: rawQuestions.quiz_seed});
const usage = await prisma.user_usage_data.create({
data: {
Expand All @@ -55,14 +55,41 @@ const getQuizVideo = async (req, res) => {
response_time_taken: timeTaken
}
});
}
catch (e) {
} catch (e) {
res.status(500).json({error: 'An error occurred while generating quiz video.', message: e.message});
}
};

const getBlanksQuiz = async (req, res) => {
const {user: {id: user_id}} = req.user;
const startTime = process.hrtime();
try {
const {interests, numberOfQuestions} = req.query;
const rawQuestions = await generateBlanksQuiz(interests, numberOfQuestions);
const endTime = process.hrtime(startTime);
const timeTaken = (endTime[0] * 1000 + endTime[1] / 1000000) / 1000;
res.json({rawQuestions: rawQuestions.rawQuestions, seed: rawQuestions.quiz_seed});
const usage = await prisma.user_usage_data.create({
data: {
user_id: user_id,
prompt_tokens: rawQuestions.usageData.prompt_tokens,
completion_tokens: rawQuestions.usageData.completion_tokens,
total_tokens: rawQuestions.usageData.total_tokens,
system_fingerprint: rawQuestions.system_fingerprint,
quiz_seed: rawQuestions.quiz_seed,
used_model: rawQuestions.model,
count_Questions: Number(numberOfQuestions),
response_time_taken: timeTaken
}
});
} catch (error) {
console.error('Error saving quiz data:', error);
res.status(500).json({error: 'An error occurred while saving quiz data.'});
}
}

const saveQuizResults = async (req, res) => {
const { user: { id: user_id } } = req.user;
const {user: {id: user_id}} = req.user;

try {
const {rawQuestions} = req.body;
Expand Down Expand Up @@ -133,4 +160,4 @@ const saveQuizResults = async (req, res) => {
}
};

export {welcome, getQuiz, getQuizVideo, saveQuizResults};
export {welcome, getQuiz, getQuizVideo, getBlanksQuiz, saveQuizResults};
3 changes: 2 additions & 1 deletion routes/quizRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import {
welcome,
getQuiz,
getQuizVideo,
saveQuizResults
saveQuizResults, getBlanksQuiz
} from '../controllers/quizController.js';
import {isAuthenticated} from "../middlewares/isAuthenticated.js";

export default (app) => {
app.get('/', welcome);
app.get('/api/quiz', isAuthenticated, getQuiz);
app.get('/api/video-quiz', isAuthenticated, getQuizVideo);
app.get('/api/blank-quiz', isAuthenticated, getBlanksQuiz);
app.post('/api/submit-quiz', isAuthenticated, saveQuizResults);
};
82 changes: 77 additions & 5 deletions services/quizService.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ dotenv.config();

const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
const gpt_model = 'gpt-3.5-turbo-1106';
export const generateQuizQuestions = async (interests, numberOfQuestions) => {
const max_tokens = 1024;
const generateQuizQuestions = async (interests, numberOfQuestions) => {
const generatedSeed = await generateUniqueSeed();
const prompt = `Generate a quiz JSON object based on the interests: ${interests}. Create ${numberOfQuestions} questions.
The JSON object should be structured as follows:
Expand Down Expand Up @@ -46,7 +47,7 @@ export const generateQuizQuestions = async (interests, numberOfQuestions) => {
'content': `${interests}, ${numberOfQuestions} questions`
}],
temperature: 1,
max_tokens: 1024,
max_tokens,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
Expand Down Expand Up @@ -87,7 +88,7 @@ export const generateQuizQuestions = async (interests, numberOfQuestions) => {
return finalResponse;
};

export const generateQuizVideo = async (summary, topic, numberOfQuestions) => {
const generateQuizVideo = async (summary, topic, numberOfQuestions) => {
const generatedSeed = await generateUniqueSeed();
const prompt = `Generate a quiz JSON object based on the summary: ${summary} and the topic of the summary: ${topic}.
Create ${numberOfQuestions} questions. The quiz created has to be tailored on the topic and summary that the user has chosen.
Expand Down Expand Up @@ -128,7 +129,7 @@ export const generateQuizVideo = async (summary, topic, numberOfQuestions) => {
'content': `${summary}, ${topic}, ${numberOfQuestions} questions`
}],
temperature: 1,
max_tokens: 1024,
max_tokens,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
Expand Down Expand Up @@ -167,4 +168,75 @@ export const generateQuizVideo = async (summary, topic, numberOfQuestions) => {
// console.log(finalResponse);
// Converting the Map back to an array of unique questions
return finalResponse;
};
};

const generateBlanksQuiz = async(interests, numberOfQuestions) => {
const generatedSeed = await generateUniqueSeed();
const prompt = `Generate a fill in the blanks JSON object based on the interests: ${interests}.
Create ${numberOfQuestions} questions.
The JSON object should be structured as follows:
{
"quizTitle": "Contextual and Unique Quiz Title Here",
"questions":
[
{ "questionTitle": "Unique and Contextual Question Title Here",
"text": "The actual fill in the blanks sentence",
"correctAnswer": "the actual string that needs to go in the blank space inside text"
}
// More questions here...
]
}
Once the quizTitle is set, it should not change.
Each question should have a unique questionTitle.
The Contextual questionTitle is not allowed to contain 'Question Number' or 'Interest Question Number',
think of something very special for each individual question.`
const openai = new OpenAI(OPENAI_API_KEY);
const response = await openai.chat.completions.create({
model: gpt_model,
response_format: { type: 'json_object'},
messages: [{
'role': 'system',
'content': prompt
}, {
'role': 'user',
'content': `${interests}, ${numberOfQuestions} questions`
}],
temperature: 1,
max_tokens,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
seed: generatedSeed
});
const rawContent = response.choices[0].message.content;
const { usage } = response;
const { system_fingerprint } = response;

const questionStrings = rawContent.split('\n\n');
// console.log('questionStrings:', questionStrings);

const questions = questionStrings.map(qs => {
try {
return JSON.parse(qs.trim());
} catch (err) {
console.error('Error parsing question:', err);
return null;
}
}).filter(q => q);

// Removing duplicates by using a Map object
const uniqueQuestionsMap = new Map();
questions.forEach(question => {
uniqueQuestionsMap.set(question.text, question);
});

return {
rawQuestions: Array.from(uniqueQuestionsMap.values()),
usageData: usage,
system_fingerprint,
quiz_seed: generatedSeed,
model: gpt_model,
};
};

export {generateQuizQuestions, generateQuizVideo, generateBlanksQuiz};

0 comments on commit 4347ed9

Please sign in to comment.