🗿 model.nvim
在 Neovim 中使用 AI 模型进行补全或聊天。使用 lua 程序化构建提示。适合那些想要自定义提示、实验多个提供者或使用本地模型的人。
https://github.com/gsuuon/model.nvim/assets/6422188/3af3e65d-d13c-4196-abe1-07d605225c10
特性
- 🎪 提供者无关。内置以下内容:
- 托管的
- OpenAI ChatGPT(及兼容的 API)
- Google PaLM,together,huggingface
- 本地的
- llama.cpp
- ollama
- 易于添加自定义的
- 托管的
- 🎨 lua 程序化提示
- 自定义所有内容
- 异步和多步骤提示
- 初学者例子
- 🌠 流式补全
- 直接在缓冲区中
- 转换/提取文本
- 追加/替换/插入模式
- 🦜 在
mchat
文件类型缓冲区中聊天- 在任何时候编辑设置或消息
- 将对话带到不同的模型
- treesitter 高亮和折叠
目录
如果你有任何问题,欢迎在 discussions 提问。
安装
要求
- Nvim 0.9.0 或更高版本
- curl
使用 lazy.nvim
require('lazy').setup({
{
'gsuuon/model.nvim',
-- 如果 lazy = false,则不需要这些
cmd = { 'M', 'Model', 'Mchat' },
init = function()
vim.filetype.add({
extension = {
mchat = 'mchat',
}
})
end,
ft = 'mchat',
keys = {
{'<C-m>d', ':Mdelete<cr>', mode = 'n'},
{'<C-m>s', ':Mselect<cr>', mode = 'n'},
{'<C-m><space>', ':Mchat<cr>', mode = 'n'}
},
-- 要覆盖默认设置,请添加一个 config 字段并调用 setup()
-- config = function()
-- require('model').setup({
-- prompts = {..},
-- chats = {..},
-- ..
-- })
--
-- require('model.providers.llamacpp').setup({
-- binary = '~/path/to/server/binary',
-- models = '~/path/to/models/directory'
-- })
--end
}
})
Treesitter
要在带有 markdown 注入的 chat buffers 中获得 treesitter 高亮,请在加载 model.nvim 后使用 :TSInstall mchat
(如果你使用的是 Lazy,请先运行 :Lazy load model.nvim
)。语法仓库在 gsuuon/tree-sitter-mchat。
秘密
如果你更喜欢将密钥保存在环境之外,它们也可以通过 :help vim.env
或使用 model.nvim 设置表格的 secrets
字段进行编程设置。config.secrets
接受返回字符串的函数表格——当密钥被使用时会调用该函数,并且结果会被缓存用于后续调用:
require('model').setup({
secrets = {
PROVIDER_API_KEY = function()
return '一些密钥'
end
}
})
使用
https://github.com/gsuuon/model.nvim/assets/6422188/ae00076d-3327-4d97-9cc1-41acffead327
model.nvim 附带了一些 starter prompts,并且可以轻松建立你的提问库。有关更复杂的代理类多步骤提示的示例,请参阅 openapi
初始提示,我们将首先获取 openapi-schema,请求 gpt 相关端点,然后将其包含在最终提示中。
提示可以具有 5 种不同的 模式,这些模式决定了响应的处理方式:追加、插入、替换、缓冲、插入或替换。默认是追加,如果没有可视选择,默认输入是整个缓冲区,所以你的响应将位于文件末尾。模式是按每个提示配置的。
命令
运行提示
运行一个补全 提示
:Model [name]
或:M [name]
— 开始对可视选择或当前缓冲区的补全请求。如果未提供提示名称,则使用默认提示。补全通常会编辑当前缓冲区。
开始一个新的 聊天
:Mchat [name] [instruction]
— 使用name
ChatPrompt 开始一个新的聊天缓冲区进行多轮对话。提供一个可选的指令覆盖。如果你目前在mchat
缓冲区中,可以使用-
导入缓冲区的指令到新聊天中,比如:Mchat openai -
,否则它将是新聊天提示的系统指令。
运行一个聊天缓冲区
:Mchat
— 在一个聊天缓冲区请求助手响应。你可以将一个mchat
缓冲区保存为my_conversation.mchat
,稍后重新加载并使用你的下一条消息运行:Mchat
继续之前的对话。你需要在设置中配置相同的 ChatPrompt。
Telescope 扩展
如果你使用 telescope,则可以用 :Telescope model mchat
浏览 mchat 缓冲区。
管理响应
响应使用 extmarks 插入,所以一旦关闭缓冲区,响应就变成了普通文本,并且不会与以下命令一起工作。
:Mselect
— 选择光标下的响应。
删除响应
https://user-images.githubusercontent.com/6422188/233774216-4e100122-3a93-4dfb-a7c7-df50f1221bdd.mp4
:Mdelete
— 删除光标下的响应。如果prompt.mode == 'replace'
,则替换为原始文本。
取消响应
https://user-images.githubusercontent.com/6422188/233773436-3e9d2a15-bc87-47c2-bc5b-d62d62480297.mp4
:Mcancel
— 取消光标下的活动响应。
显示响应
https://user-images.githubusercontent.com/6422188/233773449-3b85355b-bad1-4e40-a699-6a8f5cf4bcd5.mp4
:Mshow
— 闪烁光标下的响应(如果有)。
管理上下文
有一些使用 quickfix 列表的基本上下文管理助手:
:MCadd
— 添加当前文件:MCremove
— 移除当前文件:MCclear
— 移除所有条目:MCpaste
— 粘贴 quickfix 列表文件的内容,包括文件路径和代码块- 示例:
文件:`src/index.tsx` ```typescriptreact import App from "./App"; render( () => <App />), document.getElementById("root")!); ```
quickfix 列表文件的内容(:
MCpaste插入的内容)可以通过
require('model.util.qflist').get_text()` 程序化访问,例如:
local qflist = require('model.util.qflist')
local starters = require('model.prompts.chats')
config.chats = {
['codellama:qfix'] = vim.tbl_deep_extend('force', starters['together:codellama'], {
system = '你是一个聪明的编程助手',
create = function()
return qflist.get_text()
end
}),
}
🚧 工作进行中 - 本地向量存储
设置和使用
要求
- Python 3.10+
pip install numpy openai tiktoken
使用
查看 store 中暴露的模块函数。这使用 OpenAI 的嵌入 API 生成向量,并通过余弦相似性查询它们。
要添加项目,请调用 model.store
lua 模块函数,例如
:lua require('model.store').add_lua_functions()
:lua require('model.store').add_files('.')
查看 store.add_lua_functions
了解如何使用 treesitter 将文件解析为节点并将其添加到本地存储的示例。
要获取查询结果,请调用 store.prompt.query_store
,输入你的查询文本、所需的数量和相似性截止阈值(0.75 似乎不错)。它返回一个 {id: string, content: string} 的列表:
builder = function(input, context)
---@type {id: string, content: string}[]
local store_results = require('model.store').prompt.query_store(input, 2, 0.75)
-- 添加 store_results 到你的消息中
end
:Mstore [命令]
:Mstore init
— 在最近的 git 根目录初始化一个 store.json 文件:Mstore query <查询文本>
— 查询一个 store.json
配置
所有 设置选项 都是可选的。将新的提示添加到 options.prompts.[name]
,将聊天提示添加到 options.chats.[name]
。
require('model').setup({
default_prompt = {},
prompts = {...},
chats = {...},
hl_group = 'Comment',
join_undo = true,
})
提示
提示 放在设置表的 prompts
字段中,通过命令 :Model [提示名称]
或 :M [提示名称]
运行。命令可以通过可用的提示进行补全。
使用 lazy.nvim:
{
'gsuuon/model.nvim',
config = function()
require('model').setup({
prompts = {
instruct = { ... },
code = { ... },
ask = { ... }
}
})
end
}
提示条目定义了如何处理补全请求 - 它接收编辑器输入(整个文件或可视选择)和一些上下文,并生成与任何默认值合并的 api 请求数据。它还定义了如何处理 API 响应 - 例如它可以用响应替换选择(或文件),或在光标位置插入。
查看 starter prompts 了解如何创建提示。查看 参考 获取类型定义。
聊天提示
https://github.com/gsuuon/llm.nvim/assets/6422188/b5082daa-173a-4739-9690-a40ce2c39d15
聊天提示 放在设置表的 chats
字段中。
{
'gsuuon/model.nvim',
config = function()
require('model').setup({
prompts = { ... },
chats = {
gpt4 = { ... },
mixtral = { ... }
starling = { ... }
}
})
end
}
使用 :Mchat [name]
创建一个新的 mchat 缓冲区,使用该聊天提示。该命令可以用可用的聊天提示进行补全。你可以在命令前加上 :horizontal Mchat [name]
或 :tab Mchat [name]
在水平拆分或新选项卡中创建缓冲区。
一个全新的 mchat
缓冲区可能如下所示:
openai
---
{
params = {
model = "gpt-4-1106-preview"
}
}
---
> 你是一个有帮助的助手
数到三
在新缓冲区中运行 :Mchat
(没有名称参数)以获取助手响应。你可以在整个对话过程中根据需要编辑任何消息、参数、选项或系统指令(如果第一行以 >
开头)。你也可以复制/粘贴到一个新缓冲区,set ft=mchat
并运行 :Mchat
。
你可以使用 .mchat
扩展名保存缓冲区,以后使用标题中显示的相同设置继续聊天。mchat
附带一些语法高亮和折叠,以展示各个聊天部分 - 聊天提示运行者的名称、标题中的选项和参数,以及系统消息。
查看 starter chat prompts 了解如何添加自定义内容。查看 参考 获取类型定义。
库自动加载
你可以使用 require('util').module.autoload
代替裸 require
以在使用时始终重新加载模块。这使得提示开发的反馈循环更快:
require('model').setup({
- prompts = require('prompt_library')
+ prompts = require('model.util').module.autoload('prompt_library')
})
我建议仅在主动提示开发期间设置此项,其他时候改用普通的 require
。
提供者
可用的提供者在 ./lua/model/providers 中。
OpenAI ChatGPT
(默认)
将 OPENAI_API_KEY
环境变量设置为你的 API 密钥。
openai 参数
参数记录在 这里。你可以通过调用初始化来覆盖该提供者的 默认参数:
config = function()
require('model.providers.openai').initialize({
model = 'gpt-4-1106-preview'
})
end
openai 提示选项
OpenAI 提示可以使用额外的选项字段与兼容的 API 交互。
compat = vim.tbl_extend('force', openai.default_prompt, {
options = {
url = 'http://127.0.0.1:8000/v1/'
}
})
url?: string
- (可选)用于 API 请求的自定义 URL。默认值为 'https://api.openai.com/v1/'。如果提供了url
,则不会发送环境密钥,你需要包括authorization
。endpoint?: string
- (可选)请求 URL 中使用的端点。默认值为 'chat/completions'。authorization?: string
- (可选)在请求中包含的授权头。覆盖通过环境密钥提供的任何授权。
例如,配置为 Mistral AI "La plateforme":
{
"gsuuon/model.nvim",
cmd = { "Model", "Mchat" },
init = function()
vim.filetype.add({ extension = { mchat = "mchat" } })
end,
ft = "mchat",
keys = { { "<leader>h", ":Model<cr>", mode = "v" } },
config = function()
local mistral = require("model.providers.openai")
local util = require("model.util")
require("model").setup({
hl_group = "Substitute",
prompts = util.module.autoload("prompt_library"),
default_prompt = {
provider = mistral,
options = {
url = "https://api.mistral.ai/v1/",
authorization = "Bearer YOUR_MISTRAL_API_KEY",
},
builder = function(input)
return {
model = "mistral-medium",
temperature = 0.3,
max_tokens = 400,
messages = {
{
role = "system",
content = "你是一个有帮助的助手。",
},
{ role = "user", content = input },
},
}
end,
},
})
end,
},
LlamaCpp
这个提供者使用 llama.cpp 服务器。
你可以手动启动服务器,或者在运行 llamacpp 提示时自动启动服务器。要自动启动服务器,请在配置函数中调用 require('model.providers.llamacpp').setup({})
,并在提示选项中设置一个 model
(见下文)。如果不想自动启动,请将 model
留空。如果提示模型或参数发生改变,服务器将自动重启。
设置
- 构建 llama.cpp
- 下载你想使用的模型,例如 Zephyr 7b beta
- 如果打算使用自动启动,请设置 llamacpp 提供者:
config = function() require('model').setup({ .. }) require('model.providers.llamacpp').setup({ binary = '~/path/to/server/binary', models = '~/path/to/models/directory' }) end
- 在提示中使用 llamacpp 提供者:
local llamacpp = require('model.providers.llamacpp') require('model').setup({ prompts = { zephyr = { provider = llamacpp, options = { model = 'zephyr-7b-beta.Q5_K_M.gguf', args = { '-c', 8192, '-ngl', 35 } }, builder = function(input, context) return { prompt = '<|system|>' .. (context.args or 'You are a helpful assistant') .. '\n</s>\n<|user|>\n' .. input .. '</s>\n<|assistant|>', stops = { '</s>' } } end } } })
LlamaCpp 设置选项
设置 require('model.providers.llamacpp').setup({})
binary: string
- llamacpp 服务器二进制可执行文件的路径models: string
- 模型的父目录路径(与prompt.model
相连)
LlamaCpp 提示选项
model?: string
- (可选)与服务器自动启动一起使用的模型文件路径。如果未指定,服务器将不会启动。args?: string[]
- (可选)在启动时传递给服务器的附加参数数组。使用此选项可指定特定于模型的上下文大小-c
或 GPU 层-ngl
等参数。url?: string
- (可选)覆盖默认服务器 URL。这对于连接到远程服务器或自定义本地服务器非常有用。
Ollama
此处使用 ollama REST 服务器的 /api/generate
端点。raw
默认为 true,并且 stream
始终为 true。
与 starling 的示例提示:
['ollama:starling'] = {
provider = ollama,
params = {
model = 'starling-lm'
},
builder = function(input)
return {
prompt = 'GPT4 Correct User: ' .. input .. '<|end_of_turn|>GPT4 Correct Assistant: '
}
end
},
Google PaLM
将 PALM_API_KEY
环境变量设置为你的 api 密钥。
PaLM 提供者默认使用文本模型(text-bison-001
)。构建器的返回参数可以包含 model = 'chat-bison-001'
以使用聊天模型。
参数应为默认的 generateText 主体,或者使用 model = 'chat-bison-001'
时为 generateMessage 主体。
palm = {
provider = palm,
builder = function(input, context)
return {
model = 'text-bison-001',
prompt = {
text = input
},
temperature = 0.2
}
end
}
Together
将 TOGETHER_API_KEY
环境变量设置为你的 api 密钥。与 together 推理端点 通信。
['together:phind/codellama34b_v2'] = {
provider = together,
params = {
model = 'Phind/Phind-CodeLlama-34B-v2',
max_tokens = 1024
},
builder = function(input)
return {
prompt = '### System Prompt\nYou are an intelligent programming assistant\n\n### User Message\n' .. input ..'\n\n### Assistant\n'
}
end
},
Huggingface API
将 HUGGINGFACE_API_KEY
环境变量设置为你的 api 密钥。
在构建器返回的参数(或 prompt.params
中的静态参数)上设置模型字段。对于不支持流的模型(例如 gpt2
),请设置 params.stream = false
。请查阅 huggingface api 文档 以获取每个任务的请求正文类型。
['hf:starcoder'] = {
provider = huggingface,
options = {
model = 'bigcode/starcoder'
},
builder = function(input)
return { inputs = input }
end
},
Kobold
对于不适用于 llama.cpp 的较旧模型,koboldcpp 可能仍然支持它们。请查看他们的 仓库 以获取设置信息。
Langserve
将 output_parser
设置为正确解析从 /stream
端点返回的内容,并使用 builder
构建输入查询。以下使用 示例 langserve 应用程序 对输入文本开个玩笑。
['langserve:make-a-joke'] = {
provider = langserve,
options = {
base_url = 'https://langserve-launch-example-vz4y4ooboq-uc.a.run.app/',
output_parser = langserve.generation_chunk_parser,
},
builder = function(input, context)
return {
topic = input,
}
end
},
添加你自己的
提供者 实现一个简单的接口,因此很容易添加你自己的。只需将你的提供者设置为提示中的 provider
字段即可。你的提供者需要启动请求并在数据流入、完成或出错时调用处理程序。查看 hf 提供者 以获取支持服务器发送事件流的简单示例。如果不需要流,只需发出请求并使用结果调用 handler.on_finish
。
基本提供者示例:
local test_provider = {
request_completion = function(handlers, params, options)
vim.notify(vim.inspect({params=params, options=options}))
handlers.on_partial('a response')
handlers.on_finish()
end
}
require('model').setup({
prompts = {
test_prompt = {
provider = test_provider,
builder = function(input, context)
return {
input = input,
context = context
}
end
}
}
})
参考
以下是类型及其包含的字段:
SetupOptions
设置 require('model').setup(SetupOptions)
default_prompt?: string
- 使用:Model
或:M
的默认提示。默认是 openai 启动器。prompts?: {string: Prompt}
- 使用:M [name]
的自定义提示表。键是提示的名称。默认是启动器。chats?: {string: ChatPrompt}
- 使用:Mchat [name]
的聊天提示表。键是聊天的名称。hl_group?: string
- 正在进行响应的默认高亮组。默认是'Comment'
。join_undo?: boolean
- 是否将流响应文本作为单个撤销命令加入。当为 true 时,在流期间进行的不相关编辑也会被撤销。默认是true
。
Prompt
params
通常是提供者发送请求的直接数据(例如内容、温度)。options
被提供者用来知道如何处理请求(例如服务器 URL 或本地 LLM 的模型名称)。
设置 require('model').setup({prompts = { [prompt name] = Prompt, .. }})
运行 :Model [prompt name]
或 :M [prompt name]
provider: Provider
- 此提示的提供者,负责请求并返回完成建议。builder: ParamsBuilder
- 将输入(视觉选择或整个缓冲区文本)和 context 转换为请求参数。返回一个参数表或一个带有参数回调的函数。transform?: fun(string): string
- 可选函数,在on_finish
之后转换完成的响应文本,例如提取代码。mode?: SegmentMode | StreamHandlers
- 响应处理模式。默认是 'append'。可以是 'append'、'replace'、'buffer'、'insert' 或 'insert_or_replace' 之一。可以是 StreamHandlers 表以手动处理提供者响应。hl_group?: string
- 活动响应的高亮组。params?: table
- 此提示的静态请求参数。options?: table
- 提供者的可选选项。
Provider
request_completion: fun(handler: StreamHandlers, params?: table, options?: table): function
- 从提供者请求完成流并返回取消回调。在完成请求期间使用处理程序方法将部分增量文本完成传递回提示运行器,并在完成后调用on_finish
。default_prompt? : Prompt
- 此提供者的默认提示(可选)。adapt?: fun(prompt: StandardPrompt): table
- 将标准提示调整为此提供者的参数(可选)。
ParamsBuilder
(函数)
fun(input: string, context: Context): table | fun(resolve: fun(params: table))
- 将输入(视觉选择或整个缓冲区文本)和 context 转换为请求参数。返回一个参数表或一个带有参数回调的函数。
SegmentMode
(枚举)
导出为 local mode = require('model').mode
APPEND = 'append'
- 附加到输入末尾。REPLACE = 'replace'
- 替换输入。BUFFER = 'buffer'
- 创建一个新缓冲区并插入。INSERT = 'insert'
- 在光标位置插入。INSERT_OR_REPLACE = 'insert_or_replace'
- 如果没有选择,则在光标位置插入,或者替换选择。
StreamHandlers
on_partial: fun(partial_text: string): nil
- 由提供者调用以在完成请求期间传递部分增量文本完成。on_finish: fun(complete_text?: string, finish_reason?: string): nil
- 由提供者在完成时调用。接受一个可选参数(complete_text
)和一个可选参数(finish_reason
)。on_error: fun(data: any, label?: string): nil
- 提供者在完成请求期间调用以传递错误数据和可选标签。
ChatPrompt
params
通常是提供者发送请求时的直接数据(例如内容、温度)。options
被提供者用来知道如何处理请求(例如服务器 URL 或本地 LLM 的模型名称)。
设置 require('model').setup({chats = { [chat name] = ChatPrompt, .. }})
运行 :Mchat [chat name]
provider: Provider
- 此聊天提示的提供者。create: fun(input: string, context: Context): string | ChatContents
- 将输入和上下文转换为第一个消息文本或 ChatContents,这些内容将被写入新聊天缓冲区。run: fun(messages: ChatMessage[], config: ChatConfig): table | fun(resolve: fun(params: table): nil )
- 将聊天消息和配置转换为完成请求参数。此函数返回一个包含生成完成所需参数的表格,或返回一个接受回调以解析参数的函数。system?: string
- 可选系统指令,用于为提供者提供特定指示。params?: table
- 在生成完成期间提供给提供者的静态请求参数。options?: table
- 提供者选项,用户可以通过此选项定制聊天提示行为。
ChatMessage
role: 'user' | 'assistant'
- 表示该消息是由用户生成的还是助手生成的。content: string
- 消息的实际内容。
ChatConfig
system?: string
- 可选系统指令,用于为提供者提供上下文或特定指示。params?: table
- 在生成完成期间提供给提供者的静态请求参数。options?: table
- 提供者选项,用户可以通过此选项定制聊天提示行为。
ChatContents
config: ChatConfig
- 此聊天缓冲区的配置,由chatprompt.run
使用。这包括系统指令、静态请求参数和提供者选项等信息。messages: ChatMessage[]
- 聊天缓冲区中的消息。
Context
before: string
- 选择或光标之前的文本。after: string
- 选择或光标之后的文本。filename: string
- 包含所选文本的缓冲区文件名。args: string
- 提供给插件的任何附加命令参数。selection?: Selection
- 如果可用,则为表示所选文本的可选Selection
对象。
Selection
start: Position
- 选择在缓冲区中的起始位置。stop: Position
- 选择在缓冲区中的结束位置。
Position
row: number
- 缓冲区中位置的 0 索引行。col: number or vim.v.maxcol
- 位置在行中的 0 索引列。如果提供vim.v.maxcol
,则表示行的末尾。
示例
提示
require('model').setup({
prompts = {
['prompt name'] = ...
}
})
请求额外的用户指令
https://github.com/gsuuon/llm.nvim/assets/6422188/0e4b2b68-5873-42af-905c-3bd5a0bdfe46
ask = {
provider = openai,
params = {
temperature = 0.3,
max_tokens = 1500
},
builder = function(input)
local messages = {
{
role = 'user',
content = input
}
}
return util.builder.user_prompt(function(user_input)
if #user_input > 0 then
table.insert(messages, {
role = 'user',
content = user_input
})
end
return {
messages = messages
}
end, input)
end,
}
根据 `git diff --staged` 创建提交信息
https://user-images.githubusercontent.com/6422188/233807212-d1830514-fe3b-4d38-877e-f3ecbdb222aa.mp4
['commit message'] = {
provider = openai,
mode = mode.INSERT,
builder = function()
local git_diff = vim.fn.system {'git', 'diff', '--staged'}
return {
messages = {
{
role = 'system',
content = 'Write a short commit message according to the Conventional Commits specification for the following git diff: ```\n' .. git_diff .. '\n```'
}
}
}
end,
}
修改输入以附加消息
https://user-images.githubusercontent.com/6422188/233748890-5dac719a-eb9a-4f76-ab9d-8eba3694a350.mp4
lua/prompt_library.lua
--- 在末尾查找 `<llm:` 并拆分为之前和之后的部分
--- 如果没有指令,则返回所有文本
local function match_llm_directive(text)
local before, _, after = text:match("(.-)(<llm:)%s?(.*)$")
if not before and not after then
before, after = text, ""
elseif not before then
before = ""
elseif not after then
after = ""
end
return before, after
end
local instruct_code = 'You are a highly competent programmer. Include only valid code in your response.'
返回 { ['to code'] = { provider = openai, builder = function(input) local text, directive = match_llm_directive(input)
local msgs = {
{
role = 'system',
content = instruct_code,
},
{
role = 'user',
content = text,
}
}
if directive then
table.insert(msgs, { role = 'user', content = directive })
end
return {
messages = msgs
}
end,
mode = segment.mode.REPLACE
}, code = { provider = openai, builder = function(input) return { messages = { { role = 'system', content = instruct_code, }, { role = 'user', content = input, } } } end, }, }
</details>
<details>
<summary>Replace text with Spanish</summary>
```lua
local openai = require('model.providers.openai')
local segment = require('model.util.segment')
require('model').setup({
prompts = {
['to spanish'] =
{
provider = openai,
hl_group = 'SpecialComment',
builder = function(input)
return {
messages = {
{
role = 'system',
content = 'Translate to Spanish',
},
{
role = 'user',
content = input,
}
}
}
end,
mode = segment.mode.REPLACE
}
}
})
Notifies each stream part and the complete response
local openai = require('model.providers.openai')
require('model').setup({
prompts = {
['show parts'] = {
provider = openai,
builder = openai.default_builder,
mode = {
on_finish = function(final)
vim.notify('final: ' .. final)
end,
on_partial = function(partial)
vim.notify(partial)
end,
on_error = function(msg)
vim.notify('error: ' .. msg)
end
}
},
}
})
Configuration
You can move prompts into their own file and use util.module.autoload
to quickly iterate on prompt development.
Setup
config = function()
local openai = require('model.providers.openai')
-- configure default model params here for the provider
openai.initialize({
model = 'gpt-3.5-turbo-0301',
max_tokens = 400,
temperature = 0.2,
})
local util = require('model.util')
require('model').setup({
hl_group = 'Substitute',
prompts = util.module.autoload('prompt_library'),
default_prompt = {
provider = openai,
builder = function(input)
return {
temperature = 0.3,
max_tokens = 120,
messages = {
{
role = 'system',
content = 'You are helpful assistant.',
},
{
role = 'user',
content = input,
}
}
}
end
}
})
Prompt library
lua/prompt_library.lua
local openai = require('model.providers.openai')
local segment = require('model.util.segment')
return {
code = {
provider = openai,
builder = function(input)
return {
messages = {
{
role = 'system',
content = 'You are a 10x super elite programmer. Continue only with code. Do not write tests, examples, or output of code unless explicitly asked for.',
},
{
role = 'user',
content = input,
}
}
}
end,
},
['to spanish'] = {
provider = openai,
hl_group = 'SpecialComment',
builder = function(input)
return {
messages = {
{
role = 'system',
content = 'Translate to Spanish',
},
{
role = 'user',
content = input,
}
}
}
end,
mode = segment.mode.REPLACE
},
['to javascript'] = {
provider = openai,
builder = function(input, ctx)
return {
messages = {
{
role = 'system',
content = 'Convert the code to javascript'
},
{
role = 'user',
content = input
}
}
}
end,
},
['to rap'] = {
provider = openai,
hl_group = 'Title',
builder = function(input)
return {
messages = {
{
role = 'system',
content = "Explain the code in 90's era rap lyrics"
},
{
role = 'user',
content = input
}
}
}
end,
}
}
Contributing
New starter prompts, providers and bug fixes are welcome! If you've figured out some useful prompts and want to share, check out the discussions.
Roadmap
I'm hoping to eventually add the following features - I'd appreciate help with any of these.
Local retrieval augmented generation
The basics are here - a simple json vectorstore based on the git repo, querying, cosine similarity comparison. It just needs a couple more features to improve the DX of using from prompts.
Enhanced context
Make treesitter and LSP info available in prompt context.