Closed3
Neovim: plenary.curl で stream 処理
例
ollama へのリクエストが stream で飛んでくるので1行毎を buffer に都度送りたい
curl -s http://localhost:11434/api/generate -d '{
"model": "codegemma",
"prompt":"Hello!"
}'
{"model":"codegemma","created_at":"2024-10-13T03:22:23.277732194Z","response":"Hello","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:23.818230637Z","response":"!","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:24.357831778Z","response":" 👋","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:24.891041066Z","response":" It","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:25.411833152Z","response":"'","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:25.954475491Z","response":"s","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:26.486324009Z","response":" nice","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:27.00786642Z","response":" to","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:27.383021173Z","response":" meet","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:27.924946619Z","response":" you","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:28.44119388Z","response":".","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:28.82143907Z","response":" What","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:29.358150899Z","response":" can","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:29.889126231Z","response":" I","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:30.422004398Z","response":" do","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:30.939910817Z","response":" for","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:31.442187757Z","response":" you","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:31.949817234Z","response":" today","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:32.332719691Z","response":"?","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:32.857653405Z","response":" 😊","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:33.383532691Z","response":"\u003c/","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:33.887078247Z","response":"end","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:34.272397572Z","response":"_","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:34.670724455Z","response":"of","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:35.190621273Z","response":"_","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:35.71825778Z","response":"turn","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:36.243699266Z","response":"\u003e","done":false}
{"model":"codegemma","created_at":"2024-10-13T03:22:36.777150246Z","response":"","done":true,"done_reason":"stop","context":[968,2997,235298,559,235298,15508,235313,1645,108,4521,149907,615,235298,559,235298,15508,235313,108,235322,2997,235298,559,235298,15508,235313,2516,108,4521,235341,169692,1165,235303,235256,4866,577,4664,692,235265,2439,798,590,749,604,692,3646,235336,44416,727,615,235298,559,235298,15508,235313],"total_duration":14165388199,"load_duration":49338759,"prompt_eval_count":28,"prompt_eval_duration":573189000,"eval_count":28,"eval_duration":13499366000}
stream 関数のなかで nvim_buf_set_lines を呼ぶためには schedule で包む必要がある
local curl = require("plenary.curl")
local log = require("plenary.log"):new()
log.level = "debug"
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_set_option_value("filetype", "markdown", { buf = bufnr })
local win_opts = {
relative = "editor",
width = math.floor(vim.o.columns * 0.7),
height = math.floor(vim.o.lines / 2),
col = math.floor((vim.o.columns - vim.o.columns * 0.7) / 2), -- 中央に配置
row = math.floor(vim.o.lines * 0.1),
border = "single", -- 枠線を付ける
-- style = 'minimal',
title = "Local LLM",
title_pos = "center",
style = "minimal",
}
vim.api.nvim_open_win(bufnr, false, win_opts)
curl.post({
url = "http://localhost:11434/api/generate",
stream = function(err, chunk)
if chunk then
local res = vim.json.decode(chunk)
vim.schedule(function()
local last_line_num = vim.api.nvim_buf_line_count(bufnr)
local last_line_text = vim.api.nvim_buf_get_lines(bufnr, last_line_num - 1, last_line_num, false)[1]
last_line_text = last_line_text .. res.response
vim.api.nvim_buf_set_lines(bufnr, last_line_num - 1, -1, false, vim.split(last_line_text, "\n"))
if res.done then
vim.api.nvim_buf_set_lines(bufnr, -1, -1, false, { "", "----", "" })
end
end)
end
end,
body = vim.json.encode({
model = "codegemma",
prompt = "Hello!",
}),
})
stream の関数は第3引数に job を取るらしい。job:shutdown を呼んだほうが良いようだ
このスクラップは2024/10/13にクローズされました