diff --git a/application/src/main/java/org/thingsboard/server/service/ai/AiChatModelServiceImpl.java b/application/src/main/java/org/thingsboard/server/service/ai/AiChatModelServiceImpl.java index d6252f57a6..c1829cbf84 100644 --- a/application/src/main/java/org/thingsboard/server/service/ai/AiChatModelServiceImpl.java +++ b/application/src/main/java/org/thingsboard/server/service/ai/AiChatModelServiceImpl.java @@ -16,6 +16,11 @@ package org.thingsboard.server.service.ai; import com.google.common.util.concurrent.FluentFuture; +import dev.langchain4j.data.message.ChatMessage; +import dev.langchain4j.data.message.Content; +import dev.langchain4j.data.message.TextContent; +import dev.langchain4j.data.message.UserMessage; +import dev.langchain4j.model.ModelProvider; import dev.langchain4j.model.chat.ChatModel; import dev.langchain4j.model.chat.request.ChatRequest; import dev.langchain4j.model.chat.response.ChatResponse; @@ -24,6 +29,11 @@ import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.ai.model.chat.AiChatModelConfig; import org.thingsboard.server.common.data.ai.model.chat.Langchain4jChatModelConfigurer; +import java.util.List; +import java.util.stream.Collectors; + +import static org.thingsboard.server.common.data.StringUtils.escapeControlChars; + @Service @RequiredArgsConstructor class AiChatModelServiceImpl implements AiChatModelService { @@ -34,7 +44,39 @@ class AiChatModelServiceImpl implements AiChatModelService { @Override public > FluentFuture sendChatRequestAsync(AiChatModelConfig chatModelConfig, ChatRequest chatRequest) { ChatModel langChainChatModel = chatModelConfig.configure(chatModelConfigurer); + if (langChainChatModel.provider() == ModelProvider.GITHUB_MODELS) { + chatRequest = prepareGithubChatRequest(chatRequest); + } return aiRequestsExecutor.sendChatRequestAsync(langChainChatModel, chatRequest); } + private ChatRequest prepareGithubChatRequest(ChatRequest chatRequest) { + List messages = chatRequest.messages().stream() + .map(this::prepareUserMessage) + .collect(Collectors.toList()); + + return ChatRequest.builder() + .messages(messages) + .responseFormat(chatRequest.responseFormat()) + .build(); + } + + private ChatMessage prepareUserMessage(ChatMessage message) { + if (message instanceof UserMessage userMessage) { + List newContents = userMessage.contents().stream() + .map(this::prepareContent) + .collect(Collectors.toList()); + + return UserMessage.from(newContents); + } + return message; + } + + private Content prepareContent(Content content) { + if (content instanceof TextContent txt) { + return new TextContent(escapeControlChars(txt.text())); + } + return content; + } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java index cbc881d72f..2b8b631027 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/StringUtils.java @@ -275,4 +275,11 @@ public class StringUtils { return result; } + public static String escapeControlChars(String text) { + return text + .replace("\n", "\\n") + .replace("\r", "\\r") + .replace("\t", "\\t"); + } + }