Skip to content

Commit

Permalink
Feature: Easy translation (#15)
Browse files Browse the repository at this point in the history
* Adds a translate button if you opt in as a user
* Adds sponsorship information
* chore: version bump
  • Loading branch information
drewbaumann authored Oct 25, 2024
1 parent 9da8164 commit 69efd82
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 57 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
2 changes: 1 addition & 1 deletion _meta.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
163 changes: 107 additions & 56 deletions dialogs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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..."),
Expand All @@ -15,108 +54,120 @@ 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 ..
". I have a question about the following highlighted text: " .. highlightedText
}
table.insert(message_history, context_message)

-- Ask the question
local question_message = {
role = "user",
content = question
}
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

0 comments on commit 69efd82

Please sign in to comment.