From 5171f7cdd778ee5847019031f4a0534449043dc2 Mon Sep 17 00:00:00 2001 From: riyaa404 Date: Tue, 12 Aug 2025 00:34:20 +0530 Subject: [PATCH 1/3] Implemented improved hint prompts with word limits and temperature --- popup.html | 5 +- popup.js | 70 ++++++++------------------ prompts.js | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+), 52 deletions(-) create mode 100644 prompts.js diff --git a/popup.html b/popup.html index fe031d7..710111f 100644 --- a/popup.html +++ b/popup.html @@ -98,8 +98,7 @@

AI Model Settings

- - + + - \ No newline at end of file diff --git a/popup.js b/popup.js index 327ea0a..05f4b5e 100644 --- a/popup.js +++ b/popup.js @@ -101,55 +101,28 @@ function getHint(level) { }); } - - async function fetchHint(apiKey, model, level, context) { - const cost = { - ordinary: 2, - advanced: 3, - expert: 5, - }; - - try { - const response = await fetch('https://api.groq.com/openai/v1/chat/completions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${apiKey}`, - }, - body: JSON.stringify({ - model, - messages: [ - { - role: 'system', - content: `You are an AI assistant for LeetCode. Provide a ${level} hint for the following problem. Do not solve the entire problem. Just provide a hint.`, - }, - { - role: 'user', - content: context, - }, - ], - }), - }); - - if (!response.ok) { - throw new Error(`API request failed with status ${response.status}`); - } - - const data = await response.json(); - const hint = data.choices[0].message.content; - - hintText.innerText = hint; - hintContainer.classList.remove('hidden'); - errorContainer.classList.add('hidden'); - - // Deduct time - chrome.runtime.sendMessage({ type: 'deductTime', cost: cost[level] }); - loadTimerFromStorage(); - } catch (error) { - showError(error.message); - } +async function fetchHint(apiKey, model, level, context) { + const cost = { + ordinary: 2, + advanced: 3, + expert: 5, + }; + + try { + // Use the global window.generateHint() from prompts.js + const hint = await window.generateHint(apiKey, model, level, context); + + hintText.innerText = hint; + hintContainer.classList.remove('hidden'); + errorContainer.classList.add('hidden'); + + // Deduct time + chrome.runtime.sendMessage({ type: 'deductTime', cost: cost[level] }); + loadTimerFromStorage(); + } catch (error) { + showError(error.message); } - +} function showError(message) { errorText.innerText = message; errorContainer.classList.remove('hidden'); @@ -333,4 +306,3 @@ function loadTimerFromStorage() { updateTimerDisplay(timeAllowed); }); } - diff --git a/prompts.js b/prompts.js new file mode 100644 index 0000000..ba15e04 --- /dev/null +++ b/prompts.js @@ -0,0 +1,144 @@ +(() => { + 'use strict'; + + const HINT_PROMPTS = { + ordinary: { + systemPrompt: `You are a helpful LeetCode tutor providing ORDINARY level hints. + +Your goal: Give a gentle nudge in the right direction without revealing too much. +- Focus on understanding the problem better +- Suggest what data structures or concepts to consider +- Ask guiding questions that help the student think +- Keep it simple and encouraging +- DO NOT provide code or detailed algorithms + +Word limit: 50 words maximum.`, + temperature: 0.3, + maxWords: 50 + }, + + advanced: { + systemPrompt: `You are an experienced LeetCode mentor providing ADVANCED level hints. + +Your goal: Provide deeper and more specific guidance without fully solving the problem. +- Explain the general approach or recognized problem pattern +- Mention specific algorithms or techniques (e.g., "two pointers", "DFS with memoization") +- Discuss time/space complexity considerations +- Suggest how to break the problem into manageable steps +- Avoid giving complete pseudo-code or direct answers + +Word limit: 100 words maximum.`, + temperature: 0.3, + maxWords: 100 + }, + + expert: { + systemPrompt: `You are a LeetCode expert providing EXPERT level hints. + +Your goal: Give comprehensive strategic guidance for optimal problem-solving. +- Explain the optimal algorithm and why it works +- Discuss alternative approaches and trade-offs +- Analyze time and space complexity in detail +- Mention important edge cases +- Provide a high-level roadmap for the implementation +- Let the student write the actual code + +Word limit: 150 words maximum.`, + temperature: 0.3, + maxWords: 150 + } + }; + + function filterResponse(text) { + if (!text || typeof text !== 'string') return ''; + + let cleaned = text; + + cleaned = cleaned.replace(/[\s\S]*?<\/think>/gi, ''); + cleaned = cleaned.replace(/[\s\S]*?<\/reflection>/gi, ''); + cleaned = cleaned.replace(/<[^>]+>/g, ''); + + cleaned = cleaned.replace(/^(Assistant:|AI:|System:)\s*/i, ''); + cleaned = cleaned.replace(/^\s*(?:Sure[,\.]?\s*)?(?:here(?:'s| is)\s+(?:a\s+)?)?(?:hint|suggestion|note|tip)\s*[:\-]?\s*/i, ''); + + cleaned = cleaned.replace(/^(?:Here['’]?s|Here is|You can)\b[\s\S]*?(?:\n{1,2}|$)/i, (m) => { + return m.length > 140 ? '' : m; + }); + + cleaned = cleaned.replace(/\n\s*\n\s*\n+/g, '\n\n'); + + cleaned = cleaned.trim(); + + return cleaned; + } + + function enforceWordLimit(content, maxWords) { + if (!content) return ''; + const words = content.trim().split(/\s+/); + if (words.length <= maxWords) return content.trim(); + return words.slice(0, maxWords).join(' ') + '...'; + } + + function extractModelText(responseJson) { + try { + if (!responseJson) return ''; + + if (responseJson.choices && responseJson.choices[0] && responseJson.choices[0].message && typeof responseJson.choices[0].message.content === 'string') { + return responseJson.choices[0].message.content; + } + + if (responseJson.generations && responseJson.generations[0] && responseJson.generations[0][0] && responseJson.generations[0][0].text) { + return responseJson.generations[0][0].text; + } + + const asString = JSON.stringify(responseJson); + return asString.slice(0, 1000); + } catch (e) { + return ''; + } + } + + window.generateHint = async function (apiKey, model, level, problemContext) { + if (!apiKey) throw new Error('Groq API key is required.'); + if (!model) throw new Error('Model name is required.'); + if (!HINT_PROMPTS[level]) throw new Error('Invalid hint level.'); + + const promptConfig = HINT_PROMPTS[level]; + + const systemMessage = promptConfig.systemPrompt; + const userMessage = `Problem Context:\n${problemContext}\n\nPlease provide a ${level.toUpperCase()}-level hint for this problem. Keep within ${promptConfig.maxWords} words. Do NOT provide code or full solution.`; + + const requestBody = { + model: model, + messages: [ + { role: 'system', content: systemMessage }, + { role: 'user', content: userMessage } + ], + temperature: promptConfig.temperature, + max_tokens: Math.ceil(promptConfig.maxWords * 1.6) + }; + + const resp = await fetch('https://api.groq.com/openai/v1/chat/completions', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${apiKey}` + }, + body: JSON.stringify(requestBody) + }); + + if (!resp.ok) { + const errText = await resp.text().catch(() => ''); + throw new Error(`Groq API error ${resp.status}: ${errText || resp.statusText}`); + } + + const data = await resp.json(); + let raw = extractModelText(data); + + raw = filterResponse(raw); + const finalHint = enforceWordLimit(raw, promptConfig.maxWords); + + return finalHint; + }; + +})(); From 41fb972772726bafbce2d2382accf29a04769395 Mon Sep 17 00:00:00 2001 From: riyaa404 Date: Thu, 14 Aug 2025 22:50:52 +0530 Subject: [PATCH 2/3] Resolved merge conflict in popup.html and updated prompts.js --- prompts.js | 102 +++++++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 47 deletions(-) diff --git a/prompts.js b/prompts.js index ba15e04..1df1fee 100644 --- a/prompts.js +++ b/prompts.js @@ -1,83 +1,95 @@ (() => { 'use strict'; - const HINT_PROMPTS = { - ordinary: { - systemPrompt: `You are a helpful LeetCode tutor providing ORDINARY level hints. +const HINT_PROMPTS = { + ordinary: { + systemPrompt: `You are a helpful LeetCode tutor providing ORDINARY level hints. Your goal: Give a gentle nudge in the right direction without revealing too much. +Rules: +- FIRST LINE must be exactly: "Here's an Ordinary level hint..." +- Do NOT write anything before that first line. - Focus on understanding the problem better - Suggest what data structures or concepts to consider - Ask guiding questions that help the student think - Keep it simple and encouraging - DO NOT provide code or detailed algorithms +- STRICTLY respond in no more than 50 words. The first line counts as part of the 50 words. +- Do not add filler or background text before or after the hint.`, + temperature: 0.3, + maxWords: 50 + }, -Word limit: 50 words maximum.`, - temperature: 0.3, - maxWords: 50 - }, - - advanced: { - systemPrompt: `You are an experienced LeetCode mentor providing ADVANCED level hints. + advanced: { + systemPrompt: `You are an experienced LeetCode mentor providing ADVANCED level hints. Your goal: Provide deeper and more specific guidance without fully solving the problem. +Rules: +- FIRST LINE must be exactly: "Here's an Advanced level hint..." +- Do NOT write anything before that first line. - Explain the general approach or recognized problem pattern - Mention specific algorithms or techniques (e.g., "two pointers", "DFS with memoization") - Discuss time/space complexity considerations - Suggest how to break the problem into manageable steps - Avoid giving complete pseudo-code or direct answers +- STRICTLY respond in no more than 75 words. The first line counts as part of the 75 words. +- Do not add filler or background text before or after the hint.`, + temperature: 0.3, + maxWords: 75 + }, -Word limit: 100 words maximum.`, - temperature: 0.3, - maxWords: 100 - }, - - expert: { - systemPrompt: `You are a LeetCode expert providing EXPERT level hints. + expert: { + systemPrompt: `You are a LeetCode expert providing EXPERT level hints. Your goal: Give comprehensive strategic guidance for optimal problem-solving. +Rules: +- FIRST LINE must be exactly: "Here's an Expert level hint..." +- Do NOT write anything before that first line. - Explain the optimal algorithm and why it works - Discuss alternative approaches and trade-offs - Analyze time and space complexity in detail - Mention important edge cases - Provide a high-level roadmap for the implementation - Let the student write the actual code +- STRICTLY respond in no more than 100 words. The first line counts as part of the 100 words. +- Do not add filler or background text before or after the hint.`, + temperature: 0.3, + maxWords: 100 + } +}; -Word limit: 150 words maximum.`, - temperature: 0.3, - maxWords: 150 - } - }; - function filterResponse(text) { + function filterResponse(text, maxWords) { if (!text || typeof text !== 'string') return ''; - let cleaned = text; - + let cleaned = text.trimStart(); cleaned = cleaned.replace(/[\s\S]*?<\/think>/gi, ''); cleaned = cleaned.replace(/[\s\S]*?<\/reflection>/gi, ''); cleaned = cleaned.replace(/<[^>]+>/g, ''); - cleaned = cleaned.replace(/^(Assistant:|AI:|System:)\s*/i, ''); + + const match = cleaned.match(/^Here(?:'s| is) an (Ordinary|Advanced|Expert) level hint.*$/im); + let firstLine = match ? match[0].trim() : ''; + if (firstLine) { + const index = cleaned.indexOf(firstLine); + cleaned = cleaned.slice(index); + } + else { cleaned = cleaned.replace(/^\s*(?:Sure[,\.]?\s*)?(?:here(?:'s| is)\s+(?:a\s+)?)?(?:hint|suggestion|note|tip)\s*[:\-]?\s*/i, ''); + } - cleaned = cleaned.replace(/^(?:Here['’]?s|Here is|You can)\b[\s\S]*?(?:\n{1,2}|$)/i, (m) => { - return m.length > 140 ? '' : m; - }); - - cleaned = cleaned.replace(/\n\s*\n\s*\n+/g, '\n\n'); - - cleaned = cleaned.trim(); + cleaned = cleaned.replace(/\n\s*\n\s*\n+/g, '\n\n').trim(); - return cleaned; + // Rare-case safety net for word limit + if (maxWords && Number.isFinite(maxWords)) { + const words = cleaned.split(/\s+/); + if (words.length > maxWords + 5) { + cleaned = words.slice(0, maxWords).join(' ') + '...'; + } } - function enforceWordLimit(content, maxWords) { - if (!content) return ''; - const words = content.trim().split(/\s+/); - if (words.length <= maxWords) return content.trim(); - return words.slice(0, maxWords).join(' ') + '...'; - } + return cleaned; +} function extractModelText(responseJson) { try { @@ -91,8 +103,7 @@ Word limit: 150 words maximum.`, return responseJson.generations[0][0].text; } - const asString = JSON.stringify(responseJson); - return asString.slice(0, 1000); + return JSON.stringify(responseJson).slice(0, 1000); } catch (e) { return ''; } @@ -134,11 +145,8 @@ Word limit: 150 words maximum.`, const data = await resp.json(); let raw = extractModelText(data); - - raw = filterResponse(raw); - const finalHint = enforceWordLimit(raw, promptConfig.maxWords); - - return finalHint; + raw = filterResponse(raw, promptConfig.maxWords); + return raw; }; })(); From 765cfb4bb9dce8783f705f67197186f35ca88500 Mon Sep 17 00:00:00 2001 From: riyaa404 Date: Fri, 15 Aug 2025 15:28:29 +0530 Subject: [PATCH 3/3] Save current changes: hint system update --- prompts.js | 55 ++++++++++++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/prompts.js b/prompts.js index 1df1fee..4be938b 100644 --- a/prompts.js +++ b/prompts.js @@ -9,11 +9,12 @@ Your goal: Give a gentle nudge in the right direction without revealing too much Rules: - FIRST LINE must be exactly: "Here's an Ordinary level hint..." - Do NOT write anything before that first line. -- Focus on understanding the problem better -- Suggest what data structures or concepts to consider -- Ask guiding questions that help the student think -- Keep it simple and encouraging -- DO NOT provide code or detailed algorithms +- Focus on understanding the problem better. +- Suggest what data structures or concepts to consider. +- Ask guiding questions that help the student think. +- Keep it simple, concise, and encouraging. +- Do NOT provide code, pseudo-code, or partial algorithms. +- Stop immediately when you reach 50 words. Do NOT exceed 50 words. - STRICTLY respond in no more than 50 words. The first line counts as part of the 50 words. - Do not add filler or background text before or after the hint.`, temperature: 0.3, @@ -27,11 +28,12 @@ Your goal: Provide deeper and more specific guidance without fully solving the p Rules: - FIRST LINE must be exactly: "Here's an Advanced level hint..." - Do NOT write anything before that first line. -- Explain the general approach or recognized problem pattern -- Mention specific algorithms or techniques (e.g., "two pointers", "DFS with memoization") -- Discuss time/space complexity considerations -- Suggest how to break the problem into manageable steps -- Avoid giving complete pseudo-code or direct answers +- Explain the general approach or recognized problem pattern. +- Mention specific algorithms or techniques (e.g., "two pointers", "DFS with memoization") without giving full implementation. +- Discuss time/space complexity considerations. +- Suggest how to break the problem into manageable steps. +- Avoid giving complete pseudo-code or direct answers. +- Stop immediately when you reach 75 words. Do NOT exceed 75 words. - STRICTLY respond in no more than 75 words. The first line counts as part of the 75 words. - Do not add filler or background text before or after the hint.`, temperature: 0.3, @@ -45,12 +47,13 @@ Your goal: Give comprehensive strategic guidance for optimal problem-solving. Rules: - FIRST LINE must be exactly: "Here's an Expert level hint..." - Do NOT write anything before that first line. -- Explain the optimal algorithm and why it works -- Discuss alternative approaches and trade-offs -- Analyze time and space complexity in detail -- Mention important edge cases -- Provide a high-level roadmap for the implementation -- Let the student write the actual code +- Explain the optimal algorithm and why it works. +- Discuss alternative approaches and trade-offs. +- Analyze time and space complexity in detail. +- Mention important edge cases. +- Provide a high-level roadmap for the implementation. +- Let the student write the actual code. +- Stop immediately when you reach 100 words. Do NOT exceed 100 words. - STRICTLY respond in no more than 100 words. The first line counts as part of the 100 words. - Do not add filler or background text before or after the hint.`, temperature: 0.3, @@ -68,26 +71,12 @@ Rules: cleaned = cleaned.replace(/<[^>]+>/g, ''); cleaned = cleaned.replace(/^(Assistant:|AI:|System:)\s*/i, ''); - const match = cleaned.match(/^Here(?:'s| is) an (Ordinary|Advanced|Expert) level hint.*$/im); - let firstLine = match ? match[0].trim() : ''; - if (firstLine) { - const index = cleaned.indexOf(firstLine); - cleaned = cleaned.slice(index); + const match = cleaned.match(/(Here's an (Ordinary|Advanced|Expert) level hint.*)/i); + if (match) { + cleaned = match[1] + ' ' + cleaned.slice(match.index + match[0].length).trim(); } - else { - cleaned = cleaned.replace(/^\s*(?:Sure[,\.]?\s*)?(?:here(?:'s| is)\s+(?:a\s+)?)?(?:hint|suggestion|note|tip)\s*[:\-]?\s*/i, ''); - } - cleaned = cleaned.replace(/\n\s*\n\s*\n+/g, '\n\n').trim(); - // Rare-case safety net for word limit - if (maxWords && Number.isFinite(maxWords)) { - const words = cleaned.split(/\s+/); - if (words.length > maxWords + 5) { - cleaned = words.slice(0, maxWords).join(' ') + '...'; - } - } - return cleaned; }