From 3c91b7176993799dbd7bb01fa6c18bc3fdb4270d Mon Sep 17 00:00:00 2001 From: frianasoa Date: Sat, 23 Dec 2023 02:29:40 +0900 Subject: [PATCH] Added OpenAi Chat GPT --- content/notes/menus.js | 144 ++++++++++++++++++++++++-------- content/settings/ai.xhtml | 12 +++ content/settings/preferences.js | 7 +- content/ui/tabbed-dialog.js | 2 +- core/ai.js | 83 +++++++++++++++++- core/format.js | 41 ++++----- install.rdf | 2 +- manifest.json | 2 +- zenote-update.json | 6 +- zenote-update.rdf | 6 +- 10 files changed, 235 insertions(+), 70 deletions(-) diff --git a/content/notes/menus.js b/content/notes/menus.js index e9718a8..d1571fd 100644 --- a/content/notes/menus.js +++ b/content/notes/menus.js @@ -74,39 +74,49 @@ Menus = { } items_ai["sep-ai-02"] = "---------"; - if(Zotero.ZeNotes.Prefs.getb("bard-api-key")!="") + if(Zotero.ZeNotes.Prefs.getb("bard-api-key")!="" || Zotero.ZeNotes.Prefs.getb("openai-api-key")!="") { items_ai["paraphrase-annotation"] = { name: "Paraphrase annotation", icon: "fa-repeat", - items: { - "paraphrase-bard": {name: "Using bard", icon: "fa-b"}, - } + items: {} } items_ai["custom-prompt-on-cell"] = { name: "Run custom prompt on cell", icon: "fa-square", - items: { - "custom-prompt-cell-bard": {name: "Using bard", icon: "fa-b"}, - } + items: {} } items_ai["custom-prompt-on-row"] = { name: "Run custom prompt on row", icon: "fa-arrow-right", - items: { - "custom-prompt-row-bard": {name: "Using bard", icon: "fa-b"}, - } + items: {} } items_ai["custom-prompt-on-table"] = { name: "Run custom prompt on table", icon: "fa-table", - items: { - "custom-prompt-table-bard": {name: "Using bard", icon: "fa-b"}, - } + items: {} + } + + + if(Zotero.ZeNotes.Prefs.getb("bard-api-key")!="") + { + items_ai["paraphrase-annotation"]["items"]["paraphrase-bard"] = {name: "Using bard", icon: "fa-b"}; + items_ai["custom-prompt-on-cell"]["items"]["custom-prompt-cell-bard"] = {name: "Using bard", icon: "fa-b"}; + items_ai["custom-prompt-on-row"]["items"]["custom-prompt-row-bard"] = {name: "Using bard", icon: "fa-b"}; + items_ai["custom-prompt-on-table"]["items"]["custom-prompt-row-table"] = {name: "Using bard", icon: "fa-b"}; + } + + if(Zotero.ZeNotes.Prefs.getb("openai-api-key")!="") + { + items_ai["paraphrase-annotation"]["items"]["paraphrase-openai-gpt"] = {name: "Using Chat GPT", icon: "fa-g"}; + items_ai["custom-prompt-on-cell"]["items"]["custom-prompt-cell-openai"] = {name: "Using Chat GPT", icon: "fa-g"}; + items_ai["custom-prompt-on-row"]["items"]["custom-prompt-row-openai"] = {name: "Using Chat GPT", icon: "fa-g"}; + items_ai["custom-prompt-on-table"]["items"]["custom-prompt-table-openai"] = {name: "Using Chat GPT", icon: "fa-g"}; } + items_ai["sep-ai-01"] = "---------"; } @@ -439,10 +449,13 @@ Menus = { else if(key.includes("custom-prompt-")) { var annotation = Zotero.Items.get(annotationid); - var target = "cell"; - data = Table.celldata(td); - if(key.includes("-row")) + if(key.includes("cell")) + { + target = "cell"; + data = Table.celldata(td); + } + else if(key.includes("-row")) { target = "row"; data = Table.rowdata(td.closest("tr")); @@ -503,11 +516,39 @@ Menus = { }); }); } + else if(key.includes("-openai")) + { + Zotero.ZeNotes.Ai.OpenAi.customprompt(JSON.stringify(data), target).then(r=>{ + var model = Zotero.ZeNotes.Prefs.get("openai-model"); + var table = AiUi.createdialog(annotation, currentcomment, r, "openai"); + var div = document.createElement("div"); + div.innerHTML = "

Custom prompt

"+customprompt+"
"+this.displayjson(data); + try { + TabbedDialog.open(table, div, function(){}, "Edit and choose a candidate [OpenAi: "+model+"]", "close"); + } + catch(e) + { + alert(e); + } + }).catch(r=>{ + var div = document.createElement("div"); + div.innerHTML = "

Custom prompt

"+customprompt+"
"+this.displayjson(data); + var html = ""; + if(Array.isArray(r)) + { + html = r.join("
"); + } + else + { + html="-"+r; + } + TabbedDialog.open(html, div, function(){ + }); + }); + } } - - - else if(key=="paraphrase-bard") + else if(key.startsWith("paraphrase")) { if(!annotationkey) { @@ -515,35 +556,64 @@ Menus = { return; } - if(Zotero.ZeNotes.Prefs.getb("bard-api-key")=="") - { - alert("Please set API key first.\nGo to ZeNotes > Settings > General Settings > AI API settings"); - return; - } - var annotation = Zotero.Items.get(annotationid); var currentcomment = annotation.annotationComment; if(currentcomment==null) { currentcomment = ""; } - Zotero.ZeNotes.Ai.Bard.paraphrase(annotation["annotationText"]).then(r=>{ - var table = AiUi.createdialog(annotation, currentcomment, r, "bard"); - var model = Zotero.ZeNotes.Prefs.get("bard-model"); - Dialog.open(table, function(){}, "Edit and choose a paraphrase [Bard: "+model+"]", "close"); - }).catch(r=>{ - var html = ""; - if(Array.isArray(r)) + + if(key.endsWith("-bard")) + { + if(Zotero.ZeNotes.Prefs.getb("bard-api-key")=="") { - html = r.join("
"); + alert("Please set API key first.\nGo to ZeNotes > Settings > General Settings > AI API settings"); + return; } - else + Zotero.ZeNotes.Ai.Bard.paraphrase(annotation["annotationText"]).then(r=>{ + var table = AiUi.createdialog(annotation, currentcomment, r, "bard"); + var model = Zotero.ZeNotes.Prefs.get("bard-model"); + Dialog.open(table, function(){}, "Edit and choose a paraphrase [Bard: "+model+"]", "close"); + }).catch(r=>{ + var html = ""; + if(Array.isArray(r)) + { + html = r.join("
"); + } + else + { + html="-"+r; + } + Dialog.open(html, function(){ + }); + }); + } + else if(key.endsWith("-openai-gpt")) + { + if(Zotero.ZeNotes.Prefs.getb("openai-api-key")=="") { - html="-"+r; + alert("Please set API key first.\nGo to ZeNotes > Settings > General Settings > AI API settings"); + return; } - Dialog.open(html, function(){ + + Zotero.ZeNotes.Ai.OpenAi.paraphrase(annotation["annotationText"]).then(r=>{ + var table = AiUi.createdialog(annotation, currentcomment, r, "gpt"); + var model = Zotero.ZeNotes.Prefs.get("openai-model"); + Dialog.open(table, function(){}, "Edit and choose a paraphrase [OpenAi: "+model+"]", "close"); + }).catch(r=>{ + var html = ""; + if(Array.isArray(r)) + { + html = r.join("
"); + } + else + { + html="-"+r; + } + Dialog.open(html, function(){ + }); }); - }); + } } else if(key=="showfile") diff --git a/content/settings/ai.xhtml b/content/settings/ai.xhtml index 995c2e4..870c017 100644 --- a/content/settings/ai.xhtml +++ b/content/settings/ai.xhtml @@ -5,10 +5,22 @@ Bard API key Model + + OpenAi API key + Model + + + OpenAi max token + Cell custom prompt Row summary prompt Table summary prompt diff --git a/content/settings/preferences.js b/content/settings/preferences.js index d0d91e6..6aede9b 100644 --- a/content/settings/preferences.js +++ b/content/settings/preferences.js @@ -314,11 +314,16 @@ Zotero_Preferences.ZeNotes = { Zotero_Preferences.ZeNotes.loadpreference("column-width", "zn-column-width"); Zotero_Preferences.ZeNotes.loadpreference("bard-api-key", "zn-bard-api-key", "encrypt"); + Zotero_Preferences.ZeNotes.loadpreference("bard-model", "zn-bard-model"); + + Zotero_Preferences.ZeNotes.loadpreference("openai-api-key", "zn-openai-api-key", "encrypt"); + Zotero_Preferences.ZeNotes.loadpreference("openai-model", "zn-openai-model"); + Zotero_Preferences.ZeNotes.loadpreference("openai-max-token", "zn-openai-max-token"); Zotero_Preferences.ZeNotes.loadpreference("google-translate-key", "zn-google-translate-key", "encrypt"); Zotero_Preferences.ZeNotes.loadpreference("deepl-api-key", "zn-deepl-api-key", "encrypt"); - Zotero_Preferences.ZeNotes.loadpreference("bard-model", "zn-bard-model"); + Zotero_Preferences.ZeNotes.loadpreference("cell-custom-prompt", "zn-cell-custom-prompt"); Zotero_Preferences.ZeNotes.loadpreference("row-custom-prompt", "zn-row-custom-prompt"); Zotero_Preferences.ZeNotes.loadpreference("table-custom-prompt", "zn-table-custom-prompt"); diff --git a/content/ui/tabbed-dialog.js b/content/ui/tabbed-dialog.js index 669f271..1d1167e 100644 --- a/content/ui/tabbed-dialog.js +++ b/content/ui/tabbed-dialog.js @@ -110,7 +110,7 @@ TabbedDialog = { if(title!="") { - this.dialog.title = title; + $("#main-tabbed-dialog").dialog( "option", "title", title); } if(buttons==null) diff --git a/core/ai.js b/core/ai.js index 3aa894f..9ba921d 100644 --- a/core/ai.js +++ b/core/ai.js @@ -93,7 +93,16 @@ Ai={ return Promise.resolve(["Error: "+e, JSON.stringify(data)]); } } - + else if(mode.startsWith("gpt")) + { + try { + return Promise.resolve(data.choices.map(function(e){return e.message.content})); + } + catch(e) + { + return Promise.resolve(["Error: "+e, JSON.stringify(data)]); + } + } }).catch(e=>{ return Promise.reject(["Error: "+e, JSON.stringify(data)]); }); @@ -102,6 +111,7 @@ Ai={ cell: "Paraphrase and summarize 'Direct quotes'", row: "Summarize the data below into a coherent literature review. Add source for each claim in the form (Author date). ", table: "Summarize the data below into a coherent literature review. Add source for each claim in the form (Author date). ", + paraphrase: "Paraphrase the following passage.", } } @@ -140,9 +150,7 @@ Ai.Bard = { { model = "gemini-pro"; } - - var prompts = "Your are an academic. Paraphrase the following. " - return this.sendprompt(sentence, prompts, model) + return this.sendprompt(sentence, Ai.prompts["paraphrase"], model) }, async customprompt(sentence, target) @@ -264,4 +272,71 @@ Ai.DeepL = { } return Ai.request(url, options, "deepl-translate"); }, +} + +Ai.OpenAi = { + paraphrase(sentence){ + var model = Zotero.ZeNotes.Prefs.get("openai-model"); + return this.sendprompt(sentence, Ai.prompts["paraphrase"], model) + }, + + async customprompt(sentence, target) + { + var model = Zotero.ZeNotes.Prefs.get("openai-model"); + var prompts = Zotero.ZeNotes.Prefs.get(target+"-custom-prompt"); + + if(prompts=="") + { + prompts = Ai.prompts[target]; + } + return this.sendprompt(sentence, prompts, model) + }, + + async sendprompt(sentence, prompts, model) { + var apikey = Zotero.ZeNotes.Prefs.getb("openai-api-key"); + var url = "https://api.openai.com/v1/chat/completions"; + var maxtoken = 300; + try { + maxtoken = Zotero.ZeNotes.Prefs.get("openai-max-token"); + + if(maxtoken=="") + { + maxtoken = 300; + } + else if(isNaN(parseInt(maxtoken))) + { + alert("Please input Max token (a number) in settings > open ai max token.\nThe value 100 is used by default!\nCurrent value: "+maxtoken); + maxtoken = 300; + } + else + { + maxtoken = parseInt(maxtoken); + } + + }catch(e){ + maxtoken = 300; + } + + var payload = { + model: model, + max_tokens: maxtoken, + messages: [ + {role: "system", content: "You are an academic assistant."}, + {role: "user", content: prompts}, + {role: "user", content: sentence}, + ], + } + + var options = { + method: 'POST', + headers: { + "Authorization": "Bearer "+apikey, + "Content-Type": "application/json", + }, + body: JSON.stringify(payload), + } + return Ai.request(url, options, model); + }, + + } \ No newline at end of file diff --git a/core/format.js b/core/format.js index 90929aa..7809fbe 100644 --- a/core/format.js +++ b/core/format.js @@ -2,18 +2,19 @@ Format = { async formatitems(items, tags) { var tagged_items = {}; - var itemlist = {}; + var itemlist = []; for(item of items) { - var itemnotes = await Format.itemnotes(item); - itemlist[item.id] = await Format.formatitem(item); + var itemnotes = await Format.itemnotes(item); + let itemelement = await Format.formatitem(item); + itemlist.push(itemelement); for(const tag of tags) { if(this.hastag(item, tag)) { if(!Object.keys(tagged_items).includes(item.id)) { - tagged_items[item.id] = itemlist[item.id]; + tagged_items[item.id] = itemelement; } if(!Object.keys(tagged_items[item.id]).includes(tag)) @@ -40,7 +41,7 @@ Format = { if(!Object.keys(tagged_items).includes(item.id)) { - tagged_items[item.id] = itemlist[item.id]; + tagged_items[item.id] = itemelement; } if(!Object.keys(tagged_items[item.id]).includes(tag)) { @@ -53,7 +54,7 @@ Format = { } } return { - data: Object.values(itemlist), + data: itemlist, columns: ["id", "itemid", "key", "title", "date", "journal", "author", "creators", "filekey"], tagged_items: Object.values(tagged_items), } @@ -251,19 +252,21 @@ Format = { }, async formatitem(item) { - var line = { - id: item.getID(), - itemid: item.id, - key: item.getField("key"), - title: this.xmlescape(item.getField("title")), - date: Format.year(item), - journal: this.xmlescape(item.getField("publicationTitle")), - author: Format.creatorshort(item)+" ("+Format.year(item)+")", - creators: Format.creators(item), - filenames: await Format.filenames(item), - filekey: Format.filekey(item), - } - return line; + return Format.filenames(item).then(filenames=>{ + var line = { + id: item.getID(), + itemid: item.id, + key: item.getField("key"), + title: this.xmlescape(item.getField("title")), + date: Format.year(item), + journal: this.xmlescape(item.getField("publicationTitle")), + author: Format.creatorshort(item)+" ("+Format.year(item)+")", + creators: Format.creators(item), + filenames: filenames, + filekey: Format.filekey(item), + } + return Promise.resolve(line); + }) }, year(item) { diff --git a/install.rdf b/install.rdf index b22ebed..2f12127 100644 --- a/install.rdf +++ b/install.rdf @@ -5,7 +5,7 @@ zenotes@alefa.net ZeNotes - 0.6.8 + 0.6.9 true https://raw.githubusercontent.com/frianasoa/zenotes/main/zenote-update.json https://github.com/frianasoa/zenotes diff --git a/manifest.json b/manifest.json index f14cd3f..e7f08a4 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Ze Notes", - "version": "0.6.8", + "version": "0.6.9", "description": "Advanced notes manager", "homepage_url": "https://github.com/frianasoa/zenotes", "author": "Fanantenana Rianasoa Andriariniaina", diff --git a/zenote-update.json b/zenote-update.json index 8af28f9..4345fce 100644 --- a/zenote-update.json +++ b/zenote-update.json @@ -3,9 +3,9 @@ "zenotes@alefa.net": { "updates": [ { - "version": "0.6.8", - "update_link": "https://github.com/frianasoa/Ze-Notes/releases/download/v0.6.8/zenotes-v0.6.8.xpi", - "update_hash": "sha256:baa8d6abadd563420521cc87c0a34469324aab265b0ed615dcbb3a73337526da", + "version": "0.6.9", + "update_link": "https://github.com/frianasoa/Ze-Notes/releases/download/v0.6.9/zenotes-v0.6.9.xpi", + "update_hash": "sha256:94fbed3ed282bdb1291d95bf4b464f312897e8053d7d23cd054d7e964ca8c242", "applications": { "gecko": { "strict_min_version": "60.0" diff --git a/zenote-update.rdf b/zenote-update.rdf index f4cc39c..3e19530 100644 --- a/zenote-update.rdf +++ b/zenote-update.rdf @@ -5,13 +5,13 @@ - 0.6.8 + 0.6.9 zotero@chnm.gmu.edu 5.0.0 6.* - https://github.com/frianasoa/Ze-Notes/releases/download/v0.6.8/zenotes-v0.6.8.xpi + https://github.com/frianasoa/Ze-Notes/releases/download/v0.6.9/zenotes-v0.6.9.xpi @@ -20,7 +20,7 @@ juris-m@juris-m.github.io 4.999 6.* - https://github.com/frianasoa/Ze-Notes/releases/download/v0.6.8/zenotes-v0.6.8.xpi + https://github.com/frianasoa/Ze-Notes/releases/download/v0.6.9/zenotes-v0.6.9.xpi