From 6ba3abdddf0a84426b759971952f169449e9f400 Mon Sep 17 00:00:00 2001 From: mzegla Date: Tue, 28 Apr 2026 13:02:46 +0200 Subject: [PATCH 1/3] init major rework minor changes less restrictive bos/eos check revert rework --- src/llm/apis/openai_completions.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/llm/apis/openai_completions.cpp b/src/llm/apis/openai_completions.cpp index b69b682611..b7a69f7d25 100644 --- a/src/llm/apis/openai_completions.cpp +++ b/src/llm/apis/openai_completions.cpp @@ -201,8 +201,7 @@ absl::Status OpenAIChatCompletionsHandler::parseMessages(std::optionalvalue.GetArray()) { if (!v.IsObject()) { return absl::InvalidArgumentError("Invalid message structure - content array should contain objects"); @@ -216,7 +215,10 @@ absl::Status OpenAIChatCompletionsHandler::parseMessages(std::optionalvalue = contentText; // Add new field to the last message in history if content is text if (member->value.IsString()) { From b064253186a0e50596b703b2eccec02c43591d0b Mon Sep 17 00:00:00 2001 From: mzegla Date: Tue, 5 May 2026 15:29:25 +0200 Subject: [PATCH 2/3] tests --- src/test/http_openai_handler_test.cpp | 69 +++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/test/http_openai_handler_test.cpp b/src/test/http_openai_handler_test.cpp index 112c1d69ad..17813f5a2c 100644 --- a/src/test/http_openai_handler_test.cpp +++ b/src/test/http_openai_handler_test.cpp @@ -2278,6 +2278,75 @@ TEST_F(HttpOpenAIHandlerParsingTest, ParsingMessagesEmptyContentArrayFails) { EXPECT_EQ(apiHandler->parseMessages(), absl::InvalidArgumentError("Invalid message structure - content array is empty")); } +TEST_F(HttpOpenAIHandlerParsingTest, ParsingMessagesMultipleTextItemsConcatenatesWithNewline) { + std::string json = R"({ + "model": "llama", + "messages": [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "First part." + }, + { + "type": "text", + "text": "Second part." + } + ] + } + ] + })"; + doc.Parse(json.c_str()); + ASSERT_FALSE(doc.HasParseError()); + std::shared_ptr apiHandler = std::make_shared(doc, ovms::Endpoint::CHAT_COMPLETIONS, std::chrono::system_clock::now(), *tokenizer); + ASSERT_EQ(apiHandler->parseMessages(), absl::OkStatus()); + // Non-Python path: chatHistory content is the concatenated string + auto& chatHistory = apiHandler->getChatHistory(); + ASSERT_EQ(chatHistory.size(), 1); + EXPECT_EQ(chatHistory[0]["content"], "First part.\nSecond part."); + // Python Jinja path: processedJson carries the same flattened content for applyChatTemplate + EXPECT_EQ(apiHandler->getProcessedJson(), R"({"model":"llama","messages":[{"role":"user","content":"First part.\nSecond part."}]})"); +} + +TEST_F(HttpOpenAIHandlerParsingTest, ParsingMessagesTextBeforeAndAfterImageConcatenatesAllText) { + std::string json = R"({ + "model": "llama", + "messages": [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "Before image." + }, + { + "type": "image_url", + "image_url": { + "url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAEElEQVR4nGLK27oAEAAA//8DYAHGgEvy5AAAAABJRU5ErkJggg==" + } + }, + { + "type": "text", + "text": "After image." + } + ] + } + ] + })"; + doc.Parse(json.c_str()); + ASSERT_FALSE(doc.HasParseError()); + std::shared_ptr apiHandler = std::make_shared(doc, ovms::Endpoint::CHAT_COMPLETIONS, std::chrono::system_clock::now(), *tokenizer); + ASSERT_EQ(apiHandler->parseMessages(), absl::OkStatus()); + // Non-Python path: chatHistory content is the concatenated string + auto& chatHistory = apiHandler->getChatHistory(); + ASSERT_EQ(chatHistory.size(), 1); + EXPECT_EQ(chatHistory[0]["content"], "Before image.\nAfter image."); + EXPECT_EQ(apiHandler->getImageHistory().size(), 1); + // Python Jinja path: processedJson carries the same flattened content for applyChatTemplate + EXPECT_EQ(apiHandler->getProcessedJson(), R"({"model":"llama","messages":[{"role":"user","content":"Before image.\nAfter image."}]})"); +} + TEST_F(HttpOpenAIHandlerParsingTest, maxTokensValueDefaultToMaxTokensLimit) { std::string json = R"({ "model": "llama", From 19c3d5694f0816be595355a37b6c49ce2b67072b Mon Sep 17 00:00:00 2001 From: mzegla Date: Tue, 5 May 2026 15:32:19 +0200 Subject: [PATCH 3/3] copilot suggestion --- src/llm/apis/openai_completions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llm/apis/openai_completions.cpp b/src/llm/apis/openai_completions.cpp index b7a69f7d25..433ce59c3f 100644 --- a/src/llm/apis/openai_completions.cpp +++ b/src/llm/apis/openai_completions.cpp @@ -218,7 +218,7 @@ absl::Status OpenAIChatCompletionsHandler::parseMessages(std::optional