Open Chewt opened 1 month ago
In case anyone else wants to test this, here is the custom command function I made:
local custom_command = function(options)
local context = require('gen.init').context
local body = vim.tbl_extend("force",
{model = options.model, stream = true},
options.body)
local messages = {}
if context then messages = context end
-- Add new prompt to the context
table.insert(messages, {role = "user", content = options.prompt})
body.messages = messages
if options.model_options ~= nil then -- override model options from gen command (if exist)
body = vim.tbl_extend("force", body, options.model_options)
end
local json = options.json(body)
json = json:match("^'(.*)'$") or json -- remove surrounding quotes
-- Write json to tmp file
local fh, err = io.open("/tmp/tempfile", "w")
if not fh then
return nil, err
end
fh:write(json)
fh:close()
-- return curl command
return "curl --no-buffer --silent -X POST http://" .. options.host .. ":" .. options.port .. "/api/chat -d @/tmp/tempfile"
end
just add command=custom_command
to your require('gen').setup()
config
Thanks for opening this issue and doing the research, @Chewt !
Would it also be possible to increase the character limit for your shell commands?
Which os/shell do you use?
Thank you and best regards, David
My OS is Linux (EndeavourOS specifically), and my shell is Zsh.
However I have discovered that my assumption that the shell was the cause has turned out to be false.
It turns out there is a hardcoded limit in linux for the maximum length of a single argument on the command line, which is hardcoded as 131072 bytes (this number comes from 32 * PAGESIZE in the Linux kernal, where the page size is 4kB)
Since the curl command is curl --no-buffer --silent -X POST http://localhost:11434/api/chat -d $body
and $body
is replaced by a string json object, the json object is treated as a single argument.
Depending on the model, this is a hard limit on context size to be within the bounds of a single string argument on the command line.
If a sufficiently long prompt is given, say for example a long enough file, then the curl command fails due to shell character limits. To be clear this isn't a context window error, its the shell running the curl command failing because too many characters are in the shell command. I've been researching ways to fix this on my own the past couple of days, but I thought I would open an issue to get some more eyes on it. I believe this is what was happening in #95 as well, but it looks like they closed their issue after no response was given for a few weeks.
Some options I have come across: Writing the prompt to a temp file then using the curl command with
curl ..... -d @/temp/file/path
instead ofcurl ..... -d $body
like it is in the default. I have tried this by replacing the default
command
option with my own custom command that implements this, however reading from a file seems to disable the--no-buffer
option set in curl (or at least this is what I think is happening), so the response looks like this (run with :mesasges in nvim and the debug flag in gen.options set to true):As you can see, each response is prefixed with
Response data:
rather than one long Response as seen when running:messages
with the default config:Another way to potentially fix this is using an external plugin which implements curl in lua such as plenary. This is a common plugin used as a dependancy in many other nvim plugins, such as ollama.nvim and others. I don't know for sure if their implementation overcomes this issue with too many characters in the shell command, but I think it is worth testing.