AI generation for notes (#1112)

* feat: ai generation for notes

* feat - ai generation -default to gpt-4o-mini

* feat - ai generation - change update text

* feat - ai generation - improve prompt

---------

Co-authored-by: Azgaar <azgaar.fmg@yandex.com>
This commit is contained in:
Azgaar 2024-08-23 18:08:50 +02:00 committed by GitHub
parent 1f280133be
commit 6df54d1ef6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 139 additions and 4 deletions

View file

@ -0,0 +1,87 @@
"use strict";
const GPT_MODELS = ["gpt-4o-mini", "chatgpt-4o-latest", "gpt-4o", "gpt-4-turbo", "gpt-4", "gpt-3.5-turbo"];
const SYSTEM_MESSAGE = "I'm working on my fantasy map.";
function geneateWithAi(defaultPrompt, onApply) {
updateValues();
$("#aiGenerator").dialog({
title: "AI Text Generator",
position: {my: "center", at: "center", of: "svg"},
resizable: false,
buttons: {
Generate: function (e) {
generate(e.target);
},
Apply: function () {
const result = byId("aiGeneratorResult").value;
if (!result) return tip("No result to apply", true, "error", 4000);
onApply(result);
$(this).dialog("close");
},
Close: function () {
$(this).dialog("close");
}
}
});
if (modules.geneateWithAi) return;
modules.geneateWithAi = true;
function updateValues() {
byId("aiGeneratorResult").value = "";
byId("aiGeneratorPrompt").value = defaultPrompt;
byId("aiGeneratorKey").value = localStorage.getItem("fmg-ai-kl") || "";
const select = byId("aiGeneratorModel");
select.options.length = 0;
GPT_MODELS.forEach(model => select.options.add(new Option(model, model)));
select.value = localStorage.getItem("fmg-ai-model") || GPT_MODELS[0];
}
async function generate(button) {
const key = byId("aiGeneratorKey").value;
if (!key) return tip("Please enter an OpenAI API key", true, "error", 4000);
localStorage.setItem("fmg-ai-kl", key);
const model = byId("aiGeneratorModel").value;
if (!model) return tip("Please select a model", true, "error", 4000);
localStorage.setItem("fmg-ai-model", model);
const prompt = byId("aiGeneratorPrompt").value;
if (!prompt) return tip("Please enter a prompt", true, "error", 4000);
try {
button.disabled = true;
byId("aiGeneratorResult").disabled = true;
const response = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {"Content-Type": "application/json", Authorization: `Bearer ${key}`},
body: JSON.stringify({
model,
messages: [
{role: "system", content: SYSTEM_MESSAGE},
{role: "user", content: prompt}
],
temperature: 1.2
})
});
if (!response.ok) {
const json = await response.json();
throw new Error(json?.error?.message || "Failed to generate");
}
const {choices} = await response.json();
const result = choices[0].message.content;
byId("aiGeneratorResult").value = result;
} catch (error) {
return tip(error.message, true, "error", 4000);
} finally {
button.disabled = false;
byId("aiGeneratorResult").disabled = false;
}
}
}

View file

@ -55,6 +55,7 @@ function editNotes(id, name) {
byId("notesLegend").addEventListener("blur", updateLegend);
byId("notesPin").addEventListener("click", toggleNotesPin);
byId("notesFocus").addEventListener("click", validateHighlightElement);
byId("notesGenerateWithAi").addEventListener("click", openAiGenerator);
byId("notesDownload").addEventListener("click", downloadLegends);
byId("notesUpload").addEventListener("click", () => legendsToLoad.click());
byId("legendsToLoad").addEventListener("change", function () {
@ -143,6 +144,25 @@ function editNotes(id, name) {
});
}
function openAiGenerator() {
const note = notes.find(note => note.id === notesSelect.value);
let prompt = `Respond with description. Use simple dry language. Invent facts, names and details. Split to paragraphs and format to HTML. Remove h tags, remove markdown.`;
if (note?.name) prompt += ` Name: ${note.name}.`;
if (note?.legend) prompt += ` Data: ${note.legend}`;
const onApply = result => {
notesLegend.innerHTML = result;
if (note) {
note.legend = result;
updateNotesBox(note);
if (window.tinymce) tinymce.activeEditor.setContent(note.legend);
}
};
geneateWithAi(prompt, onApply);
}
function downloadLegends() {
const notesData = JSON.stringify(notes);
const name = getFileName("Notes") + ".txt";