AI rule node: add JSON Schema to rule node config

This commit is contained in:
Dmytro Skarzhynets 2025-05-20 17:59:58 +03:00
parent 7093032516
commit c2776ce7a6
No known key found for this signature in database
GPG Key ID: 2B51652F224037DF
3 changed files with 66 additions and 6 deletions

View File

@ -114,7 +114,10 @@
<dependency>
<groupId>net.objecthunter</groupId>
<artifactId>exp4j</artifactId>
<version>${exp4j.version}</version>
</dependency>
<dependency>
<groupId>com.networknt</groupId>
<artifactId>json-schema-validator</artifactId>
</dependency>
</dependencies>

View File

@ -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.common.util;
import com.fasterxml.jackson.databind.JsonNode;
import com.networknt.schema.JsonSchemaFactory;
import com.networknt.schema.SchemaId;
import com.networknt.schema.SchemaLocation;
import com.networknt.schema.SpecVersion;
import com.networknt.schema.ValidationMessage;
import java.util.Set;
public final class JsonSchemaUtils {
private JsonSchemaUtils() {
throw new AssertionError("Can't instantiate utility class");
}
/**
* Validates that the provided JsonNode is a valid JSON Schema (Draft 2020-12).
*
* @param schemaNode the JSON Schema document as a JsonNode
* @return true if the schema is well-formed, false otherwise
*/
public static boolean isValidJsonSchema(JsonNode schemaNode) {
Set<ValidationMessage> errors = JsonSchemaFactory
.getInstance(SpecVersion.VersionFlag.V202012)
.getSchema(SchemaLocation.of(SchemaId.V202012))
.validate(schemaNode);
return errors.isEmpty();
}
}

View File

@ -15,9 +15,12 @@
*/
package org.thingsboard.rule.engine.ai;
import com.fasterxml.jackson.databind.JsonNode;
import jakarta.validation.constraints.AssertTrue;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.thingsboard.common.util.JsonSchemaUtils;
import org.thingsboard.rule.engine.api.NodeConfiguration;
import org.thingsboard.server.common.data.id.AiSettingsId;
import org.thingsboard.server.common.data.validation.Length;
@ -36,15 +39,22 @@ public class TbAiNodeConfiguration implements NodeConfiguration<TbAiNodeConfigur
@Length(min = 1, max = 1000)
private String userPrompt;
private JsonNode jsonSchema;
@AssertTrue(message = "provided JSON Schema must conform to the Draft 2020-12 meta-schema")
public boolean isJsonSchemaValid() {
return jsonSchema == null || JsonSchemaUtils.isValidJsonSchema(jsonSchema);
}
@Override
public TbAiNodeConfiguration defaultConfiguration() {
var configuration = new TbAiNodeConfiguration();
configuration.setSystemPrompt("""
Take a deep breath and work on this step by step.
You are an industry-leading IoT domain expert with deep experience in telemetry data analysis.
Your task is to complete the user-provided task or answer a question.
You may use additional context information called "Rule engine message payload", "Rule engine message metadata" and "Rule engine message type".
Your response must be in JSON format.""");
Take a deep breath and work on this step by step.
You are an industry-leading IoT domain expert with deep experience in telemetry data analysis.
Your task is to complete the user-provided task or answer a question.
You may use additional context information called "Rule engine message payload", "Rule engine message metadata" and "Rule engine message type".
Your response must be in JSON format.""");
configuration.setUserPrompt("Tell me a joke");
return configuration;
}