Giter Site home page Giter Site logo

frankroeder / parrot.nvim Goto Github PK

View Code? Open in Web Editor NEW
17.0 1.0 3.0 416 KB

parrot.nvim ๐Ÿฆœ - the plugin that brings stochastic parrots to Neovim.

License: MIT License

Lua 99.94% Shell 0.06%
gpt large-language-models llm neovim nvim perplexity-ai plugin prompting chatgpt chatgpt-plugin openai openai-api openai-chatgpt ollama stochastic-parrot anthropic claude-3

parrot.nvim's Introduction

parrot.nvim ๐Ÿฆœ

This is parrot.nvim, the ultimate stochastic parrot to support your text editing inside Neovim.

parrot.nvim logo

[!NOTE]โš ๏ธ This repository is still a work in progress, as large parts of the code are still being simplified and restructured. It is based on the brilliant work gp.nvim by https://github.com/Robitx.

Currently, we support the following providers:

I started this repository because a perplexity subscription provides $5 of API credits every month for free. Instead of letting them go to waste, I modified my favorite GPT plugin, gp.nvim, to meet my needs - a new Neovim plugin was born! ๐Ÿ”ฅ

Demo

Seamlessly switch between providers and agents.


Trigger code completions based on comments.


Let the parrot fix your bugs.

Getting Started

Dependencies

lazy.nvim

{
  "frankroeder/parrot.nvim",
  dependencies = { 'ibhagwan/fzf-lua', 'nvim-lua/plenary.nvim' },
  config = function()
    require("parrot").setup {
      providers = {
        pplx = {
          api_key = os.getenv "PERPLEXITY_API_KEY",
          -- OPTIONAL
          -- gpg command
          -- api_key = { "gpg", "--decrypt", vim.fn.expand("$HOME") .. "/pplx_api_key.txt.gpg"  },
          -- macOS security tool
          -- api_key = { "/usr/bin/security", "find-generic-password", "-s pplx-api-key", "-w" },
        },
        openai = {
          api_key = os.getenv "OPENAI_API_KEY",
        },
        anthropic = {
          api_key = os.getenv "ANTHROPIC_API_KEY",
        },
      },
    }
  end,
}

Configuration

For now, refer to my personal lazy.nvim setup for custom hooks and key bindings.

https://github.com/frankroeder/dotfiles/blob/master/nvim/lua/plugins/parrot.lua

Adding a new agents

We provide two types of agents that might need different system prompts and API parameters. To make a new chat agent available, one simply adds a new entry to the list chat or to command, respectively.

require("parrot").setup {
    -- ...
    agents = {
        chat = {
          {
              name = "CodeLlama",
              model = { model = "codellama", temperature = 1.5, top_p = 1, num_ctx = 8192, min_p = 0.05 },
              system_prompt = "Help me!",
              provider = "ollama",
          }
        }
    },
    -- ...
}

Commands

Below are the available commands that can be configured as keybindings. These commands are included in the default setup. Additional useful commands are implemented through hooks (see my example configuration).

General

Command Description
PrtNew open a new chat
PrtProvider <provider> switch the provider (empty arg triggers fzf)
PrtAgent <agent> switch the agent (empty arg triggers fzf)
PrtChatToggle <target> toggle chat window
PrtInfo print plugin config
PrtContext edits the local context file
PrtAsk ask the selected agent a single question
PrtChatFinder fuzzy search chat files using fzf

Interactive

The following commands can be triggered with visual selections.

Command Description
PrtChatNew <target> paste visual selection into new chat (defaults to toggle_target)
PrtChatToggle <target> paste visual selection into new chat (defaults to toggle_target)
PrtImplement implements selected comment/instruction

Chat

The following commands are available within the chat files.

Command Description
PrtChatDelete delete the present chat file (requires confirmation)
PrtChatRespond trigger chat respond
PrtAsk ask the selected agent a single question
PrtStop interrupt ongoing respond

Adding a new command

WIP

require("parrot").setup {
    -- ...
    hooks = {
      -- PrtAsk simply ask a question that should be answered short and precisely.
      Ask = function(parrot, params)
            local template = [[
            In light of your existing knowledge base, please generate a response that
            is succinct and directly addresses the question posed. Prioritize accuracy
            and relevance in your answer, drawing upon the most recent information
            available to you. Aim to deliver your response in a concise manner,
            focusing on the essence of the inquiry.
            Question: {{command}}
            ]]
            local agent = parrot.get_command_agent()
            parrot.logger.info("Asking agent: " .. agent.name)
            parrot.Prompt(params, parrot.ui.Target.popup, "๐Ÿค– Ask ~ ", agent.model, template, "", agent.provider)
      end,
    }
    -- ...
}

Known Issues

  • In case of a corrupted state, simply remove the file ~/.local/share/nvim/parrot/persisted/state.json

more to come ...

parrot.nvim's People

Contributors

argshook avatar denismaciel avatar frankroeder avatar github-actions[bot] avatar isak102 avatar jayeheffernan avatar judaew avatar lintaoamons avatar mindshade avatar oliverchao avatar rob-3 avatar robitx avatar tarruda avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

parrot.nvim's Issues

Deprecation warning for `vim.tbl_add_reverse_lookup`

I am getting this warning when loading parrot.nvim on NVIM v0.11.0-dev+d62d181.

vim.deprecated: require("vim.deprecated.health").check()

 ~
- WARNING vim.tbl_add_reverse_lookup is deprecated. Feature will be removed in Nvim 0.12
  - ADVICE:
    - stack traceback:
        /home/denis/.local/share/nvim/lazy/typescript-tools.nvim/lua/typescript-tools/protocol/module_mapper.lua:21
        [C]:-1
        /home/denis/.local/share/nvim/lazy/typescript-tools.nvim/lua/typescript-tools/tsserver.lua:6
        [C]:-1
        /home/denis/.local/share/nvim/lazy/typescript-tools.nvim/lua/typescript-tools/rpc.lua:3
        [C]:-1
        /home/denis/.local/share/nvim/lazy/typescript-tools.nvim/lua/typescript-tools/init.lua:4
        [C]:-1
        /home/denis/.config/nvim/lua/init.lua:1001
        /home/denis/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/loader.lua:366
        [C]:-1
        /home/denis/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/util.lua:113
        /home/denis/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/loader.lua:381
        /home/denis/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/loader.lua:348
        /home/denis/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/loader.lua:191
        /home/denis/.local/share/nvim/lazy/lazy.nvim/lua/lazy/core/handler/event.lua:83
        [C]:-1
        /home/denis/.local/share/nvim/lazy/parrot.nvim/lua/parrot/init.lua:856
        /home/denis/.local/share/nvim/lazy/parrot.nvim/lua/parrot/init.lua:964
        /home/denis/.local/share/nvim/lazy/parrot.nvim/lua/parrot/init.lua:203

Working configuration for lazyvim users

Just in case someone is using lazyvim, here is my configuration.

return {
  {
    "frankroeder/parrot.nvim",
    -- OPTIONAL dependency
    dependencies = { "fzf-lua" },
    -- OPTIONAL condition
    cond = os.getenv("OPENAI_API_KEY") ~= nil or os.getenv("PERPLEXITY_API_KEY") ~= nil,
    config = function()
      local cmd_prefix = "Prt"
      require("parrot").setup({
        providers = {
          pplx = {
            api_key = os.getenv("PERPLEXITY_API_KEY"),
            -- OPTIONAL
            -- gpg command
            -- api_key = { "gpg", "--decrypt", vim.fn.expand("$HOME") .. "/pplx_api_key.txt.gpg"  },
            -- macOS security tool
            -- api_key = { "/usr/bin/security", "find-generic-password", "-s pplx-api-key", "-w" },
          },
        },
        cmd_prefix = cmd_prefix,
        chat_conceal_model_params = false,
        hooks = {
          Complete = function(prt, params)
            local template = [[
        I have the following code from {{filename}}:

        ```{{filetype}}
        {{selection}}
        ```

        Please finish the code above carefully and logically.
        Respond just with the snippet of code that should be inserted."
        ]]
            local agent = prt.get_command_agent()
            prt.Prompt(params, prt.Target.append, nil, agent.model, template, agent.system_prompt, agent.provider)
          end,
          Explain = function(prt, params)
            local template = [[
        Explain the following code from {{filename}}:

        ```{{filetype}}
        {{selection}}
        ```

        Use the markdown format with codeblocks.
        A brief explanation of what the code above is doing:
        ]]
            local agent = prt.get_chat_agent()
            prt.logger.info("Explaining selection with agent: " .. agent.name)
            prt.Prompt(params, prt.Target.popup, nil, agent.model, template, agent.system_prompt, agent.provider)
          end,
          FixBugs = function(prt, params)
            local template = [[
        You are an expert in {{filetype}}.
        Fix bugs in the below code from {{filename}} carefully and logically:

        ```{{filetype}}
        {{selection}}
        ```

        Fixed code:
        ]]
            local agent = prt.get_command_agent()
            prt.logger.info("Fixing bugs in selection with agent: " .. agent.name)
            prt.Prompt(params, prt.Target.popup, nil, agent.model, template, agent.system_prompt, agent.provider)
          end,
          Optimize = function(prt, params)
            local template = [[
        You are an expert in {{filetype}}.
        Optimize the following code from {{filename}}:

        ```{{filetype}}
        {{selection}}
        ```

        Optimized code:
        ]]
            local agent = prt.get_command_agent()
            prt.logger.info("Optimizing selection with agent: " .. agent.name)
            prt.Prompt(params, prt.Target.popup, nil, agent.model, template, agent.system_prompt, agent.provider)
          end,
          UnitTests = function(prt, params)
            local template = [[
        I have the following code from {{filename}}:

        ```{{filetype}}
        {{selection}}
        ```

        Please respond by writing table driven unit tests for the code above.
        ]]
            local agent = prt.get_command_agent()
            prt.logger.info("Creating unit tests for selection with agent: " .. agent.name)
            prt.Prompt(params, prt.Target.enew, nil, agent.model, template, agent.system_prompt, agent.provider)
          end,
          ProofReader = function(prt, params)
            local chat_system_prompt = [[
        I want you to act as a proofreader. I will provide you with texts and
        I would like you to review them for any spelling, grammar, or
        punctuation errors. Once you have finished reviewing the text,
        provide me with any necessary corrections or suggestions to improve the
        text. Highlight the corrections with markdown bold or italics style.
        ]]
            local agent = prt.get_chat_agent()
            prt.logger.info("Proofreading selection with agent: " .. agent.name)
            prt.cmd.ChatNew(params, agent.model, chat_system_prompt)
          end,
          Debug = function(prt, params)
            local template = [[
        I want you to act as {{filetype}} expert.
        Review the following code, carefully examine it, and report potential
        bugs and edge cases alongside solutions to resolve them.
        Keep your explanation short and to the point:

        ```{{filetype}}
        {{selection}}
        ```
        ]]
            local agent = prt.get_chat_agent()
            prt.logger.info("Debugging selection with agent: " .. agent.name)
            prt.Prompt(params, prt.Target.enew, nil, agent.model, template, agent.system_prompt, agent.provider)
          end,
        },
      })
    end,
    keys = {
      -- Normal and Insert mode mappings
      { "<C-g>c", "<cmd>PrtChatNew<cr>", mode = { "n", "i" }, desc = "New Chat" },
      { "<C-g>t", "<cmd>PrtChatToggle tabnew<cr>", mode = { "n", "i" }, desc = "Toggle Popup Chat" },
      { "<C-g>f", "<cmd>PrtChatFinder<cr>", mode = { "n", "i" }, desc = "Chat Finder" },
      { "<C-g>r", "<cmd>PrtRewrite<cr>", mode = { "n", "i" }, desc = "Inline Rewrite" },
      { "<C-g>a", "<cmd>PrtAppend<cr>", mode = { "n", "i" }, desc = "Append" },
      { "<C-g>o", "<cmd>PrtPrepend<cr>", mode = { "n", "i" }, desc = "Prepend" },

      -- Visual mode mappings
      { "<C-g>c", "<cmd>PrtChatNew<cr>", mode = "v", desc = "Visual Chat New" },
      { "<C-g>r", "<cmd>PrtRewrite<cr>", mode = "v", desc = "Visual Rewrite" },
      { "<C-g>a", "<cmd>PrtAppend<cr>", mode = "v", desc = "Visual Append" },
      { "<C-g>o", "<cmd>PrtPrepend<cr>", mode = "v", desc = "Visual Prepend" },
      { "<C-g>e", "<cmd>PrtEnew<cr>", mode = "v", desc = "Visual Enew" },

      -- Additional mappings
      { "<C-g>s", "<cmd>PrtStop<cr>", mode = { "n", "i", "v", "x" }, desc = "Stop" },
      { "<C-g>i", "<cmd>PrtComplete<cr>", mode = { "n", "i", "v", "x" }, desc = "Complete the visual selection" },

      -- Context and agent/provider selection mappings
      { "<C-g>x", "<cmd>PrtContext<cr>", mode = "n", desc = "Open file with custom context" },
      { "<C-g>n", "<cmd>PrtAgent<cr>", mode = "n", desc = "Select agent or show info" },
      { "<C-g>p", "<cmd>PrtProvider<cr>", mode = "n", desc = "Select provider or show info" },
    },
  },
}


P.S. I get rid of refactoring the keymap as it obscures readability. This should be a human-readable config file, not an efficient code.

[sugestion] AI completion

How hard would it be to generate suggestions based on n-lines before and m-lines after? But I mean something that will work with LSP.

[Bug] parrot.nvim: messages.0.role: Input should be 'user' or 'assistant'

Today, Anthropic API has changed to return the following error.

parrot.nvim: messages.0.role: Input should be 'user' or 'assistant'
Screenshot 2024-05-06 at 9 44 14

The log of the payload is here.

parrot.nvim: M.query(): payload: {
  max_tokens = 4096,
  messages = { {
      content = "",
      role = ""
    }, {
      content = "hello",
      role = "user"
    } },
  model = "claude-3-haiku-20240307",
  stream = true,
  system = "You are a versatile AI assistant with capabilities\nextending to general knowledge and coding support. Whe
n engaging\nwith users, please adhere to the following guidelines to ensure\nthe highest quality of interaction:\n\n-
Admit when unsure by saying 'I don't know.'\n- Ask for clarification when needed.\n- Use first principles thinking to
analyze queries.\n- Start with the big picture, then focus on details.\n- Apply the Socratic method to enhance underst
anding.\n- Include all necessary code in your responses.\n- Stay calm and confident with each task.\n"
}

I make it work with the following changes.

$ git diff
diff --git a/lua/parrot/init.lua b/lua/parrot/init.lua
index cf19ce0..8248c71 100644
--- a/lua/parrot/init.lua
+++ b/lua/parrot/init.lua
@@ -1155,6 +1155,13 @@ M.chat_respond = function(params)
     message.content = message.content:gsub("^%s*(.-)%s*$", "%1")
   end

+  -- remove a message if it's role is empty
+  for i = #messages, 1, -1 do
+    if messages[i].role == "" then
+      table.remove(messages, i)
+    end
+  end
+
   -- write assistant prompt
   local last_content_line = utils.last_content_line(buf)
   vim.api.nvim_buf_set_lines(buf, last_content_line, last_content_line, false, { "", agent_prefix .. agent_suffix, "" })

PrtProvider and PrtAgent doesn't accept args, always run fzf

After updating to the last version of parrot.nvim, I've encountered an error with PrtProvied and PrtAgent. I've defined custom shortcuts that were relying on both of those commands to accept parameters, but after the update the shortcuts stopped working. I've run the commands manually, and even when I did it like :PrtProvider openai it opened fzf window where I had to select provied, as if the "openai" argument was ignored. The same problem was with PrtAgent.

I've prepared simple fix for this on my fork: https://github.com/lzieniew/parrot.nvim and it works for my purposes.
If you are interested in merging it I can open a Pull request - but it's a quick fix and a bit messy, so you might want to rework it

a nil value

Whatever I do, I end up with the following issue:

 ๎ช‡  Error  03:14:26 notify.error lazy.nvim Failed to run `config` for parrot.nvim

/home/tofi/.config/lazy/lua/plugins/parrot.lua:12: attempt to call field 'setup' (a nil value)

# stacktrace:
  - parrot.lua:12 _in_ **config**

I have tried the default config, your config, but the result is the same - a nill value while calling config. I noticed that there is something about running without a user prompt inherited from gp.nvim, but I could not figure out an alternative value for it.

BTW, I use only perplexity API key; open AI is removed from my config.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.