Skip to content

Latest commit

 

History

History
538 lines (431 loc) · 27.4 KB

File metadata and controls

538 lines (431 loc) · 27.4 KB

llm.nvim

English | 简体中文


Important

大语言模型插件,让你在Neovim中与大模型交互

  1. 支持任意一款大模型,比如GPT,GLM,Kimi、DeepSeek、Gemini、Qwen或者本地运行的大模型(比如ollama)

  2. 支持定义属于你自己的AI工具,且不同工具可以使用不同的模型

  3. 最重要的一点,你可以使用任何平台提供的免费模型(比如CopilotGithub modelssiliconflowopenrouterCloudflare或者其他的平台)

Note

不同大模型的配置(比如ollama, deepseek)、 界面的配置、以及AI工具的配置(包括代码补全) 请先查阅 examples. 这里有你想知道的大部分内容。在使用插件之前,应该确保你的LLM_KEY是有效的,并且该环境变量已经生效。

wikidocs也可能对你有用。

用户QQ群:1037412539

目录

截图

聊天界面

模型配置 | 界面配置

?显示快捷键帮助窗口

  • 浮动风格

llm-float-ui

  • 分屏风格

llm-split-ui

enable_cword_context = true: normal模式下翻译当前光标下的文本

llm-translate

解释代码

流式输出 | 非流式输出

llm-explain-code

一次性,不保留历史记录

你可以配置 inline_assistant 来决定是否展示diff (默认按'd'展示)

llm-ask

你可以配置 inline_assistant 来决定是否展示diff (默认按'd'展示)

llm-attach

优化代码

llm-optimize-code

llm-optimize-compare-action

test-case

llm-trans

llm-images

llm-git-commit-msg

llm-docstring

/buffer | /file | @web_search

web-search

诊断信息

disposable_ask_handlerattach_to_chat_handlerside_by_side_handleraction_handler均可以开启该特性:

diagnostic = { min = vim.diagnostic.severity.HINT },
-- or
-- diagnostic = { vim.diagnostic.severity.WARN, vim.diagnostic.severity.ERROR },
-- see `:h diagnostic-severity`

diagnostic

Lsp

Note

新特性,还在持续迭代

disposable_ask_handlerattach_to_chat_handleraction_handler均可以开启该特性:

lsp = {
  cpp = { methods = { "definition", "declaration" } },
  python = { methods = { "definition" } },
  lua = { methods = { "definition", "declaration" } },

  root_dir = { {'pyproject.toml', 'setup.py' }, ".git" },
},

lsp

⬆ 返回目录

安装

依赖

  • curl: 请自行安装
  • fzf >= 0.37.0: 可选的,split风格预览会话历史以及图像识别工具选择图片会依赖fzf(作者用的0.39.0)
  • render-markdown.nvim: 可选的。更好的markdown预览依赖此插件。
{
    "MeanderingProgrammer/render-markdown.nvim",
    dependencies = {
      {
        "nvim-treesitter/nvim-treesitter",
        branch = "main",
        config = function()
          vim.api.nvim_create_autocmd("FileType", {
            pattern = { "llm", "markdown" },
            callback = function()
              vim.treesitter.start(0, "markdown")
            end,
          })
        end,
      },
      "nvim-mini/mini.icons",
    }, -- if you use standalone mini plugins
    ft = { "markdown", "llm" },

    config = function()
      require("render-markdown").setup({
        restart_highlighter = true,
        heading = {
          enabled = true,
          sign = false,
          position = "overlay", -- inline | overlay
          icons = { "󰎤 ", "󰎧 ", "󰎪 ", "󰎭 ", "󰎱 ", "󰎳 " },
          signs = { "󰫎 " },
          width = "block",
          left_margin = 0,
          left_pad = 0,
          right_pad = 0,
          min_width = 0,
          border = false,
          border_virtual = false,
          border_prefix = false,
          above = "",
          below = "",
          backgrounds = {},
          foregrounds = {
            "RenderMarkdownH1",
            "RenderMarkdownH2",
            "RenderMarkdownH3",
            "RenderMarkdownH4",
            "RenderMarkdownH5",
            "RenderMarkdownH6",
          },
        },
        dash = {
          enabled = true,
          icon = "",
          width = 0.5,
          left_margin = 0.5,
          highlight = "RenderMarkdownDash",
        },
        code = { style = "normal" },
      })
    end,
  }

准备工作

  1. 在官网注册并获取你的API Key (Cloudflare 需要额外获取你的 account).

  2. 在你的zshrc或者bashrc中设置LLM_KEY环境变量(Cloudflare 需要额外设置 ACCOUNT)

export LLM_KEY=<Your API_KEY>
export ACCOUNT=<Your ACCOUNT> # just for cloudflare

不同AI平台的官网

Expand the table.
平台 获取API Key的链接 备注
Cloudflare https://dash.cloudflare.com/ 你可以在这里看到cloudflare的所有模型, 其中标注beta的是免费模型.
ChatGLM(智谱清言) https://open.bigmodel.cn/
Kimi(月之暗面) Moonshot AI 开放平台
Github Models Github Token
siliconflow (硅基流动) siliconflow 你可以在这里看到硅基流动上所有的模型,选择只看免费可以看到所有的免费模型
Deepseek https://platform.deepseek.com/api_keys
Openrouter https://openrouter.ai/
Chatanywhere https://api.chatanywhere.org/v1/oauth/free/render 每天200次免费调用GPT-4o-mini.

对于本地大模型, 在zshrc or bashrc中设置 LLM_KEYNONE.

⬆ 返回目录

最小安装示例

  • lazy.nvim
  {
    "Kurama622/llm.nvim",
    dependencies = { "nvim-lua/plenary.nvim", "MunifTanjim/nui.nvim"},
    cmd = { "LLMSessionToggle", "LLMSelectedTextHandler", "LLMAppHandler" },
    config = function()
      require("llm").setup({
        url = "https://models.inference.ai.azure.com/chat/completions",
        model = "gpt-4o-mini",
        api_type = "openai"
      })
    end,
    keys = {
      { "<leader>ac", mode = "n", "<cmd>LLMSessionToggle<cr>" },
    },
  }
  • Mini.deps
require("mini.deps").setup()
MiniDeps.add({
        source = "Kurama622/llm.nvim",
        depends = { "nvim-lua/plenary.nvim", "MunifTanjim/nui.nvim" },
        cmd = { "LLMSessionToggle", "LLMSelectedTextHandler", "LLMAppHandler" },
})

require("llm").setup({
        url = "https://models.inference.ai.azure.com/chat/completions",
        model = "gpt-4o-mini",
        api_type = "openai"
})

配置模板

配置

Commands

Cmd Description
LLMSessionToggle 打开/隐藏聊天界面
LLMSelectedTextHandler 处理所选文本,其处理方式取决于您输入的提示词
LLMAppHandler 调用AI工具

模型参数

Expand the table.
Parameter Description Value
url 请求地址 String
model 模型名 String
api_type 输出解析格式 workers-ai | zhipu|
openai | ollama|
deepseek | copilot |
lmstudio
timeout 响应最大超时时间 (单位: 秒) Number
proxy Curl请求代理 String (noproxy|<ip>:<port>) | nil
fetch_key API KEY或者返回API KEY的函数 Function | String
max_tokens 响应的最大token数 Number
temperature 取值范围0到1。值越小,回复越贴近主题; 值越大,回复越发散,但太高的值也容易使回复偏离主题 Number
top_p 取值范围0到1。值越高,回复越多样化,重复性越低。(也越容易产生偏离主题的回复) Number
enable_thinking 启用thinking功能 (模型本身需要支持thinking) Boolean
thinking_budget 思考过程的最大token长度 (仅在 enable_thinking 为真时生效) Number
schema Function-calling 所需的函数参数描述 Table
functions_tbl Function-calling 所需的函数字典 Table
keep_alive 保持连接 (一般用于ollama) see keep_alive/OLLAMA_KEEP_ALIVE
streaming_handler 自定义流式输出的解析格式 Function
parse_handler 自定义非流式输出的解析格式 Function

快捷键

Expand the table.
Style Keyname Description Default: [mode] keymap Window
float Input:Submit 提交问题 [i] ctrl+g Input
float Input:Cancel 中止对话请求 [i] ctrl+c Input
float Input:Resend 重新请求 [i] ctrl+r Input
float Input:HistoryNext 选择下一个历史会话 [i] ctrl+j Input
float Input:HistoryPrev 选择上一个历史会话 [i] ctrl+k Input
float Input:ModelsNext 选择下一个模型 [i] ctrl+shift+j Input
float Input:ModelsPrev 选择上一个模型 [i] ctrl+shift+k Input
split Output:Ask 打开输入窗口。normal 模式下, 按回车提交问题 [n] i Output
split Output:Cancel 中止对话请求 [n] ctrl+c Output
split Output:Resend 重新请求 [n] ctrl+r Output
float/split Session:Toggle 打开/隐藏聊天界面 [n] <leader>ac Input+Output
float/split Session:Close 关闭聊天界面 [n] <esc> float: Input+Output
split: Output
float/split Session:New 创建一个新的会话 [n] <C-n> float: Input+Output
split: Output
float/split Session:Models 打开模型列表窗口 [n] ctrl+m float: App input window
split: Output
split Session:History 打开会话历史窗口: 移动遵循fzf的配置, <cr> 确认选择, <esc>关闭 [n] ctrl+h Output
float Focus:Input 从输出窗口切换到输入窗口 - Output
float Focus:Output 从输入窗口切换到输出窗口 - Input
float PageUp 输出窗口向上翻页 [n/i] Ctrl+b Input
float PageDown 输出窗口向下翻页 [n/i] Ctrl+f Input
float HalfPageUp 输出窗口向上翻半页 [n/i] Ctrl+u Input
float HalfPageDown 输出窗口向下翻半页 [n/i] Ctrl+d Input
float JumpToTop 定位到输出窗口顶部 [n] gg Input
float JumpToBottom 定位到输出窗口低部 [n] G Input

工具

Handler name Description
side_by_side_handler 用两个并排的窗口来展示结果
action_handler 在原文件中展示AI建议代码和原代码的diff
qa_handler 单轮对话的问答
flexi_handler 结果将在一个弹性窗口中显示(窗口大小根据输出文本的量自动计算)
disposable_ask_handler 灵活的提问,您可以选择一段代码进行提问,或者直接提问(当前缓冲区是上下文)
attach_to_chat_handler 将选择的文本附加到Chat会话的上下文
completion_handler 代码补全
curl_request_handler 与LLM之间最简单的交互通常用于查询账户余额或可用的模型列表等

每个handler的具体参数参考docs/tools.

示例: AI 工具配置

UI

参考 UI 配置nui/popup

⬆ 返回目录

自定义解析函数

对于流式输出,我们使用自定义的streaming_handler;对于一次性返回输出结果的AI工具,我们使用自定义的parse_handler

下面是ollama运行llama3.2:1b的样例

展开代码
local function local_llm_streaming_handler(chunk, ctx, F)
  if not chunk then
    return ctx.assistant_output
  end
  local tail = chunk:sub(-1, -1)
  if tail:sub(1, 1) ~= "}" then
    ctx.line = ctx.line .. chunk
  else
    ctx.line = ctx.line .. chunk
    local status, data = pcall(vim.json.decode, ctx.line)
    if not status or not data.message.content then
      return ctx.assistant_output
    end
    ctx.assistant_output = ctx.assistant_output .. data.message.content
    F.WriteContent(ctx.bufnr, ctx.winid, data.message.content)
    ctx.line = ""
  end
  return ctx.assistant_output
end

local function local_llm_parse_handler(chunk)
  local assistant_output = chunk.message.content
  return assistant_output
end

return {
  {
    "Kurama622/llm.nvim",
    dependencies = { "nvim-lua/plenary.nvim", "MunifTanjim/nui.nvim" },
    cmd = { "LLMSessionToggle", "LLMSelectedTextHandler" },
    config = function()
      require("llm").setup({
        url = "http://localhost:11434/api/chat", -- your url
        model = "llama3.2:1b",

        streaming_handler = local_llm_streaming_handler,
        app_handler = {
          WordTranslate = {
            handler = tools.flexi_handler,
            prompt = "Translate the following text to Chinese, please only return the translation",
            opts = {
              parse_handler = local_llm_parse_handler,
              exit_on_move = true,
              enter_flexible_window = false,
            },
          },
        }
      })
    end,
    keys = {
      { "<leader>ac", mode = "n", "<cmd>LLMSessionToggle<cr>" },
    },
  }
}

⬆ 返回目录

待办

todo-list

⬆ 返回目录

作者的配置文件

plugins/llm

致谢

以下开源项目为llm.nvim提供了宝贵的灵感和参考:

特别鸣谢

ACKNOWLEDGMENTS