Skip to content

Commit

Permalink
Updated.
Browse files Browse the repository at this point in the history
  • Loading branch information
emeryberger committed Jul 28, 2023
1 parent 9009fc2 commit 20eb4a0
Showing 1 changed file with 94 additions and 32 deletions.
126 changes: 94 additions & 32 deletions scalene-gui.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ const maxLinesPerRegion = 50; // Only show regions that are no more than this ma

let showedExplosion = {}; // Used so we only show one explosion per region.

function unescapeUnicode(s) {
return s.replace(/\\u([\dA-F]{4})/gi, function (match, p1) {
return String.fromCharCode(parseInt(p1, 16));
});
}

async function isValidApiKey(apiKey) {
const response = await fetch("https://api.openai.com/v1/completions", {
method: "GET",
Expand Down Expand Up @@ -49,34 +55,81 @@ function checkApiKey(apiKey) {
})();
}

function extractCode(text) {
/**
* Extracts code block from the given completion text.
*
* @param {string} text - A string containing text and other data.
* @returns {string} Extracted code block from the completion object.
*/
const lines = text.split('\n');
let i = 0;
while (i < lines.length && lines[i].trim() === '') {
i++;
}
const first_line = lines[i].trim();
let code_block;
if (first_line === '```') {
code_block = text.slice(3);
} else if (first_line.startsWith('```')) {
const word = first_line.slice(3).trim();
if (word.length > 0 && !word.includes(' ')) {
code_block = text.slice(first_line.length);
} else {
code_block = text;
}
} else {
code_block = text;
}
const end_index = code_block.indexOf('```');
if (end_index !== -1) {
code_block = code_block.slice(0, end_index);
}
return code_block;
}

async function sendPromptToOpenAI(prompt, len, apiKey) {
const endpoint = "https://api.openai.com/v1/completions";
const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({
model: "text-davinci-003",
prompt: prompt,
temperature: 0.3,
max_tokens: len,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
// 'response_format': 'url'
}),
});
const endpoint = "https://api.openai.com/v1/chat/completions";
const body = JSON.stringify({
// model: 'gpt-3.5-turbo',
model: 'gpt-4',
messages: [
{
role: 'system',
content: 'You are a Python programming assistant who ONLY responds with blocks of commented, optimized code. You never respond with text. Just code, starting with ``` and ending with ```.'
},
{
role: 'user',
content: prompt
}
],
temperature: 0.3,
frequency_penalty: 0,
presence_penalty: 0,
user: "scalene-user"
});

const data = await response.json();
// Chop off any blank lines in the header.
console.log(body);

const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: body,
});

try {
return data.choices[0].text.replace(/^\s*[\r\n]/gm, "");
} catch {
return "# Query failed.\n";
}
const data = await response.json();
// Chop off any blank lines in the header.

try {
// WAS (GPT-3): return data.choices[0].text.replace(/^\s*[\r\n]/gm, "");
return data.choices[0].message.content.replace(/^\s*[\r\n]/gm, "");
} catch {
return "# Query failed.\n";

}
}

function countSpaces(str) {
Expand All @@ -102,7 +155,7 @@ async function optimizeCode(imports, code, context) {
alert(
"To activate proposed optimizations, enter an OpenAI API key in advanced options."
);
return null;
return '';
}
// If the code to be optimized is just one line of code, say so.
let lineOf = " ";
Expand All @@ -123,13 +176,15 @@ async function optimizeCode(imports, code, context) {

const optimizePerformancePrompt = `Optimize the following${lineOf}Python code:\n\n${context}\n\n# Start of code\n\n${code}\n\n# End of code\n\nRewrite the above Python code only from "Start of code" to "End of code", to make it more efficient WITHOUT CHANGING ITS RESULTS. Assume the code has already executed all these imports; do NOT include them in the optimized code:\n\n${imports}\n\nUse native libraries if that would make it faster than pure Python. Consider using the following other libraries, if appropriate:\n\n${libraries}\n\nYour output should only consist of valid Python code. Output the resulting Python with brief explanations only included as comments prefaced with #. Include a detailed explanatory comment before the code, starting with the text "# Proposed optimization:". Make the code as clear and simple as possible, while also making it as fast and memory-efficient as possible. Use vectorized operations${useGPUstring}whenever it would substantially increase performance, and quantify the speedup in terms of orders of magnitude. Eliminate as many for loops, while loops, and list or dict comprehensions as possible, replacing them with vectorized equivalents. If the performance is not likely to increase, leave the code unchanged. Fix any errors in the optimized code. Optimized${lineOf}code:`

const pure_optimizePerformancePrompt = `Optimize the following${lineOf}Python code:\n\n${context}\n\n# Start of code\n\n${code}\n\n# End of code\n\nRewrite the above Python code only from "Start of code" to "End of code", to make it more efficient WITHOUT CHANGING ITS RESULTS. Assume the code has already executed all these imports; do NOT include them in the optimized code:\n\n${imports}\n\nONLY USE PURE PYTHON.\n\nYour output should only consist of valid Python code. Output the resulting Python with brief explanations only included as comments prefaced with #. Include a detailed explanatory comment before the code, starting with the text "# Proposed optimization:". Make the code as clear and simple as possible, while also making it as fast and memory-efficient as possible. If the performance is not likely to increase, leave the code unchanged. Fix any errors in the optimized code. Optimized${lineOf}code:`

const memoryEfficiencyPrompt = `Optimize the following${lineOf} Python code:\n\n${context}\n\n# Start of code\n\n${code}\n\n\n# End of code\n\nRewrite the above Python code only from "Start of code" to "End of code", to make it more memory-efficient WITHOUT CHANGING ITS RESULTS. Assume the code has already executed all these imports; do NOT include them in the optimized code:\n\n${imports}\n\nUse native libraries if that would make it more space efficient than pure Python. Consider using the following other libraries, if appropriate:\n\n${libraries}\n\nYour output should only consist of valid Python code. Output the resulting Python with brief explanations only included as comments prefaced with #. Include a detailed explanatory comment before the code, starting with the text "# Proposed optimization:". Make the code as clear and simple as possible, while also making it as fast and memory-efficient as possible. Use native libraries whenever possible to reduce memory consumption; invoke del on variables and array elements as soon as it is safe to do so. If the memory consumption is not likely to be reduced, leave the code unchanged. Fix any errors in the optimized code. Optimized${lineOf}code:`

const optimizePerf = document.getElementById('optimize-performance').checked;

let prompt;
if (optimizePerf) {
prompt = optimizePerformancePrompt;
prompt = optimizePerformancePrompt;
} else {
prompt = memoryEfficiencyPrompt;
}
Expand All @@ -142,8 +197,9 @@ async function optimizeCode(imports, code, context) {

// Use number of words in the original code as a proxy for the number of tokens.
const numWords = (code.match(/\b\w+\b/g)).length;

return await sendPromptToOpenAI(prompt, Math.max(numWords * 4, 500), apiKey);

const result = await sendPromptToOpenAI(prompt, Math.max(numWords * 4, 500), apiKey);
return extractCode(result);
}

function proposeOptimizationRegion(filename, file_number, lineno) {
Expand All @@ -155,6 +211,7 @@ function proposeOptimizationLine(filename, file_number, lineno) {
}

function proposeOptimization(filename, file_number, lineno, params) {
filename = unescape(filename)
const useRegion = params["regions"];
const prof = globalThis.profile;
const this_file = prof.files[filename].lines;
Expand Down Expand Up @@ -923,10 +980,13 @@ function makeProfileLine(
? `${explosionString}&nbsp;`
: `${WhiteExplosion}&nbsp;`;

// Convert back any escaped Unicode.
line.line = unescapeUnicode(line.line);

const codeLine = Prism.highlight(line.line, Prism.languages.python, "python");
s += `<td style="height:10" align="left" bgcolor="whitesmoke" style="vertical-align: middle" data-sort="${line.lineno}">`;
if (propose_optimizations && showExplosion) {
s += `<span style="vertical-align: middle; cursor: pointer" title="Propose an optimization for the entire region starting here." onclick="proposeOptimizationRegion('${filename}', ${file_number}, ${parseInt(
s += `<span style="vertical-align: middle; cursor: pointer" title="Propose an optimization for the entire region starting here." onclick="proposeOptimizationRegion('${escape(filename)}', ${file_number}, ${parseInt(
line.lineno
)}); event.preventDefault()">${regionOptimizationString}</span>`;
} else {
Expand All @@ -937,7 +997,7 @@ function makeProfileLine(
? `${Lightning}`
: `${WhiteLightning}`;
if (propose_optimizations) {
s += `<span style="vertical-align: middle; cursor: pointer" title="Propose an optimization for this line." onclick="proposeOptimizationLine('${filename}', ${file_number}, ${parseInt(
s += `<span style="vertical-align: middle; cursor: pointer" title="Propose an optimization for this line." onclick="proposeOptimizationLine('${escape(filename)}', ${file_number}, ${parseInt(
line.lineno
)}); event.preventDefault()">${lineOptimizationString}</span>`;
} else {
Expand Down Expand Up @@ -1115,6 +1175,7 @@ async function display(prof) {
);
}


s += '<tr><td colspan="10">';
s += `<span class="text-center"><font style="font-size: 90%; font-style: italic; font-color: darkgray">hover over bars to see breakdowns; click on <font style="font-variant:small-caps; text-decoration:underline">column headers</font> to sort.</font></span>`;
s += "</td></tr>";
Expand Down Expand Up @@ -1158,7 +1219,8 @@ async function display(prof) {
// Print per-line profiles.
let prevLineno = -1;
for (const l in ff[1].lines) {
const line = ff[1].lines[l];
const line = ff[1].lines[l];

if (false) {
// Disabling spacers
// Add a space whenever we skip a line.
Expand Down

0 comments on commit 20eb4a0

Please sign in to comment.