AI rule node: add basic support for Azure OpenAI

This commit is contained in:
Dmytro Skarzhynets 2025-06-23 21:09:40 +03:00
parent bee8f370b9
commit c98f746aaf
No known key found for this signature in database
GPG Key ID: 2B51652F224037DF
9 changed files with 114 additions and 3 deletions

View File

@ -381,6 +381,10 @@
<groupId>org.rocksdb</groupId> <groupId>org.rocksdb</groupId>
<artifactId>rocksdbjni</artifactId> <artifactId>rocksdbjni</artifactId>
</dependency> </dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-azure-open-ai</artifactId>
</dependency>
<dependency> <dependency>
<groupId>dev.langchain4j</groupId> <groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId> <artifactId>langchain4j-open-ai</artifactId>

View File

@ -17,6 +17,7 @@ package org.thingsboard.server.service.ai;
import dev.langchain4j.model.chat.ChatModel; import dev.langchain4j.model.chat.ChatModel;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.ai.model.chat.AzureOpenAiChatModel;
import org.thingsboard.server.common.data.ai.model.chat.GoogleAiGeminiChatModel; import org.thingsboard.server.common.data.ai.model.chat.GoogleAiGeminiChatModel;
import org.thingsboard.server.common.data.ai.model.chat.Langchain4jChatModelConfigurer; import org.thingsboard.server.common.data.ai.model.chat.Langchain4jChatModelConfigurer;
import org.thingsboard.server.common.data.ai.model.chat.MistralAiChatModel; import org.thingsboard.server.common.data.ai.model.chat.MistralAiChatModel;
@ -39,6 +40,18 @@ public class Langchain4jChatModelConfigurerImpl implements Langchain4jChatModelC
.build(); .build();
} }
@Override
public ChatModel configureChatModel(AzureOpenAiChatModel chatModel) {
AzureOpenAiChatModel.Config modelConfig = chatModel.modelConfig();
return dev.langchain4j.model.azure.AzureOpenAiChatModel.builder()
.apiKey(chatModel.providerConfig().apiKey())
.deploymentName(chatModel.modelId())
.temperature(modelConfig.temperature())
.timeout(toDuration(modelConfig.timeoutSeconds()))
.maxRetries(modelConfig.maxRetries())
.build();
}
@Override @Override
public ChatModel configureChatModel(GoogleAiGeminiChatModel chatModel) { public ChatModel configureChatModel(GoogleAiGeminiChatModel chatModel) {
GoogleAiGeminiChatModel.Config modelConfig = chatModel.modelConfig(); GoogleAiGeminiChatModel.Config modelConfig = chatModel.modelConfig();

View File

@ -20,7 +20,7 @@ import org.thingsboard.server.common.data.ai.model.AiModel;
import org.thingsboard.server.common.data.ai.model.AiModelType; import org.thingsboard.server.common.data.ai.model.AiModelType;
public sealed interface AiChatModel<C extends AiChatModelConfig<C>> extends AiModel<C> public sealed interface AiChatModel<C extends AiChatModelConfig<C>> extends AiModel<C>
permits OpenAiChatModel, GoogleAiGeminiChatModel, MistralAiChatModel { permits OpenAiChatModel, AzureOpenAiChatModel, GoogleAiGeminiChatModel, MistralAiChatModel {
ChatModel configure(Langchain4jChatModelConfigurer configurer); ChatModel configure(Langchain4jChatModelConfigurer configurer);

View File

@ -18,7 +18,7 @@ package org.thingsboard.server.common.data.ai.model.chat;
import org.thingsboard.server.common.data.ai.model.AiModelConfig; import org.thingsboard.server.common.data.ai.model.AiModelConfig;
public sealed interface AiChatModelConfig<C extends AiChatModelConfig<C>> extends AiModelConfig<C> public sealed interface AiChatModelConfig<C extends AiChatModelConfig<C>> extends AiModelConfig<C>
permits OpenAiChatModel.Config, GoogleAiGeminiChatModel.Config, MistralAiChatModel.Config { permits OpenAiChatModel.Config, AzureOpenAiChatModel.Config, GoogleAiGeminiChatModel.Config, MistralAiChatModel.Config {
Double temperature(); Double temperature();

View File

@ -0,0 +1,60 @@
/**
* 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.chat;
import dev.langchain4j.model.chat.ChatModel;
import org.thingsboard.server.common.data.ai.provider.AzureOpenAiProviderConfig;
public record AzureOpenAiChatModel(
AzureOpenAiProviderConfig providerConfig,
String modelId,
Config modelConfig
) implements AiChatModel<AzureOpenAiChatModel.Config> {
public record Config(
Double temperature,
Integer timeoutSeconds,
Integer maxRetries
) implements AiChatModelConfig<AzureOpenAiChatModel.Config> {
@Override
public AzureOpenAiChatModel.Config withTemperature(Double temperature) {
return new Config(temperature, timeoutSeconds, maxRetries);
}
@Override
public AzureOpenAiChatModel.Config withTimeoutSeconds(Integer timeoutSeconds) {
return new Config(temperature, timeoutSeconds, maxRetries);
}
@Override
public AzureOpenAiChatModel.Config withMaxRetries(Integer maxRetries) {
return new Config(temperature, timeoutSeconds, maxRetries);
}
}
@Override
public ChatModel configure(Langchain4jChatModelConfigurer configurer) {
return configurer.configureChatModel(this);
}
@Override
public AzureOpenAiChatModel withModelConfig(AzureOpenAiChatModel.Config config) {
return new AzureOpenAiChatModel(providerConfig, modelId, config);
}
}

View File

@ -21,6 +21,8 @@ public interface Langchain4jChatModelConfigurer {
ChatModel configureChatModel(OpenAiChatModel chatModel); ChatModel configureChatModel(OpenAiChatModel chatModel);
ChatModel configureChatModel(AzureOpenAiChatModel chatModel);
ChatModel configureChatModel(GoogleAiGeminiChatModel chatModel); ChatModel configureChatModel(GoogleAiGeminiChatModel chatModel);
ChatModel configureChatModel(MistralAiChatModel chatModel); ChatModel configureChatModel(MistralAiChatModel chatModel);

View File

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data.ai.provider;
public enum AiProvider { public enum AiProvider {
OPENAI, OPENAI,
AZURE_OPENAI,
GOOGLE_AI_GEMINI, GOOGLE_AI_GEMINI,
MISTRAL_AI MISTRAL_AI

View File

@ -25,11 +25,12 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
) )
@JsonSubTypes({ @JsonSubTypes({
@JsonSubTypes.Type(value = OpenAiProviderConfig.class, name = "OPENAI"), @JsonSubTypes.Type(value = OpenAiProviderConfig.class, name = "OPENAI"),
@JsonSubTypes.Type(value = AzureOpenAiProviderConfig.class, name = "AZURE_OPENAI"),
@JsonSubTypes.Type(value = GoogleAiGeminiProviderConfig.class, name = "GOOGLE_AI_GEMINI"), @JsonSubTypes.Type(value = GoogleAiGeminiProviderConfig.class, name = "GOOGLE_AI_GEMINI"),
@JsonSubTypes.Type(value = MistralAiProviderConfig.class, name = "MISTRAL_AI") @JsonSubTypes.Type(value = MistralAiProviderConfig.class, name = "MISTRAL_AI")
}) })
public sealed interface AiProviderConfig public sealed interface AiProviderConfig
permits OpenAiProviderConfig, GoogleAiGeminiProviderConfig, MistralAiProviderConfig { permits OpenAiProviderConfig, AzureOpenAiProviderConfig, GoogleAiGeminiProviderConfig, MistralAiProviderConfig {
AiProvider provider(); AiProvider provider();

View File

@ -0,0 +1,30 @@
/**
* 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.provider;
public record AzureOpenAiProviderConfig(String apiKey) implements AiProviderConfig {
@Override
public AiProvider provider() {
return AiProvider.AZURE_OPENAI;
}
@Override
public String apiKey() {
return apiKey;
}
}