From 189a4fc203273e475a138aeeb09197ecc4dfa338 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Mon, 5 Jan 2026 13:45:50 +0100 Subject: [PATCH] Glue together adjacent user messages. In most cases this is not needed. However, some models, like Gemma3 or Devstral require that user and assistant messages alternate. The only case where this can happen in Tracy is when an attachment is added: [ { "role": "user", "content": "\n..." }, { "role": "user", "content": "Tell me something about..." } ] It is trivial to glue these messages together. This is only done when sending the data in the REST request, as the chat rendering logic expects these to be separate and it would be too much work unnecessary work to do it "proper". --- profiler/src/profiler/TracyLlm.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/profiler/src/profiler/TracyLlm.cpp b/profiler/src/profiler/TracyLlm.cpp index c6cb321a..485d9be5 100644 --- a/profiler/src/profiler/TracyLlm.cpp +++ b/profiler/src/profiler/TracyLlm.cpp @@ -854,6 +854,24 @@ void TracyLlm::SendMessage( std::unique_lock& lock ) auto chat = m_chat; AddMessageBlocking( { { "role", "assistant" } }, lock ); + size_t i = 1; + while( i < chat.size() ) + { + if( chat[i]["role"].get_ref() == "user" && + chat[i-1]["role"].get_ref() == "user" ) + { + auto& str = chat[i-1]["content"].get_ref(); + assert( str.starts_with( "\n" ) ); + str.append( "\n\n" ); + str.append( chat[i]["content"].get_ref() ); + chat.erase( chat.begin() + i ); + } + else + { + i++; + } + } + nlohmann::json req; req["model"] = m_api->GetModels()[m_modelIdx].name; req["messages"] = std::move( chat );