From 227d18f116b2c5500e917fcf4758a2f8553d3b86 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 18:08:08 +0100 Subject: [PATCH 01/22] added a feature where the model parameter in openai_params can now be a function to allow dynamically changing the model. the readme has been updated appropriately. I have also added an example configuration with gpt-4-1106-preview to the readme after the configuration section. --- README.md | 37 ++++++++++++++- lua/chatgpt/api.lua | 109 +++++++++++++++++++++++++++----------------- 2 files changed, 103 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 5371a6bc..d9523557 100644 --- a/README.md +++ b/README.md @@ -140,11 +140,44 @@ or if you are using [lazy.nvim](https://github.com/folke/lazy.nvim): ## Configuration -`ChatGPT.nvim` comes with the following defaults, you can override them by -passing config as setup param +`ChatGPT.nvim` comes with the following defaults, you can override them by passing config as setup param https://github.com/jackMort/ChatGPT.nvim/blob/f1453f588eb47e49e57fa34ac1776b795d71e2f1/lua/chatgpt/config.lua#L10-L182 +### Example Configuration + +A simple configuration of the chat model could look something like this: +```lua +{ + "jackMort/ChatGPT.nvim", + event = "VeryLazy", + config = function() + require("chatgpt").setup({ + -- this config assumes you have OPENAI_API_KEY environment variable set + openai_params = { + -- NOTE: model can be a function returning the model name + -- this is useful if you want to change the model on the fly + -- using commands + -- Example: + -- model = function() if some_condition() then return "gpt-4-1106-preview" else return "gpt-3.5-turbo" end end + model = "gpt-4-1106-preview", + frequency_penalty = 0, + presence_penalty = 0, + max_tokens = 4095, + temperature = 0.2, + top_p = 0.1, + n = 1, + } + }) + end, + dependencies = { + "MunifTanjim/nui.nvim", + "nvim-lua/plenary.nvim", + "nvim-telescope/telescope.nvim" + } +} +``` + ### Secrets Management Providing the OpenAI API key via an environment variable is dangerous, as it diff --git a/lua/chatgpt/api.lua b/lua/chatgpt/api.lua index 76f78a54..0432cc9b 100644 --- a/lua/chatgpt/api.lua +++ b/lua/chatgpt/api.lua @@ -4,13 +4,39 @@ local logger = require("chatgpt.common.logger") local Api = {} +---@param tbl table +---@return table +local function table_shallow_copy(tbl) + local copy = {} + for key, value in pairs(tbl) do + copy[key] = value + end + return copy +end + +--- A function that collapses the openai params. +--- This means all the parameters of the openai_params that can be either constants or functions +--- will be set to constants by evaluating the functions. +---@param openai_params table +---@return table +local function collapsed_openai_params(openai_params) + local collapsed = table_shallow_copy(openai_params) + -- use copied version of table so the original model value remains a function and can still change + if type(collapsed.model) == "function" then + collapsed.model = collapsed.model() + end + return collapsed +end + function Api.completions(custom_params, cb) - local params = vim.tbl_extend("keep", custom_params, Config.options.openai_params) + local openai_params = collapsed_openai_params(Config.options.openai_params) + local params = vim.tbl_extend("keep", custom_params, openai_params) Api.make_call(Api.COMPLETIONS_URL, params, cb) end function Api.chat_completions(custom_params, cb, should_stop) - local params = vim.tbl_extend("keep", custom_params, Config.options.openai_params) + local openai_params = collapsed_openai_params(Config.options.openai_params) + local params = vim.tbl_extend("keep", custom_params, openai_params) local stream = params.stream or false if stream then local raw_chunks = "" @@ -62,11 +88,11 @@ function Api.chat_completions(custom_params, cb, should_stop) }) if ok and json ~= nil then if - json - and json.choices - and json.choices[1] - and json.choices[1].delta - and json.choices[1].delta.content + json + and json.choices + and json.choices[1] + and json.choices[1].delta + and json.choices[1].delta.content then cb(json.choices[1].delta.content, state) raw_chunks = raw_chunks .. json.choices[1].delta.content @@ -90,7 +116,8 @@ function Api.chat_completions(custom_params, cb, should_stop) end function Api.edits(custom_params, cb) - local params = vim.tbl_extend("keep", custom_params, Config.options.openai_edit_params) + local openai_params = collapsed_openai_params(Config.options.openai_params) + local params = vim.tbl_extend("keep", custom_params, openai_params) if params.model == "text-davinci-edit-001" or params.model == "code-davinci-edit-001" then vim.notify("Edit models are deprecated", vim.log.levels.WARN) Api.make_call(Api.EDITS_URL, params, cb) @@ -128,14 +155,14 @@ function Api.make_call(url, params, cb) end Api.job = job - :new({ - command = "curl", - args = args, - on_exit = vim.schedule_wrap(function(response, exit_code) - Api.handle_response(response, exit_code, cb) - end), - }) - :start() + :new({ + command = "curl", + args = args, + on_exit = vim.schedule_wrap(function(response, exit_code) + Api.handle_response(response, exit_code, cb) + end), + }) + :start() end Api.handle_response = vim.schedule_wrap(function(response, exit_code, cb) @@ -194,23 +221,23 @@ end local function loadConfigFromCommand(command, optionName, callback, defaultValue) local cmd = splitCommandIntoTable(command) job - :new({ - command = cmd[1], - args = vim.list_slice(cmd, 2, #cmd), - on_exit = function(j, exit_code) - if exit_code ~= 0 then - logger.warn("Config '" .. optionName .. "' did not return a value when executed") - return - end - local value = j:result()[1]:gsub("%s+$", "") - if value ~= nil and value ~= "" then - callback(value) - elseif defaultValue ~= nil and defaultValue ~= "" then - callback(defaultValue) - end - end, - }) - :start() + :new({ + command = cmd[1], + args = vim.list_slice(cmd, 2, #cmd), + on_exit = function(j, exit_code) + if exit_code ~= 0 then + logger.warn("Config '" .. optionName .. "' did not return a value when executed") + return + end + local value = j:result()[1]:gsub("%s+$", "") + if value ~= nil and value ~= "" then + callback(value) + elseif defaultValue ~= nil and defaultValue ~= "" then + callback(defaultValue) + end + end, + }) + :start() end local function loadConfigFromEnv(envName, configName, callback) @@ -264,15 +291,15 @@ local function loadAzureConfigs() if Api["OPENAI_API_BASE"] and Api["OPENAI_API_AZURE_ENGINE"] then Api.COMPLETIONS_URL = Api.OPENAI_API_BASE - .. "/openai/deployments/" - .. Api.OPENAI_API_AZURE_ENGINE - .. "/completions?api-version=" - .. Api.OPENAI_API_AZURE_VERSION + .. "/openai/deployments/" + .. Api.OPENAI_API_AZURE_ENGINE + .. "/completions?api-version=" + .. Api.OPENAI_API_AZURE_VERSION Api.CHAT_COMPLETIONS_URL = Api.OPENAI_API_BASE - .. "/openai/deployments/" - .. Api.OPENAI_API_AZURE_ENGINE - .. "/chat/completions?api-version=" - .. Api.OPENAI_API_AZURE_VERSION + .. "/openai/deployments/" + .. Api.OPENAI_API_AZURE_ENGINE + .. "/chat/completions?api-version=" + .. Api.OPENAI_API_AZURE_VERSION end end, "2023-05-15" From c81ab7604510d8f6f238ad158a0f75460a98df46 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 19:54:01 +0100 Subject: [PATCH 02/22] on opening chat window, the model was not being collapsed for the settings panel. now doing this and testing if it works --- lua/chatgpt/api.lua | 31 ++++--------------------------- lua/chatgpt/flows/chat/base.lua | 3 ++- lua/chatgpt/utils.lua | 24 ++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/lua/chatgpt/api.lua b/lua/chatgpt/api.lua index 0432cc9b..f2bbfefc 100644 --- a/lua/chatgpt/api.lua +++ b/lua/chatgpt/api.lua @@ -1,41 +1,18 @@ local job = require("plenary.job") local Config = require("chatgpt.config") local logger = require("chatgpt.common.logger") +local Utils = require("chatgpt.utils") local Api = {} ----@param tbl table ----@return table -local function table_shallow_copy(tbl) - local copy = {} - for key, value in pairs(tbl) do - copy[key] = value - end - return copy -end - ---- A function that collapses the openai params. ---- This means all the parameters of the openai_params that can be either constants or functions ---- will be set to constants by evaluating the functions. ----@param openai_params table ----@return table -local function collapsed_openai_params(openai_params) - local collapsed = table_shallow_copy(openai_params) - -- use copied version of table so the original model value remains a function and can still change - if type(collapsed.model) == "function" then - collapsed.model = collapsed.model() - end - return collapsed -end - function Api.completions(custom_params, cb) - local openai_params = collapsed_openai_params(Config.options.openai_params) + local openai_params = Utils.collapsed_openai_params(Config.options.openai_params) local params = vim.tbl_extend("keep", custom_params, openai_params) Api.make_call(Api.COMPLETIONS_URL, params, cb) end function Api.chat_completions(custom_params, cb, should_stop) - local openai_params = collapsed_openai_params(Config.options.openai_params) + local openai_params = Utils.collapsed_openai_params(Config.options.openai_params) local params = vim.tbl_extend("keep", custom_params, openai_params) local stream = params.stream or false if stream then @@ -116,7 +93,7 @@ function Api.chat_completions(custom_params, cb, should_stop) end function Api.edits(custom_params, cb) - local openai_params = collapsed_openai_params(Config.options.openai_params) + local openai_params = Utils.collapsed_openai_params(Config.options.openai_params) local params = vim.tbl_extend("keep", custom_params, openai_params) if params.model == "text-davinci-edit-001" or params.model == "code-davinci-edit-001" then vim.notify("Edit models are deprecated", vim.log.levels.WARN) diff --git a/lua/chatgpt/flows/chat/base.lua b/lua/chatgpt/flows/chat/base.lua index f37e1386..bbf3d9ac 100644 --- a/lua/chatgpt/flows/chat/base.lua +++ b/lua/chatgpt/flows/chat/base.lua @@ -736,7 +736,8 @@ function Chat:get_layout_params() end function Chat:open() - self.settings_panel = Settings.get_settings_panel("chat_completions", self.params) + local openai_params = Utils.collapsed_openai_params(self.params) + self.settings_panel = Settings.get_settings_panel("chat_completions", openai_params) self.help_panel = Help.get_help_panel("chat") self.sessions_panel = Sessions.get_panel(function(session) self:set_session(session) diff --git a/lua/chatgpt/utils.lua b/lua/chatgpt/utils.lua index e9b89f32..71ea35e7 100644 --- a/lua/chatgpt/utils.lua +++ b/lua/chatgpt/utils.lua @@ -2,6 +2,30 @@ local M = {} local ESC_FEEDKEY = vim.api.nvim_replace_termcodes("", true, false, true) +---@param tbl table +---@return table +function M.table_shallow_copy(tbl) + local copy = {} + for key, value in pairs(tbl) do + copy[key] = value + end + return copy +end + +--- A function that collapses the openai params. +--- This means all the parameters of the openai_params that can be either constants or functions +--- will be set to constants by evaluating the functions. +---@param openai_params table +---@return table +function M.collapsed_openai_params(openai_params) + local collapsed = M.table_shallow_copy(openai_params) + -- use copied version of table so the original model value remains a function and can still change + if type(collapsed.model) == "function" then + collapsed.model = collapsed.model() + end + return collapsed +end + function M.split(text) local t = {} for str in string.gmatch(text, "%S+") do From e1c5a05ccbcf1911396d83ad65f984330666e222 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 19:58:12 +0100 Subject: [PATCH 03/22] testing using debug output --- lua/chatgpt/settings.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/chatgpt/settings.lua b/lua/chatgpt/settings.lua index fbb55649..08ad2a7b 100644 --- a/lua/chatgpt/settings.lua +++ b/lua/chatgpt/settings.lua @@ -69,6 +69,7 @@ end M.get_settings_panel = function(type, default_params) M.type = type local custom_params = M.read_config() + vim.notify("reading of custom params returned " .. vim.inspect(custom_params)) M.params = vim.tbl_deep_extend("force", {}, default_params, custom_params or {}) M.panel = Popup(Config.options.settings_window) From b5293e43a53e3cac8051b1e23410b1e767170daa Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 19:59:46 +0100 Subject: [PATCH 04/22] removed debug out again because it seems to now work magically? --- lua/chatgpt/settings.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/chatgpt/settings.lua b/lua/chatgpt/settings.lua index 08ad2a7b..35229bb3 100644 --- a/lua/chatgpt/settings.lua +++ b/lua/chatgpt/settings.lua @@ -69,7 +69,7 @@ end M.get_settings_panel = function(type, default_params) M.type = type local custom_params = M.read_config() - vim.notify("reading of custom params returned " .. vim.inspect(custom_params)) + -- vim.notify("reading of custom params returned " .. vim.inspect(custom_params)) M.params = vim.tbl_deep_extend("force", {}, default_params, custom_params or {}) M.panel = Popup(Config.options.settings_window) From 2240812afd410c1d382b17deddc0978652b9407b Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 20:05:36 +0100 Subject: [PATCH 05/22] debugging --- lua/chatgpt/flows/chat/base.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/chatgpt/flows/chat/base.lua b/lua/chatgpt/flows/chat/base.lua index bbf3d9ac..719b3d1e 100644 --- a/lua/chatgpt/flows/chat/base.lua +++ b/lua/chatgpt/flows/chat/base.lua @@ -737,6 +737,7 @@ end function Chat:open() local openai_params = Utils.collapsed_openai_params(self.params) + vim.notify(vim.inspect(openai_params)) self.settings_panel = Settings.get_settings_panel("chat_completions", openai_params) self.help_panel = Help.get_help_panel("chat") self.sessions_panel = Sessions.get_panel(function(session) From 45b4972b730f11384a1824578e031e7e55ecf3f2 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 20:19:44 +0100 Subject: [PATCH 06/22] debugging --- lua/chatgpt/flows/chat/base.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/chatgpt/flows/chat/base.lua b/lua/chatgpt/flows/chat/base.lua index 719b3d1e..47587e63 100644 --- a/lua/chatgpt/flows/chat/base.lua +++ b/lua/chatgpt/flows/chat/base.lua @@ -737,6 +737,7 @@ end function Chat:open() local openai_params = Utils.collapsed_openai_params(self.params) + vim.notify(vim.inspect(self.params)) vim.notify(vim.inspect(openai_params)) self.settings_panel = Settings.get_settings_panel("chat_completions", openai_params) self.help_panel = Help.get_help_panel("chat") From 4373c35521905369f2b6c1674db3ccedbac60999 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 21:10:25 +0100 Subject: [PATCH 07/22] still debugging --- lua/chatgpt/flows/chat/base.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lua/chatgpt/flows/chat/base.lua b/lua/chatgpt/flows/chat/base.lua index 47587e63..4fccbc50 100644 --- a/lua/chatgpt/flows/chat/base.lua +++ b/lua/chatgpt/flows/chat/base.lua @@ -517,7 +517,7 @@ function Chat:toMessages() role = "assistant" end local content = {} - if self.params.model == "gpt-4-vision-preview" then + if Utils.collapsed_openai_params(self.params.model) == "gpt-4-vision-preview" then for _, line in ipairs(msg.lines) do table.insert(content, createContent(line)) end @@ -1029,6 +1029,8 @@ function Chat:open_system_panel() end function Chat:redraw(noinit) + local openai_params = Utils.collapsed_openai_params(self.params) + self.settings_panel = Settings.get_settings_panel("chat_completions", openai_params) noinit = noinit or false self.layout:update(self:get_layout_params()) if not noinit then From 984492c56e167eee8640d8bd51c135c8849666d7 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 21:38:22 +0100 Subject: [PATCH 08/22] if the model is determined by a function, just display in settings menu --- lua/chatgpt/api.lua | 5 +++++ lua/chatgpt/flows/chat/base.lua | 20 ++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lua/chatgpt/api.lua b/lua/chatgpt/api.lua index f2bbfefc..8644e773 100644 --- a/lua/chatgpt/api.lua +++ b/lua/chatgpt/api.lua @@ -14,6 +14,11 @@ end function Api.chat_completions(custom_params, cb, should_stop) local openai_params = Utils.collapsed_openai_params(Config.options.openai_params) local params = vim.tbl_extend("keep", custom_params, openai_params) + -- the custom params contains if model is not constant but function + -- therefore, use collapsed openai params (with function evaluated to get model) if that is the case + if params.model == "" then + params.model = openai_params.model + end local stream = params.stream or false if stream then local raw_chunks = "" diff --git a/lua/chatgpt/flows/chat/base.lua b/lua/chatgpt/flows/chat/base.lua index 4fccbc50..86efdf81 100644 --- a/lua/chatgpt/flows/chat/base.lua +++ b/lua/chatgpt/flows/chat/base.lua @@ -736,10 +736,20 @@ function Chat:get_layout_params() end function Chat:open() - local openai_params = Utils.collapsed_openai_params(self.params) - vim.notify(vim.inspect(self.params)) - vim.notify(vim.inspect(openai_params)) - self.settings_panel = Settings.get_settings_panel("chat_completions", openai_params) + -- local openai_params = Utils.collapsed_openai_params(self.params) + -- vim.notify(vim.inspect(self.params)) + -- vim.notify(vim.inspect(openai_params)) + local displayed_params = Utils.table_shallow_copy(self.params) + -- if the param is decided by a function and not constant, write for now + -- TODO: if the current model should be displayed, the settings_panel would + -- have to be constantly modified or rewritten to be able to manage a function + -- returning the model as well + for value, key in pairs(displayed_params) do + if type(value) == "function" then + displayed_params[key] = "" + end + end + self.settings_panel = Settings.get_settings_panel("chat_completions", displayed_params) self.help_panel = Help.get_help_panel("chat") self.sessions_panel = Sessions.get_panel(function(session) self:set_session(session) @@ -1029,8 +1039,6 @@ function Chat:open_system_panel() end function Chat:redraw(noinit) - local openai_params = Utils.collapsed_openai_params(self.params) - self.settings_panel = Settings.get_settings_panel("chat_completions", openai_params) noinit = noinit or false self.layout:update(self:get_layout_params()) if not noinit then From 04180ba492a1337ecf1e4fd277427c770da481f2 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 21:42:04 +0100 Subject: [PATCH 09/22] debugging --- lua/chatgpt/flows/chat/base.lua | 2 +- lua/chatgpt/settings.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/chatgpt/flows/chat/base.lua b/lua/chatgpt/flows/chat/base.lua index 86efdf81..0541e128 100644 --- a/lua/chatgpt/flows/chat/base.lua +++ b/lua/chatgpt/flows/chat/base.lua @@ -744,7 +744,7 @@ function Chat:open() -- TODO: if the current model should be displayed, the settings_panel would -- have to be constantly modified or rewritten to be able to manage a function -- returning the model as well - for value, key in pairs(displayed_params) do + for value, key in pairs(self.params) do if type(value) == "function" then displayed_params[key] = "" end diff --git a/lua/chatgpt/settings.lua b/lua/chatgpt/settings.lua index 35229bb3..5dc7eaa2 100644 --- a/lua/chatgpt/settings.lua +++ b/lua/chatgpt/settings.lua @@ -69,8 +69,8 @@ end M.get_settings_panel = function(type, default_params) M.type = type local custom_params = M.read_config() - -- vim.notify("reading of custom params returned " .. vim.inspect(custom_params)) M.params = vim.tbl_deep_extend("force", {}, default_params, custom_params or {}) + vim.notify("Settings.params are " .. vim.inspect(M.params)) M.panel = Popup(Config.options.settings_window) From 6f5aa425bb3ac439f9f0d07135b829e1d1c1ba40 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 21:46:01 +0100 Subject: [PATCH 10/22] still debugging --- lua/chatgpt/flows/chat/base.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lua/chatgpt/flows/chat/base.lua b/lua/chatgpt/flows/chat/base.lua index 0541e128..31e1923a 100644 --- a/lua/chatgpt/flows/chat/base.lua +++ b/lua/chatgpt/flows/chat/base.lua @@ -744,11 +744,13 @@ function Chat:open() -- TODO: if the current model should be displayed, the settings_panel would -- have to be constantly modified or rewritten to be able to manage a function -- returning the model as well + vim.notify("Chat.params are " .. vim.inspect(displayed_params) .. " and should equal " .. vim.inspect(self.params)) for value, key in pairs(self.params) do if type(value) == "function" then displayed_params[key] = "" end end + vim.notify("processed displayed_params are " .. vim.inspect(displayed_params)) self.settings_panel = Settings.get_settings_panel("chat_completions", displayed_params) self.help_panel = Help.get_help_panel("chat") self.sessions_panel = Sessions.get_panel(function(session) From d62599aef1294684c7776bd74f6bbbd50e9a5bd6 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 21:48:18 +0100 Subject: [PATCH 11/22] had value, key instead of key, value in a for loop because I dont know lua lmao now testing --- lua/chatgpt/flows/chat/base.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/chatgpt/flows/chat/base.lua b/lua/chatgpt/flows/chat/base.lua index 31e1923a..aefe5c1b 100644 --- a/lua/chatgpt/flows/chat/base.lua +++ b/lua/chatgpt/flows/chat/base.lua @@ -745,7 +745,7 @@ function Chat:open() -- have to be constantly modified or rewritten to be able to manage a function -- returning the model as well vim.notify("Chat.params are " .. vim.inspect(displayed_params) .. " and should equal " .. vim.inspect(self.params)) - for value, key in pairs(self.params) do + for key, value in pairs(self.params) do if type(value) == "function" then displayed_params[key] = "" end From 43dbe14086b332e2205328d3b1ed1e220d993d37 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 21:50:32 +0100 Subject: [PATCH 12/22] seems to be working, testing it now --- lua/chatgpt/flows/chat/base.lua | 5 ----- lua/chatgpt/settings.lua | 1 - 2 files changed, 6 deletions(-) diff --git a/lua/chatgpt/flows/chat/base.lua b/lua/chatgpt/flows/chat/base.lua index aefe5c1b..c0fdebbf 100644 --- a/lua/chatgpt/flows/chat/base.lua +++ b/lua/chatgpt/flows/chat/base.lua @@ -736,21 +736,16 @@ function Chat:get_layout_params() end function Chat:open() - -- local openai_params = Utils.collapsed_openai_params(self.params) - -- vim.notify(vim.inspect(self.params)) - -- vim.notify(vim.inspect(openai_params)) local displayed_params = Utils.table_shallow_copy(self.params) -- if the param is decided by a function and not constant, write for now -- TODO: if the current model should be displayed, the settings_panel would -- have to be constantly modified or rewritten to be able to manage a function -- returning the model as well - vim.notify("Chat.params are " .. vim.inspect(displayed_params) .. " and should equal " .. vim.inspect(self.params)) for key, value in pairs(self.params) do if type(value) == "function" then displayed_params[key] = "" end end - vim.notify("processed displayed_params are " .. vim.inspect(displayed_params)) self.settings_panel = Settings.get_settings_panel("chat_completions", displayed_params) self.help_panel = Help.get_help_panel("chat") self.sessions_panel = Sessions.get_panel(function(session) diff --git a/lua/chatgpt/settings.lua b/lua/chatgpt/settings.lua index 5dc7eaa2..fbb55649 100644 --- a/lua/chatgpt/settings.lua +++ b/lua/chatgpt/settings.lua @@ -70,7 +70,6 @@ M.get_settings_panel = function(type, default_params) M.type = type local custom_params = M.read_config() M.params = vim.tbl_deep_extend("force", {}, default_params, custom_params or {}) - vim.notify("Settings.params are " .. vim.inspect(M.params)) M.panel = Popup(Config.options.settings_window) From ef700387c8fb99bc88e072cedbdc6e5156ff3a7e Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 21:51:57 +0100 Subject: [PATCH 13/22] debug output for model --- lua/chatgpt/api.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/chatgpt/api.lua b/lua/chatgpt/api.lua index 8644e773..e6f15691 100644 --- a/lua/chatgpt/api.lua +++ b/lua/chatgpt/api.lua @@ -19,6 +19,7 @@ function Api.chat_completions(custom_params, cb, should_stop) if params.model == "" then params.model = openai_params.model end + vim.notify("Sending request with model " .. params.model) local stream = params.stream or false if stream then local raw_chunks = "" From bad2508843dfc1bc16358f2e51db1c65348e23cd Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 21:54:45 +0100 Subject: [PATCH 14/22] typo in toMessages function in settings.lua, fixed now --- lua/chatgpt/flows/chat/base.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/chatgpt/flows/chat/base.lua b/lua/chatgpt/flows/chat/base.lua index c0fdebbf..4387bdc2 100644 --- a/lua/chatgpt/flows/chat/base.lua +++ b/lua/chatgpt/flows/chat/base.lua @@ -517,7 +517,7 @@ function Chat:toMessages() role = "assistant" end local content = {} - if Utils.collapsed_openai_params(self.params.model) == "gpt-4-vision-preview" then + if Utils.collapsed_openai_params(self.params).model == "gpt-4-vision-preview" then for _, line in ipairs(msg.lines) do table.insert(content, createContent(line)) end From 64ec8023315119b1c3dad6f573e330f95682aaad Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 21:59:40 +0100 Subject: [PATCH 15/22] more debugging --- lua/chatgpt/api.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/chatgpt/api.lua b/lua/chatgpt/api.lua index e6f15691..4440c227 100644 --- a/lua/chatgpt/api.lua +++ b/lua/chatgpt/api.lua @@ -19,7 +19,7 @@ function Api.chat_completions(custom_params, cb, should_stop) if params.model == "" then params.model = openai_params.model end - vim.notify("Sending request with model " .. params.model) + vim.notify("Sending request with model " .. params.model .. " (openai model is " .. openai_params.model .. ")") local stream = params.stream or false if stream then local raw_chunks = "" From a38eca74bcbfa7ef0b4882092e0ea29a4f11f7e9 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 22:03:41 +0100 Subject: [PATCH 16/22] still debugging :( --- lua/chatgpt/utils.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lua/chatgpt/utils.lua b/lua/chatgpt/utils.lua index 71ea35e7..ce2fe1a2 100644 --- a/lua/chatgpt/utils.lua +++ b/lua/chatgpt/utils.lua @@ -20,9 +20,12 @@ end function M.collapsed_openai_params(openai_params) local collapsed = M.table_shallow_copy(openai_params) -- use copied version of table so the original model value remains a function and can still change + vim.notify("collapsing openai params: params " .. openai_params) if type(collapsed.model) == "function" then collapsed.model = collapsed.model() end + vim.notify("collapsing openai params: collapsed" .. collapsed) + vim.notify("collapsing openai params: params now" .. openai_params) return collapsed end From 2f4ff37b2ed8cf4beef94b5dcaacabea446d4bc7 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 22:05:27 +0100 Subject: [PATCH 17/22] vim.inspect missing --- lua/chatgpt/utils.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lua/chatgpt/utils.lua b/lua/chatgpt/utils.lua index ce2fe1a2..b73b91ab 100644 --- a/lua/chatgpt/utils.lua +++ b/lua/chatgpt/utils.lua @@ -20,12 +20,12 @@ end function M.collapsed_openai_params(openai_params) local collapsed = M.table_shallow_copy(openai_params) -- use copied version of table so the original model value remains a function and can still change - vim.notify("collapsing openai params: params " .. openai_params) + vim.notify("collapsing openai params: params " .. vim.inspect(openai_params)) if type(collapsed.model) == "function" then collapsed.model = collapsed.model() end - vim.notify("collapsing openai params: collapsed" .. collapsed) - vim.notify("collapsing openai params: params now" .. openai_params) + vim.notify("collapsing openai params: collapsed" .. vim.inspect(collapsed)) + vim.notify("collapsing openai params: params now" .. vim.inspect(openai_params)) return collapsed end From fe2560326c9e71de4729ec27acd0a2973085cb6d Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 22:21:13 +0100 Subject: [PATCH 18/22] the plugin is tested and working, you can now switch models dynamically and if this is enabled, it will say in the chat settings. the completion features etc have not been tested with the changes, but they should be unaffected as I did not touch the openai_completion_params etc, only openai_params. if you want to see currently active model, add a shortcut to your config (because your config manages the model) --- lua/chatgpt/utils.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/lua/chatgpt/utils.lua b/lua/chatgpt/utils.lua index b73b91ab..71ea35e7 100644 --- a/lua/chatgpt/utils.lua +++ b/lua/chatgpt/utils.lua @@ -20,12 +20,9 @@ end function M.collapsed_openai_params(openai_params) local collapsed = M.table_shallow_copy(openai_params) -- use copied version of table so the original model value remains a function and can still change - vim.notify("collapsing openai params: params " .. vim.inspect(openai_params)) if type(collapsed.model) == "function" then collapsed.model = collapsed.model() end - vim.notify("collapsing openai params: collapsed" .. vim.inspect(collapsed)) - vim.notify("collapsing openai params: params now" .. vim.inspect(openai_params)) return collapsed end From 295e26fcd35bf418d91a284ad1e2820914ecf896 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 22:34:57 +0100 Subject: [PATCH 19/22] reformatted the config sample to be more readable. you can now pass a function as model to change the model used on the fly --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d9523557..533250a7 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,13 @@ A simple configuration of the chat model could look something like this: -- this is useful if you want to change the model on the fly -- using commands -- Example: - -- model = function() if some_condition() then return "gpt-4-1106-preview" else return "gpt-3.5-turbo" end end + -- model = function() + -- if some_condition() then + -- return "gpt-4-1106-preview" + -- else + -- return "gpt-3.5-turbo" + -- end + -- end, model = "gpt-4-1106-preview", frequency_penalty = 0, presence_penalty = 0, From 2955f4f2ff4bb3fd7b41498b12ad54ac55c9949a Mon Sep 17 00:00:00 2001 From: barnii77 Date: Sat, 23 Mar 2024 22:36:47 +0100 Subject: [PATCH 20/22] finally, removed all debug notifications --- lua/chatgpt/api.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/chatgpt/api.lua b/lua/chatgpt/api.lua index 4440c227..8644e773 100644 --- a/lua/chatgpt/api.lua +++ b/lua/chatgpt/api.lua @@ -19,7 +19,6 @@ function Api.chat_completions(custom_params, cb, should_stop) if params.model == "" then params.model = openai_params.model end - vim.notify("Sending request with model " .. params.model .. " (openai model is " .. openai_params.model .. ")") local stream = params.stream or false if stream then local raw_chunks = "" From 47701e11a8ea0620dadc5d72cfedfac29d78dd18 Mon Sep 17 00:00:00 2001 From: Paper <118065958+PaperTarsier692@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:23:13 +0100 Subject: [PATCH 21/22] Update api.lua --- lua/chatgpt/api.lua | 76 ++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/lua/chatgpt/api.lua b/lua/chatgpt/api.lua index 8644e773..a557fdaa 100644 --- a/lua/chatgpt/api.lua +++ b/lua/chatgpt/api.lua @@ -70,11 +70,11 @@ function Api.chat_completions(custom_params, cb, should_stop) }) if ok and json ~= nil then if - json - and json.choices - and json.choices[1] - and json.choices[1].delta - and json.choices[1].delta.content + json + and json.choices + and json.choices[1] + and json.choices[1].delta + and json.choices[1].delta.content then cb(json.choices[1].delta.content, state) raw_chunks = raw_chunks .. json.choices[1].delta.content @@ -137,14 +137,14 @@ function Api.make_call(url, params, cb) end Api.job = job - :new({ - command = "curl", - args = args, - on_exit = vim.schedule_wrap(function(response, exit_code) - Api.handle_response(response, exit_code, cb) - end), - }) - :start() + :new({ + command = "curl", + args = args, + on_exit = vim.schedule_wrap(function(response, exit_code) + Api.handle_response(response, exit_code, cb) + end), + }) + :start() end Api.handle_response = vim.schedule_wrap(function(response, exit_code, cb) @@ -203,23 +203,23 @@ end local function loadConfigFromCommand(command, optionName, callback, defaultValue) local cmd = splitCommandIntoTable(command) job - :new({ - command = cmd[1], - args = vim.list_slice(cmd, 2, #cmd), - on_exit = function(j, exit_code) - if exit_code ~= 0 then - logger.warn("Config '" .. optionName .. "' did not return a value when executed") - return - end - local value = j:result()[1]:gsub("%s+$", "") - if value ~= nil and value ~= "" then - callback(value) - elseif defaultValue ~= nil and defaultValue ~= "" then - callback(defaultValue) - end - end, - }) - :start() + :new({ + command = cmd[1], + args = vim.list_slice(cmd, 2, #cmd), + on_exit = function(j, exit_code) + if exit_code ~= 0 then + logger.warn("Config '" .. optionName .. "' did not return a value when executed") + return + end + local value = j:result()[1]:gsub("%s+$", "") + if value ~= nil and value ~= "" then + callback(value) + elseif defaultValue ~= nil and defaultValue ~= "" then + callback(defaultValue) + end + end, + }) + :start() end local function loadConfigFromEnv(envName, configName, callback) @@ -273,15 +273,15 @@ local function loadAzureConfigs() if Api["OPENAI_API_BASE"] and Api["OPENAI_API_AZURE_ENGINE"] then Api.COMPLETIONS_URL = Api.OPENAI_API_BASE - .. "/openai/deployments/" - .. Api.OPENAI_API_AZURE_ENGINE - .. "/completions?api-version=" - .. Api.OPENAI_API_AZURE_VERSION + .. "/openai/deployments/" + .. Api.OPENAI_API_AZURE_ENGINE + .. "/completions?api-version=" + .. Api.OPENAI_API_AZURE_VERSION Api.CHAT_COMPLETIONS_URL = Api.OPENAI_API_BASE - .. "/openai/deployments/" - .. Api.OPENAI_API_AZURE_ENGINE - .. "/chat/completions?api-version=" - .. Api.OPENAI_API_AZURE_VERSION + .. "/openai/deployments/" + .. Api.OPENAI_API_AZURE_ENGINE + .. "/chat/completions?api-version=" + .. Api.OPENAI_API_AZURE_VERSION end end, "2023-05-15" From 62fc6fbb976688a51ca4db888ed90de7a35e4903 Mon Sep 17 00:00:00 2001 From: barnii77 Date: Fri, 29 Mar 2024 11:21:31 +0100 Subject: [PATCH 22/22] removed a goto statement by refactoring the code because goto does not work for some stylua versions and that's really annoying and unnecessary --- lua/chatgpt/code_edits.lua | 93 ++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/lua/chatgpt/code_edits.lua b/lua/chatgpt/code_edits.lua index 1b02a830..659c2f25 100644 --- a/lua/chatgpt/code_edits.lua +++ b/lua/chatgpt/code_edits.lua @@ -350,57 +350,54 @@ M.edit_with_instructions = function(output_lines, bufnr, selection, ...) -- cycle windows for _, popup in ipairs({ input_window, output_window, settings_panel, help_panel, instructions_input }) do for _, mode in ipairs({ "n", "i" }) do - if mode == "i" and (popup == input_window or popup == output_window) then - goto continue - end - - popup:map(mode, Config.options.edit_with_instructions.keymaps.cycle_windows, function() - -- #352 is a bug where active_panel is something not in here, maybe an - -- old window or something, lost amongst the global state - local possible_windows = { - input_window, - output_window, - settings_panel, - help_panel, - instructions_input, - unpack(open_extra_panels), - } - - -- So if active_panel isn't something we expect it to be, make it do be. - if not inTable(possible_windows, active_panel) then - active_panel = instructions_input - end - - local active_panel_is_in_extra_panels = inTable(open_extra_panels, active_panel) - if active_panel == instructions_input then - vim.api.nvim_set_current_win(input_window.winid) - active_panel = input_window - vim.api.nvim_command("stopinsert") - elseif active_panel == input_window and mode ~= "i" then - vim.api.nvim_set_current_win(output_window.winid) - active_panel = output_window - vim.api.nvim_command("stopinsert") - elseif active_panel == output_window and mode ~= "i" then - if #open_extra_panels == 0 then - vim.api.nvim_set_current_win(instructions_input.winid) + if not (mode == "i" and (popup == input_window or popup == output_window)) then + popup:map(mode, Config.options.edit_with_instructions.keymaps.cycle_windows, function() + -- #352 is a bug where active_panel is something not in here, maybe an + -- old window or something, lost amongst the global state + local possible_windows = { + input_window, + output_window, + settings_panel, + help_panel, + instructions_input, + unpack(open_extra_panels), + } + + -- So if active_panel isn't something we expect it to be, make it do be. + if not inTable(possible_windows, active_panel) then active_panel = instructions_input - else - vim.api.nvim_set_current_win(open_extra_panels[1].winid) - active_panel = open_extra_panels[1] end - elseif active_panel_is_in_extra_panels then - -- next index with wrap around and 0 for instructions_input - local next_index = (active_panel_is_in_extra_panels + 1) % (#open_extra_panels + 1) - if next_index == 0 then - vim.api.nvim_set_current_win(instructions_input.winid) - active_panel = instructions_input - else - vim.api.nvim_set_current_win(open_extra_panels[next_index].winid) - active_panel = open_extra_panels[next_index] + + local active_panel_is_in_extra_panels = inTable(open_extra_panels, active_panel) + if active_panel == instructions_input then + vim.api.nvim_set_current_win(input_window.winid) + active_panel = input_window + vim.api.nvim_command("stopinsert") + elseif active_panel == input_window and mode ~= "i" then + vim.api.nvim_set_current_win(output_window.winid) + active_panel = output_window + vim.api.nvim_command("stopinsert") + elseif active_panel == output_window and mode ~= "i" then + if #open_extra_panels == 0 then + vim.api.nvim_set_current_win(instructions_input.winid) + active_panel = instructions_input + else + vim.api.nvim_set_current_win(open_extra_panels[1].winid) + active_panel = open_extra_panels[1] + end + elseif active_panel_is_in_extra_panels then + -- next index with wrap around and 0 for instructions_input + local next_index = (active_panel_is_in_extra_panels + 1) % (#open_extra_panels + 1) + if next_index == 0 then + vim.api.nvim_set_current_win(instructions_input.winid) + active_panel = instructions_input + else + vim.api.nvim_set_current_win(open_extra_panels[next_index].winid) + active_panel = open_extra_panels[next_index] + end end - end - end, {}) - ::continue:: + end, {}) + end end end