diff --git a/README.md b/README.md index 358f0a6..8d4e628 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,19 @@ local CONFIGURATION = { return CONFIGURATION ``` +Additionally, as other extra features are rolled out, they will be optional and can be set in the `features` table in the `configuration.lua` file. For example, if you want to use the `translate_to` parameter, you can set it in the `features` table like so: + +```lua +local CONFIGURATION = { + api_key = "YOUR_API_KEY", + model = "gpt-4o-mini", + base_url = "https://api.openai.com/v1/chat/completions" + features = { + translate_to = "French" + } +} +``` + If you clone this project, you should be able to put the directory, `askgpt.koplugin`, in the `koreader/plugins` directory and it should work. If you want to use the plugin without cloning the project, you can download the zip file from the releases page and extract the `askgpt.koplugin` directory to the `koreader/plugins` directory. If for some reason you extract the files of this repository in another directory, rename it before moving it to the `koreader/plugins` directory. ## How To Use @@ -47,4 +60,6 @@ To use AskGPT, simply highlight the text that you want to ask a question about, I hope you enjoy using this plugin and that it enhances your e-reading experience. If you have any feedback or suggestions, please let me know! +If you want to support development, become a [Sponsor on GitHub](https://github.com/sponsors/drewbaumann). + License: GPLv3 diff --git a/_meta.lua b/_meta.lua index 1bae6b0..dbbdf4c 100644 --- a/_meta.lua +++ b/_meta.lua @@ -3,5 +3,5 @@ return { name = "askgpt", fullname = _("AskGPT"), description = _([[Allows the user to query the ChatGPT API for answers to questions about highlighted text.]]), - version = 0.6, + version = 0.9, } diff --git a/dialogs.lua b/dialogs.lua index fa1da06..16911d2 100644 --- a/dialogs.lua +++ b/dialogs.lua @@ -6,6 +6,45 @@ local _ = require("gettext") local queryChatGPT = require("gpt_query") +local CONFIGURATION = nil +local buttons, input_dialog + +local success, result = pcall(function() return require("configuration") end) +if success then + CONFIGURATION = result +else + print("configuration.lua not found, skipping...") +end + +local function translateText(text, target_language) + local translation_message = { + role = "user", + content = "Translate the following text to " .. target_language .. ": " .. text + } + local translation_history = { + { + role = "system", + content = "You are a helpful translation assistant. Provide direct translations without additional commentary." + }, + translation_message + } + return queryChatGPT(translation_history) +end + +local function createResultText(highlightedText, message_history) + local result_text = _("Highlighted text: ") .. "\"" .. highlightedText .. "\"\n\n" + + for i = 3, #message_history do + if message_history[i].role == "user" then + result_text = result_text .. _("User: ") .. message_history[i].content .. "\n\n" + else + result_text = result_text .. _("ChatGPT: ") .. message_history[i].content .. "\n\n" + end + end + + return result_text +end + local function showLoadingDialog() local loading = InfoMessage:new{ text = _("Loading..."), @@ -15,33 +54,47 @@ local function showLoadingDialog() end local function showChatGPTDialog(ui, highlightedText, message_history) - local title, author = + local title, author = ui.document:getProps().title or _("Unknown Title"), ui.document:getProps().authors or _("Unknown Author") local message_history = message_history or {{ role = "system", content = "The following is a conversation with an AI assistant. The assistant is helpful, creative, clever, and very friendly. Answer as concisely as possible." }} - local input_dialog - input_dialog = InputDialog:new{ - title = _("Ask a question about the highlighted text"), - input_hint = _("Type your question here..."), - input_type = "text", - buttons = {{{ + + local function handleNewQuestion(chatgpt_viewer, question) + table.insert(message_history, { + role = "user", + content = question + }) + + local answer = queryChatGPT(message_history) + + table.insert(message_history, { + role = "assistant", + content = answer + }) + + local result_text = createResultText(highlightedText, message_history) + + chatgpt_viewer:update(result_text) + end + + buttons = { + { text = _("Cancel"), callback = function() UIManager:close(input_dialog) end - }, { + }, + { text = _("Ask"), callback = function() local question = input_dialog:getInputText() UIManager:close(input_dialog) showLoadingDialog() - -- do the actual work after a short delay to allow the loading dialog to show UIManager:scheduleIn(0.1, function() - -- Give context to the question local context_message = { role = "user", content = "I'm reading something titled '" .. title .. "' by " .. author .. @@ -49,7 +102,6 @@ local function showChatGPTDialog(ui, highlightedText, message_history) } table.insert(message_history, context_message) - -- Ask the question local question_message = { role = "user", content = question @@ -57,66 +109,65 @@ local function showChatGPTDialog(ui, highlightedText, message_history) table.insert(message_history, question_message) local answer = queryChatGPT(message_history) - -- Save the answer to the message history local answer_message = { role = "assistant", content = answer } - table.insert(message_history, answer_message) - local result_text = _("Highlighted text: ") .. "\"" .. highlightedText .. "\"" .. "\n\n" .. _("User: ") .. - question .. "\n\n" .. _("ChatGPT: ") .. answer - - local function createResultText(highlightedText, message_history) - local result_text = _("Highlighted text: ") .. "\"" .. highlightedText .. "\"\n\n" - - for i = 3, #message_history do - if message_history[i].role == "user" then - result_text = result_text .. _("User: ") .. message_history[i].content .. "\n\n" - else - result_text = result_text .. _("ChatGPT: ") .. message_history[i].content .. "\n\n" - end - end - - return result_text - end - - local function handleNewQuestion(chatgpt_viewer, question) - -- Add the new question to the message history - table.insert(message_history, { - role = "user", - content = question - }) - - -- Send the query to ChatGPT with the updated message_history - local answer = queryChatGPT(message_history) - - -- Add the answer to the message history - table.insert(message_history, { - role = "assistant", - content = answer - }) - - -- Update the result text - local result_text = createResultText(highlightedText, message_history) - - -- Update the text and refresh the viewer - chatgpt_viewer:update(result_text) - end + + local result_text = createResultText(highlightedText, message_history) local chatgpt_viewer = ChatGPTViewer:new { title = _("AskGPT"), text = result_text, - onAskQuestion = handleNewQuestion -- Pass the callback function + onAskQuestion = handleNewQuestion } UIManager:show(chatgpt_viewer) end) end - }}} + } + } + + if CONFIGURATION and CONFIGURATION.features and CONFIGURATION.features.translate_to then + table.insert(buttons, { + text = _("Translate"), + callback = function() + showLoadingDialog() + + UIManager:scheduleIn(0.1, function() + local translated_text = translateText(highlightedText, CONFIGURATION.features.translate_to) + + table.insert(message_history, { + role = "user", + content = "Translate to " .. CONFIGURATION.features.translate_to .. ": " .. highlightedText + }) + + table.insert(message_history, { + role = "assistant", + content = translated_text + }) + + local result_text = createResultText(highlightedText, message_history) + local chatgpt_viewer = ChatGPTViewer:new { + title = _("Translation"), + text = result_text, + onAskQuestion = handleNewQuestion + } + + UIManager:show(chatgpt_viewer) + end) + end + }) + end + + input_dialog = InputDialog:new{ + title = _("Ask a question about the highlighted text"), + input_hint = _("Type your question here..."), + input_type = "text", + buttons = {buttons} } UIManager:show(input_dialog) - input_dialog:onShowKeyboard() end -return showChatGPTDialog +return showChatGPTDialog \ No newline at end of file