better history based on cmid and attempt

This commit is contained in:
yoannchb-pro
2024-03-14 16:46:58 -04:00
parent 334e30c1c3
commit b0d2fc8f48
4 changed files with 37 additions and 43 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+32 -40
View File
@@ -3,11 +3,11 @@ import { ROLE, CONTENT_TYPE, type MessageContent, type Message } from '@typing/m
import imageToBase64 from '@utils/image-to-base64';
import isGPTModelGreaterOrEqualTo4 from '@utils/version-support-images';
// @TODO: implement cmid, attempt, effacer choix
// The attempt and the cmid allow us to identify a quiz
type History = {
url: string | null;
params: Record<string, string>;
host: string;
cmid: string; // The id of the quiz
attempt: string; // The attempt of the current quiz
history: { role: ROLE; content: MessageContent }[];
};
@@ -28,7 +28,7 @@ Act as a quiz solver for the best notation with the following rules:
const SYSTEM_INSTRUCTION_MESSAGE = {
role: ROLE.SYSTEM,
content: INSTRUCTION
} as const;
} as const satisfies Message;
/**
* Get the content to send to ChatGPT API (it allows to includes images if supported)
@@ -42,36 +42,35 @@ async function getContent(
const imagesElements = questionElement.querySelectorAll('img');
if (
config.includeImages &&
isGPTModelGreaterOrEqualTo4(config.model) &&
!config.includeImages ||
!isGPTModelGreaterOrEqualTo4(config.model) ||
imagesElements.length === 0
) {
return question;
}
let content: MessageContent = [];
const contentWithImages: MessageContent = [];
const base64Images = Array.from(imagesElements).map(imgEl => imageToBase64(imgEl));
const results = await Promise.all(base64Images);
const filteredResults = results.filter(value => value !== null) as string[];
const base64ImagesResolved = await Promise.allSettled(base64Images);
for (const result of filteredResults) {
content.push({
type: CONTENT_TYPE.IMAGE,
image_url: { url: result }
});
for (const result of base64ImagesResolved) {
if (result.status === 'fulfilled') {
contentWithImages.push({
type: CONTENT_TYPE.IMAGE,
image_url: { url: result.value }
});
} else if (config.logs) {
console.error(result.reason);
}
}
if (content.length > 0) {
content.push({
type: CONTENT_TYPE.TEXT,
text: question
});
} else {
content = question;
}
contentWithImages.push({
type: CONTENT_TYPE.TEXT,
text: question
});
return content;
return contentWithImages;
}
/**
@@ -79,17 +78,12 @@ async function getContent(
* @returns
*/
function createNewHistory(): History {
const url_params = new URLSearchParams(document.location.search).entries();
const params: Record<string, string> = {};
for (const [key, value] of url_params) {
if (key === 'page') continue;
params[key] = value;
}
const urlParams = new URLSearchParams(document.location.search);
return {
url: document.location.host,
params,
host: document.location.host,
cmid: urlParams.get('cmid') ?? '',
attempt: urlParams.get('attempt') ?? '',
history: []
};
}
@@ -108,13 +102,11 @@ function loadPastHistory(): History | null {
* @param b
* @returns
*/
function areHistorySameOrigin(a: History, b: History): boolean {
if (a.url !== b.url) return false;
function areHistoryFromSameQuiz(a: History, b: History): boolean {
const KEYS_TO_COMPARE: (keyof History)[] = ['host', 'cmid', 'attempt'];
if (Object.keys(a.params).length !== Object.keys(b.params).length) return false;
for (const [key, value] of Object.entries(a.params)) {
if (!(key in b.params) || b.params[key] !== value) return false;
for (const key of KEYS_TO_COMPARE) {
if (a[key] !== b[key]) return false;
}
return true;
@@ -145,7 +137,7 @@ async function getContentWithHistory(
const pastHistory: History | null = loadPastHistory();
const newHistory: History = createNewHistory();
if (pastHistory === null || !areHistorySameOrigin(pastHistory, newHistory)) {
if (pastHistory === null || !areHistoryFromSameQuiz(pastHistory, newHistory)) {
history = newHistory;
} else {
history = pastHistory;
+3 -1
View File
@@ -17,6 +17,8 @@ async function getChatGPTResponse(
const controller = new AbortController();
const timeoutControler = setTimeout(() => controller.abort(), 20 * 1000);
// Get the content to send to chatgpt
// Including the instructions to the AI, the images as base64 if needed, the question and the past conversation if history is set to true
const contentHandler = await getContentWithHistory(config, questionElement, question);
const req = await fetch('https://api.openai.com/v1/chat/completions', {
@@ -43,7 +45,7 @@ async function getChatGPTResponse(
const response = rep.choices[0].message.content;
// Save the response into the history
if (contentHandler.saveResponse) contentHandler.saveResponse(response);
if (typeof contentHandler.saveResponse === 'function') contentHandler.saveResponse(response);
return {
question,