From 45fbbf201fe3020b109d94de87e310626eba9d49 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Thu, 22 May 2025 11:28:21 +0300 Subject: [PATCH] AI rule node: split AI config into AI provider config and AI model config; add support for model temperature --- .../main/data/upgrade/basic/schema_update.sql | 17 ++++--- .../server/service/ai/AiServiceImpl.java | 47 ++++++++++++----- .../server/common/data/ai/AiSettings.java | 21 ++++++-- .../common/data/ai/model/AiModelConfig.java | 47 +++++++++++++++++ .../model/GoogleAiGeminiChatModelConfig.java | 50 +++++++++++++++++++ .../ai/model/MistralAiChatModelConfig.java | 50 +++++++++++++++++++ .../data/ai/model/OpenAiChatModelConfig.java | 50 +++++++++++++++++++ .../data/ai/{ => provider}/AiProvider.java | 2 +- .../AiProviderConfig.java} | 13 +++-- .../GoogleAiGeminiProviderConfig.java} | 8 +-- .../MistralAiProviderConfig.java} | 8 +-- .../OpenAiProviderConfig.java} | 8 +-- .../server/dao/model/ModelConstants.java | 3 +- .../dao/model/sql/AiSettingsEntity.java | 19 ++++--- .../main/resources/sql/schema-entities.sql | 17 ++++--- 15 files changed, 301 insertions(+), 59 deletions(-) create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/ai/model/AiModelConfig.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/ai/model/GoogleAiGeminiChatModelConfig.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/ai/model/MistralAiChatModelConfig.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/ai/model/OpenAiChatModelConfig.java rename common/data/src/main/java/org/thingsboard/server/common/data/ai/{ => provider}/AiProvider.java (92%) rename common/data/src/main/java/org/thingsboard/server/common/data/ai/{AiConfig.java => provider/AiProviderConfig.java} (76%) rename common/data/src/main/java/org/thingsboard/server/common/data/ai/{GoogleAiGeminiConfig.java => provider/GoogleAiGeminiProviderConfig.java} (82%) rename common/data/src/main/java/org/thingsboard/server/common/data/ai/{MistralAiConfig.java => provider/MistralAiProviderConfig.java} (82%) rename common/data/src/main/java/org/thingsboard/server/common/data/ai/{OpenAiConfig.java => provider/OpenAiProviderConfig.java} (83%) diff --git a/application/src/main/data/upgrade/basic/schema_update.sql b/application/src/main/data/upgrade/basic/schema_update.sql index e148403be2..9685847278 100644 --- a/application/src/main/data/upgrade/basic/schema_update.sql +++ b/application/src/main/data/upgrade/basic/schema_update.sql @@ -15,13 +15,14 @@ -- CREATE TABLE ai_settings ( - id UUID NOT NULL PRIMARY KEY, - created_time BIGINT NOT NULL, - tenant_id UUID NOT NULL, - version BIGINT NOT NULL DEFAULT 1, - name VARCHAR(255) NOT NULL, - provider VARCHAR(255) NOT NULL, - model VARCHAR(255) NOT NULL, - configuration JSONB NOT NULL, + id UUID NOT NULL PRIMARY KEY, + created_time BIGINT NOT NULL, + tenant_id UUID NOT NULL, + version BIGINT NOT NULL DEFAULT 1, + name VARCHAR(255) NOT NULL, + provider VARCHAR(255) NOT NULL, + provider_config JSONB NOT NULL, + model VARCHAR(255) NOT NULL, + model_config JSONB, CONSTRAINT ai_settings_name_unq_key UNIQUE (tenant_id, name) ); diff --git a/application/src/main/java/org/thingsboard/server/service/ai/AiServiceImpl.java b/application/src/main/java/org/thingsboard/server/service/ai/AiServiceImpl.java index 7207501d7e..864c0034c1 100644 --- a/application/src/main/java/org/thingsboard/server/service/ai/AiServiceImpl.java +++ b/application/src/main/java/org/thingsboard/server/service/ai/AiServiceImpl.java @@ -23,6 +23,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.thingsboard.rule.engine.api.RuleEngineAiService; import org.thingsboard.server.common.data.ai.AiSettings; +import org.thingsboard.server.common.data.ai.model.MistralAiChatModelConfig; +import org.thingsboard.server.common.data.ai.model.OpenAiChatModelConfig; import org.thingsboard.server.common.data.id.AiSettingsId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.ai.AiSettingsService; @@ -45,18 +47,39 @@ class AiServiceImpl implements RuleEngineAiService { var aiSettings = aiSettingsOpt.get(); return switch (aiSettings.getProvider()) { - case OPENAI -> OpenAiChatModel.builder() - .apiKey(aiSettings.getConfiguration().getApiKey()) - .modelName(aiSettings.getModel()) - .build(); - case MISTRAL_AI -> MistralAiChatModel.builder() - .apiKey(aiSettings.getConfiguration().getApiKey()) - .modelName(aiSettings.getModel()) - .build(); - case GOOGLE_AI_GEMINI -> GoogleAiGeminiChatModel.builder() - .apiKey(aiSettings.getConfiguration().getApiKey()) - .modelName(aiSettings.getModel()) - .build(); + case OPENAI -> { + var modelBuilder = OpenAiChatModel.builder() + .apiKey(aiSettings.getProviderConfig().getApiKey()) + .modelName(aiSettings.getModel()); + + if (aiSettings.getModelConfig() instanceof OpenAiChatModelConfig config) { + modelBuilder.temperature(config.getTemperature()); + } + + yield modelBuilder.build(); + } + case MISTRAL_AI -> { + var modelBuilder = MistralAiChatModel.builder() + .apiKey(aiSettings.getProviderConfig().getApiKey()) + .modelName(aiSettings.getModel()); + + if (aiSettings.getModelConfig() instanceof MistralAiChatModelConfig config) { + modelBuilder.temperature(config.getTemperature()); + } + + yield modelBuilder.build(); + } + case GOOGLE_AI_GEMINI -> { + var modelBuilder = GoogleAiGeminiChatModel.builder() + .apiKey(aiSettings.getProviderConfig().getApiKey()) + .modelName(aiSettings.getModel()); + + if (aiSettings.getModelConfig() instanceof OpenAiChatModelConfig config) { + modelBuilder.temperature(config.getTemperature()); + } + + yield modelBuilder.build(); + } }; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/AiSettings.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/AiSettings.java index d3ef2fa419..6083f09f90 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/AiSettings.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/AiSettings.java @@ -24,6 +24,9 @@ import org.thingsboard.server.common.data.BaseData; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.HasVersion; +import org.thingsboard.server.common.data.ai.model.AiModelConfig; +import org.thingsboard.server.common.data.ai.provider.AiProvider; +import org.thingsboard.server.common.data.ai.provider.AiProviderConfig; import org.thingsboard.server.common.data.id.AiSettingsId; import org.thingsboard.server.common.data.id.TenantId; @@ -76,17 +79,27 @@ public final class AiSettings extends BaseData implements HasTenan @Schema( requiredMode = Schema.RequiredMode.REQUIRED, accessMode = Schema.AccessMode.READ_WRITE, - description = "Identifier of the AI model to use", + description = "Configuration specific to the AI provider" + ) + AiProviderConfig providerConfig; + + @Schema( + requiredMode = Schema.RequiredMode.REQUIRED, + accessMode = Schema.AccessMode.READ_WRITE, + description = "Identifier of the AI model", example = "gpt-4o-mini" ) String model; @Schema( - requiredMode = Schema.RequiredMode.REQUIRED, + requiredMode = Schema.RequiredMode.NOT_REQUIRED, accessMode = Schema.AccessMode.READ_WRITE, - description = "Settings specific to the selected AI provider and model" + description = """ + Optional configuration specific to the AI model. + If provided, it must be one of the known AiModelConfig subtypes and any settings + you specify will override the model’s defaults; if omitted, the model will run with its built-in defaults.""" ) - AiConfig configuration; + AiModelConfig modelConfig; public AiSettings() {} 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 new file mode 100644 index 0000000000..5112df3213 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/AiModelConfig.java @@ -0,0 +1,47 @@ +/** + * Copyright © 2016-2025 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data.ai.model; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXISTING_PROPERTY, + property = "model", + visible = true +) +@JsonSubTypes({ + @JsonSubTypes.Type(value = OpenAiChatModelConfig.class, name = "gpt-4o"), + @JsonSubTypes.Type(value = OpenAiChatModelConfig.class, name = "gpt-4o-mini"), + @JsonSubTypes.Type(value = GoogleAiGeminiChatModelConfig.class, name = "gemini-2.0-flash"), + @JsonSubTypes.Type(value = MistralAiChatModelConfig.class, name = "mistral-medium-latest") +}) +public abstract class AiModelConfig { + + @Schema( + requiredMode = Schema.RequiredMode.REQUIRED, + accessMode = Schema.AccessMode.READ_WRITE, + description = "Identifier of the AI model" + ) + private String model; + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/GoogleAiGeminiChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/GoogleAiGeminiChatModelConfig.java new file mode 100644 index 0000000000..761ec998cc --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/GoogleAiGeminiChatModelConfig.java @@ -0,0 +1,50 @@ +/** + * Copyright © 2016-2025 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data.ai.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@Schema( + name = "GoogleAiGeminiChatModelConfig", + description = "Configuration for Google AI Gemini chat models" +) +public final class GoogleAiGeminiChatModelConfig extends AiModelConfig { + + @Schema( + requiredMode = Schema.RequiredMode.REQUIRED, + accessMode = Schema.AccessMode.READ_WRITE, + description = "Identifier of the AI model", + allowableValues = "gemini-2.0-flash", + example = "gemini-2.0-flash" + ) + public String getModel() { + return super.getModel(); + } + + @Schema( + accessMode = Schema.AccessMode.READ_WRITE, + description = "Sampling temperature to control randomness: 0.0 (most deterministic) to 1.0 (most creative)", + example = "0.7" + ) + private Double temperature; + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/MistralAiChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/MistralAiChatModelConfig.java new file mode 100644 index 0000000000..20a8cfea7c --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/MistralAiChatModelConfig.java @@ -0,0 +1,50 @@ +/** + * Copyright © 2016-2025 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data.ai.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@Schema( + name = "MistralAiChatModelConfig", + description = "Configuration for Mistral AI chat models" +) +public final class MistralAiChatModelConfig extends AiModelConfig { + + @Schema( + requiredMode = Schema.RequiredMode.REQUIRED, + accessMode = Schema.AccessMode.READ_WRITE, + description = "Identifier of the AI model", + allowableValues = "mistral-medium-latest", + example = "mistral-medium-latest" + ) + public String getModel() { + return super.getModel(); + } + + @Schema( + accessMode = Schema.AccessMode.READ_WRITE, + description = "Sampling temperature to control randomness: 0.0 (most deterministic) to 1.0 (most creative)", + example = "0.7" + ) + private Double temperature; + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/OpenAiChatModelConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/OpenAiChatModelConfig.java new file mode 100644 index 0000000000..a7bc3725ef --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/model/OpenAiChatModelConfig.java @@ -0,0 +1,50 @@ +/** + * Copyright © 2016-2025 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data.ai.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@Schema( + name = "OpenAiChatModelConfig", + description = "Configuration for OpenAI chat models" +) +public final class OpenAiChatModelConfig extends AiModelConfig { + + @Schema( + requiredMode = Schema.RequiredMode.REQUIRED, + accessMode = Schema.AccessMode.READ_WRITE, + description = "Identifier of the AI model", + allowableValues = {"gpt-4o", "gpt-4o-mini"}, + example = "gpt-4o" + ) + public String getModel() { + return super.getModel(); + } + + @Schema( + accessMode = Schema.AccessMode.READ_WRITE, + description = "Sampling temperature to control randomness: 0.0 (most deterministic) to 1.0 (most creative)", + example = "0.7" + ) + private Double temperature; + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/AiProvider.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AiProvider.java similarity index 92% rename from common/data/src/main/java/org/thingsboard/server/common/data/ai/AiProvider.java rename to common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AiProvider.java index e2938cdddc..068d75873b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/AiProvider.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AiProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.data.ai; +package org.thingsboard.server.common.data.ai.provider; public enum AiProvider { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/AiConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AiProviderConfig.java similarity index 76% rename from common/data/src/main/java/org/thingsboard/server/common/data/ai/AiConfig.java rename to common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AiProviderConfig.java index 5c37d21454..06b82cdef2 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/AiConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/AiProviderConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.data.ai; +package org.thingsboard.server.common.data.ai.provider; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -30,17 +30,16 @@ import lombok.NoArgsConstructor; visible = true ) @JsonSubTypes({ - @JsonSubTypes.Type(value = OpenAiConfig.class, name = "OPENAI"), - @JsonSubTypes.Type(value = GoogleAiGeminiConfig.class, name = "GOOGLE_AI_GEMINI"), - @JsonSubTypes.Type(value = MistralAiConfig.class, name = "MISTRAL_AI") + @JsonSubTypes.Type(value = OpenAiProviderConfig.class, name = "OPENAI"), + @JsonSubTypes.Type(value = GoogleAiGeminiProviderConfig.class, name = "GOOGLE_AI_GEMINI"), + @JsonSubTypes.Type(value = MistralAiProviderConfig.class, name = "MISTRAL_AI") }) -public abstract class AiConfig { +public abstract class AiProviderConfig { @Schema( requiredMode = Schema.RequiredMode.REQUIRED, accessMode = Schema.AccessMode.READ_WRITE, - description = "API key for authenticating with the AI provider", - example = "sk-********************************" + description = "API key for authenticating with the AI provider" ) private String apiKey; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/GoogleAiGeminiConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GoogleAiGeminiProviderConfig.java similarity index 82% rename from common/data/src/main/java/org/thingsboard/server/common/data/ai/GoogleAiGeminiConfig.java rename to common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GoogleAiGeminiProviderConfig.java index 915fb41d55..9ca8643173 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/GoogleAiGeminiConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/GoogleAiGeminiProviderConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.data.ai; +package org.thingsboard.server.common.data.ai.provider; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -22,10 +22,10 @@ import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = true) @Schema( - name = "GoogleAiGemini", - description = "Configuration properties for the Google AI Gemini" + name = "GoogleAiGeminiProviderConfig", + description = "Configuration for the Google AI Gemini provider" ) -public class GoogleAiGeminiConfig extends AiConfig { +public final class GoogleAiGeminiProviderConfig extends AiProviderConfig { @Schema( requiredMode = Schema.RequiredMode.REQUIRED, diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/MistralAiConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/MistralAiProviderConfig.java similarity index 82% rename from common/data/src/main/java/org/thingsboard/server/common/data/ai/MistralAiConfig.java rename to common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/MistralAiProviderConfig.java index bbfd849f59..bc17f34220 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/MistralAiConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/MistralAiProviderConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.data.ai; +package org.thingsboard.server.common.data.ai.provider; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -22,10 +22,10 @@ import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = true) @Schema( - name = "MistralAi", - description = "Configuration properties for the Mistral AI" + name = "MistralAiProviderConfig", + description = "Configuration for the Mistral AI provider" ) -public class MistralAiConfig extends AiConfig { +public final class MistralAiProviderConfig extends AiProviderConfig { @Schema( requiredMode = Schema.RequiredMode.REQUIRED, diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/ai/OpenAiConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/OpenAiProviderConfig.java similarity index 83% rename from common/data/src/main/java/org/thingsboard/server/common/data/ai/OpenAiConfig.java rename to common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/OpenAiProviderConfig.java index cce6e3aa90..36ac8b4b35 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/ai/OpenAiConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/ai/provider/OpenAiProviderConfig.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.data.ai; +package org.thingsboard.server.common.data.ai.provider; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -22,10 +22,10 @@ import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = true) @Schema( - name = "OpenAiConfig", - description = "Configuration properties for the OpenAI" + name = "OpenAiProviderConfig", + description = "Configuration for the OpenAI provider" ) -public class OpenAiConfig extends AiConfig { +public final class OpenAiProviderConfig extends AiProviderConfig { @Schema( requiredMode = Schema.RequiredMode.REQUIRED, diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 20ef6ceb08..ecd93df6fd 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -746,8 +746,9 @@ public class ModelConstants { public static final String AI_SETTINGS_TENANT_ID_COLUMN_NAME = TENANT_ID_COLUMN; public static final String AI_SETTINGS_NAME_COLUMN_NAME = NAME_PROPERTY; public static final String AI_SETTINGS_PROVIDER_COLUMN_NAME = "provider"; + public static final String AI_SETTINGS_PROVIDER_CONFIG_COLUMN_NAME = "provider_config"; public static final String AI_SETTINGS_MODEL_COLUMN_NAME = "model"; - public static final String AI_SETTINGS_CONFIGURATION_COLUMN_NAME = "configuration"; + public static final String AI_SETTINGS_MODEL_CONFIG_COLUMN_NAME = "model_config"; protected static final String[] NONE_AGGREGATION_COLUMNS = new String[]{LONG_VALUE_COLUMN, DOUBLE_VALUE_COLUMN, BOOLEAN_VALUE_COLUMN, STRING_VALUE_COLUMN, JSON_VALUE_COLUMN, KEY_COLUMN, TS_COLUMN}; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AiSettingsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AiSettingsEntity.java index 458b434711..e2775e3cbb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AiSettingsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AiSettingsEntity.java @@ -26,9 +26,10 @@ import lombok.Setter; import lombok.ToString; import org.hibernate.annotations.Type; import org.hibernate.proxy.HibernateProxy; -import org.thingsboard.server.common.data.ai.AiConfig; -import org.thingsboard.server.common.data.ai.AiProvider; import org.thingsboard.server.common.data.ai.AiSettings; +import org.thingsboard.server.common.data.ai.model.AiModelConfig; +import org.thingsboard.server.common.data.ai.provider.AiProvider; +import org.thingsboard.server.common.data.ai.provider.AiProviderConfig; import org.thingsboard.server.common.data.id.AiSettingsId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.BaseVersionedEntity; @@ -54,12 +55,16 @@ public class AiSettingsEntity extends BaseVersionedEntity { @Column(name = ModelConstants.AI_SETTINGS_PROVIDER_COLUMN_NAME, nullable = false) private AiProvider provider; + @Type(JsonBinaryType.class) + @Column(name = ModelConstants.AI_SETTINGS_PROVIDER_CONFIG_COLUMN_NAME, nullable = false, columnDefinition = "JSONB") + private AiProviderConfig providerConfig; + @Column(name = ModelConstants.AI_SETTINGS_MODEL_COLUMN_NAME, nullable = false) private String model; @Type(JsonBinaryType.class) - @Column(name = ModelConstants.AI_SETTINGS_CONFIGURATION_COLUMN_NAME, nullable = false, columnDefinition = "JSONB") - private AiConfig configuration; + @Column(name = ModelConstants.AI_SETTINGS_MODEL_CONFIG_COLUMN_NAME, columnDefinition = "JSONB") + private AiModelConfig modelConfig; public AiSettingsEntity() {} @@ -68,8 +73,9 @@ public class AiSettingsEntity extends BaseVersionedEntity { tenantId = getTenantUuid(aiSettings.getTenantId()); name = aiSettings.getName(); provider = aiSettings.getProvider(); + providerConfig = aiSettings.getProviderConfig(); model = aiSettings.getModel(); - configuration = aiSettings.getConfiguration(); + modelConfig = aiSettings.getModelConfig(); } @Override @@ -80,8 +86,9 @@ public class AiSettingsEntity extends BaseVersionedEntity { settings.setTenantId(TenantId.fromUUID(tenantId)); settings.setName(name); settings.setProvider(provider); + settings.setProviderConfig(providerConfig); settings.setModel(model); - settings.setConfiguration(configuration); + settings.setModelConfig(modelConfig); return settings; } diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index b2b9ffaded..d2fabc71ec 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -950,13 +950,14 @@ CREATE TABLE IF NOT EXISTS cf_debug_event ( ) PARTITION BY RANGE (ts); CREATE TABLE IF NOT EXISTS ai_settings ( - id UUID NOT NULL PRIMARY KEY, - created_time BIGINT NOT NULL, - tenant_id UUID NOT NULL, - version BIGINT NOT NULL DEFAULT 1, - name VARCHAR(255) NOT NULL, - provider VARCHAR(255) NOT NULL, - model VARCHAR(255) NOT NULL, - configuration JSONB NOT NULL, + id UUID NOT NULL PRIMARY KEY, + created_time BIGINT NOT NULL, + tenant_id UUID NOT NULL, + version BIGINT NOT NULL DEFAULT 1, + name VARCHAR(255) NOT NULL, + provider VARCHAR(255) NOT NULL, + provider_config JSONB NOT NULL, + model VARCHAR(255) NOT NULL, + model_config JSONB, CONSTRAINT ai_settings_name_unq_key UNIQUE (tenant_id, name) );