From 1bc14ae26a735c6593a3da0605d78aa21296e17c Mon Sep 17 00:00:00 2001 From: Tibor Schmidt Date: Fri, 12 Jul 2024 08:55:27 +0200 Subject: [PATCH 01/23] fix: nil err for healthcheck if oai key missing --- lua/gp/config.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/gp/config.lua b/lua/gp/config.lua index 013d6a6f..2a317584 100644 --- a/lua/gp/config.lua +++ b/lua/gp/config.lua @@ -460,7 +460,7 @@ local config = { InspectPlugin = function(plugin, params) local bufnr = vim.api.nvim_create_buf(false, true) local copy = vim.deepcopy(plugin) - local key = copy.config.openai_api_key + local key = copy.config.openai_api_key or "" copy.config.openai_api_key = key:sub(1, 3) .. string.rep("*", #key - 6) .. key:sub(-3) for provider, _ in pairs(copy.providers) do local s = copy.providers[provider].secret From 30cb8b491971ea219ade92ab90f58e2aefda6d31 Mon Sep 17 00:00:00 2001 From: Tibor Schmidt Date: Fri, 12 Jul 2024 10:57:08 +0200 Subject: [PATCH 02/23] feat: disable flag for agents and providers (resolve: #120) --- lua/gp/config.lua | 56 ++++++++++++++++++++++++++++++----------------- lua/gp/init.lua | 30 ++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 23 deletions(-) diff --git a/lua/gp/config.lua b/lua/gp/config.lua index 2a317584..0c3db2a1 100644 --- a/lua/gp/config.lua +++ b/lua/gp/config.lua @@ -41,38 +41,46 @@ local config = { -- secret : "sk-...", -- secret = os.getenv("env_name.."), openai = { + disable = false, endpoint = "https://api.openai.com/v1/chat/completions", -- secret = os.getenv("OPENAI_API_KEY"), }, azure = { - -- endpoint = "https://$URL.openai.azure.com/openai/deployments/{{model}}/chat/completions", - -- secret = os.getenv("AZURE_API_KEY"), + disable = true, + endpoint = "https://$URL.openai.azure.com/openai/deployments/{{model}}/chat/completions", + secret = os.getenv("AZURE_API_KEY"), }, copilot = { - -- endpoint = "https://api.githubcopilot.com/chat/completions", - -- secret = { - -- "bash", - -- "-c", - -- "cat ~/.config/github-copilot/hosts.json | sed -e 's/.*oauth_token...//;s/\".*//'", - -- }, + disable = true, + endpoint = "https://api.githubcopilot.com/chat/completions", + secret = { + "bash", + "-c", + "cat ~/.config/github-copilot/hosts.json | sed -e 's/.*oauth_token...//;s/\".*//'", + }, }, ollama = { - -- endpoint = "http://localhost:11434/v1/chat/completions", + disable = true, + endpoint = "http://localhost:11434/v1/chat/completions", }, lmstudio = { - -- endpoint = "http://localhost:1234/v1/chat/completions", + disable = true, + endpoint = "http://localhost:1234/v1/chat/completions", }, googleai = { - -- endpoint = "https://generativelanguage.googleapis.com/v1beta/models/{{model}}:streamGenerateContent?key={{secret}}", - -- secret = os.getenv("GOOGLEAI_API_KEY"), + disable = true, + endpoint = "https://generativelanguage.googleapis.com/v1beta/models/{{model}}:streamGenerateContent?key={{secret}}", + secret = os.getenv("GOOGLEAI_API_KEY"), }, pplx = { - -- endpoint = "https://api.perplexity.ai/chat/completions", - -- secret = os.getenv("PPLX_API_KEY"), + disable = true, + endpoint = "https://api.perplexity.ai/chat/completions", + secret = os.getenv("PPLX_API_KEY"), }, anthropic = { - -- endpoint = "https://api.anthropic.com/v1/messages", - -- secret = os.getenv("ANTHROPIC_API_KEY"), + disable = true, + endpoint = "https://api.anthropic.com/v1/messages", + secret = os.getenv("ANTHROPIC_API_KEY"), }, }, @@ -88,9 +96,13 @@ local config = { -- default command agents (model + persona) -- name, model and system_prompt are mandatory fields -- to use agent for chat set chat = true, for command set command = true - -- to remove some default agent completely set it just with the name like: - -- agents = { { name = "ChatGPT4" }, ... }, + -- to remove some default agent completely set it like: + -- agents = { { name = "ChatGPT3-5", disable = true, }, ... }, agents = { + { + name = "ExampleDisabledAgent", + disable = true, + }, { name = "ChatGPT4o", chat = true, @@ -366,9 +378,13 @@ local config = { -- default folder for saving images image_dir = (os.getenv("TMPDIR") or os.getenv("TEMP") or "/tmp") .. "/gp_images", -- default image agents (model + settings) - -- to remove some default agent completely set it just with the name like: - -- image_agents = { { name = "DALL-E-3-1024x1792-vivid" }, ... }, + -- to remove some default agent completely set it like: + -- image_agents = { { name = "DALL-E-3-1024x1792-vivid", disable = true, }, ... }, image_agents = { + { + name = "ExampleDisabledAgent", + disable = true, + }, { name = "DALL-E-3-1024x1024-vivid", model = "dall-e-3", diff --git a/lua/gp/init.lua b/lua/gp/init.lua index c7ae41ba..464db5e1 100644 --- a/lua/gp/init.lua +++ b/lua/gp/init.lua @@ -762,6 +762,7 @@ M.setup = function(opts) M[tbl][k] = v elseif tbl == "providers" then M[tbl][k] = M[tbl][k] or {} + M[tbl][k].disable = false for pk, pv in pairs(v) do M[tbl][k][pk] = pv end @@ -817,20 +818,43 @@ M.setup = function(opts) -- remove invalid agents for name, agent in pairs(M.agents) do - if type(agent) ~= "table" or not agent.model or not agent.system_prompt then + if type(agent) ~= "table" or agent.disable then + M.agents[name] = nil + elseif not agent.model or not agent.system_prompt then + M.warning( + "Agent " + .. name + .. " is missing model or system_prompt\n" + .. "If you want to disable an agent, use: { name = '" + .. name + .. "', disable = true }," + ) M.agents[name] = nil end end for name, agent in pairs(M.image_agents) do - if type(agent) ~= "table" or not agent.model then + if type(agent) ~= "table" or agent.disable then + M.image_agents[name] = nil + elseif not agent.model then + M.warning( + "Image agent " + .. name + .. " is missing model\n" + .. "If you want to disable an agent, use: { name = '" + .. name + .. "', disable = true }," + ) M.image_agents[name] = nil end end -- remove invalid providers for name, provider in pairs(M.providers) do - if type(provider) ~= "table" or not provider.endpoint then + if type(provider) ~= "table" or provider.disable then + M.providers[name] = nil + elseif not provider.endpoint then + M.warning("Provider " .. name .. " is missing endpoint") M.providers[name] = nil end end From 570d1d4000c194a8a9ce728b9575b6bd65c02bd3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 12 Jul 2024 08:57:49 +0000 Subject: [PATCH 03/23] chore: auto-generate vimdoc --- doc/gp.nvim.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gp.nvim.txt b/doc/gp.nvim.txt index 7a325b1c..c3c9f0b8 100644 --- a/doc/gp.nvim.txt +++ b/doc/gp.nvim.txt @@ -1,4 +1,4 @@ -*gp.nvim.txt* For NVIM v0.8.0 Last change: 2024 July 09 +*gp.nvim.txt* For NVIM v0.8.0 Last change: 2024 July 12 ============================================================================== Table of Contents *gp.nvim-table-of-contents* From f0bbf1e226a3f0aa6d0d31ee2072981a69ca1937 Mon Sep 17 00:00:00 2001 From: Tibor Schmidt Date: Fri, 12 Jul 2024 11:15:07 +0200 Subject: [PATCH 04/23] fix: undefined provider in M.prompt (resolve: #149, resolve: #147) --- lua/gp/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/gp/init.lua b/lua/gp/init.lua index 464db5e1..51e372c5 100644 --- a/lua/gp/init.lua +++ b/lua/gp/init.lua @@ -3166,7 +3166,7 @@ M.Prompt = function(params, target, prompt, model, template, system_template, wh local agent = M.get_command_agent() M.query( buf, - provider, + provider or agent.provider, M.prepare_payload(messages, model, agent.model, agent.provider), handler, vim.schedule_wrap(function(qid) From ed48d69d87814541765ef282fc2fe1fd2e2ff6f7 Mon Sep 17 00:00:00 2001 From: exosyphon Date: Mon, 15 Jul 2024 09:25:26 -0500 Subject: [PATCH 05/23] chore: fix spelling of the word bellow to below (#151) --- README.md | 6 +++--- doc/gp.nvim.txt | 6 +++--- lua/gp/config.lua | 2 +- lua/gp/init.lua | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 99f6e456..e96fb6aa 100644 --- a/README.md +++ b/README.md @@ -207,7 +207,7 @@ Voice commands (`:GpWhisper*`) depend on `SoX` (Sound eXchange) to handle audio ## 5. Configuration -Bellow is a linked snippet with the default values, but I suggest starting with minimal config possible (just `openai_api_key` if you don't have `OPENAI_API_KEY` env set up). Defaults change over time to improve things, options might get deprecated and so on - it's better to change only things where the default doesn't fit your needs. +Below is a linked snippet with the default values, but I suggest starting with minimal config possible (just `openai_api_key` if you don't have `OPENAI_API_KEY` env set up). Defaults change over time to improve things, options might get deprecated and so on - it's better to change only things where the default doesn't fit your needs. https://github.com/Robitx/gp.nvim/blob/d90816b2e9185202d72f7b1346b6d33b36350886/lua/gp/config.lua#L8-L355 @@ -463,7 +463,7 @@ Ahoy there! # Shortcuts -There are no default global shortcuts to mess with your own config. Bellow are examples for you to adjust or just use directly. +There are no default global shortcuts to mess with your own config. Below are examples for you to adjust or just use directly. ## Native @@ -878,7 +878,7 @@ The raw plugin text editing method `Prompt` has seven aprameters: - `template` - template of the user message send to gpt - - string can include variables bellow: + - string can include variables below: | name | Description | | --------------- | --------------------------------- | diff --git a/doc/gp.nvim.txt b/doc/gp.nvim.txt index c3c9f0b8..417b2c74 100644 --- a/doc/gp.nvim.txt +++ b/doc/gp.nvim.txt @@ -245,7 +245,7 @@ recording and processing: 5. CONFIGURATION *gp.nvim-5.-configuration* -Bellow is a linked snippet with the default values, but I suggest starting with +Below is a linked snippet with the default values, but I suggest starting with minimal config possible (just `openai_api_key` if you don’t have `OPENAI_API_KEY` env set up). Defaults change over time to improve things, options might get deprecated and so on - it’s better to change only things @@ -601,7 +601,7 @@ resulting `test` file: ============================================================================== 4. Shortcuts *gp.nvim-shortcuts* -There are no default global shortcuts to mess with your own config. Bellow are +There are no default global shortcuts to mess with your own config. Below are examples for you to adjust or just use directly. @@ -1008,7 +1008,7 @@ The raw plugin text editing method `Prompt` has seven aprameters: - see gpt model overview - `template` - template of the user message send to gpt - - string can include variables bellow: + - string can include variables below: name Description --------------- ----------------------------------- {{filetype}} filetype of the current buffer diff --git a/lua/gp/config.lua b/lua/gp/config.lua index 0c3db2a1..cdff2382 100644 --- a/lua/gp/config.lua +++ b/lua/gp/config.lua @@ -321,7 +321,7 @@ local config = { style_popup_margin_top = 2, style_popup_max_width = 160, - -- command config and templates bellow are used by commands like GpRewrite, GpEnew, etc. + -- command config and templates below are used by commands like GpRewrite, GpEnew, etc. -- command prompt prefix for asking user for input (supports {{agent}} template variable) command_prompt_prefix_template = "πŸ€– {{agent}} ~ ", -- auto select command response (easier chaining of commands) diff --git a/lua/gp/init.lua b/lua/gp/init.lua index 51e372c5..68755eaf 100644 --- a/lua/gp/init.lua +++ b/lua/gp/init.lua @@ -2881,7 +2881,7 @@ M.cmd.Context = function(params) end if vim.fn.filereadable(file_name) ~= 1 then - vim.fn.writefile({ "Additional context is provided bellow.", "" }, file_name) + vim.fn.writefile({ "Additional context is provided below.", "" }, file_name) end params.args = params.args or "" From 87c94be8263da7b7ed517f654ac8e7dac37add82 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 15 Jul 2024 14:25:49 +0000 Subject: [PATCH 06/23] chore: auto-generate vimdoc --- doc/gp.nvim.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gp.nvim.txt b/doc/gp.nvim.txt index 417b2c74..36079efd 100644 --- a/doc/gp.nvim.txt +++ b/doc/gp.nvim.txt @@ -1,4 +1,4 @@ -*gp.nvim.txt* For NVIM v0.8.0 Last change: 2024 July 12 +*gp.nvim.txt* For NVIM v0.8.0 Last change: 2024 July 15 ============================================================================== Table of Contents *gp.nvim-table-of-contents* From 34094879c4ea9f654245cb70dc011c57151f4a94 Mon Sep 17 00:00:00 2001 From: Tibor Schmidt Date: Mon, 15 Jul 2024 22:59:37 +0200 Subject: [PATCH 07/23] feat: add claude 3.5 sonnet among default agents --- lua/gp/config.lua | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lua/gp/config.lua b/lua/gp/config.lua index cdff2382..493c15c1 100644 --- a/lua/gp/config.lua +++ b/lua/gp/config.lua @@ -152,6 +152,16 @@ local config = { -- system prompt (use this to specify the persona/role of the AI) system_prompt = default_chat_system_prompt, }, + { + provider = "anthropic", + name = "ChatClaude-3-5-Sonnet", + chat = true, + command = false, + -- string with model name or table with model name and parameters + model = { model = "claude-3-5-sonnet-20240620", temperature = 0.8, top_p = 1 }, + -- system prompt (use this to specify the persona/role of the AI) + system_prompt = default_chat_system_prompt, + }, { provider = "anthropic", name = "ChatClaude-3-Haiku", @@ -238,6 +248,15 @@ local config = { model = { model = "mixtral-8x7b-instruct", temperature = 0.8, top_p = 1 }, system_prompt = default_code_system_prompt, }, + { + provider = "anthropic", + name = "CodeClaude-3-5-Sonnet", + chat = false, + command = true, + -- string with model name or table with model name and parameters + model = { model = "claude-3-5-sonnet-20240620", temperature = 0.8, top_p = 1 }, + system_prompt = default_code_system_prompt, + }, { provider = "anthropic", name = "CodeClaude-3-Haiku", From 44864c964cb62571778acf8fce6a9aa06a733449 Mon Sep 17 00:00:00 2001 From: Tibor Schmidt Date: Tue, 16 Jul 2024 11:01:50 +0200 Subject: [PATCH 08/23] docs: fix config reference in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e96fb6aa..a9fca2d1 100644 --- a/README.md +++ b/README.md @@ -209,7 +209,7 @@ Voice commands (`:GpWhisper*`) depend on `SoX` (Sound eXchange) to handle audio Below is a linked snippet with the default values, but I suggest starting with minimal config possible (just `openai_api_key` if you don't have `OPENAI_API_KEY` env set up). Defaults change over time to improve things, options might get deprecated and so on - it's better to change only things where the default doesn't fit your needs. -https://github.com/Robitx/gp.nvim/blob/d90816b2e9185202d72f7b1346b6d33b36350886/lua/gp/config.lua#L8-L355 +https://github.com/Robitx/gp.nvim/blob/2169a731aec0108ad545b68bd95ef705e6c0e27b/lua/gp/config.lua#L8-L569 # Usage From 3adf3dc7589f54cf7af887879c995aa9846aace5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 16 Jul 2024 09:02:15 +0000 Subject: [PATCH 09/23] chore: auto-generate vimdoc --- doc/gp.nvim.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/gp.nvim.txt b/doc/gp.nvim.txt index 36079efd..3571eb60 100644 --- a/doc/gp.nvim.txt +++ b/doc/gp.nvim.txt @@ -1,4 +1,4 @@ -*gp.nvim.txt* For NVIM v0.8.0 Last change: 2024 July 15 +*gp.nvim.txt* For NVIM v0.8.0 Last change: 2024 July 16 ============================================================================== Table of Contents *gp.nvim-table-of-contents* @@ -252,7 +252,7 @@ options might get deprecated and so on - it’s better to change only things where the default doesn’t fit your needs. -https://github.com/Robitx/gp.nvim/blob/d90816b2e9185202d72f7b1346b6d33b36350886/lua/gp/config.lua#L8-L355 +https://github.com/Robitx/gp.nvim/blob/2169a731aec0108ad545b68bd95ef705e6c0e27b/lua/gp/config.lua#L8-L569 ============================================================================== From fb1a42831ba469a2024c2364ba691478acafc009 Mon Sep 17 00:00:00 2001 From: Tibor Schmidt Date: Tue, 16 Jul 2024 11:04:27 +0200 Subject: [PATCH 10/23] docs: fix to local blob id --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a9fca2d1..5dc79c68 100644 --- a/README.md +++ b/README.md @@ -209,7 +209,7 @@ Voice commands (`:GpWhisper*`) depend on `SoX` (Sound eXchange) to handle audio Below is a linked snippet with the default values, but I suggest starting with minimal config possible (just `openai_api_key` if you don't have `OPENAI_API_KEY` env set up). Defaults change over time to improve things, options might get deprecated and so on - it's better to change only things where the default doesn't fit your needs. -https://github.com/Robitx/gp.nvim/blob/2169a731aec0108ad545b68bd95ef705e6c0e27b/lua/gp/config.lua#L8-L569 +https://github.com/Robitx/gp.nvim/blob/3adf3dc7589f54cf7af887879c995aa9846aace5/lua/gp/config.lua#L8-L568 # Usage From 0878f2fcc319ad0c5bd02d35b082becdc0666ad3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 16 Jul 2024 09:04:48 +0000 Subject: [PATCH 11/23] chore: auto-generate vimdoc --- doc/gp.nvim.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gp.nvim.txt b/doc/gp.nvim.txt index 3571eb60..58eaeace 100644 --- a/doc/gp.nvim.txt +++ b/doc/gp.nvim.txt @@ -252,7 +252,7 @@ options might get deprecated and so on - it’s better to change only things where the default doesn’t fit your needs. -https://github.com/Robitx/gp.nvim/blob/2169a731aec0108ad545b68bd95ef705e6c0e27b/lua/gp/config.lua#L8-L569 +https://github.com/Robitx/gp.nvim/blob/3adf3dc7589f54cf7af887879c995aa9846aace5/lua/gp/config.lua#L8-L568 ============================================================================== From 272eee103b5d426b2fd203db0c8082536c50d136 Mon Sep 17 00:00:00 2001 From: Tibor Schmidt Date: Wed, 17 Jul 2024 08:04:54 +0200 Subject: [PATCH 12/23] feat: simplify Prompt function signature --- lua/gp/init.lua | 77 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/lua/gp/init.lua b/lua/gp/init.lua index 68755eaf..0e946d37 100644 --- a/lua/gp/init.lua +++ b/lua/gp/init.lua @@ -1144,16 +1144,7 @@ M.prepare_commands = function() template = M.config.template_prepend end end - M.Prompt( - params, - target, - agent.cmd_prefix, - agent.model, - template, - agent.system_prompt, - whisper, - agent.provider - ) + M.Prompt(params, target, agent, template, agent.cmd_prefix, whisper) end M.cmd[command] = function(params) @@ -1179,12 +1170,9 @@ M.call_hook = function(name, params) end ---@param messages table ----@param model string | table | nil ----@param default_model string | table +---@param model string | table ---@param provider string | nil -M.prepare_payload = function(messages, model, default_model, provider) - model = model or default_model - +M.prepare_payload = function(messages, model, provider) if type(model) == "string" then return { model = model, @@ -1724,7 +1712,7 @@ M.not_chat = function(buf, file_name) end local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, false) - if #lines < 4 then + if #lines < 7 then return "file too short" end @@ -1732,9 +1720,17 @@ M.not_chat = function(buf, file_name) return "missing topic header" end - if not (lines[3]:match("^- file: ") or lines[4]:match("^- file: ")) then + local header_found = nil + for i = 1, 6 do + if lines[i]:match("^- file: ") then + header_found = true + break + end + end + if not header_found then return "missing file header" end + return nil end @@ -2287,6 +2283,10 @@ M.chat_respond = function(params) agent_name = agent_name .. " & custom role" end + if headers.model and not headers.provider then + headers.provider = "openai" + end + local agent_prefix = config.chat_assistant_prefix[1] local agent_suffix = config.chat_assistant_prefix[2] if type(M.config.chat_assistant_prefix) == "string" then @@ -2352,8 +2352,8 @@ M.chat_respond = function(params) -- call the model and write response M.query( buf, - agent.provider, - M.prepare_payload(messages, headers.model, agent.model, agent.provider), + headers.provider or agent.provider, + M.prepare_payload(messages, headers.model or agent.model, headers.provider or agent.provider), M.create_handler(buf, win, M._H.last_content_line(buf), true, "", not M.config.chat_free_cursor), vim.schedule_wrap(function(qid) local qt = M.get_query(qid) @@ -2395,8 +2395,8 @@ M.chat_respond = function(params) -- call the model M.query( nil, - agent.provider, - M.prepare_payload(messages, nil, agent.model, agent.provider), + headers.provider or agent.provider, + M.prepare_payload(messages, headers.model or agent.model, headers.provider or agent.provider), topic_handler, vim.schedule_wrap(function() -- get topic from invisible buffer @@ -2898,7 +2898,33 @@ M.cmd.Context = function(params) M._H.feedkeys("G", "xn") end -M.Prompt = function(params, target, prompt, model, template, system_template, whisper, provider) +local exampleHook = [[ +UnitTests = function(gp, params) + local template = "I have the following code from {{filename}}:\n\n" + .. "```{{filetype}}\n{{selection}}\n```\n\n" + .. "Please respond by writing table driven unit tests for the code above." + local agent = gp.get_command_agent() + gp.Prompt(params, gp.Target.vnew, agent, template) +end, +]] + +---@param params table +---@param target integer | function | table +---@param agent table # obtained from get_command_agent or get_chat_agent +---@param template string # te +---@param prompt string | nil # nil for non interactive commads +---@param whisper string | nil # predefined input (e.g. obtained from Whisper) +M.Prompt = function(params, target, agent, template, prompt, whisper) + if not agent or not type(agent) == "table" or not agent.provider then + M.warning( + "The `gp.Prompt` method signature has changed.\n" + .. "Please update your hook functions as demonstrated in the example below::\n\n" + .. exampleHook + .. "\nFor more information, refer to the 'Extend Functionality' section in the documentation." + ) + return + end + -- enew, new, vnew, tabnew should be resolved into table if type(target) == "function" then target = target() @@ -3060,7 +3086,7 @@ M.Prompt = function(params, target, prompt, model, template, system_template, wh local filetype = M._H.get_filetype(buf) local filename = vim.api.nvim_buf_get_name(buf) - local sys_prompt = M.template_render(system_template, command, selection, filetype, filename) + local sys_prompt = M.template_render(agent.system_template, command, selection, filetype, filename) sys_prompt = sys_prompt or "" table.insert(messages, { role = "system", content = sys_prompt }) @@ -3163,11 +3189,10 @@ M.Prompt = function(params, target, prompt, model, template, system_template, wh end -- call the model and write the response - local agent = M.get_command_agent() M.query( buf, - provider or agent.provider, - M.prepare_payload(messages, model, agent.model, agent.provider), + agent.provider, + M.prepare_payload(messages, agent.model, agent.provider), handler, vim.schedule_wrap(function(qid) on_exit(qid) From f3664deee8fc99013c28523d1069f19d5f3ea854 Mon Sep 17 00:00:00 2001 From: Tibor Schmidt Date: Wed, 17 Jul 2024 09:53:53 +0200 Subject: [PATCH 13/23] feat: improve gp.cmd.ChatNew signature --- lua/gp/init.lua | 78 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/lua/gp/init.lua b/lua/gp/init.lua index 0e946d37..f092a60b 100644 --- a/lua/gp/init.lua +++ b/lua/gp/init.lua @@ -2015,12 +2015,12 @@ M.open_buf = function(file_name, target, kind, toggle) return buf end ----@param params table # table with args ----@param model string | table | nil # model to use ----@param system_prompt string | nil # system prompt to use +---@param params table # vim command parameters such as range, args, etc. ---@param toggle boolean # whether chat is toggled +---@param system_prompt string | nil # system prompt to use +---@param agent table | nil # obtained from get_command_agent or get_chat_agent ---@return number # buffer number -M.new_chat = function(params, model, system_prompt, toggle) +M.new_chat = function(params, toggle, system_prompt, agent) M._toggle_close(M._toggle_kind.popup) -- prepare filename @@ -2034,12 +2034,18 @@ M.new_chat = function(params, model, system_prompt, toggle) local filename = M.config.chat_dir .. "/" .. time .. ".md" -- encode as json if model is a table - if model and type(model) == "table" then - model = "- model: " .. vim.json.encode(model) .. "\n" - elseif model then - model = "- model: " .. model .. "\n" - else - model = "" + local model = "" + local provider = "" + if agent and agent.model and agent.provider then + model = agent.model + provider = agent.provider + if type(model) == "table" then + model = "- model: " .. vim.json.encode(model) .. "\n" + else + model = "- model: " .. model .. "\n" + end + + provider = "- provider: " .. provider:gsub("\n", "\\n") .. "\n" end -- display system prompt as single line with escaped newlines @@ -2052,7 +2058,7 @@ M.new_chat = function(params, model, system_prompt, toggle) local template = string.format( M.chat_template, string.match(filename, "([^/]+)$"), - model .. system_prompt, + model .. provider .. system_prompt, M.config.chat_user_prefix, M.config.chat_shortcut_respond.shortcut, M.config.cmd_prefix, @@ -2085,21 +2091,49 @@ M.new_chat = function(params, model, system_prompt, toggle) return buf end +local exampleChatHook = [[ +Translator = function(gp, params) + local chat_system_prompt = "You are a Translator, help me translate between English and Chinese." + local agent = gp.get_chat_agent() + gp.cmd.ChatNew(params, chat_system_prompt, agent) + + -- nil agent is also valid (you can switch agents dynamically during the chat) + -- gp.cmd.ChatNew(params, chat_system_prompt) +end, +]] + +---@param params table +---@param system_prompt string | nil +---@param agent table | nil # obtained from get_command_agent or get_chat_agent ---@return number # buffer number -M.cmd.ChatNew = function(params, model, system_prompt) +M.cmd.ChatNew = function(params, system_prompt, agent) + if agent then + if not type(agent) == "table" or not agent.provider then + M.warning( + "The `gp.cmd.ChatNew` method signature has changed.\n" + .. "Please update your hook functions as demonstrated in the example below:\n\n" + .. exampleChatHook + .. "\nFor more information, refer to the 'Extend Functionality' section in the documentation." + ) + return -1 + end + end -- if chat toggle is open, close it and start a new one if M._toggle_close(M._toggle_kind.chat) then params.args = params.args or "" if params.args == "" then params.args = M.config.toggle_target end - return M.new_chat(params, model, system_prompt, true) + return M.new_chat(params, true, system_prompt, agent) end - return M.new_chat(params, model, system_prompt, false) + return M.new_chat(params, false, system_prompt, agent) end -M.cmd.ChatToggle = function(params, model, system_prompt) +---@param params table +---@param system_prompt string | nil +---@param agent table | nil # obtained from get_command_agent or get_chat_agent +M.cmd.ChatToggle = function(params, system_prompt, agent) if M._toggle_close(M._toggle_kind.popup) then return end @@ -2125,7 +2159,7 @@ M.cmd.ChatToggle = function(params, model, system_prompt) end end - M.new_chat(params, model, system_prompt, true) + M.new_chat(params, true, system_prompt, agent) end M.cmd.ChatPaste = function(params) @@ -2898,7 +2932,7 @@ M.cmd.Context = function(params) M._H.feedkeys("G", "xn") end -local exampleHook = [[ +local examplePromptHook = [[ UnitTests = function(gp, params) local template = "I have the following code from {{filename}}:\n\n" .. "```{{filetype}}\n{{selection}}\n```\n\n" @@ -2908,18 +2942,18 @@ UnitTests = function(gp, params) end, ]] ----@param params table ----@param target integer | function | table +---@param params table # vim command parameters such as range, args, etc. +---@param target integer | function | table # where to put the response ---@param agent table # obtained from get_command_agent or get_chat_agent ----@param template string # te +---@param template string # template with model instructions ---@param prompt string | nil # nil for non interactive commads ---@param whisper string | nil # predefined input (e.g. obtained from Whisper) M.Prompt = function(params, target, agent, template, prompt, whisper) if not agent or not type(agent) == "table" or not agent.provider then M.warning( "The `gp.Prompt` method signature has changed.\n" - .. "Please update your hook functions as demonstrated in the example below::\n\n" - .. exampleHook + .. "Please update your hook functions as demonstrated in the example below:\n\n" + .. examplePromptHook .. "\nFor more information, refer to the 'Extend Functionality' section in the documentation." ) return From e1acbcad9c254e241a06f3d1339658cf1af836c1 Mon Sep 17 00:00:00 2001 From: Tibor Schmidt Date: Wed, 17 Jul 2024 10:53:38 +0200 Subject: [PATCH 14/23] feat: picking specific agent via get_chat_agent/get_command_agent(name) --- lua/gp/init.lua | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/lua/gp/init.lua b/lua/gp/init.lua index f092a60b..82c521ee 100644 --- a/lua/gp/init.lua +++ b/lua/gp/init.lua @@ -2856,11 +2856,16 @@ M.cmd.NextAgent = function() set_agent(agent_list[1]) end ----@return table # { cmd_prefix, name, model, system_prompt } -M.get_command_agent = function() +---@param name string | nil +---@return table | nil # { cmd_prefix, name, model, system_prompt } +M.get_command_agent = function(name) + name = name or M._state.command_agent + if M.agents[name] == nil then + M.warning("Command Agent " .. name .. " not found, using " .. M._state.command_agent) + name = M._state.command_agent + end local template = M.config.command_prompt_prefix_template - local cmd_prefix = M._H.template_render(template, { ["{{agent}}"] = M._state.command_agent }) - local name = M._state.command_agent + local cmd_prefix = M._H.template_render(template, { ["{{agent}}"] = name }) local model = M.agents[name].model local system_prompt = M.agents[name].system_prompt local provider = M.agents[name].provider @@ -2873,11 +2878,16 @@ M.get_command_agent = function() } end +---@param name string | nil ---@return table # { cmd_prefix, name, model, system_prompt } -M.get_chat_agent = function() +M.get_chat_agent = function(name) + name = name or M._state.chat_agent + if M.agents[name] == nil then + M.warning("Chat Agent " .. name .. " not found, using " .. M._state.chat_agent) + name = M._state.chat_agent + end local template = M.config.command_prompt_prefix_template - local cmd_prefix = M._H.template_render(template, { ["{{agent}}"] = M._state.chat_agent }) - local name = M._state.chat_agent + local cmd_prefix = M._H.template_render(template, { ["{{agent}}"] = name }) local model = M.agents[name].model local system_prompt = M.agents[name].system_prompt local provider = M.agents[name].provider From c9ed444644e85404a1cbb3832da4d3a4f8616f1f Mon Sep 17 00:00:00 2001 From: Tibor Schmidt Date: Wed, 17 Jul 2024 11:25:19 +0200 Subject: [PATCH 15/23] chore: update hooks in default config --- lua/gp/config.lua | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lua/gp/config.lua b/lua/gp/config.lua index 493c15c1..893eaabe 100644 --- a/lua/gp/config.lua +++ b/lua/gp/config.lua @@ -523,10 +523,10 @@ local config = { gp.Prompt( params, gp.Target.rewrite, - nil, -- command will run directly without any prompting for user input - agent.model, + agent, template, - agent.system_prompt + nil, -- command will run directly without any prompting for user input + nil -- no predefined instructions (e.g. speech-to-text from Whisper) ) end, @@ -542,9 +542,12 @@ local config = { -- -- example of adding command which opens new chat dedicated for translation -- Translator = function(gp, params) - -- local agent = gp.get_command_agent() -- local chat_system_prompt = "You are a Translator, please translate between English and Chinese." - -- gp.cmd.ChatNew(params, agent.model, chat_system_prompt) + -- gp.cmd.ChatNew(params, chat_system_prompt) + -- + -- -- -- you can also create a chat with a specific fixed agent like this: + -- -- local agent = gp.get_chat_agent("ChatGPT4o") + -- -- gp.cmd.ChatNew(params, chat_system_prompt, agent) -- end, -- -- example of adding command which writes unit tests for the selected code @@ -553,7 +556,7 @@ local config = { -- .. "```{{filetype}}\n{{selection}}\n```\n\n" -- .. "Please respond by writing table driven unit tests for the code above." -- local agent = gp.get_command_agent() - -- gp.Prompt(params, gp.Target.enew, nil, agent.model, template, agent.system_prompt) + -- gp.Prompt(params, gp.Target.enew, agent, template) -- end, -- -- example of adding command which explains the selected code @@ -562,7 +565,7 @@ local config = { -- .. "```{{filetype}}\n{{selection}}\n```\n\n" -- .. "Please respond by explaining the code above." -- local agent = gp.get_chat_agent() - -- gp.Prompt(params, gp.Target.popup, nil, agent.model, template, agent.system_prompt) + -- gp.Prompt(params, gp.Target.popup, agent, template) -- end, }, } From 5cc8a4e10daee252187124537eba428c5abfa839 Mon Sep 17 00:00:00 2001 From: Matthieu Coudron <886074+teto@users.noreply.github.com> Date: Tue, 2 Apr 2024 15:48:11 +0200 Subject: [PATCH 16/23] add .editorconfig to help contributions set tab by default --- .editorconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..ee480627 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +indent_style = tab +indent_size = 1 +tab_width = 4 +end_of_line = lf +insert_final_newline = true +charset = utf-8 + From 44f62561f3992e8d245cdb7f13c5716fdf7984b8 Mon Sep 17 00:00:00 2001 From: Matthieu Coudron <886074+teto@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:46:43 +0100 Subject: [PATCH 17/23] make it possible tu use `:GpWhisper ` so this can be changed on the fly. --- lua/gp/init.lua | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lua/gp/init.lua b/lua/gp/init.lua index 68755eaf..a0d14f03 100644 --- a/lua/gp/init.lua +++ b/lua/gp/init.lua @@ -1161,7 +1161,7 @@ M.prepare_commands = function() end M.cmd["Whisper" .. command] = function(params) - M.Whisper(function(text) + M.Whisper(M.config.whisper_language, function(text) vim.schedule(function() cmd(params, text) end) @@ -3200,7 +3200,7 @@ M.Prompt = function(params, target, prompt, model, template, system_template, wh end ---@param callback function # callback function(text) -M.Whisper = function(callback) +M.Whisper = function(language, callback) -- make sure sox is installed if vim.fn.executable("sox") == 0 then M.error("sox is not installed") @@ -3356,7 +3356,7 @@ M.Whisper = function(callback) .. M.config.openai_api_key .. '" -H "Content-Type: multipart/form-data" ' .. '-F model="whisper-1" -F language="' - .. M.config.whisper_language + .. language .. '" -F file="@final.mp3" ' .. '-F response_format="json"' @@ -3459,7 +3459,14 @@ M.cmd.Whisper = function(params) end_line = params.line2 end - M.Whisper(function(text) + local args = vim.split(params.args, " ") + + local language = config.whisper_language + if args[1] ~= "" then + language = args[1] + end + + M.Whisper(language, function(text) if not vim.api.nvim_buf_is_valid(buf) then return end From 6a7a78fc78f249f31cd99c3c8d9c4e419684aa53 Mon Sep 17 00:00:00 2001 From: "Matthieu C." <886074+teto@users.noreply.github.com> Date: Wed, 17 Jul 2024 12:03:03 +0200 Subject: [PATCH 18/23] doc: updated GpWhisper doc in README --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5dc79c68..ad34507b 100644 --- a/README.md +++ b/README.md @@ -311,12 +311,15 @@ Provides custom context per repository: ## Speech commands -#### `:GpWhisper` +#### `:GpWhisper` {lang?} Transcription replaces the current line, visual selection or range in the current buffer. Use your mouth to ask a question in a chat buffer instead of writing it by hand, dictate some comments for the code, notes or even your next novel.. For the rest of the whisper commands, the transcription is used as an editable prompt for the equivalent non whisper command - `GpWhisperRewrite` dictates instructions for `GpRewrite` etc. +You can override the default language by setting {lang} with the 2 letter +shortname of your language (e.g. "en" for English, "fr" for French etc). + #### `:GpWhisperRewrite` Similar to `:GpRewrite`, but the prompt instruction dialog uses transcribed spoken instructions. From a55dbda45210c99375d7301319ec8421305dbd1d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 17 Jul 2024 10:29:39 +0000 Subject: [PATCH 19/23] chore: auto-generate vimdoc --- doc/gp.nvim.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/gp.nvim.txt b/doc/gp.nvim.txt index 58eaeace..bde9f29a 100644 --- a/doc/gp.nvim.txt +++ b/doc/gp.nvim.txt @@ -1,4 +1,4 @@ -*gp.nvim.txt* For NVIM v0.8.0 Last change: 2024 July 16 +*gp.nvim.txt* For NVIM v0.8.0 Last change: 2024 July 17 ============================================================================== Table of Contents *gp.nvim-table-of-contents* @@ -396,7 +396,7 @@ Provides custom context per repository: SPEECH COMMANDS *gp.nvim-speech-commands* -:GpWhisper *:GpWhisper* +:GpWhisper {lang?} *:GpWhisper* Transcription replaces the current line, visual selection or range in the current buffer. Use your mouth to ask a question in a chat buffer instead of @@ -407,6 +407,9 @@ For the rest of the whisper commands, the transcription is used as an editable prompt for the equivalent non whisper command - `GpWhisperRewrite` dictates instructions for `GpRewrite` etc. +You can override the default language by setting {lang} with the 2 letter +shortname of your language (e.g.Β "en" for English, "fr" for French etc). + :GpWhisperRewrite *:GpWhisperRewrite* From 6217a51651ad8d1340d091d718d345f0597d0e83 Mon Sep 17 00:00:00 2001 From: Tibor Schmidt Date: Wed, 17 Jul 2024 13:10:51 +0200 Subject: [PATCH 20/23] chore: some comments --- lua/gp/init.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lua/gp/init.lua b/lua/gp/init.lua index 82c521ee..26c7f605 100644 --- a/lua/gp/init.lua +++ b/lua/gp/init.lua @@ -2093,12 +2093,12 @@ end local exampleChatHook = [[ Translator = function(gp, params) - local chat_system_prompt = "You are a Translator, help me translate between English and Chinese." - local agent = gp.get_chat_agent() - gp.cmd.ChatNew(params, chat_system_prompt, agent) + local chat_system_prompt = "You are a Translator, please translate between English and Chinese." + gp.cmd.ChatNew(params, chat_system_prompt) - -- nil agent is also valid (you can switch agents dynamically during the chat) - -- gp.cmd.ChatNew(params, chat_system_prompt) + -- -- you can also create a chat with a specific fixed agent like this: + -- local agent = gp.get_chat_agent("ChatGPT4o") + -- gp.cmd.ChatNew(params, chat_system_prompt, agent) end, ]] @@ -2857,7 +2857,7 @@ M.cmd.NextAgent = function() end ---@param name string | nil ----@return table | nil # { cmd_prefix, name, model, system_prompt } +---@return table | nil # { cmd_prefix, name, model, system_prompt, provider} M.get_command_agent = function(name) name = name or M._state.command_agent if M.agents[name] == nil then @@ -2879,7 +2879,7 @@ M.get_command_agent = function(name) end ---@param name string | nil ----@return table # { cmd_prefix, name, model, system_prompt } +---@return table # { cmd_prefix, name, model, system_prompt, provider } M.get_chat_agent = function(name) name = name or M._state.chat_agent if M.agents[name] == nil then From 90f61c722b08d7168458269d6fcbbc388e5b0cd8 Mon Sep 17 00:00:00 2001 From: Tibor Schmidt Date: Wed, 17 Jul 2024 13:12:27 +0200 Subject: [PATCH 21/23] docs: update README.md --- README.md | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 5dc79c68..55b98b62 100644 --- a/README.md +++ b/README.md @@ -731,7 +731,7 @@ Here are some more examples: .. "```{{filetype}}\n{{selection}}\n```\n\n" .. "Please respond by writing table driven unit tests for the code above." local agent = gp.get_command_agent() - gp.Prompt(params, gp.Target.enew, nil, agent.model, template, agent.system_prompt) + gp.Prompt(params, gp.Target.vnew, agent, template) end, ```` @@ -744,7 +744,7 @@ Here are some more examples: .. "```{{filetype}}\n{{selection}}\n```\n\n" .. "Please respond by explaining the code above." local agent = gp.get_chat_agent() - gp.Prompt(params, gp.Target.popup, nil, agent.model, template, agent.system_prompt) + gp.Prompt(params, gp.Target.popup, agent, template) end, ```` @@ -757,7 +757,7 @@ Here are some more examples: .. "```{{filetype}}\n{{selection}}\n```\n\n" .. "Please analyze for code smells and suggest improvements." local agent = gp.get_chat_agent() - gp.Prompt(params, gp.Target.enew("markdown"), nil, agent.model, template, agent.system_prompt) + gp.Prompt(params, gp.Target.enew("markdown"), agent, template) end, ```` @@ -766,9 +766,12 @@ Here are some more examples: ```lua -- example of adding command which opens new chat dedicated for translation Translator = function(gp, params) - local agent = gp.get_command_agent() - local chat_system_prompt = "You are a Translator, please translate between English and Chinese." - gp.cmd.ChatNew(params, agent.model, chat_system_prompt) + local chat_system_prompt = "You are a Translator, please translate between English and Chinese." + gp.cmd.ChatNew(params, chat_system_prompt) + + -- -- you can also create a chat with a specific fixed agent like this: + -- local agent = gp.get_chat_agent("ChatGPT4o") + -- gp.cmd.ChatNew(params, chat_system_prompt, agent) end, ``` @@ -783,7 +786,16 @@ Here are some more examples: end, ``` -The raw plugin text editing method `Prompt` has seven aprameters: +The raw plugin text editing method `Prompt` has following signature: +```lua +---@param params table # vim command parameters such as range, args, etc. +---@param target integer | function | table # where to put the response +---@param agent table # obtained from get_command_agent or get_chat_agent +---@param template string # template with model instructions +---@param prompt string | nil # nil for non interactive commads +---@param whisper string | nil # predefined input (e.g. obtained from Whisper) +Prompt(params, target, agent, template, prompt, whisper) +``` - `params` is a [table passed to neovim user commands](https://neovim.io/doc/user/lua-guide.html#lua-guide-commands-create), `Prompt` currently uses: @@ -868,13 +880,14 @@ The raw plugin text editing method `Prompt` has seven aprameters: } ``` -- `prompt` - - string used similarly as bash/zsh prompt in terminal, when plugin asks for user command to gpt. - - if `nil`, user is not asked to provide input (for specific predefined commands - document this, explain that, write tests ..) - - simple `πŸ€– ~ ` might be used or you could use different msg to convey info about the method which is called - (`πŸ€– rewrite ~`, `πŸ€– popup ~`, `πŸ€– enew ~`, `πŸ€– inline ~`, etc.) -- `model` - - see [gpt model overview](https://platform.openai.com/docs/models/overview) + +- `agent` table obtainable via `get_command_agent` and `get_chat_agent` methods which have following signature: + ```lua + ---@param name string | nil + ---@return table # { cmd_prefix, name, model, system_prompt, provider } + get_command_agent(name) + ``` + - `template` - template of the user message send to gpt @@ -886,7 +899,10 @@ The raw plugin text editing method `Prompt` has seven aprameters: | `{{selection}}` | last or currently selected text | | `{{command}}` | instructions provided by the user | -- `system_template` - - See [gpt api intro](https://platform.openai.com/docs/guides/chat/introduction) +- `prompt` + - string used similarly as bash/zsh prompt in terminal, when plugin asks for user command to gpt. + - if `nil`, user is not asked to provide input (for specific predefined commands - document this, explain that, write tests ..) + - simple `πŸ€– ~ ` might be used or you could use different msg to convey info about the method which is called + (`πŸ€– rewrite ~`, `πŸ€– popup ~`, `πŸ€– enew ~`, `πŸ€– inline ~`, etc.) - `whisper` - optional string serving as a default for input prompt (for example generated from speech by Whisper) From 360ee314aa1ca4742ef51519e114274bde633b5d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 17 Jul 2024 11:35:45 +0000 Subject: [PATCH 22/23] chore: auto-generate vimdoc --- doc/gp.nvim.txt | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/doc/gp.nvim.txt b/doc/gp.nvim.txt index bde9f29a..e03b3d9d 100644 --- a/doc/gp.nvim.txt +++ b/doc/gp.nvim.txt @@ -879,7 +879,7 @@ Here are some more examples: .. "```{{filetype}}\n{{selection}}\n```\n\n" .. "Please respond by writing table driven unit tests for the code above." local agent = gp.get_command_agent() - gp.Prompt(params, gp.Target.enew, nil, agent.model, template, agent.system_prompt) + gp.Prompt(params, gp.Target.vnew, agent, template) end, < - `:GpExplain` @@ -890,7 +890,7 @@ Here are some more examples: .. "```{{filetype}}\n{{selection}}\n```\n\n" .. "Please respond by explaining the code above." local agent = gp.get_chat_agent() - gp.Prompt(params, gp.Target.popup, nil, agent.model, template, agent.system_prompt) + gp.Prompt(params, gp.Target.popup, agent, template) end, < - `:GpCodeReview` @@ -901,16 +901,19 @@ Here are some more examples: .. "```{{filetype}}\n{{selection}}\n```\n\n" .. "Please analyze for code smells and suggest improvements." local agent = gp.get_chat_agent() - gp.Prompt(params, gp.Target.enew("markdown"), nil, agent.model, template, agent.system_prompt) + gp.Prompt(params, gp.Target.enew("markdown"), agent, template) end, < - `:GpTranslator` >lua -- example of adding command which opens new chat dedicated for translation Translator = function(gp, params) - local agent = gp.get_command_agent() - local chat_system_prompt = "You are a Translator, please translate between English and Chinese." - gp.cmd.ChatNew(params, agent.model, chat_system_prompt) + local chat_system_prompt = "You are a Translator, please translate between English and Chinese." + gp.cmd.ChatNew(params, chat_system_prompt) + + -- -- you can also create a chat with a specific fixed agent like this: + -- local agent = gp.get_chat_agent("ChatGPT4o") + -- gp.cmd.ChatNew(params, chat_system_prompt, agent) end, < - `:GpBufferChatNew` @@ -923,7 +926,17 @@ Here are some more examples: end, < -The raw plugin text editing method `Prompt` has seven aprameters: +The raw plugin text editing method `Prompt` has following signature: + +>lua + ---@param params table # vim command parameters such as range, args, etc. + ---@param target integer | function | table # where to put the response + ---@param agent table # obtained from get_command_agent or get_chat_agent + ---@param template string # template with model instructions + ---@param prompt string | nil # nil for non interactive commads + ---@param whisper string | nil # predefined input (e.g. obtained from Whisper) + Prompt(params, target, agent, template, prompt, whisper) +< - `params` is a |table passed to neovim user commands|, `Prompt` currently uses: - `range, line1, line2` to work with |ranges| @@ -1002,13 +1015,13 @@ The raw plugin text editing method `Prompt` has seven aprameters: end, } < -- `prompt` - - string used similarly as bash/zsh prompt in terminal, when plugin asks for user command to gpt. - - if `nil`, user is not asked to provide input (for specific predefined commands - document this, explain that, write tests ..) - - simple `πŸ€– ~` might be used or you could use different msg to convey info about the method which is called - (`πŸ€– rewrite ~`, `πŸ€– popup ~`, `πŸ€– enew ~`, `πŸ€– inline ~`, etc.) -- `model` - - see gpt model overview +- `agent` table obtainable via `get_command_agent` and `get_chat_agent` methods + which have following signature: + >lua + ---@param name string | nil + ---@return table # { cmd_prefix, name, model, system_prompt, provider } + get_command_agent(name) + < - `template` - template of the user message send to gpt - string can include variables below: @@ -1017,8 +1030,11 @@ The raw plugin text editing method `Prompt` has seven aprameters: {{filetype}} filetype of the current buffer {{selection}} last or currently selected text {{command}} instructions provided by the user -- `system_template` - - See gpt api intro +- `prompt` + - string used similarly as bash/zsh prompt in terminal, when plugin asks for user command to gpt. + - if `nil`, user is not asked to provide input (for specific predefined commands - document this, explain that, write tests ..) + - simple `πŸ€– ~` might be used or you could use different msg to convey info about the method which is called + (`πŸ€– rewrite ~`, `πŸ€– popup ~`, `πŸ€– enew ~`, `πŸ€– inline ~`, etc.) - `whisper` - optional string serving as a default for input prompt (for example generated from speech by Whisper) From 56740e089ac0117e7a61e3c03e979c1bfbe1a498 Mon Sep 17 00:00:00 2001 From: "Matthieu C." <886074+teto@users.noreply.github.com> Date: Wed, 17 Jul 2024 12:39:13 +0200 Subject: [PATCH 23/23] feat: expose default_(chat|code)_system_prompt to user When adding your own agents, you have to provide default prompts. Let's expose gp.nvim's default ones t avoid the user troubling him/herself with the issue. --- lua/gp/config.lua | 42 ++++++++++++++---------------------------- lua/gp/defaults.lua | 16 ++++++++++++++++ 2 files changed, 30 insertions(+), 28 deletions(-) create mode 100644 lua/gp/defaults.lua diff --git a/lua/gp/config.lua b/lua/gp/config.lua index 893eaabe..9d167791 100644 --- a/lua/gp/config.lua +++ b/lua/gp/config.lua @@ -5,20 +5,6 @@ -- Default config -------------------------------------------------------------------------------- -local default_chat_system_prompt = "You are a general AI assistant.\n\n" - .. "The user provided the additional info about how they would like you to respond:\n\n" - .. "- If you're unsure don't guess and say you don't know instead.\n" - .. "- Ask question if you need clarification to provide better answer.\n" - .. "- Think deeply and carefully from first principles step by step.\n" - .. "- Zoom out first to see the big picture and then zoom in to details.\n" - .. "- Use Socratic method to improve your thinking and coding skills.\n" - .. "- Don't elide any code from your output if the answer requires coding.\n" - .. "- Take a deep breath; You've got this!\n" - -local default_code_system_prompt = "You are an AI working as a code editor.\n\n" - .. "Please AVOID COMMENTARY OUTSIDE OF THE SNIPPET RESPONSE.\n" - .. "START AND END YOUR ANSWER WITH:\n\n```" - local config = { -- Please start with minimal config possible. -- Just openai_api_key if you don't have OPENAI_API_KEY env set up. @@ -110,7 +96,7 @@ local config = { -- string with model name or table with model name and parameters model = { model = "gpt-4o", temperature = 1.1, top_p = 1 }, -- system prompt (use this to specify the persona/role of the AI) - system_prompt = default_chat_system_prompt, + system_prompt = require'gp.defaults'.chat_system_prompt, }, { provider = "openai", @@ -120,7 +106,7 @@ local config = { -- string with model name or table with model name and parameters model = { model = "gpt-3.5-turbo", temperature = 1.1, top_p = 1 }, -- system prompt (use this to specify the persona/role of the AI) - system_prompt = default_chat_system_prompt, + system_prompt = require'gp.defaults'.chat_system_prompt, }, { provider = "copilot", @@ -130,7 +116,7 @@ local config = { -- string with model name or table with model name and parameters model = { model = "gpt-4", temperature = 1.1, top_p = 1 }, -- system prompt (use this to specify the persona/role of the AI) - system_prompt = default_chat_system_prompt, + system_prompt = require'gp.defaults'.chat_system_prompt, }, { provider = "googleai", @@ -140,7 +126,7 @@ local config = { -- string with model name or table with model name and parameters model = { model = "gemini-pro", temperature = 1.1, top_p = 1 }, -- system prompt (use this to specify the persona/role of the AI) - system_prompt = default_chat_system_prompt, + system_prompt = require'gp.defaults'.chat_system_prompt, }, { provider = "pplx", @@ -150,7 +136,7 @@ local config = { -- string with model name or table with model name and parameters model = { model = "mixtral-8x7b-instruct", temperature = 1.1, top_p = 1 }, -- system prompt (use this to specify the persona/role of the AI) - system_prompt = default_chat_system_prompt, + system_prompt = require'gp.defaults'.chat_system_prompt, }, { provider = "anthropic", @@ -160,7 +146,7 @@ local config = { -- string with model name or table with model name and parameters model = { model = "claude-3-5-sonnet-20240620", temperature = 0.8, top_p = 1 }, -- system prompt (use this to specify the persona/role of the AI) - system_prompt = default_chat_system_prompt, + system_prompt = require'gp.defaults'.chat_system_prompt, }, { provider = "anthropic", @@ -170,7 +156,7 @@ local config = { -- string with model name or table with model name and parameters model = { model = "claude-3-haiku-20240307", temperature = 0.8, top_p = 1 }, -- system prompt (use this to specify the persona/role of the AI) - system_prompt = default_chat_system_prompt, + system_prompt = require'gp.defaults'.chat_system_prompt, }, { provider = "ollama", @@ -208,7 +194,7 @@ local config = { -- string with model name or table with model name and parameters model = { model = "gpt-4o", temperature = 0.8, top_p = 1 }, -- system prompt (use this to specify the persona/role of the AI) - system_prompt = default_code_system_prompt, + system_prompt = require'gp.defaults'.code_system_prompt, }, { provider = "openai", @@ -218,7 +204,7 @@ local config = { -- string with model name or table with model name and parameters model = { model = "gpt-3.5-turbo", temperature = 0.8, top_p = 1 }, -- system prompt (use this to specify the persona/role of the AI) - system_prompt = default_code_system_prompt, + system_prompt = require'gp.defaults'.code_system_prompt, }, { provider = "copilot", @@ -228,7 +214,7 @@ local config = { -- string with the Copilot engine name or table with engine name and parameters if applicable model = { model = "gpt-4", temperature = 0.8, top_p = 1, n = 1 }, -- system prompt (use this to specify the persona/role of the AI) - system_prompt = default_code_system_prompt, + system_prompt = require'gp.defaults'.code_system_prompt, }, { provider = "googleai", @@ -237,7 +223,7 @@ local config = { command = true, -- string with model name or table with model name and parameters model = { model = "gemini-pro", temperature = 0.8, top_p = 1 }, - system_prompt = default_code_system_prompt, + system_prompt = require'gp.defaults'.code_system_prompt, }, { provider = "pplx", @@ -246,7 +232,7 @@ local config = { command = true, -- string with model name or table with model name and parameters model = { model = "mixtral-8x7b-instruct", temperature = 0.8, top_p = 1 }, - system_prompt = default_code_system_prompt, + system_prompt = require'gp.defaults'.code_system_prompt, }, { provider = "anthropic", @@ -255,7 +241,7 @@ local config = { command = true, -- string with model name or table with model name and parameters model = { model = "claude-3-5-sonnet-20240620", temperature = 0.8, top_p = 1 }, - system_prompt = default_code_system_prompt, + system_prompt = require'gp.defaults'.code_system_prompt, }, { provider = "anthropic", @@ -264,7 +250,7 @@ local config = { command = true, -- string with model name or table with model name and parameters model = { model = "claude-3-haiku-20240307", temperature = 0.8, top_p = 1 }, - system_prompt = default_code_system_prompt, + system_prompt = require'gp.defaults'.code_system_prompt, }, { provider = "ollama", diff --git a/lua/gp/defaults.lua b/lua/gp/defaults.lua new file mode 100644 index 00000000..763c6e00 --- /dev/null +++ b/lua/gp/defaults.lua @@ -0,0 +1,16 @@ +local M = {} +M.chat_system_prompt = "You are a general AI assistant.\n\n" + .. "The user provided the additional info about how they would like you to respond:\n\n" + .. "- If you're unsure don't guess and say you don't know instead.\n" + .. "- Ask question if you need clarification to provide better answer.\n" + .. "- Think deeply and carefully from first principles step by step.\n" + .. "- Zoom out first to see the big picture and then zoom in to details.\n" + .. "- Use Socratic method to improve your thinking and coding skills.\n" + .. "- Don't elide any code from your output if the answer requires coding.\n" + .. "- Take a deep breath; You've got this!\n" + +M.code_system_prompt = "You are an AI working as a code editor.\n\n" + .. "Please AVOID COMMENTARY OUTSIDE OF THE SNIPPET RESPONSE.\n" + .. "START AND END YOUR ANSWER WITH:\n\n```" + +return M