Scrapboxに書いたコンテキストを元にChatGPTにテキストを作ってもらう
下記のUserScriptを使えば誰でも使えます。
入力例:「このページを説明してください。」
出力例:
ChatGPTからの回答
このページはScrapboxに書いたコンテキストを元にChatGPTにテキストを作成するためのUserScriptを紹介しています。特定のテキストを選択し、ChatGPTに質問をすることができます。
参考
code:script.js
scrapbox.PageMenu.addMenu({
title: 'set Open API Key',
onClick: setOpenAPIKey
});
function setOpenAPIKey() {
const apiKey = prompt("OpenAI APIキーを入力してください:");
if (apiKey) {
localStorage.setItem("OPENAI_API_KEY", apiKey);
alert("APIキーが正常に保存されました");
}
}
(function() {
'use strict';
window.askChatGPT = async (
userInput,
userQuote,
pageContent,
{ temperature = 0.7, max_tokens = 500 } = {}
) => {
const apiKey = localStorage.getItem("OPENAI_API_KEY");
if (!apiKey) {
console.error("APIキーが見つかりません");
alert("OpenAI APIキーが設定されていません。設定画面でAPIキーを入力してください。");
return; // APIキーがない場合は処理を中断
}
console.log("Sending request to GPT:", { userInput, userQuote, pageContent });
const headers = {
"Content-Type": "application/json",
Authorization: Bearer ${apiKey},
};
function escapeString(str) {
return str
.replace(/\\/g, "\\\\")
.replace(/"/g, '\\"')
.replace(/\n/g, "\\n")
.replace(/\r/g, "\\r")
.replace(/\t/g, "\\t");
}
if (typeof pageContent === "string") pageContent = escapeString(pageContent);
if (typeof userInput === "string") userInput = escapeString(userInput);
if (typeof userQuote === "string") userQuote = escapeString(userQuote);
const data = JSON.stringify({
model: "gpt-4o-mini",
temperature: temperature,
max_tokens: max_tokens,
messages: [
{
role: "system",
content: "あなたはScrapboxのページと密接に統合されたエージェントです。ユーザーはScrapboxに日記や議事録、そのほかWebからのまとめなどを日々書いています。「ユーザーが選択したテキスト(userQuote)」に対して『ユーザーからの指示(userInput)』が投げられています。*指示の通りに最小限で明確な返答をしてください。返事は指示を達成するためだけに使用することにしてください。*コンテキストはScrapboxページの全文(pageContent)を参照してください",
},
{
role: "user",
content: userInput: ${userInput}\nuserQuote: ${userQuote}\npageContent: ${pageContent},
},
],
});
method: "POST",
headers: headers,
body: data
})
.then(response => response.json())
.catch(error => {
console.error("GPT Request Error:", error);
throw error;
});
};
scrapbox.PopupMenu.addButton({
title: "ChatGPT",
onClick: () => {
const userQuote = window.getSelection().toString();
const userInput = prompt("ChatGPTに質問する:");
if (userInput) {
const pageContent = scrapbox.Page.lines.map(line => line.text).join('\n');
window.askChatGPT(userInput, userQuote, pageContent)
.then((response) => {
if (response.choices && response.choices.length > 0) {
const result = "ChatGPTからの回答\n" + response.choices[0].message.content.trim() + "";
// システムのカラースキームを検出
const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
const modal = document.createElement('div');
modal.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: ${isDarkMode ? '#333' : '#f0f0f0'};
color: ${isDarkMode ? '#f0f0f0' : '#333'};
padding: 20px;
z-index: 1000;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
max-width: 80%;
max-height: 80%;
overflow-y: auto;
font-family: Arial, sans-serif;
`;
const textArea = document.createElement('textarea');
textArea.value = result;
textArea.style.cssText = `
width: 100%;
height: 300px;
margin-bottom: 10px;
padding: 10px;
border: 1px solid ${isDarkMode ? '#555' : '#ccc'};
border-radius: 4px;
font-size: 14px;
line-height: 1.5;
resize: vertical;
background-color: ${isDarkMode ? '#444' : '#fff'};
color: ${isDarkMode ? '#f0f0f0' : '#333'};
`;
const closeButton = document.createElement('button');
closeButton.textContent = '閉じる';
closeButton.style.cssText = `
border: none;
color: white;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
border-radius: 4px;
`;
closeButton.onclick = () => document.body.removeChild(modal);
modal.appendChild(textArea);
modal.appendChild(closeButton);
document.body.appendChild(modal);
} else {
console.error('GPT Response Error:', response);
alert('エラーが発生しました。');
}
})
.catch((error) => {
console.error('Error calling askChatGPT:', error);
alert('ChatGPTとの通信中にエラーが発生しました。');
});
}
},
});
})();