AI rule node: add support for GitHub Models
This commit is contained in:
parent
4f38422df8
commit
4507b312de
@ -409,6 +409,10 @@
|
|||||||
<groupId>dev.langchain4j</groupId>
|
<groupId>dev.langchain4j</groupId>
|
||||||
<artifactId>langchain4j-bedrock</artifactId>
|
<artifactId>langchain4j-bedrock</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>dev.langchain4j</groupId>
|
||||||
|
<artifactId>langchain4j-github-models</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.ai;
|
package org.thingsboard.server.service.ai;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
import com.google.auth.oauth2.ServiceAccountCredentials;
|
import com.google.auth.oauth2.ServiceAccountCredentials;
|
||||||
import com.google.cloud.vertexai.Transport;
|
import com.google.cloud.vertexai.Transport;
|
||||||
import com.google.cloud.vertexai.VertexAI;
|
import com.google.cloud.vertexai.VertexAI;
|
||||||
@ -30,6 +29,7 @@ import org.thingsboard.common.util.JacksonUtil;
|
|||||||
import org.thingsboard.server.common.data.ai.model.chat.AmazonBedrockChatModel;
|
import org.thingsboard.server.common.data.ai.model.chat.AmazonBedrockChatModel;
|
||||||
import org.thingsboard.server.common.data.ai.model.chat.AnthropicChatModel;
|
import org.thingsboard.server.common.data.ai.model.chat.AnthropicChatModel;
|
||||||
import org.thingsboard.server.common.data.ai.model.chat.AzureOpenAiChatModel;
|
import org.thingsboard.server.common.data.ai.model.chat.AzureOpenAiChatModel;
|
||||||
|
import org.thingsboard.server.common.data.ai.model.chat.GitHubModelsChatModel;
|
||||||
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.GoogleVertexAiGeminiChatModel;
|
import org.thingsboard.server.common.data.ai.model.chat.GoogleVertexAiGeminiChatModel;
|
||||||
import org.thingsboard.server.common.data.ai.model.chat.Langchain4jChatModelConfigurer;
|
import org.thingsboard.server.common.data.ai.model.chat.Langchain4jChatModelConfigurer;
|
||||||
@ -91,11 +91,10 @@ class Langchain4jChatModelConfigurerImpl implements Langchain4jChatModelConfigur
|
|||||||
GoogleVertexAiGeminiChatModel.Config modelConfig = chatModel.modelConfig();
|
GoogleVertexAiGeminiChatModel.Config modelConfig = chatModel.modelConfig();
|
||||||
|
|
||||||
// construct service account credentials using service account key JSON
|
// construct service account credentials using service account key JSON
|
||||||
ObjectNode serviceAccountKeyJson = providerConfig.serviceAccountKey();
|
|
||||||
ServiceAccountCredentials serviceAccountCredentials;
|
ServiceAccountCredentials serviceAccountCredentials;
|
||||||
try {
|
try {
|
||||||
serviceAccountCredentials = ServiceAccountCredentials
|
serviceAccountCredentials = ServiceAccountCredentials
|
||||||
.fromStream(new ByteArrayInputStream(JacksonUtil.writeValueAsBytes(serviceAccountKeyJson)));
|
.fromStream(new ByteArrayInputStream(JacksonUtil.writeValueAsBytes(providerConfig.serviceAccountKey())));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Failed to parse service account key JSON", e);
|
throw new RuntimeException("Failed to parse service account key JSON", e);
|
||||||
}
|
}
|
||||||
@ -173,6 +172,18 @@ class Langchain4jChatModelConfigurerImpl implements Langchain4jChatModelConfigur
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChatModel configureChatModel(GitHubModelsChatModel chatModel) {
|
||||||
|
GitHubModelsChatModel.Config modelConfig = chatModel.modelConfig();
|
||||||
|
return dev.langchain4j.model.github.GitHubModelsChatModel.builder()
|
||||||
|
.gitHubToken(chatModel.providerConfig().personalAccessToken())
|
||||||
|
.modelName(modelConfig.modelId())
|
||||||
|
.temperature(modelConfig.temperature())
|
||||||
|
.timeout(toDuration(modelConfig.timeoutSeconds()))
|
||||||
|
.maxRetries(modelConfig.maxRetries())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
private static Duration toDuration(Integer timeoutSeconds) {
|
private static Duration toDuration(Integer timeoutSeconds) {
|
||||||
return timeoutSeconds != null ? Duration.ofSeconds(timeoutSeconds) : null;
|
return timeoutSeconds != null ? Duration.ofSeconds(timeoutSeconds) : null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.JavaType;
|
|||||||
import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase;
|
import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase;
|
||||||
import org.thingsboard.server.common.data.ai.model.chat.AmazonBedrockChatModel;
|
import org.thingsboard.server.common.data.ai.model.chat.AmazonBedrockChatModel;
|
||||||
import org.thingsboard.server.common.data.ai.model.chat.AnthropicChatModel;
|
import org.thingsboard.server.common.data.ai.model.chat.AnthropicChatModel;
|
||||||
|
import org.thingsboard.server.common.data.ai.model.chat.GitHubModelsChatModel;
|
||||||
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.GoogleVertexAiGeminiChatModel;
|
import org.thingsboard.server.common.data.ai.model.chat.GoogleVertexAiGeminiChatModel;
|
||||||
import org.thingsboard.server.common.data.ai.model.chat.MistralAiChatModel;
|
import org.thingsboard.server.common.data.ai.model.chat.MistralAiChatModel;
|
||||||
@ -90,6 +91,9 @@ public final class AiModelTypeIdResolver extends TypeIdResolverBase {
|
|||||||
// Amazon Bedrock models
|
// Amazon Bedrock models
|
||||||
map.put("AMAZON_BEDROCK::amazon.nova-lite-v1:0", AmazonBedrockChatModel.class);
|
map.put("AMAZON_BEDROCK::amazon.nova-lite-v1:0", AmazonBedrockChatModel.class);
|
||||||
|
|
||||||
|
// GitHub Models models
|
||||||
|
map.put("GITHUB_MODELS::gpt-4o", GitHubModelsChatModel.class);
|
||||||
|
|
||||||
typeIdToModelClass = Collections.unmodifiableMap(map);
|
typeIdToModelClass = Collections.unmodifiableMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ public sealed interface AiChatModel<C extends AiChatModelConfig<C>> extends AiMo
|
|||||||
permits
|
permits
|
||||||
OpenAiChatModel, AzureOpenAiChatModel, GoogleAiGeminiChatModel,
|
OpenAiChatModel, AzureOpenAiChatModel, GoogleAiGeminiChatModel,
|
||||||
GoogleVertexAiGeminiChatModel, MistralAiChatModel, AnthropicChatModel,
|
GoogleVertexAiGeminiChatModel, MistralAiChatModel, AnthropicChatModel,
|
||||||
AmazonBedrockChatModel {
|
AmazonBedrockChatModel, GitHubModelsChatModel {
|
||||||
|
|
||||||
ChatModel configure(Langchain4jChatModelConfigurer configurer);
|
ChatModel configure(Langchain4jChatModelConfigurer configurer);
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ public sealed interface AiChatModelConfig<C extends AiChatModelConfig<C>> extend
|
|||||||
permits
|
permits
|
||||||
OpenAiChatModel.Config, AzureOpenAiChatModel.Config, GoogleAiGeminiChatModel.Config,
|
OpenAiChatModel.Config, AzureOpenAiChatModel.Config, GoogleAiGeminiChatModel.Config,
|
||||||
GoogleVertexAiGeminiChatModel.Config, MistralAiChatModel.Config, AnthropicChatModel.Config,
|
GoogleVertexAiGeminiChatModel.Config, MistralAiChatModel.Config, AnthropicChatModel.Config,
|
||||||
AmazonBedrockChatModel.Config {
|
AmazonBedrockChatModel.Config, GitHubModelsChatModel.Config {
|
||||||
|
|
||||||
Double temperature();
|
Double temperature();
|
||||||
|
|
||||||
|
|||||||
@ -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.GithubModelsProviderConfig;
|
||||||
|
|
||||||
|
public record GitHubModelsChatModel(
|
||||||
|
GithubModelsProviderConfig providerConfig,
|
||||||
|
Config modelConfig
|
||||||
|
) implements AiChatModel<GitHubModelsChatModel.Config> {
|
||||||
|
|
||||||
|
public record Config(
|
||||||
|
String modelId,
|
||||||
|
Double temperature,
|
||||||
|
Integer timeoutSeconds,
|
||||||
|
Integer maxRetries
|
||||||
|
) implements AiChatModelConfig<GitHubModelsChatModel.Config> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GitHubModelsChatModel.Config withTemperature(Double temperature) {
|
||||||
|
return new Config(modelId, temperature, timeoutSeconds, maxRetries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GitHubModelsChatModel.Config withTimeoutSeconds(Integer timeoutSeconds) {
|
||||||
|
return new Config(modelId, temperature, timeoutSeconds, maxRetries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GitHubModelsChatModel.Config withMaxRetries(Integer maxRetries) {
|
||||||
|
return new Config(modelId, temperature, timeoutSeconds, maxRetries);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChatModel configure(Langchain4jChatModelConfigurer configurer) {
|
||||||
|
return configurer.configureChatModel(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GitHubModelsChatModel withModelConfig(GitHubModelsChatModel.Config config) {
|
||||||
|
return new GitHubModelsChatModel(providerConfig, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -33,4 +33,6 @@ public interface Langchain4jChatModelConfigurer {
|
|||||||
|
|
||||||
ChatModel configureChatModel(AmazonBedrockChatModel chatModel);
|
ChatModel configureChatModel(AmazonBedrockChatModel chatModel);
|
||||||
|
|
||||||
|
ChatModel configureChatModel(GitHubModelsChatModel chatModel);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@ public enum AiProvider {
|
|||||||
GOOGLE_VERTEX_AI_GEMINI,
|
GOOGLE_VERTEX_AI_GEMINI,
|
||||||
MISTRAL_AI,
|
MISTRAL_AI,
|
||||||
ANTHROPIC,
|
ANTHROPIC,
|
||||||
AMAZON_BEDROCK
|
AMAZON_BEDROCK,
|
||||||
|
GITHUB_MODELS
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,13 +30,14 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
|||||||
@JsonSubTypes.Type(value = GoogleVertexAiGeminiProviderConfig.class, name = "GOOGLE_VERTEX_AI_GEMINI"),
|
@JsonSubTypes.Type(value = GoogleVertexAiGeminiProviderConfig.class, name = "GOOGLE_VERTEX_AI_GEMINI"),
|
||||||
@JsonSubTypes.Type(value = MistralAiProviderConfig.class, name = "MISTRAL_AI"),
|
@JsonSubTypes.Type(value = MistralAiProviderConfig.class, name = "MISTRAL_AI"),
|
||||||
@JsonSubTypes.Type(value = AnthropicProviderConfig.class, name = "ANTHROPIC"),
|
@JsonSubTypes.Type(value = AnthropicProviderConfig.class, name = "ANTHROPIC"),
|
||||||
@JsonSubTypes.Type(value = AmazonBedrockProviderConfig.class, name = "AMAZON_BEDROCK")
|
@JsonSubTypes.Type(value = AmazonBedrockProviderConfig.class, name = "AMAZON_BEDROCK"),
|
||||||
|
@JsonSubTypes.Type(value = GithubModelsProviderConfig.class, name = "GITHUB_MODELS")
|
||||||
})
|
})
|
||||||
public sealed interface AiProviderConfig
|
public sealed interface AiProviderConfig
|
||||||
permits
|
permits
|
||||||
OpenAiProviderConfig, AzureOpenAiProviderConfig, GoogleAiGeminiProviderConfig,
|
OpenAiProviderConfig, AzureOpenAiProviderConfig, GoogleAiGeminiProviderConfig,
|
||||||
GoogleVertexAiGeminiProviderConfig, MistralAiProviderConfig, AnthropicProviderConfig,
|
GoogleVertexAiGeminiProviderConfig, MistralAiProviderConfig, AnthropicProviderConfig,
|
||||||
AmazonBedrockProviderConfig {
|
AmazonBedrockProviderConfig, GithubModelsProviderConfig {
|
||||||
|
|
||||||
AiProvider provider();
|
AiProvider provider();
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* 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 GithubModelsProviderConfig(String personalAccessToken) implements AiProviderConfig {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AiProvider provider() {
|
||||||
|
return AiProvider.GITHUB_MODELS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user