feat: remove chunking and switch it to a multi step process instead if tokens are too high

This commit is contained in:
2024-12-30 00:42:51 +01:00
parent 761ef836cd
commit 9251043aec
3 changed files with 40 additions and 79 deletions

View File

@@ -37,6 +37,9 @@ local prompt_blocks = {
and a top-level key named 'files', which is a list of file changes. Each element in 'files' must be a mapping with: and a top-level key named 'files', which is a list of file changes. Each element in 'files' must be a mapping with:
- 'path' for the file path relative to the projects root directory. - 'path' for the file path relative to the projects root directory.
- either 'content' with a multiline string for new content, or 'delete: true' if the file should be deleted. - either 'content' with a multiline string for new content, or 'delete: true' if the file should be deleted.
Important: dont use comments in the code to explain which steps you have taken.
Comments should just explain the code and not your thought process.
You can explain your thought process outside of the YAML.
If more context is needed at any point before providing the final YAML, request it outside of the YAML. If more context is needed at any point before providing the final YAML, request it outside of the YAML.
Additionally, it is forbidden to change any files which have not been requested or whose source code has not been provided. Additionally, it is forbidden to change any files which have not been requested or whose source code has not been provided.

View File

@@ -77,18 +77,25 @@ local function get_estimate_fn()
end end
end end
----------------------------------------------------------------------------- ---------------------------------------------------------------------------------
-- CHUNKING -- Step-by-Step Handling (replaces chunking)
----------------------------------------------------------------------------- ---------------------------------------------------------------------------------
local function handle_chunking_if_needed(prompt, estimate_fn) local function handle_step_by_step_if_needed(prompt, estimate_fn)
local conf = config.load() local conf = config.load()
local token_count = estimate_fn(prompt) local token_count = estimate_fn(prompt)
if not conf.enable_chunking or token_count <= (conf.token_limit or 8000) then -- If step-by-step is disabled or token count is within limit, return original prompt
if not conf.enable_step_by_step or token_count <= (conf.token_limit or 8000) then
return { prompt } return { prompt }
end end
local chunks = ui.chunkify(prompt, estimate_fn, conf.token_limit or 8000) -- If we exceed the token limit, create a single message prompting the user to split tasks
return chunks local step_prompt = [[
It appears this request might exceed the model's token limit if done all at once.
Please break down the tasks into smaller steps and handle them one by one.
At each step, we'll provide relevant files or context if needed.
Thank you!
]]
return { step_prompt }
end end
-- Close an existing buffer by name (if it exists) -- Close an existing buffer by name (if it exists)
@@ -339,33 +346,16 @@ function M.run_chatgpt_command()
store_prompt_for_reference(prompt) store_prompt_for_reference(prompt)
local estimate_fn = get_estimate_fn() local estimate_fn = get_estimate_fn()
local chunks = handle_chunking_if_needed(prompt, estimate_fn) local chunks = handle_step_by_step_if_needed(prompt, estimate_fn)
-- We either get the original prompt or a single special prompt
copy_to_clipboard(chunks[1])
if #chunks == 1 then if #chunks == 1 then
copy_to_clipboard(chunks[1])
vim.api.nvim_out_write("Prompt copied to clipboard! Paste into ChatGPT.\n") vim.api.nvim_out_write("Prompt copied to clipboard! Paste into ChatGPT.\n")
else else
-- Multiple chunks. We'll create separate scratch buffers -- In this revised approach, we no longer generate multiple buffers.
for i, chunk in ipairs(chunks) do -- We simply rely on the single step-by-step prompt in chunks[1].
close_existing_buffer_by_name("ChatGPT_Generated_Chunk_" .. i .. "$") vim.api.nvim_out_write("Step-by-step prompt copied to clipboard!\n")
local cbuf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_name(cbuf, "ChatGPT_Generated_Chunk_" .. i)
vim.api.nvim_buf_set_option(cbuf, "filetype", "markdown")
local lines = {
"# Chunk " .. i .. " of " .. #chunks .. ":",
"# Copy/paste this chunk into ChatGPT, then come back and copy the next chunk as needed.",
""
}
vim.list_extend(lines, vim.split(chunk, "\n"))
vim.api.nvim_buf_set_lines(cbuf, 0, -1, false, lines)
if i == 1 then
copy_to_clipboard(chunk)
vim.api.nvim_out_write("Copied chunk #1 of " .. #chunks .. " to clipboard!\n")
end
end
end end
vim.api.nvim_buf_set_option(bufnr, "modified", false) vim.api.nvim_buf_set_option(bufnr, "modified", false)
@@ -498,28 +488,17 @@ function M.run_chatgpt_paste_command()
local token_count = estimate_fn(prompt) local token_count = estimate_fn(prompt)
ui.debug_log("Returning requested files. Token count: " .. token_count) ui.debug_log("Returning requested files. Token count: " .. token_count)
if token_count > (conf.token_limit or 8000) then -- We simply check if step-by-step is enabled, then provide a short note if needed
if conf.enable_chunking then if token_count > (conf.token_limit or 8000) and conf.enable_step_by_step then
local chunks = ui.chunkify(prompt, estimate_fn, conf.token_limit or 8000) local step_message = [[
for i, chunk in ipairs(chunks) do It appears this requested data is quite large. Please consider handling these files step by step.
local cbuf = vim.api.nvim_create_buf(false, true) Let me know how you would like to proceed.
vim.api.nvim_buf_set_name(cbuf, "ChatGPT_Requested_Files_Chunk_" .. i) ]]
local lines = { copy_to_clipboard(step_message)
"# Chunk " .. i .. " of " .. #chunks .. ":", print("Step-by-step guidance copied to clipboard!")
"# Copy/paste this chunk into ChatGPT, then come back and copy next chunk as needed.", return
"" elseif token_count > (conf.token_limit or 8000) then
} vim.api.nvim_err_writeln("Requested files exceed token limit. No step-by-step support enabled.")
vim.list_extend(lines, vim.split(chunk, "\n"))
vim.api.nvim_buf_set_lines(cbuf, 0, -1, false, lines)
if i == 1 then
copy_to_clipboard(chunk)
print("Copied chunk #1 of " .. #chunks .. " to clipboard!")
end
end
else
vim.api.nvim_err_writeln("Too many requested files. Exceeds token limit.")
end
return return
end end
@@ -531,4 +510,4 @@ function M.run_chatgpt_paste_command()
end end
end end
return M return M

View File

@@ -19,8 +19,7 @@ end
function M.debug_log(msg) function M.debug_log(msg)
if conf.improved_debug and debug_bufnr then if conf.improved_debug and debug_bufnr then
local lines = vim.split(msg, "\n") vim.api.nvim_buf_set_lines(debug_bufnr, -1, -1, false, { msg })
vim.api.nvim_buf_set_lines(debug_bufnr, -1, -1, false, lines)
else else
if conf.debug then if conf.debug then
vim.api.nvim_out_write("[chatgpt_nvim:debug] " .. msg .. "\n") vim.api.nvim_out_write("[chatgpt_nvim:debug] " .. msg .. "\n")
@@ -89,28 +88,8 @@ function M.pick_directories(dirs)
return selected_dirs return selected_dirs
end end
function M.chunkify(text, estimate_tokens_fn, token_limit) --------------------------------------------------------------------------------
local lines = vim.split(text, "\n") -- The old chunkify method has been removed, since we now rely on step-by-step
local chunks = {} --------------------------------------------------------------------------------
local current_chunk = {}
local current_text = ""
for _, line in ipairs(lines) do return M
local test_text = (current_text == "") and line or (current_text .. "\n" .. line)
local est_tokens = estimate_tokens_fn(test_text)
if est_tokens > token_limit then
table.insert(chunks, current_text)
current_text = line
else
current_text = test_text
end
end
if current_text ~= "" then
table.insert(chunks, current_text)
end
return chunks
end
return M