yukicoderの言語欄に ChatGPT を追加するユーザスクリプトです。2023/04/01 エイプリルフールネタです。
言語 ChatGPT を選択すると、ChatGPT によって問題文から Python3 コードを生成し、テキストに貼り付けます。
動作にはユーザスクリプトを動作させるための tampermonkey と API を呼び出すための OpenAI API Key が必要です。
// ==UserScript== | |
// @name ChatGPT on yukicoder | |
// @namespace http://app.ukibune.net/ | |
// @version 0.2023.4.1 | |
// @description try to take over the world! | |
// @author mai buyoh | |
// @match https://yukicoder.me/problems/* | |
// @exclude https://yukicoder.me/problems/*/submit | |
// @exclude https://yukicoder.me/problems/*/submissions | |
// @exclude https://yukicoder.me/problems/*/code | |
// @exclude https://yukicoder.me/problems/*/gen | |
// @exclude https://yukicoder.me/problems/*/validation | |
// @icon https://yukicoder.me/public/img/icon.png | |
// @license WTFPL | |
// @grant none | |
// ==/UserScript== | |
(function () { | |
"use strict"; | |
const kMock = false; | |
let openAiApiKey = null; | |
// let openAiApiKey = "sk-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaa"; | |
const kOpenAiModel = "gpt-3.5-turbo"; | |
const getOpenAiApiKey = () => { | |
if (openAiApiKey === null) { | |
const res = prompt( | |
"Please input openAI API key!", | |
"sk-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaa" | |
); | |
if (!res) throw new Error("No api key!"); | |
openAiApiKey = res; | |
} | |
return openAiApiKey; | |
}; | |
const postToChatGPT = async (content) => { | |
const query = { | |
model: kOpenAiModel, | |
messages: [{ role: "user", content }], | |
temperature: 0.7, | |
}; | |
const res = await fetch("https://api.openai.com/v1/chat/completions", { | |
headers: new Headers([ | |
["Content-Type", "application/json"], | |
["Authorization", "Bearer " + getOpenAiApiKey()], | |
]), | |
method: "POST", | |
body: JSON.stringify(query), | |
}); | |
if (!res.ok) { | |
console.error("fetch failed!", res); | |
return null; | |
} | |
const json = await res.json(); | |
return { | |
content: json.choices[0].message.content, | |
}; | |
}; | |
// For testing | |
const mock_postToChatGPT = (content) => | |
new Promise((resolve) => { | |
const _ = getOpenAiApiKey(); | |
console.log("query: ", content); | |
setTimeout(() => { | |
resolve({ | |
content: | |
'year, month, day = map(int, input().split("/"))\nif year < 1989:\n' + | |
' print("No")\nelif year == 1989:\n if month < 1 or (month == 1 and day < 8):\n' + | |
' print("No")\n else:\n print("Yes")\nelse:\n print("Yes")', | |
}); | |
}, 1500); | |
}); | |
// | |
const getCode = () => ace.edit("rich_source").getValue(); | |
const setCode = (text) => ace.edit("rich_source").setValue(text); | |
const getProblemText = () => | |
Array.from(document.getElementById("content").querySelectorAll(".block")) | |
.map((e) => e.innerText) | |
.join("\n\n"); | |
const putResult = (code) => { | |
const domSelect = document.getElementById("lang"); | |
domSelect.value = "python3"; | |
setTimeout(() => { | |
setCode(code); | |
}, 0); | |
}; | |
const askToAI = async () => { | |
setCode("chatGPTing..."); | |
const problem = getProblemText(); | |
const content = | |
"Write a Python3 code that solves the following competitive programming problem. " + | |
'Do not write anything other than the code."""' + | |
problem + | |
'"""'; | |
const answer = kMock | |
? await mock_postToChatGPT(content) | |
: await postToChatGPT(content); | |
putResult(answer.content); | |
}; | |
const addOptionIntoLang = () => { | |
const domSelect = document.getElementById("lang"); | |
const o = document.createElement("option"); | |
o.appendChild(document.createTextNode("ChatGPT (" + kOpenAiModel + ")")); | |
o.value = "_user_chatgpt"; | |
domSelect.addEventListener("change", () => { | |
if (domSelect.value != "_user_chatgpt") return; | |
setTimeout(askToAI, 0); | |
}); | |
domSelect.appendChild(o); | |
}; | |
setTimeout(addOptionIntoLang, 2000); | |
})(); |