diff --git a/common/rest-java-model/build.gradle b/common/rest-java-model/build.gradle index 60135688..dc5a23eb 100644 --- a/common/rest-java-model/build.gradle +++ b/common/rest-java-model/build.gradle @@ -23,6 +23,7 @@ openApiGenerate { invokerPackage = "ai.h2o.mojos.deploy.common.rest" inputSpec = "$rootDir/common/swagger/v1openapi3/swagger.json" outputDir = "$buildDir/gen" + generateAliasAsModel = true globalProperties.set([ "skipFormModel": "false", ]) diff --git a/common/rest-jdbc-spring-api/build.gradle b/common/rest-jdbc-spring-api/build.gradle index 640a6bd4..06a8cd0e 100644 --- a/common/rest-jdbc-spring-api/build.gradle +++ b/common/rest-jdbc-spring-api/build.gradle @@ -20,6 +20,7 @@ openApiGenerate { generatorName = 'spring' inputSpec = "$rootDir/common/swagger/v1/jdbc_swagger.json" outputDir = "$buildDir/gen" + generateAliasAsModel = true configOptions.set([ "useSpringBoot3": "true", "interfaceOnly": "true", diff --git a/common/rest-spring-api/build.gradle b/common/rest-spring-api/build.gradle index 7bb85789..7e7ef5cb 100644 --- a/common/rest-spring-api/build.gradle +++ b/common/rest-spring-api/build.gradle @@ -20,6 +20,7 @@ openApiGenerate { generatorName = 'spring' inputSpec = "$rootDir/common/swagger/v1openapi3/swagger.json" outputDir = "$buildDir/gen" + generateAliasAsModel = true globalProperties.set([ "skipFormModel": "false", ]) diff --git a/common/rest-vertex-ai-spring-api/build.gradle b/common/rest-vertex-ai-spring-api/build.gradle index f636917a..d0eb811a 100644 --- a/common/rest-vertex-ai-spring-api/build.gradle +++ b/common/rest-vertex-ai-spring-api/build.gradle @@ -20,6 +20,7 @@ openApiGenerate { generatorName = 'spring' inputSpec = "$rootDir/common/swagger/v1/vertex-ai-swagger.json" outputDir = "$buildDir/gen" + generateAliasAsModel = true configOptions.set([ "useSpringBoot3": "true", "interfaceOnly": "true", diff --git a/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/MojoFrameToContributionResponseConverter.java b/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/MojoFrameToContributionResponseConverter.java index fef44d63..74f9b7d5 100644 --- a/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/MojoFrameToContributionResponseConverter.java +++ b/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/MojoFrameToContributionResponseConverter.java @@ -19,8 +19,8 @@ public class MojoFrameToContributionResponseConverter { * ContributionResponse}. */ public ContributionResponse contributionResponseWithNoOutputGroup(MojoFrame shapleyMojoFrame) { - List> outputRows = - Stream.generate(ArrayList::new) + List outputRows = + Stream.generate(Row::new) .limit(shapleyMojoFrame.getNrows()) .collect(Collectors.toList()); Utils.copyResultFields(shapleyMojoFrame, outputRows); diff --git a/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/MojoFrameToScoreResponseConverter.java b/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/MojoFrameToScoreResponseConverter.java index 59a6a60c..b81327cf 100644 --- a/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/MojoFrameToScoreResponseConverter.java +++ b/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/MojoFrameToScoreResponseConverter.java @@ -37,7 +37,7 @@ public class MojoFrameToScoreResponseConverter // Note: assumption is that pipeline supports Prediction interval. // However for some h2o3 model, even classification model may still set // this to be true. - private Boolean supportPredictionInterval; + private final Boolean supportPredictionInterval; public MojoFrameToScoreResponseConverter(boolean supportPredictionInterval) { this.supportPredictionInterval = supportPredictionInterval; @@ -57,8 +57,8 @@ public MojoFrameToScoreResponseConverter() { @Override public ScoreResponse apply(MojoFrame mojoFrame, ScoreRequest scoreRequest) { Set includedFields = getSetOfIncludedFields(scoreRequest); - List> outputRows = - Stream.generate(ArrayList::new) + List outputRows = + Stream.generate(Row::new) .limit(mojoFrame.getNrows()) .collect(Collectors.toList()); copyFilteredInputFields(scoreRequest, includedFields, outputRows); @@ -81,7 +81,7 @@ public ScoreResponse apply(MojoFrame mojoFrame, ScoreRequest scoreRequest) { * response frame, only one column rows will be populated into the outputRows to ensure backward * compatible. */ - private void fillOutputRows(MojoFrame mojoFrame, List> outputRows) { + private void fillOutputRows(MojoFrame mojoFrame, List outputRows) { List> targetRows = getTargetRows(mojoFrame); for (int rowIdx = 0; rowIdx < mojoFrame.getNrows(); rowIdx++) { outputRows.get(rowIdx).addAll(targetRows.get(rowIdx)); @@ -182,9 +182,9 @@ private List getTargetFieldIndices(MojoFrame mojoFrame) { * Extract prediction interval columns rows from MOJO response frame. Note: Assumption is * prediction interval should already be enabled and response frame has expected structure. */ - private List> getPredictionIntervalRows(MojoFrame mojoFrame, int targetIdx) { - List> predictionIntervalRows = - Stream.generate(ArrayList::new) + private List getPredictionIntervalRows(MojoFrame mojoFrame, int targetIdx) { + List predictionIntervalRows = + Stream.generate(Row::new) .limit(mojoFrame.getNrows()) .collect(Collectors.toList()); for (int row = 0; row < mojoFrame.getNrows(); row++) { @@ -234,12 +234,12 @@ private int getTargetColIdx(List mojoColumns) { } private static void copyFilteredInputFields( - ScoreRequest scoreRequest, Set includedFields, List> outputRows) { + ScoreRequest scoreRequest, Set includedFields, List outputRows) { if (includedFields.isEmpty()) { return; } boolean generateRowIds = shouldGenerateRowIds(scoreRequest, includedFields); - List> inputRows = scoreRequest.getRows(); + List inputRows = scoreRequest.getRows(); for (int row = 0; row < outputRows.size(); row++) { List inputRow = inputRows.get(row); List outputRow = outputRows.get(row); diff --git a/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/RequestChecker.java b/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/RequestChecker.java index 00044180..dcf55f4c 100644 --- a/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/RequestChecker.java +++ b/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/RequestChecker.java @@ -2,8 +2,10 @@ import static java.util.Arrays.asList; +import ai.h2o.mojos.deploy.common.rest.model.Row; import ai.h2o.mojos.deploy.common.rest.model.ScoreRequest; import ai.h2o.mojos.runtime.frame.MojoFrameMeta; +import java.util.HashSet; import java.util.List; /** Checks that the request is of the correct form matching the corresponding mojo pipeline. */ @@ -36,15 +38,15 @@ private String getProblemMessageOrNull(ScoreRequest scoreRequest, MojoFrameMeta if (fields == null || fields.isEmpty()) { return "List of input fields cannot be empty"; } - List> rows = scoreRequest.getRows(); + List rows = scoreRequest.getRows(); if (rows == null || rows.isEmpty()) { return "List of input data rows cannot be empty"; } List expectedFields = asList(expectedMeta.getColumnNames()); - if (!fields.containsAll(expectedFields)) { + if (!new HashSet<>(fields).containsAll(expectedFields)) { return String.format( "Input fields don't contain all the Mojo fields, expected %s actual %s", - expectedFields.toString(), fields.toString()); + expectedFields, fields); } int i = 0; for (List row : scoreRequest.getRows()) { diff --git a/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/ScoreRequestTransformer.java b/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/ScoreRequestTransformer.java index a530d993..d04647a1 100644 --- a/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/ScoreRequestTransformer.java +++ b/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/ScoreRequestTransformer.java @@ -1,9 +1,9 @@ package ai.h2o.mojos.deploy.common.transform; import ai.h2o.mojos.deploy.common.rest.model.DataField; +import ai.h2o.mojos.deploy.common.rest.model.Row; import ai.h2o.mojos.deploy.common.rest.model.ScoreRequest; import com.google.common.collect.ImmutableMap; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.BiConsumer; @@ -30,35 +30,29 @@ public void accept(ScoreRequest scoreRequest, List dataFields) { transformRow(scoreRequest.getFields(), scoreRequest.getRows(), dataFieldMap)); } - private List> transformRow( - List fields, List> rows, Map dataFields) { + private List transformRow( + List fields, List rows, Map dataFields) { return rows.stream() .map( - row -> { - List transformData = - IntStream.range(0, row.size()) - .mapToObj( - fieldIdx -> { - String colName = fields.get(fieldIdx); - String origin = row.get(fieldIdx); - if (dataFields.containsKey(colName)) { - String sanitizeValue = - Utils.sanitizeBoolean( - origin, dataFields.get(colName).getDataType()); - if (!sanitizeValue.equals(origin)) { - logger.debug("Value '{}' parsed as '{}'", origin, sanitizeValue); - } - return sanitizeValue; - } else { - logger.debug("Column '{}' can not be found in Input schema", colName); - return origin; + row -> + IntStream.range(0, row.size()) + .mapToObj( + fieldIdx -> { + String colName = fields.get(fieldIdx); + String origin = row.get(fieldIdx); + if (dataFields.containsKey(colName)) { + String sanitizeValue = + Utils.sanitizeBoolean( + origin, dataFields.get(colName).getDataType()); + if (!sanitizeValue.equals(origin)) { + logger.debug("Value '{}' parsed as '{}'", origin, sanitizeValue); } - }) - .collect(Collectors.toList()); - List transformedRow = new ArrayList<>(); - transformedRow.addAll(transformData); - return transformedRow; - }) - .collect(Collectors.toList()); + return sanitizeValue; + } else { + logger.debug("Column '{}' can not be found in Input schema", colName); + return origin; + } + }) + .collect(Collectors.toCollection(Row::new))).collect(Collectors.toList()); } } diff --git a/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/Utils.java b/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/Utils.java index cf8a55eb..6ea5e0d7 100644 --- a/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/Utils.java +++ b/common/transform/src/main/java/ai/h2o/mojos/deploy/common/transform/Utils.java @@ -1,6 +1,7 @@ package ai.h2o.mojos.deploy.common.transform; import ai.h2o.mojos.deploy.common.rest.model.DataField; +import ai.h2o.mojos.deploy.common.rest.model.Row; import ai.h2o.mojos.runtime.frame.MojoFrame; import java.util.List; @@ -10,7 +11,7 @@ public class Utils { * * @param mojoFrame {@link MojoFrame} */ - public static void copyResultFields(MojoFrame mojoFrame, List> outputRows) { + public static void copyResultFields(MojoFrame mojoFrame, List outputRows) { String[][] outputColumns = new String[mojoFrame.getNcols()][]; for (int col = 0; col < mojoFrame.getNcols(); col++) { outputColumns[col] = mojoFrame.getColumn(col).getDataAsStrings(); diff --git a/common/transform/src/test/java/ai/h2o/mojos/deploy/common/transform/MojoScorerTest.java b/common/transform/src/test/java/ai/h2o/mojos/deploy/common/transform/MojoScorerTest.java index b1de0e40..5896de01 100644 --- a/common/transform/src/test/java/ai/h2o/mojos/deploy/common/transform/MojoScorerTest.java +++ b/common/transform/src/test/java/ai/h2o/mojos/deploy/common/transform/MojoScorerTest.java @@ -474,8 +474,8 @@ private MojoFrame generateDummyTransformedMojoFrame() { private ScoreResponse generateDummyResponse() { ScoreResponse response = new ScoreResponse(); - List> outputRows = - Stream.generate(ArrayList::new).limit(4).collect(Collectors.toList()); + List outputRows = + Stream.generate(Row::new).limit(4).collect(Collectors.toList()); response.setScore(outputRows); response.setFields(Arrays.asList("field1")); return response; diff --git a/common/transform/src/test/java/ai/h2o/mojos/deploy/common/transform/ScoreRequestTransformerTest.java b/common/transform/src/test/java/ai/h2o/mojos/deploy/common/transform/ScoreRequestTransformerTest.java index 8807ff4e..e3cb0064 100644 --- a/common/transform/src/test/java/ai/h2o/mojos/deploy/common/transform/ScoreRequestTransformerTest.java +++ b/common/transform/src/test/java/ai/h2o/mojos/deploy/common/transform/ScoreRequestTransformerTest.java @@ -38,16 +38,16 @@ void transform_BooleanLiteral_Transformed() { // Given ScoreRequest scoreRequest = new ScoreRequest(); scoreRequest.setFields(Collections.singletonList("test")); - List> rows = + List rows = new ArrayList<>( Arrays.asList( - new ArrayList<>(), - new ArrayList<>(), - new ArrayList<>(), - new ArrayList<>(), - new ArrayList<>(), - new ArrayList<>(), - new ArrayList<>())); + new Row(), + new Row(), + new Row(), + new Row(), + new Row(), + new Row(), + new Row())); rows.get(0).addAll(Collections.singletonList("true")); rows.get(1).addAll(Collections.singletonList("False")); rows.get(2).addAll(Collections.singletonList("TrUE")); @@ -65,11 +65,11 @@ void transform_BooleanLiteral_Transformed() { scoreRequestTransformer.accept(scoreRequest, dataFields); // Then - List> expected = + List expected = new ArrayList<>( Arrays.asList( - new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), - new ArrayList<>(), new ArrayList<>(), new ArrayList<>())); + new Row(), new Row(), new Row(), new Row(), + new Row(), new Row(), new Row())); expected.get(0).addAll(Collections.singletonList("1")); expected.get(1).addAll(Collections.singletonList("0")); expected.get(2).addAll(Collections.singletonList("1")); @@ -85,7 +85,7 @@ void transform_NonBooleanLiteral_Unchanged() { // Given ScoreRequest scoreRequest = new ScoreRequest(); scoreRequest.setFields(Collections.singletonList("test")); - List> rows = new ArrayList<>(Arrays.asList(new Row(), new Row())); + List rows = new ArrayList<>(Arrays.asList(new Row(), new Row())); rows.get(0).addAll(Collections.singletonList("unchangedFeature1")); rows.get(1).addAll(Collections.singletonList("unchangedFeature2")); scoreRequest.setRows(rows); diff --git a/gcp-vertex-ai-mojo-scorer/src/main/java/ai/h2o/mojos/deploy/gcp/vertex/ai/controller/ModelsApiController.java b/gcp-vertex-ai-mojo-scorer/src/main/java/ai/h2o/mojos/deploy/gcp/vertex/ai/controller/ModelsApiController.java index 977cd50f..a678cbdc 100644 --- a/gcp-vertex-ai-mojo-scorer/src/main/java/ai/h2o/mojos/deploy/gcp/vertex/ai/controller/ModelsApiController.java +++ b/gcp-vertex-ai-mojo-scorer/src/main/java/ai/h2o/mojos/deploy/gcp/vertex/ai/controller/ModelsApiController.java @@ -123,7 +123,7 @@ public static ScoreRequest getRestScoreRequest( } } - List row; + Row row; for (List gcpRow : gcpRequest.getInstances()) { row = new Row(); for (int i = 0; i < gcpRow.size(); i++) { @@ -149,9 +149,9 @@ public static ScoreResponse getGcpScoreResponse( response.setId(restResponse.getId()); response.setFields(restResponse.getFields()); - List row; + ai.h2o.mojos.deploy.common.rest.vertex.ai.model.Row row; for (List restRow : restResponse.getScore()) { - row = new ArrayList<>(); + row = new ai.h2o.mojos.deploy.common.rest.vertex.ai.model.Row(); for (int i = 0; i < restRow.size(); i++) { row.add(restRow.get(i)); } diff --git a/gradle.properties b/gradle.properties index e1e2ecc6..4cb5067c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -52,8 +52,8 @@ errorproneVersion = 2.23.0 # Docker settings dockerRepositoryPrefix = harbor.h2o.ai/opsh2oai/h2oai/ dockerIncludePython = true -# Digest of eclipse-temurin:17.0.9_9-jdk-alpine -javaBaseImage = eclipse-temurin@sha256:24643c2dd329ef482ecd042b59cbfb7fe13716342e22674a0abd763559c8a1dd +# Digest of eclipse-temurin:17.0.10_7-jdk-alpine +javaBaseImage = eclipse-temurin@sha256:0e6e494ac4da6509a038b7689250bc7ea68beaf8a5efbca5ed7c8692457b283c # Increase timeouts to avoid read error from OSS Nexus # See: diff --git a/settings.gradle b/settings.gradle index 29b59ed7..e1a32c9e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,18 +14,18 @@ dependencyResolutionManagement { } rootProject.name = 'dai-deployment-templates' -include 'aws-lambda-scorer:lambda-template' -include 'aws-lambda-scorer:terraform-recipe' -include 'common:jdbc' +//include 'aws-lambda-scorer:lambda-template' +//include 'aws-lambda-scorer:terraform-recipe' +//include 'common:jdbc' include 'common:rest-java-model' -include 'common:rest-jdbc-spring-api' +//include 'common:rest-jdbc-spring-api' include 'common:rest-spring-api' include 'common:transform' -include 'common:kdb-java' -include 'common:rest-vertex-ai-spring-api' +//include 'common:kdb-java' +//include 'common:rest-vertex-ai-spring-api' include 'local-rest-scorer' -include 'kdb-mojo-scorer' -include 'aws-sagemaker-hosted-scorer' -include 'gcp-cloud-run' -include 'sql-jdbc-scorer' -include 'gcp-vertex-ai-mojo-scorer' +//include 'kdb-mojo-scorer' +//include 'aws-sagemaker-hosted-scorer' +//include 'gcp-cloud-run' +//include 'sql-jdbc-scorer' +//include 'gcp-vertex-ai-mojo-scorer'