diff --git a/nvim/lazy-lock.json b/nvim/lazy-lock.json index 17c56bb..67a545f 100644 --- a/nvim/lazy-lock.json +++ b/nvim/lazy-lock.json @@ -16,6 +16,7 @@ "indent-blankline.nvim": { "branch": "master", "commit": "e7a4442e055ec953311e77791546238d1eaae507" }, "lazy.nvim": { "branch": "main", "commit": "1159bdccd8910a0fd0914b24d6c3d186689023d9" }, "lazydev.nvim": { "branch": "main", "commit": "491452cf1ca6f029e90ad0d0368848fac717c6d2" }, + "llm.nvim": { "branch": "main", "commit": "9832a149bdcf0709433ca9c2c3a1c87460e98d13" }, "lualine.nvim": { "branch": "master", "commit": "b431d228b7bbcdaea818bdc3e25b8cdbe861f056" }, "luvit-meta": { "branch": "main", "commit": "ce76f6f6cdc9201523a5875a4471dcfe0186eb60" }, "mason-lspconfig.nvim": { "branch": "main", "commit": "25c11854aa25558ee6c03432edfa0df0217324be" }, diff --git a/nvim/lua/plugins/llm.lua b/nvim/lua/plugins/llm.lua new file mode 100644 index 0000000..d2239d8 --- /dev/null +++ b/nvim/lua/plugins/llm.lua @@ -0,0 +1,140 @@ +return { + { + 'huggingface/llm.nvim', + config = function() + local function get_stop_tokens(model) + if model:match '^codellama' then + return { '
', '', ' ', ' ' } + elseif model:match '^qwen' then + return { + '<|endoftext|>', + '<|fim_prefix|>', + '<|fim_middle|>', + '<|fim_suffix|>', + '<|fim_pad|>', + '<|repo_name|>', + '<|file_sep|>', + '<|im_start|>', + '<|im_end|>', + } + elseif model:match '^starcoder' then + return { ' ', ' ', ' ', ' ', '<|endoftext|>' } + elseif model:match '^codestral' then + return { '[INST]', '[/INST]', '[PREFIX]', '[MIDDLE]', '[SUFFIX]' } + elseif model:match '^deepseek%-coder' then + return { '<|fim▁begin|>', '<|fim▁hole|>', '<|fim▁end|>', '<|end▁of▁sentence|>' } + elseif model:match '^granite%-code' then + return { 'System:', 'Question:', 'Answer:' } + end + end + + local function get_fim_options(model) + if model:match '^codellama' then + --return ' ' .. prefix .. '' .. suffix .. ' ' + return { + enabled = true, + prefix = ' ', + suffix = '', + middle = ' ', + } + elseif model:match '^qwen' then + -- return '<|fim_prefix|>' .. prefix .. '<|fim_suffix|>' .. suffix .. '<|fim_middle|>' + return { + enabled = true, + prefix = '<|fim_prefix|>', + suffix = '<|fim_suffix|>', + middle = '<|fim_middle|>', + } + elseif model:match '^starcoder' then + -- return ' ' .. prefix .. ' ' .. suffix .. ' ' + return { + enabled = true, + prefix = ' ', + suffix = ' ', + middle = ' ', + } + elseif model:match '^codestral' then + -- return '[SUFFIX]' .. suffix .. '[PREFIX]' .. prefix + return { + enabled = true, + prefix = '[PREFIX]', + suffix = '[SUFFIX]', + middle = '', + } + elseif model:match '^deepseek%-coder' then + -- return '<|fim▁begin|>' .. prefix .. '<|fim▁hole|>' .. suffix .. '<|fim▁end|>' + return { + enabled = true, + prefix = '<|fim▁begin|>', + suffix = '<|fim▁hole|>', + middle = '<|fim▁end|>', + } + elseif model:match '^granite%-code' then + -- return ' ' .. prefix .. ' ' .. suffix .. ' ' + return { + enabled = true, + prefix = ' ', + suffix = ' ', + middle = ' ', + } + end + end + + local llama_base_url = os.getenv 'LLAMA_API_BASE' or 'http://localhost:11434' + local llama_api_key = os.getenv 'LLAMA_API_KEY' + local model = 'codellama:13b-code-q4_K_M' + -- local model = 'qwen2.5-coder:7b-base-q4_K_M' + -- local model = 'starcoder2:7b-q4_K_M' + -- local model = 'codestral:22b-v0.1-q4_K_M' + -- local model = 'deepseek-coder-v2:16b-lite-base-q4_K_M-fixed' + -- local model = 'granite-code:8b-base-q4_K_M' + + require('llm').setup { + enable_suggestions_on_startup = false, + accept_keymap = ' ', + dismiss_keymap = ' ', + api_token = llama_api_key, + model = model, + backend = 'ollama', + url = llama_base_url .. '/api/generate', + tokens_to_clear = get_stop_tokens(model), + fim = get_fim_options(model), + debounce_ms = 500, + request_body = { + temperature = 0.2, + n = 1, + -- max_tokens = 256, + -- stop = get_stop_tokens(model), + }, + lsp = { + -- NOTE: custom fork of llm-ls is required to use api keys with ollama (e.g. via open webui) + -- to install: + -- git clone https://code.blarg.ca/gered/llm-ls.git + -- cd llm-ls/ + -- cargo install --path ./crates/llm-ls/ --locked + bin_path = os.getenv 'HOME' .. '/.cargo/bin/llm-ls', + -- host = '127.0.0.1', + -- port = 12345, + -- cmd_env = { LLM_LOG_LEVEL = 'INFO' }, + }, + } + + local function map(mode, lhs, rhs, desc) + local opts = { silent = true, noremap = true, desc = desc or '' } + vim.keymap.set(mode, lhs, rhs, opts) + end + + map('i', ' ', ' LLMSuggestion ', 'Request LLM suggestion') + map('n', ' ta', ' LLMToggleAutoSuggest ', 'Toggle: LLM [A]uto Suggestions') + map('i', ' ', function() + local llm = require 'llm.completion' + if llm.shown_suggestion ~= nil then + llm.complete() + else + local keys = vim.api.nvim_replace_termcodes(' ', true, false, true) + vim.api.nvim_feedkeys(keys, 'n', false) + end + end) + end, + }, +}