vim-ai
这个插件为您的 Vim 和 Neovim 增加了人工智能 (AI) 功能。 您可以生成代码、编辑文本,或与 GPT 模型进行互动对话,这些都由 OpenAI 的 API 提供支持。
要了解使用 AI 命令可以做什么,请参见 社区 Wiki 上的 prompts。
特性
- 生成文本或代码,回答 AI 提问
- 使用 AI 就地编辑选定文本
- 与 ChatGPT 互动对话
- 支持自定义角色等
工作原理
这个插件使用 OpenAI 的 API 生成响应。 您需要注册一个账户并获取 API 密钥。 使用 API 是不免费的,但成本合理,取决于您使用的 tokens 数量,简单来说,就是您发送和接收的文本量 (参见 价格)。 请注意,插件不会在后台发送您的代码。 您只会为您具体选择、提示和聊天内容而分享和支付费用。
安装
前提条件
- 支持 python3 的 Vim 或 Neovim
- API 密钥
# 将 api 密钥保存到 `~/.config/openai.token` 文件
echo "YOUR_OPENAI_API_KEY" > ~/.config/openai.token
# 或者将其设置为环境变量
export OPENAI_API_KEY="YOUR_OPENAI_API_KEY"
# 或配置您的组织 id
echo "YOUR_OPENAI_API_KEY,YOUR_OPENAI_ORG_ID" > ~/.config/openai.token
export OPENAI_API_KEY="YOUR_OPENAI_API_KEY,YOUR_OPENAI_ORG_ID"
默认的 api 密钥文件位置是 ~/.config/openai.token
,但您可以通过在 .vimrc
文件中设置 g:vim_ai_token_file_path
来更改它:
let g:vim_ai_token_file_path = '~/.config/openai.token'
使用 vim-plug
Plug 'madox2/vim-ai'
手动安装
使用内置的 Vim 包 :help packages
# vim
mkdir -p ~/.vim/pack/plugins/start
git clone https://github.com/madox2/vim-ai.git ~/.vim/pack/plugins/start/vim-ai
# neovim
mkdir -p ~/.local/share/nvim/site/pack/plugins/start
git clone https://github.com/madox2/vim-ai.git ~/.local/share/nvim/site/pack/plugins/start/vim-ai
使用方法
要使用 AI 命令,请输入命令并跟上指令提示。您也可以与可视选择结合使用。以下是可用命令的简要概述:
========= 基本 AI 命令 =========
:AI 补全文本
:AIEdit 编辑文本
:AIChat 继续或开启新对话
============= 实用命令 ============
:AIRedo 重复上一个 AI 命令
:AINewChat 开启新对话
:help vim-ai
提示: 按 Ctrl-c
随时取消补全
提示: 设置您自己的 键绑定 或使用命令快捷方式 - :AIE
,:AIC
,:AIR
提示: 通过初始参数 /{role} 将 自定义角色 {role} 传递给上述命令,例如 :AIEdit /grammar
。
提示: 将命令与范围结合 :help range
,例如选择整个缓冲区 - :%AIE fix grammar
如果您对更多提示感兴趣或希望通过更多命令(如 :GitCommitMessage
- 建议 git 提交信息)提升 Vim,用法说明请访问 社区 Wiki。
参考
下文中的 <selection>
表示可视选择或任何其他范围,{instruction}
表示指令提示,{role}
表示 自定义角色,而 ?
符号表示可选参数。
:AI
:AI
- 补全当前行的文本
:AI {prompt}
- 补全提示
<selection> :AI
- 补全选择内容
<selection> :AI {instruction}
- 使用指令补全选择内容
<selection>? :AI /{role} {instruction}?
- 使用角色补全
:AIEdit
<selection>? :AIEdit
- 编辑当前行或选择内容
<selection>? :AIEdit {instruction}
- 使用指令编辑当前行或选择内容
<selection>? :AIEdit /{role} {instruction}?
- 使用角色编辑
:AIChat
:AIChat
- 继续或开始新的对话。
<selection>? :AIChat {instruction}?
- 基于选择内容、指令或两者开始新的对话
<selection>? :AIChat /{role} {instruction}?
- 使用角色补全
当 AI 回答完毕后,您可以进入插入模式,添加您的提示,然后再次使用命令 :AIChat
继续对话。
.aichat
文件
您可以编辑并保存聊天对话到 .aichat
文件并稍后恢复。
这样可以创建可重用的自定义提示,例如:
# ./refactoring-prompt.aichat
>>> system
您是一个 Clean Code 专家,我有以下代码,请将其重构得更简洁明了,以便我的同事更容易维护。同时,请解释您为何要这样重构,以便我在 Pull Request 中添加解释。
>>> user
[附上代码]
要在聊天中包含文件,使用特殊的 include
角色:
>>> user
为以下文件生成文档
>>> include
/home/user/myproject/requirements.txt
/home/user/myproject/**/*.py
每个文件的内容将被添加到一个额外的 user
角色消息中,文件之间用 ==> {path} <==
分隔,其中 path 是文件的路径。通过 glob.gob
进行扩展,当前工作目录(由 getcwd()
决定)的相对路径将解析为绝对路径。
支持的聊天角色有 >>> system
,>>> user
,>>> include
和 <<< assistant
。
:AINewChat
:AINewChat {preset shortname}?
- 开始新的对话
当您需要以特定方式开启新的聊天或 :AIChat
通常会继续当前对话时使用此命令。
参数为打开聊天命令的预设快捷方式 - below
,tab
或 right
。例如::AINewChat right
。
:AIRedo
:AIRedo
- 重复上一个 AI 命令
在 AI
/AIEdit
/AIChat
命令之后立即使用此命令以重试或获取替代补全。
请注意,响应的随机性很大程度上取决于 temperature
参数。
角色
在此插件的上下文中,角色意味着可重用的 AI 指令和/或配置。角色在配置 .ini
文件中定义。例如通过定义 grammar
角色:
let g:vim_ai_roles_config_file = '/path/to/my/roles.ini'
# /path/to/my/roles.ini
[grammar]
prompt = 修正拼写和语法
[grammar.options]
temperature = 0.4
现在您可以选择文本并使用命令 :AIEdit /grammar
运行。
请参阅 roles-example.ini 获取更多示例。
键绑定
该插件不设置任何键绑定。在 .vimrc
中创建您自己的绑定以触发 AI 命令,例如:
" 补全当前行或可视选择中的文本
nnoremap <leader>a :AI<CR>
xnoremap <leader>a :AI<CR>
" 使用自定义提示编辑文本
xnoremap <leader>s :AIEdit 修正拼写和语法<CR>
nnoremap <leader>s :AIEdit 修正拼写和语法<CR>
" 触发聊天
xnoremap <leader>c :AIChat<CR>
nnoremap <leader>c :AIChat<CR>
" 重做上一个 AI 命令
nnoremap <leader>r :AIRedo<CR>
配置
每个命令都有相应的配置变量。
要自定义默认配置,请使用选项集初始化配置变量,例如在 .vimrc
文件中加入:
let g:vim_ai_chat = {
\ "options": {
\ "model": "gpt-4",
\ "temperature": 0.2,
\ },
\}
如上设置后,您可以在 vim 会话期间直接修改选项:
let g:vim_ai_chat['options']['model'] = 'gpt-4'
let g:vim_ai_chat['options']['temperature'] = 0.2
或在聊天缓冲区中直接自定义选项:
[chat-options]
model=gpt-4
temperature=0.2
>>> user
生成一段 lorem ipsum 段落
以下列出了所有可用的配置选项及其默认值。 请注意,聊天模型没有任何 token 限制。
" :AI
" - engine: complete | chat - 请参阅下文的 chat 引擎配置部分
" - options: openai 配置 (请参阅 https://platform.openai.com/docs/api-reference/completions)
" - options.request_timeout: 请求超时时间(秒)
" - options.enable_auth: 是否启用 openai 密钥授权
" - options.selection_boundary: 选择提示包裹 (消除空响应,参见 #20)
" - ui.paste_mode: 使用粘贴模式(请参阅下文注释)
let g:vim_ai_complete = {
\ "engine": "complete",
\ "options": {
\ "model": "gpt-3.5-turbo-instruct",
\ "endpoint_url": "https://api.openai.com/v1/completions",
\ "max_tokens": 1000,
\ "temperature": 0.1,
\ "request_timeout": 20,
\ "enable_auth": 1,
\ "selection_boundary": "#####",
\ },
\ "ui": {
\ "paste_mode": 1,
\ },
\}
" :AIEdit
" - engine: complete | chat - 请参见下文配置聊天引擎的方式
" - options: openai 配置 (参见 https://platform.openai.com/docs/api-reference/completions)
" - options.request_timeout: 请求超时时间(秒)
" - options.enable_auth: 使用 openai 密钥启用授权
" - options.selection_boundary: 选择提示包裹器(消除空响应,参见 #20)
" - ui.paste_mode: 使用粘贴模式(更多信息参见下面的注释)
let g:vim_ai_edit = {
\ "engine": "complete",
\ "options": {
\ "model": "gpt-3.5-turbo-instruct",
\ "endpoint_url": "https://api.openai.com/v1/completions",
\ "max_tokens": 1000,
\ "temperature": 0.1,
\ "request_timeout": 20,
\ "enable_auth": 1,
\ "selection_boundary": "#####",
\ },
\ "ui": {
\ "paste_mode": 1,
\ },
\}
" 此提示指示模型处理语法高亮
let s:initial_chat_prompt =<< trim END
>>> system
你是一个通用助理。
如果你附上代码块,请在 ``` 后添加语法类型以启用语法高亮。
END
" :AIChat
" - options: openai 配置 (参见 https://platform.openai.com/docs/api-reference/chat)
" - options.initial_prompt: 每个聊天请求之前附加的提示(行列表或字符串)
" - options.request_timeout: 请求超时时间(秒)
" - options.enable_auth: 使用 openai 密钥启用授权
" - options.selection_boundary: 选择提示包裹器(消除空响应,参见 #20)
" - ui.populate_options: 在聊天标题中放置 [chat-options]
" - ui.open_chat_command: 预设(preset_below, preset_tab, preset_right)或自定义命令
" - ui.scratch_buffer_keep_open: 在 vim 会话内重用 scratch buffer
" - ui.paste_mode: 使用粘贴模式(更多信息参见下面的注释)
let g:vim_ai_chat = {
\ "options": {
\ "model": "gpt-4o",
\ "endpoint_url": "https://api.openai.com/v1/chat/completions",
\ "max_tokens": 0,
\ "temperature": 1,
\ "request_timeout": 20,
\ "enable_auth": 1,
\ "selection_boundary": "",
\ "initial_prompt": s:initial_chat_prompt,
\ },
\ "ui": {
\ "code_syntax_enabled": 1,
\ "populate_options": 0,
\ "open_chat_command": "preset_below",
\ "scratch_buffer_keep_open": 0,
\ "paste_mode": 1,
\ },
\}
" 注释:
" ui.paste_mode
" - 如果禁用,代码缩进会正常工作,但 AI 不一定总是用代码块响应
" 因此可能会乱
" - 更多信息参见 vim 帮助 `:help paste`
" options.max_tokens
" - 注意提示加上 max_tokens 应小于模型的 token 限制,参见 #42, #46
" - 将 max tokens 设置为 0 会将其排除在 OpenAI API 请求参数之外,目前
" 并不明确/未记录其具体作用,但似乎可以解决模型达到 token 限制时的问题,这时
" 的响应为 `OpenAI: HTTPError 400`
使用自定义 API
可以配置插件使用不同的 OpenAI 兼容端点。 参见 Custom APIs 部分的一些很棒的项目,位于 Community Wiki。
let g:vim_ai_chat = {
\ "options": {
\ "endpoint_url": "http://localhost:8000/v1/chat/completions",
\ "enable_auth": 0,
\ },
\}
使用聊天引擎进行补全和编辑
可以配置聊天模型,如 gpt-4o
,在 :AI
和 :AIEdit
命令中使用。
这些模型更便宜,但目前不太适合代码编辑/补全,因为它们回应以类人的文字和评论。
根据使用案例,一个好的初始提示可以帮助指示聊天模型以所需方式回应:
let initial_prompt =<< trim END
>>> system
你将扮演一个补全引擎,具有以下参数:
任务:提供简洁的代码/文本补全、生成、转换或解释
主题:一般编程和文本编辑
风格:纯结果,没有任何评论,除非评论是必要的
受众:文本编辑器用户和需要转换/生成文本的程序员
END
let chat_engine_config = {
\ "engine": "chat",
\ "options": {
\ "model": "gpt-4o",
\ "endpoint_url": "https://api.openai.com/v1/chat/completions",
\ "max_tokens": 0,
\ "temperature": 0.1,
\ "request_timeout": 20,
\ "selection_boundary": "",
\ "initial_prompt": initial_prompt,
\ },
\}
let g:vim_ai_complete = chat_engine_config
let g:vim_ai_edit = chat_engine_config
自定义命令
你可能会发现 Community Wiki 上 Custom commands 中的自定义命令集合很有用。
要创建自定义命令,可以调用 AIRun
, AIEditRun
和 AIChatRun
函数。例如:
" 无参数的自定义命令建议 git 提交消息
function! GitCommitMessageFn()
let l:diff = system('git --no-pager diff --staged')
let l:prompt = "从以下 diff 中生成简短的提交消息:\n" . l:diff
let l:config = {
\ "engine": "chat",
\ "options": {
\ "model": "gpt-4o",
\ "initial_prompt": ">>> system\nyou are a code assistant",
\ "temperature": 1,
\ },
\}
call vim_ai#AIRun(l:config, l:prompt)
endfunction
command! GitCommitMessage call GitCommitMessageFn()
" 为选定代码块提供代码审查的自定义命令
function! CodeReviewFn(range) range
let l:prompt = "编程语法是 " . &filetype . ",审查下面的代码"
let l:config = {
\ "options": {
\ "initial_prompt": ">>> system\nyou are a clean code expert",
\ },
\}
exe a:firstline.",".a:lastline . "call vim_ai#AIChatRun(a:range, l:config, l:prompt)"
endfunction
command! -range=0 CodeReview <line1>,<line2>call CodeReviewFn(<count>)
贡献
欢迎贡献!请随时打开拉取请求、报告问题或贡献到 Community Wiki。
重要免责声明
准确性: GPT 擅长生成看起来正确的文本和代码,但可能完全错误。请务必彻底审查、阅读和测试所有由此插件生成的输出!
隐私: 此插件在生成补全和编辑时向 OpenAI 发送文本。因此,请勿在包含敏感信息的文件上使用它。
许可证