fix: memory (#1718)
This commit is contained in:
@@ -345,6 +345,7 @@ M._defaults = {
|
|||||||
},
|
},
|
||||||
history = {
|
history = {
|
||||||
max_tokens = 4096,
|
max_tokens = 4096,
|
||||||
|
carried_entry_count = nil,
|
||||||
storage_path = vim.fn.stdpath("state") .. "/avante",
|
storage_path = vim.fn.stdpath("state") .. "/avante",
|
||||||
paste = {
|
paste = {
|
||||||
extension = "png",
|
extension = "png",
|
||||||
|
|||||||
@@ -60,10 +60,11 @@ end
|
|||||||
|
|
||||||
---@param bufnr integer
|
---@param bufnr integer
|
||||||
---@param history avante.ChatHistory
|
---@param history avante.ChatHistory
|
||||||
|
---@param entries? avante.ChatHistoryEntry[]
|
||||||
---@param cb fun(memory: avante.ChatMemory | nil): nil
|
---@param cb fun(memory: avante.ChatMemory | nil): nil
|
||||||
function M.summarize_memory(bufnr, history, cb)
|
function M.summarize_memory(bufnr, history, entries, cb)
|
||||||
local system_prompt = [[You are a helpful AI assistant tasked with summarizing conversations.]]
|
local system_prompt = [[You are a helpful AI assistant tasked with summarizing conversations.]]
|
||||||
local entries = Utils.history.filter_active_entries(history.entries)
|
if not entries then entries = Utils.history.filter_active_entries(history.entries) end
|
||||||
if #entries == 0 then
|
if #entries == 0 then
|
||||||
cb(nil)
|
cb(nil)
|
||||||
return
|
return
|
||||||
@@ -202,9 +203,7 @@ function M.generate_prompts(opts)
|
|||||||
if memory ~= "" then table.insert(messages, { role = "user", content = memory }) end
|
if memory ~= "" then table.insert(messages, { role = "user", content = memory }) end
|
||||||
end
|
end
|
||||||
|
|
||||||
if instructions then
|
if instructions then table.insert(messages, { role = "user", content = instructions }) end
|
||||||
table.insert(messages, { role = "user", content = string.format("<question>%s</question>", instructions) })
|
|
||||||
end
|
|
||||||
|
|
||||||
local remaining_tokens = max_tokens - Utils.tokens.calculate_tokens(system_prompt)
|
local remaining_tokens = max_tokens - Utils.tokens.calculate_tokens(system_prompt)
|
||||||
|
|
||||||
@@ -212,12 +211,17 @@ function M.generate_prompts(opts)
|
|||||||
remaining_tokens = remaining_tokens - Utils.tokens.calculate_tokens(message.content)
|
remaining_tokens = remaining_tokens - Utils.tokens.calculate_tokens(message.content)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local dropped_history_messages = {}
|
||||||
if opts.history_messages then
|
if opts.history_messages then
|
||||||
if Config.history.max_tokens > 0 then remaining_tokens = math.min(Config.history.max_tokens, remaining_tokens) end
|
if Config.history.max_tokens > 0 then remaining_tokens = math.min(Config.history.max_tokens, remaining_tokens) end
|
||||||
-- Traverse the history in reverse, keeping only the latest history until the remaining tokens are exhausted and the first message role is "user"
|
-- Traverse the history in reverse, keeping only the latest history until the remaining tokens are exhausted and the first message role is "user"
|
||||||
local history_messages = {}
|
local history_messages = {}
|
||||||
for i = #opts.history_messages, 1, -1 do
|
for i = #opts.history_messages, 1, -1 do
|
||||||
local message = opts.history_messages[i]
|
local message = opts.history_messages[i]
|
||||||
|
if Config.history.carried_entry_count ~= nil then
|
||||||
|
if #history_messages > Config.history.carried_entry_count then break end
|
||||||
|
table.insert(history_messages, message)
|
||||||
|
else
|
||||||
local tokens = Utils.tokens.calculate_tokens(message.content)
|
local tokens = Utils.tokens.calculate_tokens(message.content)
|
||||||
remaining_tokens = remaining_tokens - tokens
|
remaining_tokens = remaining_tokens - tokens
|
||||||
if remaining_tokens > 0 then
|
if remaining_tokens > 0 then
|
||||||
@@ -226,6 +230,10 @@ function M.generate_prompts(opts)
|
|||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
dropped_history_messages = vim.list_slice(opts.history_messages, 1, #opts.history_messages - #history_messages)
|
||||||
|
|
||||||
-- prepend the history messages to the messages table
|
-- prepend the history messages to the messages table
|
||||||
vim.iter(history_messages):each(function(msg) table.insert(messages, 1, msg) end)
|
vim.iter(history_messages):each(function(msg) table.insert(messages, 1, msg) end)
|
||||||
if #messages > 0 and messages[1].role == "assistant" then table.remove(messages, 1) end
|
if #messages > 0 and messages[1].role == "assistant" then table.remove(messages, 1) end
|
||||||
@@ -254,6 +262,7 @@ Merge all changes from the <update> snippet into the <code> below.
|
|||||||
image_paths = image_paths,
|
image_paths = image_paths,
|
||||||
tools = opts.tools,
|
tools = opts.tools,
|
||||||
tool_histories = opts.tool_histories,
|
tool_histories = opts.tool_histories,
|
||||||
|
dropped_history_messages = dropped_history_messages,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -493,6 +502,15 @@ function M._stream(opts)
|
|||||||
|
|
||||||
local prompt_opts = M.generate_prompts(opts)
|
local prompt_opts = M.generate_prompts(opts)
|
||||||
|
|
||||||
|
if
|
||||||
|
prompt_opts.dropped_history_messages
|
||||||
|
and #prompt_opts.dropped_history_messages > 0
|
||||||
|
and opts.on_memory_summarize
|
||||||
|
then
|
||||||
|
opts.on_memory_summarize(prompt_opts.dropped_history_messages)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local resp_headers = {}
|
local resp_headers = {}
|
||||||
|
|
||||||
---@type AvanteHandlerOptions
|
---@type AvanteHandlerOptions
|
||||||
|
|||||||
@@ -2578,7 +2578,7 @@ function Sidebar:create_input_container(opts)
|
|||||||
|
|
||||||
prompts_opts.history_messages = vim.list_slice(prompts_opts.history_messages, 5)
|
prompts_opts.history_messages = vim.list_slice(prompts_opts.history_messages, 5)
|
||||||
|
|
||||||
Llm.summarize_memory(self.code.bufnr, self.chat_history, function(memory)
|
Llm.summarize_memory(self.code.bufnr, self.chat_history, nil, function(memory)
|
||||||
if memory then prompts_opts.memory = memory.content end
|
if memory then prompts_opts.memory = memory.content end
|
||||||
cb(prompts_opts)
|
cb(prompts_opts)
|
||||||
end)
|
end)
|
||||||
@@ -2815,6 +2815,28 @@ function Sidebar:create_input_container(opts)
|
|||||||
session_ctx = {},
|
session_ctx = {},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local function on_memory_summarize(dropped_history_messages)
|
||||||
|
local entries = Utils.history.filter_active_entries(self.chat_history.entries)
|
||||||
|
|
||||||
|
if self.chat_history.memory then
|
||||||
|
entries = vim
|
||||||
|
.iter(entries)
|
||||||
|
:filter(function(entry) return entry.timestamp > self.chat_history.memory.last_summarized_timestamp end)
|
||||||
|
:totable()
|
||||||
|
end
|
||||||
|
|
||||||
|
entries = vim.list_slice(entries, 1, #dropped_history_messages)
|
||||||
|
|
||||||
|
Llm.summarize_memory(self.code.bufnr, self.chat_history, entries, function(memory)
|
||||||
|
if memory then stream_options.memory = memory.content end
|
||||||
|
stream_options.history_messages =
|
||||||
|
vim.list_slice(stream_options.history_messages, #dropped_history_messages + 1)
|
||||||
|
Llm.stream(stream_options)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
stream_options.on_memory_summarize = on_memory_summarize
|
||||||
|
|
||||||
Llm.stream(stream_options)
|
Llm.stream(stream_options)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ L5: pass
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
role = "user",
|
role = "user",
|
||||||
content = '<question>{"insertSpaces":true,"tabSize":4,"indentSize":4,"position":{"row":1,"col":7}}</question>',
|
content = '{"insertSpaces":true,"tabSize":4,"indentSize":4,"position":{"row":1,"col":7}}',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
role = "assistant",
|
role = "assistant",
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Respect and use existing conventions, libraries, etc that are already present in
|
|||||||
|
|
||||||
Make sure code comments are in English when generating them.
|
Make sure code comments are in English when generating them.
|
||||||
|
|
||||||
|
Memory is crucial, you must follow the instructions in <memory>!
|
||||||
|
|
||||||
{% include "_tools-guidelines.avanterules" %}
|
{% include "_tools-guidelines.avanterules" %}
|
||||||
|
|
||||||
{% if system_info -%}
|
{% if system_info -%}
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ vim.g.avante_login = vim.g.avante_login
|
|||||||
---@field image_paths? string[]
|
---@field image_paths? string[]
|
||||||
---@field tools? AvanteLLMTool[]
|
---@field tools? AvanteLLMTool[]
|
||||||
---@field tool_histories? AvanteLLMToolHistory[]
|
---@field tool_histories? AvanteLLMToolHistory[]
|
||||||
|
---@field dropped_history_messages? AvanteLLMMessage[]
|
||||||
---
|
---
|
||||||
---@class AvanteGeminiMessage
|
---@class AvanteGeminiMessage
|
||||||
---@field role "user"
|
---@field role "user"
|
||||||
@@ -331,11 +332,14 @@ vim.g.avante_login = vim.g.avante_login
|
|||||||
---@field tool_result? AvanteLLMToolResult
|
---@field tool_result? AvanteLLMToolResult
|
||||||
---@field tool_use? AvanteLLMToolUse
|
---@field tool_use? AvanteLLMToolUse
|
||||||
---
|
---
|
||||||
|
---@alias AvanteLLMMemorySummarizeCallback fun(dropped_history_messages: AvanteLLMMessage[]): nil
|
||||||
|
---
|
||||||
---@class AvanteLLMStreamOptions: AvanteGeneratePromptsOptions
|
---@class AvanteLLMStreamOptions: AvanteGeneratePromptsOptions
|
||||||
---@field session_ctx? table
|
---@field session_ctx? table
|
||||||
---@field on_start AvanteLLMStartCallback
|
---@field on_start AvanteLLMStartCallback
|
||||||
---@field on_chunk AvanteLLMChunkCallback
|
---@field on_chunk AvanteLLMChunkCallback
|
||||||
---@field on_stop AvanteLLMStopCallback
|
---@field on_stop AvanteLLMStopCallback
|
||||||
|
---@field on_memory_summarize? AvanteLLMMemorySummarizeCallback
|
||||||
---@field on_tool_log? function(tool_name: string, log: string): nil
|
---@field on_tool_log? function(tool_name: string, log: string): nil
|
||||||
---
|
---
|
||||||
---@alias AvanteLLMToolFunc<T> fun(
|
---@alias AvanteLLMToolFunc<T> fun(
|
||||||
|
|||||||
Reference in New Issue
Block a user