Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions lua/codecompanion/adapters/http/mistral.lua
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,33 @@ return {
return openai.handlers.form_parameters(self, params, messages)
end,
form_messages = function(self, messages)
local pending_messages = self.pending_messages or {}
local is_previous_tool = false
for k, msg in ipairs(messages) do
local is_tool = msg.role == "tool"
local is_user = msg.role == "user"
-- Mistral does not like user after tool messages, those should always be assistant
if is_previous_tool and is_user then
table.insert(pending_messages, msg)
messages[k] = nil
-- message was dropped, so for the next message, the previous one
-- is still a tool
is_tool = true
else
if not is_previous_tool then
-- Flush pending messages whenever we can
for i, m in ipairs(pending_messages) do
table.insert(messages, m)
end
pending_messages = {}
end
end
is_previous_tool = is_tool
end

-- Keep the pending messages for next round
self.pending_messages = pending_messages

return openai.handlers.form_messages(self, messages)
end,
chat_output = function(self, data, tools)
Expand Down
52 changes: 52 additions & 0 deletions tests/adapters/http/test_mistral.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ T["Mistral adapter"]["form_messages"]["it can form messages with tools"] = funct
},
},
},
{ role = "tool", content = "ok" },
{ role = "assistant", content = "that works" },
}

local expected = {
Expand Down Expand Up @@ -83,6 +85,56 @@ T["Mistral adapter"]["form_messages"]["it can form messages with tools"] = funct
},
},
},
{ role = "tool", content = "ok" },
{ role = "assistant", content = "that works" },
},
}

h.eq(expected, adapter.handlers.form_messages(adapter, input))
end

T["Mistral adapter"]["form_messages"]["it skips messages when user follows tools"] = function()
local input = {
{ role = "user", content = "User1" },
{
role = "llm",
tools = {
calls = {
{
["function"] = {
arguments = '{"location":"London, UK","units":"fahrenheit"}',
name = "weather",
},
id = "call_1_a460d461-60a7-468c-a699-ef9e2dced125",
type = "function",
},
},
},
},
{ role = "tool", content = "ok" },
{ role = "user", content = "my message" },
}

local expected = {
messages = {
{
content = "User1",
role = "user",
},
{
role = "llm",
tool_calls = {
{
["function"] = {
arguments = '{"location":"London, UK","units":"fahrenheit"}',
name = "weather",
},
id = "call_1_a460d461-60a7-468c-a699-ef9e2dced125",
type = "function",
},
},
},
{ role = "tool", content = "ok" },
},
}

Expand Down