From 0a728ba4b7151e355f3b13c8ae6275f7a470fc97 Mon Sep 17 00:00:00 2001 From: dashevchenko Date: Fri, 13 Feb 2026 17:44:06 +0200 Subject: [PATCH] fixed some TB models for correct open-api json schema --- .../server/controller/AiModelController.java | 2 +- .../service/ai/AiChatModelServiceImpl.java | 3 +- .../Langchain4jChatModelConfigurerImpl.java | 118 +++++++++--------- .../common/data/ai/dto/TbChatRequest.java | 2 +- .../common/data/ai/model/AiModelConfig.java | 22 +--- .../common/data/ai/model/AiModelType.java | 3 + .../data/ai/model/chat/AiChatModelConfig.java | 5 +- .../chat/AmazonBedrockChatModelConfig.java | 39 ++---- .../model/chat/AnthropicChatModelConfig.java | 41 ++---- .../chat/AzureOpenAiChatModelConfig.java | 44 ++----- .../chat/GitHubModelsChatModelConfig.java | 42 ++----- .../chat/GoogleAiGeminiChatModelConfig.java | 45 +++---- .../GoogleVertexAiGeminiChatModelConfig.java | 44 +++---- .../model/chat/MistralAiChatModelConfig.java | 42 ++----- .../ai/model/chat/OllamaChatModelConfig.java | 44 ++----- .../ai/model/chat/OpenAiChatModelConfig.java | 42 ++----- .../common/data/ai/provider/AiProvider.java | 3 + .../provider/AmazonBedrockProviderConfig.java | 2 +- .../ai/provider/AnthropicProviderConfig.java | 2 + .../provider/AzureOpenAiProviderConfig.java | 2 + .../provider/GitHubModelsProviderConfig.java | 2 + .../GoogleAiGeminiProviderConfig.java | 2 + .../GoogleVertexAiGeminiProviderConfig.java | 2 + .../ai/provider/MistralAiProviderConfig.java | 2 + .../ai/provider/OllamaProviderConfig.java | 1 + .../ai/provider/OpenAiProviderConfig.java | 2 + .../api/RuleEngineAiChatModelService.java | 3 +- .../thingsboard/rule/engine/ai/TbAiNode.java | 7 +- 28 files changed, 210 insertions(+), 358 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AiModelController.java b/application/src/main/java/org/thingsboard/server/controller/AiModelController.java index 7d2f7d5c4a..7e4a73798d 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AiModelController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AiModelController.java @@ -174,7 +174,7 @@ class AiModelController extends BaseController { @PostMapping("/chat") public DeferredResult sendChatRequest(@Valid @RequestBody TbChatRequest tbChatRequest) { ChatRequest langChainChatRequest = tbChatRequest.toLangChainChatRequest(); - AiChatModelConfig chatModelConfig = tbChatRequest.chatModelConfig(); + AiChatModelConfig chatModelConfig = tbChatRequest.chatModelConfig(); ListenableFuture future = aiChatModelService.sendChatRequestAsync(chatModelConfig, langChainChatRequest) .transform(chatResponse -> (TbChatResponse) new TbChatResponse.Success(chatResponse.aiMessage().text()), directExecutor()) 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 6c3aca6f67..212d363280 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 @@ -29,7 +29,6 @@ import lombok.RequiredArgsConstructor; 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 org.thingsboard.server.common.data.ai.provider.AiProviderConfig; import java.util.List; import java.util.stream.Collectors; @@ -42,7 +41,7 @@ class AiChatModelServiceImpl implements AiChatModelService { private final AiRequestsExecutor aiRequestsExecutor; @Override - public , P extends AiProviderConfig> FluentFuture sendChatRequestAsync(AiChatModelConfig chatModelConfig, ChatRequest chatRequest) { + public > FluentFuture sendChatRequestAsync(AiChatModelConfig chatModelConfig, ChatRequest chatRequest) { ChatModel langChainChatModel = chatModelConfig.configure(chatModelConfigurer); if (langChainChatModel.provider() == ModelProvider.GITHUB_MODELS) { chatRequest = prepareGithubChatRequest(chatRequest); diff --git a/application/src/main/java/org/thingsboard/server/service/ai/Langchain4jChatModelConfigurerImpl.java b/application/src/main/java/org/thingsboard/server/service/ai/Langchain4jChatModelConfigurerImpl.java index 4ad975eb64..28d696468c 100644 --- a/application/src/main/java/org/thingsboard/server/service/ai/Langchain4jChatModelConfigurerImpl.java +++ b/application/src/main/java/org/thingsboard/server/service/ai/Langchain4jChatModelConfigurerImpl.java @@ -72,12 +72,12 @@ class Langchain4jChatModelConfigurerImpl implements Langchain4jChatModelConfigur return OpenAiChatModel.builder() .baseUrl(chatModelConfig.providerConfig().baseUrl()) .apiKey(chatModelConfig.providerConfig().apiKey()) - .modelName(chatModelConfig.getModelId()) - .temperature(chatModelConfig.getTemperature()) - .topP(chatModelConfig.getTopP()) - .frequencyPenalty(chatModelConfig.getFrequencyPenalty()) - .presencePenalty(chatModelConfig.getPresencePenalty()) - .maxTokens(chatModelConfig.getMaxOutputTokens()) + .modelName(chatModelConfig.modelId()) + .temperature(chatModelConfig.temperature()) + .topP(chatModelConfig.topP()) + .frequencyPenalty(chatModelConfig.frequencyPenalty()) + .presencePenalty(chatModelConfig.presencePenalty()) + .maxTokens(chatModelConfig.maxOutputTokens()) .timeout(toDuration(chatModelConfig.timeoutSeconds())) .maxRetries(chatModelConfig.maxRetries()) .build(); @@ -90,12 +90,12 @@ class Langchain4jChatModelConfigurerImpl implements Langchain4jChatModelConfigur .endpoint(providerConfig.endpoint()) .serviceVersion(providerConfig.serviceVersion()) .apiKey(providerConfig.apiKey()) - .deploymentName(chatModelConfig.getModelId()) - .temperature(chatModelConfig.getTemperature()) - .topP(chatModelConfig.getTopP()) - .frequencyPenalty(chatModelConfig.getFrequencyPenalty()) - .presencePenalty(chatModelConfig.getPresencePenalty()) - .maxTokens(chatModelConfig.getMaxOutputTokens()) + .deploymentName(chatModelConfig.modelId()) + .temperature(chatModelConfig.temperature()) + .topP(chatModelConfig.topP()) + .frequencyPenalty(chatModelConfig.frequencyPenalty()) + .presencePenalty(chatModelConfig.presencePenalty()) + .maxTokens(chatModelConfig.maxOutputTokens()) .timeout(toDuration(chatModelConfig.timeoutSeconds())) .maxRetries(chatModelConfig.maxRetries()) .build(); @@ -105,13 +105,13 @@ class Langchain4jChatModelConfigurerImpl implements Langchain4jChatModelConfigur public ChatModel configureChatModel(GoogleAiGeminiChatModelConfig chatModelConfig) { return GoogleAiGeminiChatModel.builder() .apiKey(chatModelConfig.providerConfig().apiKey()) - .modelName(chatModelConfig.getModelId()) - .temperature(chatModelConfig.getTemperature()) - .topP(chatModelConfig.getTopP()) - .topK(chatModelConfig.getTopK()) - .frequencyPenalty(chatModelConfig.getFrequencyPenalty()) - .presencePenalty(chatModelConfig.getPresencePenalty()) - .maxOutputTokens(chatModelConfig.getMaxOutputTokens()) + .modelName(chatModelConfig.modelId()) + .temperature(chatModelConfig.temperature()) + .topP(chatModelConfig.topP()) + .topK(chatModelConfig.topK()) + .frequencyPenalty(chatModelConfig.frequencyPenalty()) + .presencePenalty(chatModelConfig.presencePenalty()) + .maxOutputTokens(chatModelConfig.maxOutputTokens()) .timeout(toDuration(chatModelConfig.timeoutSeconds())) .maxRetries(chatModelConfig.maxRetries()) .build(); @@ -165,28 +165,28 @@ class Langchain4jChatModelConfigurerImpl implements Langchain4jChatModelConfigur // map model config to generation config var generationConfigBuilder = GenerationConfig.newBuilder(); - if (chatModelConfig.getTemperature() != null) { - generationConfigBuilder.setTemperature(chatModelConfig.getTemperature().floatValue()); + if (chatModelConfig.temperature() != null) { + generationConfigBuilder.setTemperature(chatModelConfig.temperature().floatValue()); } - if (chatModelConfig.getTopP() != null) { - generationConfigBuilder.setTopP(chatModelConfig.getTopP().floatValue()); + if (chatModelConfig.topP() != null) { + generationConfigBuilder.setTopP(chatModelConfig.topP().floatValue()); } - if (chatModelConfig.getTopK() != null) { - generationConfigBuilder.setTopK(chatModelConfig.getTopK()); + if (chatModelConfig.topK() != null) { + generationConfigBuilder.setTopK(chatModelConfig.topK()); } - if (chatModelConfig.getFrequencyPenalty() != null) { - generationConfigBuilder.setFrequencyPenalty(chatModelConfig.getFrequencyPenalty().floatValue()); + if (chatModelConfig.frequencyPenalty() != null) { + generationConfigBuilder.setFrequencyPenalty(chatModelConfig.frequencyPenalty().floatValue()); } - if (chatModelConfig.getFrequencyPenalty() != null) { - generationConfigBuilder.setPresencePenalty(chatModelConfig.getFrequencyPenalty().floatValue()); + if (chatModelConfig.frequencyPenalty() != null) { + generationConfigBuilder.setPresencePenalty(chatModelConfig.frequencyPenalty().floatValue()); } - if (chatModelConfig.getMaxOutputTokens() != null) { - generationConfigBuilder.setMaxOutputTokens(chatModelConfig.getMaxOutputTokens()); + if (chatModelConfig.maxOutputTokens() != null) { + generationConfigBuilder.setMaxOutputTokens(chatModelConfig.maxOutputTokens()); } var generationConfig = generationConfigBuilder.build(); // construct generative model instance - var generativeModel = new GenerativeModel(chatModelConfig.getModelId(), vertexAI).withGenerationConfig(generationConfig); + var generativeModel = new GenerativeModel(chatModelConfig.modelId(), vertexAI).withGenerationConfig(generationConfig); return new VertexAiGeminiChatModel(generativeModel, generationConfig, chatModelConfig.maxRetries()); } @@ -203,12 +203,12 @@ class Langchain4jChatModelConfigurerImpl implements Langchain4jChatModelConfigur public ChatModel configureChatModel(MistralAiChatModelConfig chatModelConfig) { return MistralAiChatModel.builder() .apiKey(chatModelConfig.providerConfig().apiKey()) - .modelName(chatModelConfig.getModelId()) - .temperature(chatModelConfig.getTemperature()) - .topP(chatModelConfig.getTopP()) - .frequencyPenalty(chatModelConfig.getFrequencyPenalty()) - .presencePenalty(chatModelConfig.getPresencePenalty()) - .maxTokens(chatModelConfig.getMaxOutputTokens()) + .modelName(chatModelConfig.modelId()) + .temperature(chatModelConfig.temperature()) + .topP(chatModelConfig.topP()) + .frequencyPenalty(chatModelConfig.frequencyPenalty()) + .presencePenalty(chatModelConfig.presencePenalty()) + .maxTokens(chatModelConfig.maxOutputTokens()) .timeout(toDuration(chatModelConfig.timeoutSeconds())) .maxRetries(chatModelConfig.maxRetries()) .build(); @@ -218,11 +218,11 @@ class Langchain4jChatModelConfigurerImpl implements Langchain4jChatModelConfigur public ChatModel configureChatModel(AnthropicChatModelConfig chatModelConfig) { return AnthropicChatModel.builder() .apiKey(chatModelConfig.providerConfig().apiKey()) - .modelName(chatModelConfig.getModelId()) - .temperature(chatModelConfig.getTemperature()) - .topP(chatModelConfig.getTopP()) - .topK(chatModelConfig.getTopK()) - .maxTokens(chatModelConfig.getMaxOutputTokens()) + .modelName(chatModelConfig.modelId()) + .temperature(chatModelConfig.temperature()) + .topP(chatModelConfig.topP()) + .topK(chatModelConfig.topK()) + .maxTokens(chatModelConfig.maxOutputTokens()) .timeout(toDuration(chatModelConfig.timeoutSeconds())) .maxRetries(chatModelConfig.maxRetries()) .build(); @@ -242,14 +242,14 @@ class Langchain4jChatModelConfigurerImpl implements Langchain4jChatModelConfigur .build(); var defaultChatRequestParams = ChatRequestParameters.builder() - .temperature(chatModelConfig.getTemperature()) - .topP(chatModelConfig.getTopP()) - .maxOutputTokens(chatModelConfig.getMaxOutputTokens()) + .temperature(chatModelConfig.temperature()) + .topP(chatModelConfig.topP()) + .maxOutputTokens(chatModelConfig.maxOutputTokens()) .build(); return BedrockChatModel.builder() .client(bedrockClient) - .modelId(chatModelConfig.getModelId()) + .modelId(chatModelConfig.modelId()) .defaultRequestParameters(defaultChatRequestParams) .timeout(toDuration(chatModelConfig.timeoutSeconds())) .maxRetries(chatModelConfig.maxRetries()) @@ -260,12 +260,12 @@ class Langchain4jChatModelConfigurerImpl implements Langchain4jChatModelConfigur public ChatModel configureChatModel(GitHubModelsChatModelConfig chatModelConfig) { return GitHubModelsChatModel.builder() .gitHubToken(chatModelConfig.providerConfig().personalAccessToken()) - .modelName(chatModelConfig.getModelId()) - .temperature(chatModelConfig.getTemperature()) - .topP(chatModelConfig.getTopP()) - .frequencyPenalty(chatModelConfig.getFrequencyPenalty()) - .presencePenalty(chatModelConfig.getPresencePenalty()) - .maxTokens(chatModelConfig.getMaxOutputTokens()) + .modelName(chatModelConfig.modelId()) + .temperature(chatModelConfig.temperature()) + .topP(chatModelConfig.topP()) + .frequencyPenalty(chatModelConfig.frequencyPenalty()) + .presencePenalty(chatModelConfig.presencePenalty()) + .maxTokens(chatModelConfig.maxOutputTokens()) .timeout(toDuration(chatModelConfig.timeoutSeconds())) .maxRetries(chatModelConfig.maxRetries()) .build(); @@ -275,12 +275,12 @@ class Langchain4jChatModelConfigurerImpl implements Langchain4jChatModelConfigur public ChatModel configureChatModel(OllamaChatModelConfig chatModelConfig) { var builder = OllamaChatModel.builder() .baseUrl(chatModelConfig.providerConfig().baseUrl()) - .modelName(chatModelConfig.getModelId()) - .temperature(chatModelConfig.getTemperature()) - .topP(chatModelConfig.getTopP()) - .topK(chatModelConfig.getTopK()) - .numCtx(chatModelConfig.getContextLength()) - .numPredict(chatModelConfig.getContextLength()) + .modelName(chatModelConfig.modelId()) + .temperature(chatModelConfig.temperature()) + .topP(chatModelConfig.topP()) + .topK(chatModelConfig.topK()) + .numCtx(chatModelConfig.contextLength()) + .numPredict(chatModelConfig.maxOutputTokens()) .timeout(toDuration(chatModelConfig.timeoutSeconds())) .maxRetries(chatModelConfig.maxRetries()); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/dto/TbChatRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/dto/TbChatRequest.java index 7a408ea0a9..c39a18ae6d 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/dto/TbChatRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/dto/TbChatRequest.java @@ -73,7 +73,7 @@ public record TbChatRequest( } ) @NotNull @Valid - AiChatModelConfig chatModelConfig + AiChatModelConfig chatModelConfig ) { public ChatRequest toLangChainChatRequest() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/AiModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/AiModelConfig.java index 52ed02fa46..d036969254 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/AiModelConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/AiModelConfig.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.common.data.ai.model; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; @@ -74,7 +73,7 @@ import org.thingsboard.server.common.data.ai.provider.OpenAiProviderConfig; @DiscriminatorMapping(value = "OLLAMA", schema = OllamaChatModelConfig.class) } ) -public interface AiModelConfig { +public interface AiModelConfig { @Schema( description = "AI Provider", @@ -82,21 +81,7 @@ public interface AiModelConfig { ) AiProvider provider(); - @Schema( - description = "Provider-specific configuration details", - discriminatorProperty = "provider", - discriminatorMapping = { - @DiscriminatorMapping(value = "OPENAI", schema = OpenAiProviderConfig.class), - @DiscriminatorMapping(value = "AZURE_OPENAI", schema = AzureOpenAiProviderConfig.class), - @DiscriminatorMapping(value = "GOOGLE_AI_GEMINI", schema = GoogleAiGeminiProviderConfig.class), - @DiscriminatorMapping(value = "GOOGLE_VERTEX_AI_GEMINI", schema = GoogleVertexAiGeminiProviderConfig.class), - @DiscriminatorMapping(value = "MISTRAL_AI", schema = MistralAiProviderConfig.class), - @DiscriminatorMapping(value = "ANTHROPIC", schema = AnthropicProviderConfig.class), - @DiscriminatorMapping(value = "AMAZON_BEDROCK", schema = AmazonBedrockProviderConfig.class), - @DiscriminatorMapping(value = "GITHUB_MODELS", schema = GitHubModelsProviderConfig.class), - @DiscriminatorMapping(value = "OLLAMA", schema = OllamaProviderConfig.class) - } - ) + @Schema(hidden = true) @JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, @@ -113,8 +98,7 @@ public interface AiModelConfig { @JsonSubTypes.Type(value = GitHubModelsProviderConfig.class, name = "GITHUB_MODELS"), @JsonSubTypes.Type(value = OllamaProviderConfig.class, name = "OLLAMA") }) - @JsonIgnore - T providerConfig(); + AiProviderConfig providerConfig(); AiModelType modelType(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/AiModelType.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/AiModelType.java index 365e375f58..8f2b5e9db7 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/AiModelType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/AiModelType.java @@ -15,6 +15,9 @@ */ package org.thingsboard.server.common.data.ai.model; +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(enumAsRef = true) public enum AiModelType { CHAT diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AiChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AiChatModelConfig.java index 920a055d3f..1d3d03b021 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AiChatModelConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AiChatModelConfig.java @@ -20,10 +20,9 @@ import dev.langchain4j.model.chat.ChatModel; import io.swagger.v3.oas.annotations.media.Schema; import org.thingsboard.server.common.data.ai.model.AiModelConfig; import org.thingsboard.server.common.data.ai.model.AiModelType; -import org.thingsboard.server.common.data.ai.provider.AiProviderConfig; -@Schema(description = "AI provider-specific configuration") -public sealed interface AiChatModelConfig, P extends AiProviderConfig> extends AiModelConfig

+@Schema +public sealed interface AiChatModelConfig> extends AiModelConfig permits OpenAiChatModelConfig, AzureOpenAiChatModelConfig, GoogleAiGeminiChatModelConfig, GoogleVertexAiGeminiChatModelConfig, MistralAiChatModelConfig, AnthropicChatModelConfig, diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AmazonBedrockChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AmazonBedrockChatModelConfig.java index 8c0e9dd750..490ae67eb2 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AmazonBedrockChatModelConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AmazonBedrockChatModelConfig.java @@ -24,51 +24,36 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.PositiveOrZero; import lombok.Builder; -import lombok.Data; import lombok.With; import org.thingsboard.server.common.data.ai.provider.AiProvider; import org.thingsboard.server.common.data.ai.provider.AmazonBedrockProviderConfig; -@Schema(description = "Amazon Bedrock chat model configuration") +@Schema @Builder -@Data -public final class AmazonBedrockChatModelConfig implements AiChatModelConfig { - - @NotNull @Valid AmazonBedrockProviderConfig providerConfig; - @NotBlank String modelId; - @PositiveOrZero Double temperature; - @Positive @Max(1) Double topP; - Integer maxOutputTokens; - @With @Positive Integer timeoutSeconds; - @With @PositiveOrZero Integer maxRetries; +public record AmazonBedrockChatModelConfig( + @Schema(ref = "#/components/schemas/AmazonBedrockProviderConfig") + @NotNull @Valid AmazonBedrockProviderConfig providerConfig, + @NotBlank String modelId, + @PositiveOrZero Double temperature, + @Positive @Max(1) Double topP, + Integer maxOutputTokens, + @With @Positive Integer timeoutSeconds, + @With @PositiveOrZero Integer maxRetries +) implements AiChatModelConfig { @Override public AiProvider provider() { return AiProvider.AMAZON_BEDROCK; } - @Override - public AmazonBedrockProviderConfig providerConfig() { - return providerConfig; - } - @Override public ChatModel configure(Langchain4jChatModelConfigurer configurer) { return configurer.configureChatModel(this); } - @Override - public Integer timeoutSeconds() { - return timeoutSeconds; - } - - @Override - public Integer maxRetries() { - return maxRetries; - } - @Override public boolean supportsJsonMode() { return false; } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AnthropicChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AnthropicChatModelConfig.java index 93b4272d56..77352b06c3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AnthropicChatModelConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AnthropicChatModelConfig.java @@ -24,51 +24,34 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.PositiveOrZero; import lombok.Builder; -import lombok.Data; import lombok.With; import org.thingsboard.server.common.data.ai.provider.AiProvider; import org.thingsboard.server.common.data.ai.provider.AnthropicProviderConfig; -@Schema() +@Schema @Builder -@Data -public final class AnthropicChatModelConfig implements AiChatModelConfig { - @NotNull @Valid AnthropicProviderConfig providerConfig; - @NotBlank String modelId; - @PositiveOrZero Double temperature; - @Positive @Max(1) Double topP; - @PositiveOrZero Integer topK; - Integer maxOutputTokens; - @With - @Positive Integer timeoutSeconds; - @With - @PositiveOrZero Integer maxRetries; +public record AnthropicChatModelConfig( + @Schema(ref = "#/components/schemas/AnthropicProviderConfig") + @NotNull @Valid AnthropicProviderConfig providerConfig, + @NotBlank String modelId, + @PositiveOrZero Double temperature, + @Positive @Max(1) Double topP, + @PositiveOrZero Integer topK, + Integer maxOutputTokens, + @With @Positive Integer timeoutSeconds, + @With @PositiveOrZero Integer maxRetries +) implements AiChatModelConfig { @Override public AiProvider provider() { return AiProvider.ANTHROPIC; } - @Override - public AnthropicProviderConfig providerConfig() { - return providerConfig; - } - @Override public ChatModel configure(Langchain4jChatModelConfigurer configurer) { return configurer.configureChatModel(this); } - @Override - public Integer timeoutSeconds() { - return timeoutSeconds; - } - - @Override - public Integer maxRetries() { - return maxRetries; - } - @Override public boolean supportsJsonMode() { return false; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AzureOpenAiChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AzureOpenAiChatModelConfig.java index d6f46b7ae3..d4df82d237 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AzureOpenAiChatModelConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/AzureOpenAiChatModelConfig.java @@ -24,53 +24,35 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.PositiveOrZero; import lombok.Builder; -import lombok.Data; import lombok.With; import org.thingsboard.server.common.data.ai.provider.AiProvider; import org.thingsboard.server.common.data.ai.provider.AzureOpenAiProviderConfig; -@Schema() +@Schema @Builder -@Data -public final class AzureOpenAiChatModelConfig implements AiChatModelConfig { - - @NotNull @Valid AzureOpenAiProviderConfig providerConfig; - @NotBlank String modelId; - @PositiveOrZero Double temperature; - @Positive @Max(1) Double topP; - Double frequencyPenalty; - Double presencePenalty; - Integer maxOutputTokens; - @With - @Positive Integer timeoutSeconds; - @With - @PositiveOrZero Integer maxRetries; +public record AzureOpenAiChatModelConfig( + @Schema(ref = "#/components/schemas/AzureOpenAiProviderConfig") + @NotNull @Valid AzureOpenAiProviderConfig providerConfig, + @NotBlank String modelId, + @PositiveOrZero Double temperature, + @Positive @Max(1) Double topP, + Double frequencyPenalty, + Double presencePenalty, + Integer maxOutputTokens, + @With @Positive Integer timeoutSeconds, + @With @PositiveOrZero Integer maxRetries +) implements AiChatModelConfig { @Override public AiProvider provider() { return AiProvider.AZURE_OPENAI; } - @Override - public AzureOpenAiProviderConfig providerConfig() { - return providerConfig; - } - @Override public ChatModel configure(Langchain4jChatModelConfigurer configurer) { return configurer.configureChatModel(this); } - @Override - public Integer timeoutSeconds() { - return timeoutSeconds; - } - - @Override - public Integer maxRetries() { - return maxRetries; - } - @Override public boolean supportsJsonMode() { return true; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/GitHubModelsChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/GitHubModelsChatModelConfig.java index 5c9aba001b..264683f7b4 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/GitHubModelsChatModelConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/GitHubModelsChatModelConfig.java @@ -24,51 +24,35 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.PositiveOrZero; import lombok.Builder; -import lombok.Data; import lombok.With; import org.thingsboard.server.common.data.ai.provider.AiProvider; import org.thingsboard.server.common.data.ai.provider.GitHubModelsProviderConfig; -@Schema() +@Schema @Builder -@Data -public final class GitHubModelsChatModelConfig implements AiChatModelConfig { - - @NotNull @Valid GitHubModelsProviderConfig providerConfig; - @NotBlank String modelId; - @PositiveOrZero Double temperature; - @Positive @Max(1) Double topP; - Double frequencyPenalty; - Double presencePenalty; - Integer maxOutputTokens; - @With @Positive Integer timeoutSeconds; - @With @PositiveOrZero Integer maxRetries; +public record GitHubModelsChatModelConfig( + @Schema(ref = "#/components/schemas/GitHubModelsProviderConfig") + @NotNull @Valid GitHubModelsProviderConfig providerConfig, + @NotBlank String modelId, + @PositiveOrZero Double temperature, + @Positive @Max(1) Double topP, + Double frequencyPenalty, + Double presencePenalty, + Integer maxOutputTokens, + @With @Positive Integer timeoutSeconds, + @With @PositiveOrZero Integer maxRetries +) implements AiChatModelConfig { @Override public AiProvider provider() { return AiProvider.GITHUB_MODELS; } - @Override - public GitHubModelsProviderConfig providerConfig() { - return providerConfig; - } - @Override public ChatModel configure(Langchain4jChatModelConfigurer configurer) { return configurer.configureChatModel(this); } - @Override - public Integer timeoutSeconds() { - return timeoutSeconds; - } - - @Override - public Integer maxRetries() { - return maxRetries; - } - @Override public boolean supportsJsonMode() { return false; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/GoogleAiGeminiChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/GoogleAiGeminiChatModelConfig.java index 8fa254a778..82ba3a0295 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/GoogleAiGeminiChatModelConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/GoogleAiGeminiChatModelConfig.java @@ -15,7 +15,6 @@ */ package org.thingsboard.server.common.data.ai.model.chat; -import com.fasterxml.jackson.annotation.JsonTypeName; import dev.langchain4j.model.chat.ChatModel; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; @@ -25,52 +24,36 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.PositiveOrZero; import lombok.Builder; -import lombok.Data; import lombok.With; import org.thingsboard.server.common.data.ai.provider.AiProvider; import org.thingsboard.server.common.data.ai.provider.GoogleAiGeminiProviderConfig; -@Schema() -@JsonTypeName("GOOGLE_AI_GEMINI") +@Schema @Builder -@Data -public final class GoogleAiGeminiChatModelConfig implements AiChatModelConfig { - @NotNull @Valid GoogleAiGeminiProviderConfig providerConfig; - @NotBlank String modelId; - @PositiveOrZero Double temperature; - @Positive @Max(1) Double topP; - @PositiveOrZero Integer topK; - Double frequencyPenalty; - Double presencePenalty; - Integer maxOutputTokens; - @With @Positive Integer timeoutSeconds; - @With @PositiveOrZero Integer maxRetries; +public record GoogleAiGeminiChatModelConfig( + @Schema(ref = "#/components/schemas/GoogleAiGeminiProviderConfig") + @NotNull @Valid GoogleAiGeminiProviderConfig providerConfig, + @NotBlank String modelId, + @PositiveOrZero Double temperature, + @Positive @Max(1) Double topP, + @PositiveOrZero Integer topK, + Double frequencyPenalty, + Double presencePenalty, + Integer maxOutputTokens, + @With @Positive Integer timeoutSeconds, + @With @PositiveOrZero Integer maxRetries +) implements AiChatModelConfig { @Override public AiProvider provider() { return AiProvider.GOOGLE_AI_GEMINI; } - @Override - public GoogleAiGeminiProviderConfig providerConfig() { - return providerConfig; - } - @Override public ChatModel configure(Langchain4jChatModelConfigurer configurer) { return configurer.configureChatModel(this); } - @Override - public Integer timeoutSeconds() { - return timeoutSeconds; - } - - @Override - public Integer maxRetries() { - return maxRetries; - } - @Override public boolean supportsJsonMode() { return true; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/GoogleVertexAiGeminiChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/GoogleVertexAiGeminiChatModelConfig.java index 8b5ab44e45..4d20a240e6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/GoogleVertexAiGeminiChatModelConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/GoogleVertexAiGeminiChatModelConfig.java @@ -24,52 +24,36 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.PositiveOrZero; import lombok.Builder; -import lombok.Data; import lombok.With; import org.thingsboard.server.common.data.ai.provider.AiProvider; import org.thingsboard.server.common.data.ai.provider.GoogleVertexAiGeminiProviderConfig; -@Schema() +@Schema @Builder -@Data -public final class GoogleVertexAiGeminiChatModelConfig implements AiChatModelConfig { - - @NotNull @Valid GoogleVertexAiGeminiProviderConfig providerConfig; - @NotBlank String modelId; - @PositiveOrZero Double temperature; - @Positive @Max(1) Double topP; - @PositiveOrZero Integer topK; - Double frequencyPenalty; - Double presencePenalty; - Integer maxOutputTokens; - @With @Positive Integer timeoutSeconds; - @With @PositiveOrZero Integer maxRetries; +public record GoogleVertexAiGeminiChatModelConfig( + @Schema(ref = "#/components/schemas/GoogleVertexAiGeminiProviderConfig") + @NotNull @Valid GoogleVertexAiGeminiProviderConfig providerConfig, + @NotBlank String modelId, + @PositiveOrZero Double temperature, + @Positive @Max(1) Double topP, + @PositiveOrZero Integer topK, + Double frequencyPenalty, + Double presencePenalty, + Integer maxOutputTokens, + @With @Positive Integer timeoutSeconds, + @With @PositiveOrZero Integer maxRetries +) implements AiChatModelConfig { @Override public AiProvider provider() { return AiProvider.GOOGLE_VERTEX_AI_GEMINI; } - @Override - public GoogleVertexAiGeminiProviderConfig providerConfig() { - return providerConfig; - } - @Override public ChatModel configure(Langchain4jChatModelConfigurer configurer) { return configurer.configureChatModel(this); } - @Override - public Integer timeoutSeconds() { - return timeoutSeconds; - } - - @Override - public Integer maxRetries() { - return maxRetries; - } - @Override public boolean supportsJsonMode() { return true; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/MistralAiChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/MistralAiChatModelConfig.java index 77b4e77579..60c208c181 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/MistralAiChatModelConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/MistralAiChatModelConfig.java @@ -24,51 +24,35 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.PositiveOrZero; import lombok.Builder; -import lombok.Data; import lombok.With; import org.thingsboard.server.common.data.ai.provider.AiProvider; import org.thingsboard.server.common.data.ai.provider.MistralAiProviderConfig; -@Schema() +@Schema @Builder -@Data -public final class MistralAiChatModelConfig implements AiChatModelConfig { - - @NotNull @Valid MistralAiProviderConfig providerConfig; - @NotBlank String modelId; - @PositiveOrZero Double temperature; - @Positive @Max(1) Double topP; - Double frequencyPenalty; - Double presencePenalty; - Integer maxOutputTokens; - @With @Positive Integer timeoutSeconds; - @With @PositiveOrZero Integer maxRetries; +public record MistralAiChatModelConfig( + @Schema(ref = "#/components/schemas/MistralAiProviderConfig") + @NotNull @Valid MistralAiProviderConfig providerConfig, + @NotBlank String modelId, + @PositiveOrZero Double temperature, + @Positive @Max(1) Double topP, + Double frequencyPenalty, + Double presencePenalty, + Integer maxOutputTokens, + @With @Positive Integer timeoutSeconds, + @With @PositiveOrZero Integer maxRetries +) implements AiChatModelConfig { @Override public AiProvider provider() { return AiProvider.MISTRAL_AI; } - @Override - public MistralAiProviderConfig providerConfig() { - return providerConfig; - } - @Override public ChatModel configure(Langchain4jChatModelConfigurer configurer) { return configurer.configureChatModel(this); } - @Override - public Integer timeoutSeconds() { - return timeoutSeconds; - } - - @Override - public Integer maxRetries() { - return maxRetries; - } - @Override public boolean supportsJsonMode() { return true; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/OllamaChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/OllamaChatModelConfig.java index ca3492e32c..5f7776a0a6 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/OllamaChatModelConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/OllamaChatModelConfig.java @@ -24,53 +24,35 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.PositiveOrZero; import lombok.Builder; -import lombok.Data; import lombok.With; import org.thingsboard.server.common.data.ai.provider.AiProvider; import org.thingsboard.server.common.data.ai.provider.OllamaProviderConfig; -@Schema() +@Schema @Builder -@Data -public final class OllamaChatModelConfig implements AiChatModelConfig { - - @NotNull @Valid OllamaProviderConfig providerConfig; - @NotBlank String modelId; - @PositiveOrZero Double temperature; - @Positive @Max(1) Double topP; - @PositiveOrZero Integer topK; - Integer contextLength; - Integer maxOutputTokens; - @With - @Positive Integer timeoutSeconds; - @With - @PositiveOrZero Integer maxRetries; +public record OllamaChatModelConfig( + @Schema(ref = "#/components/schemas/OllamaProviderConfig") + @NotNull @Valid OllamaProviderConfig providerConfig, + @NotBlank String modelId, + @PositiveOrZero Double temperature, + @Positive @Max(1) Double topP, + @PositiveOrZero Integer topK, + Integer contextLength, + Integer maxOutputTokens, + @With @Positive Integer timeoutSeconds, + @With @PositiveOrZero Integer maxRetries +) implements AiChatModelConfig { @Override public AiProvider provider() { return AiProvider.OLLAMA; } - @Override - public OllamaProviderConfig providerConfig() { - return providerConfig; - } - @Override public ChatModel configure(Langchain4jChatModelConfigurer configurer) { return configurer.configureChatModel(this); } - @Override - public Integer timeoutSeconds() { - return timeoutSeconds; - } - - @Override - public Integer maxRetries() { - return maxRetries; - } - @Override public boolean supportsJsonMode() { return true; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/OpenAiChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/OpenAiChatModelConfig.java index 6c6fafa0aa..3845aaa543 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/OpenAiChatModelConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/chat/OpenAiChatModelConfig.java @@ -24,51 +24,35 @@ import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.PositiveOrZero; import lombok.Builder; -import lombok.Data; import lombok.With; import org.thingsboard.server.common.data.ai.provider.AiProvider; import org.thingsboard.server.common.data.ai.provider.OpenAiProviderConfig; -@Schema() +@Schema @Builder -@Data -public final class OpenAiChatModelConfig implements AiChatModelConfig { - - @NotNull @Valid OpenAiProviderConfig providerConfig; - @NotBlank String modelId; - @PositiveOrZero Double temperature; - @Positive @Max(1) Double topP; - Double frequencyPenalty; - Double presencePenalty; - Integer maxOutputTokens; - @With @Positive Integer timeoutSeconds; - @With @PositiveOrZero Integer maxRetries; +public record OpenAiChatModelConfig( + @Schema(ref = "#/components/schemas/OpenAiProviderConfig") + @NotNull @Valid OpenAiProviderConfig providerConfig, + @NotBlank String modelId, + @PositiveOrZero Double temperature, + @Positive @Max(1) Double topP, + Double frequencyPenalty, + Double presencePenalty, + Integer maxOutputTokens, + @With @Positive Integer timeoutSeconds, + @With @PositiveOrZero Integer maxRetries +) implements AiChatModelConfig { @Override public AiProvider provider() { return AiProvider.OPENAI; } - @Override - public OpenAiProviderConfig providerConfig() { - return providerConfig; - } - @Override public ChatModel configure(Langchain4jChatModelConfigurer configurer) { return configurer.configureChatModel(this); } - @Override - public Integer timeoutSeconds() { - return timeoutSeconds; - } - - @Override - public Integer maxRetries() { - return maxRetries; - } - @Override public boolean supportsJsonMode() { return true; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AiProvider.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AiProvider.java index a85944d074..cae26a0f27 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AiProvider.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AiProvider.java @@ -15,6 +15,9 @@ */ package org.thingsboard.server.common.data.ai.provider; +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(enumAsRef = true) public enum AiProvider { OPENAI, diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AmazonBedrockProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AmazonBedrockProviderConfig.java index 2befbd92aa..17e886e946 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AmazonBedrockProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AmazonBedrockProviderConfig.java @@ -18,7 +18,7 @@ package org.thingsboard.server.common.data.ai.provider; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; -@Schema(description = "Amazon Bedrock AI provider configuration") +@Schema public record AmazonBedrockProviderConfig( @NotNull String region, @NotNull String accessKeyId, diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AnthropicProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AnthropicProviderConfig.java index 6e7abeee84..4108a72439 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AnthropicProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AnthropicProviderConfig.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.common.data.ai.provider; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; +@Schema public record AnthropicProviderConfig( @NotNull String apiKey ) implements AiProviderConfig {} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AzureOpenAiProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AzureOpenAiProviderConfig.java index 05d9e99569..6687f8a08e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AzureOpenAiProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AzureOpenAiProviderConfig.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.common.data.ai.provider; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; +@Schema public record AzureOpenAiProviderConfig( @NotNull String endpoint, String serviceVersion, diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GitHubModelsProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GitHubModelsProviderConfig.java index 56409c81ad..529eb2b989 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GitHubModelsProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GitHubModelsProviderConfig.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.common.data.ai.provider; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; +@Schema public record GitHubModelsProviderConfig( @NotNull String personalAccessToken ) implements AiProviderConfig {} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GoogleAiGeminiProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GoogleAiGeminiProviderConfig.java index 3492a1096d..5b20ed3d96 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GoogleAiGeminiProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GoogleAiGeminiProviderConfig.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.common.data.ai.provider; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; +@Schema public record GoogleAiGeminiProviderConfig( @NotNull String apiKey ) implements AiProviderConfig {} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GoogleVertexAiGeminiProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GoogleVertexAiGeminiProviderConfig.java index 0e0928e038..72c4b5e940 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GoogleVertexAiGeminiProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GoogleVertexAiGeminiProviderConfig.java @@ -15,9 +15,11 @@ */ package org.thingsboard.server.common.data.ai.provider; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +@Schema public record GoogleVertexAiGeminiProviderConfig( @NotBlank String fileName, // not used on BE, but needed for UI @NotNull String projectId, diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/MistralAiProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/MistralAiProviderConfig.java index 46165f9843..b0ca42de16 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/MistralAiProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/MistralAiProviderConfig.java @@ -15,8 +15,10 @@ */ package org.thingsboard.server.common.data.ai.provider; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; +@Schema public record MistralAiProviderConfig( @NotNull String apiKey ) implements AiProviderConfig {} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/OllamaProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/OllamaProviderConfig.java index 6873281fca..da83457540 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/OllamaProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/OllamaProviderConfig.java @@ -22,6 +22,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; +@Schema(allOf = AiProviderConfig.class) public record OllamaProviderConfig( @NotNull String baseUrl, @NotNull @Valid OllamaAuth auth diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/OpenAiProviderConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/OpenAiProviderConfig.java index 59eabc58a6..900eb6734c 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/OpenAiProviderConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/OpenAiProviderConfig.java @@ -16,12 +16,14 @@ package org.thingsboard.server.common.data.ai.provider; import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.AssertTrue; import lombok.Builder; import org.apache.commons.lang3.StringUtils; import java.util.Objects; +@Schema @Builder public record OpenAiProviderConfig( String baseUrl, diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineAiChatModelService.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineAiChatModelService.java index c8e069ed74..357b6c3340 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineAiChatModelService.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/RuleEngineAiChatModelService.java @@ -19,10 +19,9 @@ import com.google.common.util.concurrent.FluentFuture; import dev.langchain4j.model.chat.request.ChatRequest; import dev.langchain4j.model.chat.response.ChatResponse; import org.thingsboard.server.common.data.ai.model.chat.AiChatModelConfig; -import org.thingsboard.server.common.data.ai.provider.AiProviderConfig; public interface RuleEngineAiChatModelService { - , P extends AiProviderConfig> FluentFuture sendChatRequestAsync(AiChatModelConfig chatModelConfig, ChatRequest chatRequest); + > FluentFuture sendChatRequestAsync(AiChatModelConfig chatModelConfig, ChatRequest chatRequest); } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/ai/TbAiNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/ai/TbAiNode.java index 07dcf3f52f..bff72beb9b 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/ai/TbAiNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/ai/TbAiNode.java @@ -48,7 +48,6 @@ import org.thingsboard.server.common.data.TbResourceInfo; import org.thingsboard.server.common.data.ai.AiModel; import org.thingsboard.server.common.data.ai.model.AiModelType; import org.thingsboard.server.common.data.ai.model.chat.AiChatModelConfig; -import org.thingsboard.server.common.data.ai.provider.AiProviderConfig; import org.thingsboard.server.common.data.id.AiModelId; import org.thingsboard.server.common.data.id.TbResourceId; import org.thingsboard.server.common.data.id.TenantId; @@ -127,7 +126,7 @@ public final class TbAiNode extends TbAbstractExternalNode implements TbNode { if (modelType != AiModelType.CHAT) { throw new TbNodeException("[" + ctx.getTenantId() + "] AI model with ID: [" + modelId + "] must be of type CHAT, but was " + modelType, true); } - AiChatModelConfig chatModelConfig = (AiChatModelConfig) model.getConfiguration(); + AiChatModelConfig chatModelConfig = (AiChatModelConfig) model.getConfiguration(); if (isJsonModeConfigured(config)) { if (!chatModelConfig.supportsJsonMode()) { throw new TbNodeException("[" + ctx.getTenantId() + "] AI model with ID: [" + modelId + "] does not support '" + config.getResponseFormat().type() + "' response format", true); @@ -219,7 +218,7 @@ public final class TbAiNode extends TbAbstractExternalNode implements TbNode { }, directExecutor()); } - private , P extends AiProviderConfig> FluentFuture sendChatRequestAsync(TbContext ctx, ChatRequest chatRequest) { + private > FluentFuture sendChatRequestAsync(TbContext ctx, ChatRequest chatRequest) { return ctx.getAiModelService().findAiModelByTenantIdAndIdAsync(ctx.getTenantId(), modelId).transformAsync(modelOpt -> { if (modelOpt.isEmpty()) { throw new NoSuchElementException("[" + ctx.getTenantId() + "] AI model with ID: [" + modelId + "] was not found"); @@ -231,7 +230,7 @@ public final class TbAiNode extends TbAbstractExternalNode implements TbNode { } @SuppressWarnings("unchecked") - AiChatModelConfig chatModelConfig = (AiChatModelConfig) model.getConfiguration(); + AiChatModelConfig chatModelConfig = (AiChatModelConfig) model.getConfiguration(); chatModelConfig = chatModelConfig .withTimeoutSeconds(timeoutSeconds)