summaryrefslogtreecommitdiffstats
path: root/config-model
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@oath.com>2020-06-09 14:44:47 +0200
committerGitHub <noreply@github.com>2020-06-09 14:44:47 +0200
commita4772f8264055cdfead946140419ba215f2d7f21 (patch)
treed0aa3b6f4f729ccca948c51df257e2d56ec0fdc1 /config-model
parentbf80dc06565f1af7cfc8b7e8fea93afe0c1f2b52 (diff)
parent8d3221cdba387a76e20ebd89ef7be5e0f8fea1ee (diff)
Merge pull request #13521 from vespa-engine/bratseth/disallow-unbound-dimensions
Bratseth/disallow unbound dimensions
Diffstat (limited to 'config-model')
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java6
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/RankingConstant.java7
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/document/SDField.java74
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/document/TemporarySDField.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidator.java41
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/application/validation/RankingConstantsValidator.java2
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/search/QueryProfiles.java8
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/ml/ConvertedModel.java2
-rw-r--r--config-model/src/test/cfg/application/ml_models/searchdefinitions/test.sd2
-rw-r--r--config-model/src/test/cfg/application/validation/ranking_constants_fail/searchdefinitions/simple.sd6
-rw-r--r--config-model/src/test/cfg/application/validation/ranking_constants_ok/searchdefinitions/simple.sd6
-rw-r--r--config-model/src/test/derived/tensor/documenttypes.cfg2
-rw-r--r--config-model/src/test/derived/tensor/tensor.sd2
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/RankProfileTestCase.java21
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/RankingExpressionShadowingTestCase.java14
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/FastAccessValidatorTest.java2
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/ImportedFieldsResolverTestCase.java2
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeResolverTestCase.java22
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionWithOnnxTestCase.java17
-rw-r--r--config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionWithTensorFlowTestCase.java13
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidatorTest.java20
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/RankingConstantsValidatorTest.java8
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java4
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/ml/MlModelsTest.java12
24 files changed, 162 insertions, 133 deletions
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java b/config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java
index 8b2a190feb9..d309f48d6df 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java
@@ -304,6 +304,12 @@ public class RankProfile implements Cloneable {
}
public void addConstant(String name, Value value) {
+ if (value instanceof TensorValue) {
+ TensorType type = ((TensorValue)value).type();
+ if (type.dimensions().stream().anyMatch(d -> d.isIndexed() && d.size().isEmpty()))
+ throw new IllegalArgumentException("Illegal type of constant " + name + " type " + type +
+ ": Dense tensor dimensions must have a size");
+ }
constants.put(name, value.freeze());
}
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/RankingConstant.java b/config-model/src/main/java/com/yahoo/searchdefinition/RankingConstant.java
index 7b7265e02ae..b41cf582204 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/RankingConstant.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/RankingConstant.java
@@ -56,7 +56,9 @@ public class RankingConstant {
this.pathType = PathType.URI;
}
- public void setType(TensorType tensorType) { this.tensorType = tensorType; }
+ public void setType(TensorType type) {
+ this.tensorType = type;
+ }
/** Initiate sending of this constant to some services over file distribution */
public void sendTo(Collection<? extends AbstractService> services) {
@@ -78,6 +80,9 @@ public class RankingConstant {
throw new IllegalArgumentException("Ranking constants must have a file or uri.");
if (tensorType == null)
throw new IllegalArgumentException("Ranking constant '" + name + "' must have a type.");
+ if (tensorType.dimensions().stream().anyMatch(d -> d.isIndexed() && d.size().isEmpty()))
+ throw new IllegalArgumentException("Illegal type in field " + name + " type " + tensorType +
+ ": Dense tensor dimensions must have a size");
}
public String toString() {
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/document/SDField.java b/config-model/src/main/java/com/yahoo/searchdefinition/document/SDField.java
index 30ce142d503..e36635ba6b8 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/document/SDField.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/document/SDField.java
@@ -7,12 +7,14 @@ import com.yahoo.document.DocumentType;
import com.yahoo.document.Field;
import com.yahoo.document.MapDataType;
import com.yahoo.document.StructDataType;
+import com.yahoo.document.TensorDataType;
import com.yahoo.language.Linguistics;
import com.yahoo.language.simple.SimpleLinguistics;
import com.yahoo.searchdefinition.Index;
import com.yahoo.searchdefinition.Search;
import com.yahoo.searchdefinition.fieldoperation.FieldOperation;
import com.yahoo.searchdefinition.fieldoperation.FieldOperationContainer;
+import com.yahoo.tensor.TensorType;
import com.yahoo.vespa.documentmodel.SummaryField;
import com.yahoo.vespa.indexinglanguage.ExpressionSearcher;
import com.yahoo.vespa.indexinglanguage.ExpressionVisitor;
@@ -116,9 +118,10 @@ public class SDField extends Field implements TypedKey, FieldOperationContainer,
private boolean isExtraField = false;
/**
- * Creates a new field. This method is only used to create reserved fields
- * @param name The name of the field
- * @param dataType The datatype of the field
+ * Creates a new field. This method is only used to create reserved fields.
+ *
+ * @param name the name of the field
+ * @param dataType the datatype of the field
*/
protected SDField(SDDocumentType repo, String name, int id, DataType dataType, boolean populate) {
super(name, id, dataType);
@@ -129,64 +132,36 @@ public class SDField extends Field implements TypedKey, FieldOperationContainer,
this(repo, name, id, dataType, true);
}
- /**
- Creates a new field.
-
- @param name The name of the field
- @param dataType The datatype of the field
- */
+ /** Creates a new field */
public SDField(SDDocumentType repo, String name, DataType dataType, boolean populate) {
- super(name,dataType);
+ super(name, dataType);
populate(populate, repo, name, dataType);
}
- private void populate(boolean populate, SDDocumentType repo, String name, DataType dataType) {
- populate(populate,repo, name, dataType, null, 0);
- }
-
- private void populate(boolean populate, SDDocumentType repo, String name, DataType dataType, Matching fieldMatching, int recursion) {
- if (populate || (dataType instanceof MapDataType)) {
- populateWithStructFields(repo, name, dataType, recursion);
- populateWithStructMatching(repo, name, dataType, fieldMatching);
- }
- }
-
-
- /**
- * Creates a new field.
- *
- * @param name The name of the field
- * @param dataType The datatype of the field
- * @param owner the owning document (used to check for id collisions)
- */
+ /** Creates a new field */
protected SDField(SDDocumentType repo, String name, DataType dataType, SDDocumentType owner, boolean populate) {
super(name, dataType, owner == null ? null : owner.getDocumentType());
- this.ownerDocType=owner;
+ this.ownerDocType = owner;
populate(populate, repo, name, dataType);
}
/**
- * Creates a new field.
+ * Creates a new field
*
- * @param name The name of the field
- * @param dataType The datatype of the field
- * @param owner The owning document (used to check for id collisions)
- * @param fieldMatching The matching object to set for the field
+ * @param name the name of the field
+ * @param dataType the datatype of the field
+ * @param owner the owning document (used to check for id collisions)
+ * @param fieldMatching the matching object to set for the field
*/
protected SDField(SDDocumentType repo, String name, DataType dataType, SDDocumentType owner,
Matching fieldMatching, boolean populate, int recursion) {
super(name, dataType, owner == null ? null : owner.getDocumentType());
- this.ownerDocType=owner;
+ this.ownerDocType = owner;
if (fieldMatching != null)
this.setMatching(fieldMatching);
populate(populate, repo, name, dataType, fieldMatching, recursion);
}
- /**
- *
- * @param name The name of the field
- * @param dataType The datatype of the field
- */
public SDField(SDDocumentType repo, String name, DataType dataType) {
this(repo, name,dataType, true);
}
@@ -194,6 +169,23 @@ public class SDField extends Field implements TypedKey, FieldOperationContainer,
this(null, name,dataType);
}
+ private void populate(boolean populate, SDDocumentType repo, String name, DataType dataType) {
+ populate(populate, repo, name, dataType, null, 0);
+ }
+
+ private void populate(boolean populate, SDDocumentType repo, String name, DataType dataType, Matching fieldMatching, int recursion) {
+ if (dataType instanceof TensorDataType) {
+ TensorType type = ((TensorDataType)dataType).getTensorType();
+ if (type.dimensions().stream().anyMatch(d -> d.isIndexed() && d.size().isEmpty()))
+ throw new IllegalArgumentException("Illegal type in field " + name + " type " + type +
+ ": Dense tensor dimensions must have a size");
+ }
+ if (populate || (dataType instanceof MapDataType)) {
+ populateWithStructFields(repo, name, dataType, recursion);
+ populateWithStructMatching(repo, name, dataType, fieldMatching);
+ }
+ }
+
public void setIsExtraField(boolean isExtra) {
isExtraField = isExtra;
}
diff --git a/config-model/src/main/java/com/yahoo/searchdefinition/document/TemporarySDField.java b/config-model/src/main/java/com/yahoo/searchdefinition/document/TemporarySDField.java
index 04d11792379..2921253461d 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/document/TemporarySDField.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/document/TemporarySDField.java
@@ -4,7 +4,7 @@ package com.yahoo.searchdefinition.document;
import com.yahoo.document.DataType;
/**
- * @author <a href="mailto:einarmr@yahoo-inc.com">Einar M R Rosenvinge</a>
+ * @author Einar M R Rosenvinge
*/
public class TemporarySDField extends SDField {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidator.java
index c6bf54af760..75e6922ad15 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidator.java
@@ -90,7 +90,7 @@ public class ConstantTensorJsonValidator {
validateTensorValue();
}
} else {
- throw new InvalidConstantTensor(parser, "Only \"address\" or \"value\" fields are permitted within a cell object");
+ throw new InvalidConstantTensor(parser, "Only 'address' or 'value' fields are permitted within a cell object");
}
}
@@ -110,55 +110,52 @@ public class ConstantTensorJsonValidator {
String dimensionName = parser.getCurrentName();
TensorType.Dimension dimension = tensorDimensions.get(dimensionName);
if (dimension == null) {
- throw new InvalidConstantTensor(parser, String.format("Tensor dimension \"%s\" does not exist", parser.getCurrentName()));
+ throw new InvalidConstantTensor(parser, String.format("Tensor dimension '%s' does not exist", parser.getCurrentName()));
}
if (!cellDimensions.contains(dimensionName)) {
- throw new InvalidConstantTensor(parser, String.format("Duplicate tensor dimension \"%s\"", parser.getCurrentName()));
+ throw new InvalidConstantTensor(parser, String.format("Duplicate tensor dimension '%s'", parser.getCurrentName()));
}
cellDimensions.remove(dimensionName);
- validateTensorCoordinate(dimension);
+ validateLabel(dimension);
}
if (!cellDimensions.isEmpty()) {
- throw new InvalidConstantTensor(parser, String.format("Tensor address missing dimension(s): %s", Joiner.on(", ").join(cellDimensions)));
+ throw new InvalidConstantTensor(parser, String.format("Tensor address missing dimension(s) %s", Joiner.on(", ").join(cellDimensions)));
}
}
- /*
- * Tensor coordinates are always strings. Coordinates for a mapped dimension can be any string,
+ /**
+ * Tensor labels are always strings. Labels for a mapped dimension can be any string,
* but those for indexed dimensions needs to be able to be interpreted as integers, and,
* additionally, those for indexed bounded dimensions needs to fall within the dimension size.
*/
- private void validateTensorCoordinate(TensorType.Dimension dimension) throws IOException {
+ private void validateLabel(TensorType.Dimension dimension) throws IOException {
JsonToken token = parser.nextToken();
- if (token != JsonToken.VALUE_STRING) {
- throw new InvalidConstantTensor(parser, String.format("Tensor coordinate is not a string (%s)", token.toString()));
- }
+ if (token != JsonToken.VALUE_STRING)
+ throw new InvalidConstantTensor(parser, String.format("Tensor label is not a string (%s)", token.toString()));
if (dimension instanceof TensorType.IndexedBoundDimension) {
- validateBoundedCoordinate((TensorType.IndexedBoundDimension) dimension);
+ validateBoundIndex((TensorType.IndexedBoundDimension) dimension);
} else if (dimension instanceof TensorType.IndexedUnboundDimension) {
- validateUnboundedCoordinate(dimension);
+ validateUnboundIndex(dimension);
}
}
- private void validateBoundedCoordinate(TensorType.IndexedBoundDimension dimension) {
+ private void validateBoundIndex(TensorType.IndexedBoundDimension dimension) {
wrapIOException(() -> {
try {
int value = Integer.parseInt(parser.getValueAsString());
- if (value >= dimension.size().get()) {
- throw new InvalidConstantTensor(parser, String.format("Coordinate \"%s\" not within limits of bounded dimension %s", value, dimension.name()));
-
- }
+ if (value >= dimension.size().get())
+ throw new InvalidConstantTensor(parser, String.format("Index %s not within limits of bound dimension '%s'", value, dimension.name()));
} catch (NumberFormatException e) {
throwCoordinateIsNotInteger(parser.getValueAsString(), dimension.name());
}
});
}
- private void validateUnboundedCoordinate(TensorType.Dimension dimension) {
+ private void validateUnboundIndex(TensorType.Dimension dimension) {
wrapIOException(() -> {
try {
Integer.parseInt(parser.getValueAsString());
@@ -169,7 +166,7 @@ public class ConstantTensorJsonValidator {
}
private void throwCoordinateIsNotInteger(String value, String dimensionName) {
- throw new InvalidConstantTensor(parser, String.format("Coordinate \"%s\" for dimension %s is not an integer", value, dimensionName));
+ throw new InvalidConstantTensor(parser, String.format("Index '%s' for dimension '%s' is not an integer", value, dimensionName));
}
private void validateTensorValue() throws IOException {
@@ -198,11 +195,12 @@ public class ConstantTensorJsonValidator {
String actualFieldName = parser.getCurrentName();
if (!actualFieldName.equals(wantedFieldName)) {
- throw new InvalidConstantTensor(parser, String.format("Expected field name \"%s\", got \"%s\"", wantedFieldName, actualFieldName));
+ throw new InvalidConstantTensor(parser, String.format("Expected field name '%s', got '%s'", wantedFieldName, actualFieldName));
}
}
static class InvalidConstantTensor extends RuntimeException {
+
InvalidConstantTensor(JsonParser parser, String message) {
super(message + " " + parser.getCurrentLocation().toString());
}
@@ -210,6 +208,7 @@ public class ConstantTensorJsonValidator {
InvalidConstantTensor(JsonParser parser, Exception base) {
super("Failed to parse JSON stream " + parser.getCurrentLocation().toString(), base);
}
+
}
@FunctionalInterface
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/RankingConstantsValidator.java b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/RankingConstantsValidator.java
index 9568ea5c27c..cf8a9201668 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/application/validation/RankingConstantsValidator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/application/validation/RankingConstantsValidator.java
@@ -31,7 +31,7 @@ public class RankingConstantsValidator extends Validator {
public ExceptionMessageCollector add(Throwable throwable, String rcName, String rcFilename) {
exceptionsOccurred = true;
- combinedMessage += String.format("\nRanking constant \"%s\" (%s): %s", rcName, rcFilename, throwable.getMessage());
+ combinedMessage += String.format("\nRanking constant '%s' (%s): %s", rcName, rcFilename, throwable.getMessage());
return this;
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/search/QueryProfiles.java b/config-model/src/main/java/com/yahoo/vespa/model/container/search/QueryProfiles.java
index 0a9618e7b08..079baf6fe7d 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/search/QueryProfiles.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/search/QueryProfiles.java
@@ -9,6 +9,7 @@ import com.yahoo.search.query.profile.SubstituteString;
import com.yahoo.search.query.profile.types.FieldDescription;
import com.yahoo.search.query.profile.types.QueryProfileType;
import com.yahoo.search.query.profile.config.QueryProfilesConfig;
+import com.yahoo.tensor.TensorType;
import java.io.Serializable;
import java.util.ArrayList;
@@ -56,6 +57,7 @@ public class QueryProfiles implements Serializable, QueryProfilesConfig.Producer
Set<String> tensorFields = new HashSet<>();
for (QueryProfileType type : registry.getTypeRegistry().allComponents()) {
for (var fieldEntry : type.fields().entrySet()) {
+ validateTensorField(fieldEntry.getKey(), fieldEntry.getValue().getType().asTensorType());
if (fieldEntry.getValue().getType().asTensorType().rank() > 0)
tensorFields.add(fieldEntry.getKey());
}
@@ -73,6 +75,12 @@ public class QueryProfiles implements Serializable, QueryProfilesConfig.Producer
}
+ private void validateTensorField(String fieldName, TensorType type) {
+ if (type.dimensions().stream().anyMatch(d -> d.isIndexed() && d.size().isEmpty()))
+ throw new IllegalArgumentException("Illegal type in field " + fieldName + " type " + type +
+ ": Dense tensor dimensions must have a size");
+ }
+
@Override
public void getConfig(QueryProfilesConfig.Builder builder) {
for (QueryProfile profile : registry.allComponents()) {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/ml/ConvertedModel.java b/config-model/src/main/java/com/yahoo/vespa/model/ml/ConvertedModel.java
index c3d6f457ce8..f8b48da291d 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/ml/ConvertedModel.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/ml/ConvertedModel.java
@@ -448,7 +448,7 @@ public class ConvertedModel {
int i = rename.fromDimensions().indexOf(dimension.name());
if (i < 0) {
throw new IllegalArgumentException("Rename does not contain dimension '" +
- dimension + "' in child expression type: " + childType);
+ dimension + "' in child expression type: " + childType);
}
from.add((String)rename.fromDimensions().get(i));
to.add((String)rename.toDimensions().get(i));
diff --git a/config-model/src/test/cfg/application/ml_models/searchdefinitions/test.sd b/config-model/src/test/cfg/application/ml_models/searchdefinitions/test.sd
index 247df8a0241..6d10c50e80a 100644
--- a/config-model/src/test/cfg/application/ml_models/searchdefinitions/test.sd
+++ b/config-model/src/test/cfg/application/ml_models/searchdefinitions/test.sd
@@ -2,7 +2,7 @@
search test {
document test {
- field argument type tensor<float>(d0[],d1[784]) {
+ field argument type tensor<float>(d0[1],d1[784]) {
indexing: attribute
}
}
diff --git a/config-model/src/test/cfg/application/validation/ranking_constants_fail/searchdefinitions/simple.sd b/config-model/src/test/cfg/application/validation/ranking_constants_fail/searchdefinitions/simple.sd
index 126f8d00724..8b782a01946 100644
--- a/config-model/src/test/cfg/application/validation/ranking_constants_fail/searchdefinitions/simple.sd
+++ b/config-model/src/test/cfg/application/validation/ranking_constants_fail/searchdefinitions/simple.sd
@@ -4,12 +4,12 @@ search simple {
constant constant_tensor_1 {
file: tensors/constant_tensor_1.json
- type: tensor(x[], y[])
+ type: tensor(x[4], y[3])
}
constant constant_tensor_2 {
file: tensors/constant_tensor_2.json
- type: tensor(x[])
+ type: tensor(x[6])
}
constant constant_tensor_3 {
@@ -24,6 +24,6 @@ search simple {
constant constant_tensor_5 {
file: tensors/constant_tensor_5.json
- type: tensor(x[], y[], z[])
+ type: tensor(x[33], y[10], z[46])
}
}
diff --git a/config-model/src/test/cfg/application/validation/ranking_constants_ok/searchdefinitions/simple.sd b/config-model/src/test/cfg/application/validation/ranking_constants_ok/searchdefinitions/simple.sd
index 126f8d00724..8b782a01946 100644
--- a/config-model/src/test/cfg/application/validation/ranking_constants_ok/searchdefinitions/simple.sd
+++ b/config-model/src/test/cfg/application/validation/ranking_constants_ok/searchdefinitions/simple.sd
@@ -4,12 +4,12 @@ search simple {
constant constant_tensor_1 {
file: tensors/constant_tensor_1.json
- type: tensor(x[], y[])
+ type: tensor(x[4], y[3])
}
constant constant_tensor_2 {
file: tensors/constant_tensor_2.json
- type: tensor(x[])
+ type: tensor(x[6])
}
constant constant_tensor_3 {
@@ -24,6 +24,6 @@ search simple {
constant constant_tensor_5 {
file: tensors/constant_tensor_5.json
- type: tensor(x[], y[], z[])
+ type: tensor(x[33], y[10], z[46])
}
}
diff --git a/config-model/src/test/derived/tensor/documenttypes.cfg b/config-model/src/test/derived/tensor/documenttypes.cfg
index 68bd394c9d6..bbf9759659b 100644
--- a/config-model/src/test/derived/tensor/documenttypes.cfg
+++ b/config-model/src/test/derived/tensor/documenttypes.cfg
@@ -23,7 +23,7 @@ documenttype[].datatype[].sstruct.compression.minsize 200
documenttype[].datatype[].sstruct.field[].name "f1"
documenttype[].datatype[].sstruct.field[].id 26661415
documenttype[].datatype[].sstruct.field[].datatype 21
-documenttype[].datatype[].sstruct.field[].detailedtype "tensor(x[])"
+documenttype[].datatype[].sstruct.field[].detailedtype "tensor(x[3])"
documenttype[].datatype[].sstruct.field[].name "f2"
documenttype[].datatype[].sstruct.field[].id 2080644671
documenttype[].datatype[].sstruct.field[].datatype 21
diff --git a/config-model/src/test/derived/tensor/tensor.sd b/config-model/src/test/derived/tensor/tensor.sd
index a7248fe3200..44a84a3cbb3 100644
--- a/config-model/src/test/derived/tensor/tensor.sd
+++ b/config-model/src/test/derived/tensor/tensor.sd
@@ -2,7 +2,7 @@
search tensor {
document tensor {
- field f1 type tensor(x[]) {
+ field f1 type tensor(x[3]) {
indexing: summary
}
field f2 type tensor<float>(x[2],y[1]) {
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/RankProfileTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/RankProfileTestCase.java
index e2f2c1fd407..0f83a4db98f 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/RankProfileTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/RankProfileTestCase.java
@@ -125,7 +125,7 @@ public class RankProfileTestCase extends SchemaTestCase {
" document test { \n" +
" field a type tensor(x[10]) { indexing: attribute }\n" +
" field b type tensor(y{}) { indexing: attribute }\n" +
- " field c type tensor(x[]) { indexing: attribute }\n" +
+ " field c type tensor(x[5]) { indexing: attribute }\n" +
" }\n" +
" rank-profile p1 {}\n" +
" rank-profile p2 {}\n" +
@@ -140,11 +140,28 @@ public class RankProfileTestCase extends SchemaTestCase {
assertAttributeTypeSettings(registry.get(search, "p2"), search);
}
+ @Test
+ public void requireThatDenseDimensionsMustBeBound() throws ParseException {
+ try {
+ SearchBuilder builder = new SearchBuilder(new RankProfileRegistry());
+ builder.importString("search test {\n" +
+ " document test { \n" +
+ " field a type tensor(x[]) { indexing: attribute }\n" +
+ " }\n" +
+ "}");
+ builder.build();
+ }
+ catch (IllegalArgumentException e) {
+ assertEquals("Illegal type in field a type tensor(x[]): Dense tensor dimensions must have a size",
+ e.getMessage());
+ }
+ }
+
private static void assertAttributeTypeSettings(RankProfile profile, Search search) {
RawRankProfile rawProfile = new RawRankProfile(profile, new QueryProfileRegistry(), new ImportedMlModels(), new AttributeFields(search));
assertEquals("tensor(x[10])", findProperty(rawProfile.configProperties(), "vespa.type.attribute.a").get());
assertEquals("tensor(y{})", findProperty(rawProfile.configProperties(), "vespa.type.attribute.b").get());
- assertEquals("tensor(x[])", findProperty(rawProfile.configProperties(), "vespa.type.attribute.c").get());
+ assertEquals("tensor(x[5])", findProperty(rawProfile.configProperties(), "vespa.type.attribute.c").get());
}
@Test
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/RankingExpressionShadowingTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/RankingExpressionShadowingTestCase.java
index e4ca83640e9..02d1c3fc3b0 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/RankingExpressionShadowingTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/RankingExpressionShadowingTestCase.java
@@ -159,7 +159,7 @@ public class RankingExpressionShadowingTestCase extends SchemaTestCase {
public void testNeuralNetworkSetup() throws ParseException {
// Note: the type assigned to query profile and constant tensors here is not the correct type
RankProfileRegistry rankProfileRegistry = new RankProfileRegistry();
- QueryProfileRegistry queryProfiles = queryProfileWith("query(q)", "tensor(x[])");
+ QueryProfileRegistry queryProfiles = queryProfileWith("query(q)", "tensor(x[1])");
SearchBuilder builder = new SearchBuilder(rankProfileRegistry, queryProfiles);
builder.importString(
"search test {\n" +
@@ -184,19 +184,19 @@ public class RankingExpressionShadowingTestCase extends SchemaTestCase {
" }\n" +
" }\n" +
" constant W_hidden {\n" +
- " type: tensor(x[])\n" +
+ " type: tensor(x[1])\n" +
" file: ignored.json\n" +
" }\n" +
" constant b_input {\n" +
- " type: tensor(x[])\n" +
+ " type: tensor(x[1])\n" +
" file: ignored.json\n" +
" }\n" +
" constant W_final {\n" +
- " type: tensor(x[])\n" +
+ " type: tensor(x[1])\n" +
" file: ignored.json\n" +
" }\n" +
" constant b_final {\n" +
- " type: tensor(x[])\n" +
+ " type: tensor(x[1])\n" +
" file: ignored.json\n" +
" }\n" +
"}\n");
@@ -211,11 +211,11 @@ public class RankingExpressionShadowingTestCase extends SchemaTestCase {
censorBindingHash(testRankProperties.get(0).toString()));
assertEquals("(rankingExpression(hidden_layer).rankingScript,rankingExpression(relu@))",
censorBindingHash(testRankProperties.get(1).toString()));
- assertEquals("(rankingExpression(hidden_layer).type,tensor(x[]))",
+ assertEquals("(rankingExpression(hidden_layer).type,tensor(x[1]))",
censorBindingHash(testRankProperties.get(2).toString()));
assertEquals("(rankingExpression(final_layer).rankingScript,sigmoid(reduce(rankingExpression(hidden_layer) * constant(W_final), sum, hidden) + constant(b_final)))",
testRankProperties.get(3).toString());
- assertEquals("(rankingExpression(final_layer).type,tensor(x[]))",
+ assertEquals("(rankingExpression(final_layer).type,tensor(x[1]))",
testRankProperties.get(4).toString());
assertEquals("(rankingExpression(relu).rankingScript,max(1.0,x))",
testRankProperties.get(5).toString());
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/FastAccessValidatorTest.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/FastAccessValidatorTest.java
index 994538deed6..71277f136f8 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/FastAccessValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/FastAccessValidatorTest.java
@@ -39,7 +39,7 @@ public class FastAccessValidatorTest {
" indexing: attribute ",
" attribute: fast-access",
" }",
- " field tensor_attribute type tensor(x[]) {",
+ " field tensor_attribute type tensor(x[5]) {",
" indexing: attribute ",
" attribute: fast-access",
" }",
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/ImportedFieldsResolverTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/ImportedFieldsResolverTestCase.java
index c679bb7e61f..b7db9134b88 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/ImportedFieldsResolverTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/ImportedFieldsResolverTestCase.java
@@ -114,7 +114,7 @@ public class ImportedFieldsResolverTestCase {
parentSearch.getDocument().addField(createField("attribute_field", DataType.INT, "{ attribute }"));
parentSearch.getDocument().addField(createField("attribute_and_index", DataType.INT, "{ attribute | index }"));
parentSearch.getDocument().addField(new TemporarySDField("not_attribute", DataType.INT));
- parentSearch.getDocument().addField(createField("tensor_field", new TensorDataType(TensorType.fromSpec("tensor(x[])")), "{ attribute }"));
+ parentSearch.getDocument().addField(createField("tensor_field", new TensorDataType(TensorType.fromSpec("tensor(x[5])")), "{ attribute }"));
parentSearch.getDocument().addField(createField("predicate_field", DataType.PREDICATE, "{ attribute }"));
addRefField(parentSearch, grandParentSearch, "ref");
addImportedField(parentSearch, "ancient_field", "ref", "ancient_field");
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeResolverTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeResolverTestCase.java
index a306e0f2c90..96f12a47a2f 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeResolverTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionTypeResolverTestCase.java
@@ -37,7 +37,7 @@ public class RankingExpressionTypeResolverTestCase {
builder.importString(joinLines(
"search test {",
" document test { ",
- " field a type tensor(x[],y[]) {",
+ " field a type tensor(x[10],y[3]) {",
" indexing: attribute",
" }",
" }",
@@ -52,7 +52,7 @@ public class RankingExpressionTypeResolverTestCase {
fail("Expected exception");
}
catch (IllegalArgumentException expected) {
- assertEquals("In search definition 'test', rank profile 'my_rank_profile': The first-phase expression must produce a double (a tensor with no dimensions), but produces tensor(x[],y[])",
+ assertEquals("In search definition 'test', rank profile 'my_rank_profile': The first-phase expression must produce a double (a tensor with no dimensions), but produces tensor(x[10],y[3])",
Exceptions.toMessageString(expected));
}
}
@@ -64,7 +64,7 @@ public class RankingExpressionTypeResolverTestCase {
builder.importString(joinLines(
"search test {",
" document test { ",
- " field a type tensor(x[],y[]) {",
+ " field a type tensor(x[10],y[3]) {",
" indexing: attribute",
" }",
" }",
@@ -82,7 +82,7 @@ public class RankingExpressionTypeResolverTestCase {
fail("Expected exception");
}
catch (IllegalArgumentException expected) {
- assertEquals("In search definition 'test', rank profile 'my_rank_profile': The second-phase expression must produce a double (a tensor with no dimensions), but produces tensor(x[],y[])",
+ assertEquals("In search definition 'test', rank profile 'my_rank_profile': The second-phase expression must produce a double (a tensor with no dimensions), but produces tensor(x[10],y[3])",
Exceptions.toMessageString(expected));
}
}
@@ -94,7 +94,7 @@ public class RankingExpressionTypeResolverTestCase {
searchBuilder.importString(joinLines(
"search test {",
" document test { ",
- " field a type tensor(x[],y[]) {",
+ " field a type tensor(x[10],y[5]) {",
" indexing: attribute",
" }",
" field b type tensor(z[10]) {",
@@ -112,7 +112,7 @@ public class RankingExpressionTypeResolverTestCase {
fail("Expected exception");
}
catch (IllegalArgumentException expected) {
- assertEquals("In search definition 'test', rank profile 'my_rank_profile': The first-phase expression is invalid: An if expression must produce compatible types in both alternatives, but the 'true' type is tensor(x[],y[]) while the 'false' type is tensor(z[10])" +
+ assertEquals("In search definition 'test', rank profile 'my_rank_profile': The first-phase expression is invalid: An if expression must produce compatible types in both alternatives, but the 'true' type is tensor(x[10],y[5]) while the 'false' type is tensor(z[10])" +
"\n'true' branch: attribute(a)" +
"\n'false' branch: attribute(b)",
Exceptions.toMessageString(expected));
@@ -126,7 +126,7 @@ public class RankingExpressionTypeResolverTestCase {
builder.importString(joinLines(
"search test {",
" document test { ",
- " field a type tensor(x[],y[]) {",
+ " field a type tensor(x[10],y[3]) {",
" indexing: attribute",
" }",
" field b type tensor(z[10]) {",
@@ -147,7 +147,7 @@ public class RankingExpressionTypeResolverTestCase {
builder.build();
RankProfile profile =
builder.getRankProfileRegistry().get(builder.getSearch(), "my_rank_profile");
- assertEquals(TensorType.fromSpec("tensor(x[],y[])"),
+ assertEquals(TensorType.fromSpec("tensor(x[10],y[3])"),
summaryFeatures(profile).get("macro1(a)").type(profile.typeContext(builder.getQueryProfileRegistry())));
assertEquals(TensorType.fromSpec("tensor(z[10])"),
summaryFeatures(profile).get("macro1(b)").type(profile.typeContext(builder.getQueryProfileRegistry())));
@@ -159,7 +159,7 @@ public class RankingExpressionTypeResolverTestCase {
builder.importString(joinLines(
"search test {",
" document test { ",
- " field a type tensor(x[],y[]) {",
+ " field a type tensor(x[10],y[1]) {",
" indexing: attribute",
" }",
" field b type tensor(z[10]) {",
@@ -189,7 +189,7 @@ public class RankingExpressionTypeResolverTestCase {
builder.build();
RankProfile profile =
builder.getRankProfileRegistry().get(builder.getSearch(), "my_rank_profile");
- assertEquals(TensorType.fromSpec("tensor(x[],y[])"),
+ assertEquals(TensorType.fromSpec("tensor(x[10],y[1])"),
summaryFeatures(profile).get("return_a").type(profile.typeContext(builder.getQueryProfileRegistry())));
assertEquals(TensorType.fromSpec("tensor(z[10])"),
summaryFeatures(profile).get("return_b").type(profile.typeContext(builder.getQueryProfileRegistry())));
@@ -201,7 +201,7 @@ public class RankingExpressionTypeResolverTestCase {
builder.importString(joinLines(
"search parent {",
" document parent {",
- " field a type tensor(x[],y[]) {",
+ " field a type tensor(x[5],y[1000]) {",
" indexing: attribute",
" }",
" }",
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionWithOnnxTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionWithOnnxTestCase.java
index 4387d19c474..1fe1ebf2bb3 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionWithOnnxTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionWithOnnxTestCase.java
@@ -29,6 +29,7 @@ public class RankingExpressionWithOnnxTestCase {
private final static String name = "mnist_softmax";
private final static String vespaExpression = "join(reduce(join(rename(Placeholder, (d0, d1), (d0, d2)), constant(" + name + "_Variable), f(a,b)(a * b)), sum, d2), constant(" + name + "_Variable_1), f(a,b)(a + b))";
+ private final static String vespaExpressionWithBatchReduce = "join(join(reduce(join(reduce(rename(Placeholder, (d0, d1), (d0, d2)), sum, d0), constant(mnist_softmax_Variable), f(a,b)(a * b)), sum, d2), constant(mnist_softmax_Variable_1), f(a,b)(a + b)), tensor<float>(d0[1])(1.0), f(a,b)(a * b))";
@After
public void removeGeneratedModelFiles() {
@@ -93,10 +94,10 @@ public class RankingExpressionWithOnnxTestCase {
RankProfileSearchFixture search = fixtureWith("attribute(mytensor)",
"onnx('mnist_softmax.onnx')",
null,
- "field mytensor type tensor<float>(d0[],d1[784]) { indexing: attribute }",
+ "field mytensor type tensor<float>(d0[1],d1[784]) { indexing: attribute }",
"Placeholder",
application);
- search.assertFirstPhaseExpression(vespaExpression, "my_profile");
+ search.assertFirstPhaseExpression(vespaExpressionWithBatchReduce, "my_profile");
}
@@ -105,18 +106,16 @@ public class RankingExpressionWithOnnxTestCase {
String queryProfile = "<query-profile id='default' type='root'/>";
String queryProfileType =
"<query-profile-type id='root'>" +
- " <field name='query(mytensor)' type='tensor&lt;float&gt;(d0[3],d1[784],d2[10])'/>" +
+ " <field name='query(mytensor)' type='tensor&lt;float&gt;(d0[1],d1[784],d2[10])'/>" +
"</query-profile-type>";
- StoringApplicationPackage application = new StoringApplicationPackage(applicationDir,
- queryProfile,
- queryProfileType);
+ StoringApplicationPackage application = new StoringApplicationPackage(applicationDir, queryProfile, queryProfileType);
RankProfileSearchFixture search = fixtureWith("sum(query(mytensor) * attribute(mytensor) * constant(mytensor),d2)",
"onnx('mnist_softmax.onnx')",
- "constant mytensor { file: ignored\ntype: tensor<float>(d0[7],d1[784]) }",
- "field mytensor type tensor<float>(d0[],d1[784]) { indexing: attribute }",
+ "constant mytensor { file: ignored\ntype: tensor<float>(d0[1],d1[784]) }",
+ "field mytensor type tensor<float>(d0[1],d1[784]) { indexing: attribute }",
"Placeholder",
application);
- search.assertFirstPhaseExpression(vespaExpression, "my_profile");
+ search.assertFirstPhaseExpression(vespaExpressionWithBatchReduce, "my_profile");
}
diff --git a/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionWithTensorFlowTestCase.java b/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionWithTensorFlowTestCase.java
index 680f2dd9659..126a41e14ad 100644
--- a/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionWithTensorFlowTestCase.java
+++ b/config-model/src/test/java/com/yahoo/searchdefinition/processing/RankingExpressionWithTensorFlowTestCase.java
@@ -44,6 +44,7 @@ public class RankingExpressionWithTensorFlowTestCase {
private final String name = "mnist_softmax_saved";
private final String vespaExpression = "join(reduce(join(rename(Placeholder, (d0, d1), (d0, d2)), constant(" + name + "_layer_Variable_read), f(a,b)(a * b)), sum, d2), constant(" + name + "_layer_Variable_1_read), f(a,b)(a + b))";
+ private final static String vespaExpressionWithBatchReduce = "join(join(reduce(join(reduce(rename(Placeholder, (d0, d1), (d0, d2)), sum, d0), constant(mnist_softmax_saved_layer_Variable_read), f(a,b)(a * b)), sum, d2), constant(mnist_softmax_saved_layer_Variable_1_read), f(a,b)(a + b)), tensor(d0[1])(1.0), f(a,b)(a * b))";
@After
public void removeGeneratedModelFiles() {
@@ -114,28 +115,28 @@ public class RankingExpressionWithTensorFlowTestCase {
RankProfileSearchFixture search = fixtureWith("attribute(mytensor)",
"tensorflow('mnist_softmax/saved')",
null,
- "field mytensor type tensor(d0[],d1[784]) { indexing: attribute }",
+ "field mytensor type tensor(d0[1],d1[784]) { indexing: attribute }",
"Placeholder",
application);
- search.assertFirstPhaseExpression(vespaExpression, "my_profile");
+ search.assertFirstPhaseExpression(vespaExpressionWithBatchReduce, "my_profile");
}
@Test
public void testTensorFlowReferenceWithFeatureCombination() {
String queryProfile = "<query-profile id='default' type='root'/>";
String queryProfileType = "<query-profile-type id='root'>" +
- " <field name='query(mytensor)' type='tensor(d0[3],d1[784],d2[10])'/>" +
+ " <field name='query(mytensor)' type='tensor(d0[1],d1[784],d2[10])'/>" +
"</query-profile-type>";
StoringApplicationPackage application = new StoringApplicationPackage(applicationDir,
queryProfile,
queryProfileType);
RankProfileSearchFixture search = fixtureWith("sum(query(mytensor) * attribute(mytensor) * constant(mytensor),d2)",
"tensorflow('mnist_softmax/saved')",
- "constant mytensor { file: ignored\ntype: tensor(d0[7],d1[784]) }",
- "field mytensor type tensor(d0[],d1[784]) { indexing: attribute }",
+ "constant mytensor { file: ignored\ntype: tensor(d0[1],d1[784]) }",
+ "field mytensor type tensor(d0[1],d1[784]) { indexing: attribute }",
"Placeholder",
application);
- search.assertFirstPhaseExpression(vespaExpression, "my_profile");
+ search.assertFirstPhaseExpression(vespaExpressionWithBatchReduce, "my_profile");
}
@Test
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidatorTest.java
index 1f8dcc2da64..b594a3329d1 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/ConstantTensorJsonValidatorTest.java
@@ -86,9 +86,9 @@ public class ConstantTensorJsonValidatorTest {
}
@Test
- public void ensure_that_bounded_tensor_outside_limits_is_disallowed() {
+ public void ensure_that_bound_tensor_outside_limits_is_disallowed() {
expectedException.expect(InvalidConstantTensor.class);
- expectedException.expectMessage("Coordinate \"5\" not within limits of bounded dimension x");
+ expectedException.expectMessage("Index 5 not within limits of bound dimension 'x'");
validateTensorJson(
TensorType.fromSpec("tensor(x[5], y[10])"),
@@ -119,9 +119,9 @@ public class ConstantTensorJsonValidatorTest {
}
@Test
- public void ensure_that_non_integer_strings_in_address_points_are_disallowed_unbounded() {
+ public void ensure_that_non_integer_strings_in_address_points_are_disallowed_unbound() {
expectedException.expect(InvalidConstantTensor.class);
- expectedException.expectMessage("Coordinate \"a\" for dimension x is not an integer");
+ expectedException.expectMessage("Index 'a' for dimension 'x' is not an integer");
validateTensorJson(
TensorType.fromSpec("tensor(x[])"),
@@ -139,7 +139,7 @@ public class ConstantTensorJsonValidatorTest {
@Test
public void ensure_that_tensor_coordinates_are_strings() {
expectedException.expect(InvalidConstantTensor.class);
- expectedException.expectMessage("Tensor coordinate is not a string (VALUE_NUMBER_INT)");
+ expectedException.expectMessage("Tensor label is not a string (VALUE_NUMBER_INT)");
validateTensorJson(
TensorType.fromSpec("tensor(x[])"),
@@ -157,7 +157,7 @@ public class ConstantTensorJsonValidatorTest {
@Test
public void ensure_that_non_integer_strings_in_address_points_are_disallowed_bounded() {
expectedException.expect(InvalidConstantTensor.class);
- expectedException.expectMessage("Coordinate \"a\" for dimension x is not an integer");
+ expectedException.expectMessage("Index 'a' for dimension 'x' is not an integer");
validateTensorJson(
TensorType.fromSpec("tensor(x[5])"),
@@ -175,7 +175,7 @@ public class ConstantTensorJsonValidatorTest {
@Test
public void ensure_that_missing_coordinates_fail() {
expectedException.expect(InvalidConstantTensor.class);
- expectedException.expectMessage("Tensor address missing dimension(s): y, z");
+ expectedException.expectMessage("Tensor address missing dimension(s) y, z");
validateTensorJson(
TensorType.fromSpec("tensor(x[], y[], z[])"),
@@ -211,7 +211,7 @@ public class ConstantTensorJsonValidatorTest {
@Test
public void ensure_that_extra_dimensions_are_disallowed() {
expectedException.expect(InvalidConstantTensor.class);
- expectedException.expectMessage("Tensor dimension \"z\" does not exist");
+ expectedException.expectMessage("Tensor dimension 'z' does not exist");
validateTensorJson(
TensorType.fromSpec("tensor(x[], y[])"),
@@ -229,7 +229,7 @@ public class ConstantTensorJsonValidatorTest {
@Test
public void ensure_that_duplicate_dimensions_are_disallowed() {
expectedException.expect(InvalidConstantTensor.class);
- expectedException.expectMessage("Duplicate tensor dimension \"y\"");
+ expectedException.expectMessage("Duplicate tensor dimension 'y'");
validateTensorJson(
TensorType.fromSpec("tensor(x[], y[])"),
@@ -265,7 +265,7 @@ public class ConstantTensorJsonValidatorTest {
@Test
public void ensure_that_invalid_json_not_in_tensor_format_fails() {
expectedException.expect(InvalidConstantTensor.class);
- expectedException.expectMessage("Expected field name \"cells\", got \"stats\"");
+ expectedException.expectMessage("Expected field name 'cells', got 'stats'");
validateTensorJson(TensorType.fromSpec("tensor(x[], y[])"),
inputJsonToReader(
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/RankingConstantsValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/RankingConstantsValidatorTest.java
index d99fd93d5eb..dbf6013b167 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/RankingConstantsValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/RankingConstantsValidatorTest.java
@@ -9,6 +9,7 @@ import org.junit.rules.ExpectedException;
import static com.yahoo.vespa.model.application.validation.RankingConstantsValidator.TensorValidationFailed;
public class RankingConstantsValidatorTest {
+
@Rule
public ExpectedException expectedException = ExpectedException.none();
@@ -20,10 +21,11 @@ public class RankingConstantsValidatorTest {
@Test
public void ensure_that_failing_ranking_constants_fails() {
expectedException.expect(TensorValidationFailed.class);
- expectedException.expectMessage("Ranking constant \"constant_tensor_2\" (tensors/constant_tensor_2.json): Tensor coordinate is not a string (VALUE_NUMBER_INT)");
- expectedException.expectMessage("Ranking constant \"constant_tensor_3\" (tensors/constant_tensor_3.json): Tensor dimension \"cd\" does not exist");
- expectedException.expectMessage("Ranking constant \"constant_tensor_4\" (tensors/constant_tensor_4.json): Tensor dimension \"z\" does not exist");
+ expectedException.expectMessage("Ranking constant 'constant_tensor_2' (tensors/constant_tensor_2.json): Tensor label is not a string (VALUE_NUMBER_INT)");
+ expectedException.expectMessage("Ranking constant 'constant_tensor_3' (tensors/constant_tensor_3.json): Tensor dimension 'cd' does not exist");
+ expectedException.expectMessage("Ranking constant 'constant_tensor_4' (tensors/constant_tensor_4.json): Tensor dimension 'z' does not exist");
new VespaModelCreatorWithFilePkg("src/test/cfg/application/validation/ranking_constants_fail/").create();
}
+
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java
index e32bd09bc08..5da36d82a62 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/application/validation/change/search/AttributeChangeValidatorTest.java
@@ -119,12 +119,12 @@ public class AttributeChangeValidatorTest {
"Field 'f1' changed: tensor type: 'tensor(x[2])' -> 'tensor(x[3])'", Instant.now()));
new Fixture(
- "field f1 type tensor(x[]) { indexing: attribute }",
+ "field f1 type tensor(x[5]) { indexing: attribute }",
"field f1 type tensor(x[3]) { indexing: attribute }")
.assertValidation(newRefeedAction(
"tensor-type-change",
ValidationOverrides.empty,
- "Field 'f1' changed: tensor type: 'tensor(x[])' -> 'tensor(x[3])'", Instant.now()));
+ "Field 'f1' changed: tensor type: 'tensor(x[5])' -> 'tensor(x[3])'", Instant.now()));
}
@Test
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/ml/MlModelsTest.java b/config-model/src/test/java/com/yahoo/vespa/model/ml/MlModelsTest.java
index 57dbf132883..5b38e09537d 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/ml/MlModelsTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/ml/MlModelsTest.java
@@ -63,17 +63,17 @@ public class MlModelsTest {
private final String testProfile =
"rankingExpression(input).rankingScript: attribute(argument)\n" +
- "rankingExpression(input).type: tensor<float>(d0[],d1[784])\n" +
- "rankingExpression(imported_ml_function_mnist_saved_dnn_hidden1_add).rankingScript: join(reduce(join(rename(rankingExpression(input), (d0, d1), (d0, d4)), constant(mnist_saved_dnn_hidden1_weights_read), f(a,b)(a * b)), sum, d4), constant(mnist_saved_dnn_hidden1_bias_read), f(a,b)(a + b))\n" +
+ "rankingExpression(input).type: tensor<float>(d0[1],d1[784])\n" +
+ "rankingExpression(imported_ml_function_mnist_saved_dnn_hidden1_add).rankingScript: join(reduce(join(reduce(rename(rankingExpression(input), (d0, d1), (d0, d4)), sum, d0), constant(mnist_saved_dnn_hidden1_weights_read), f(a,b)(a * b)), sum, d4), constant(mnist_saved_dnn_hidden1_bias_read), f(a,b)(a + b))\n" +
"rankingExpression(mnist_tensorflow).rankingScript: join(reduce(join(map(join(reduce(join(join(join(0.009999999776482582, rankingExpression(imported_ml_function_mnist_saved_dnn_hidden1_add), f(a,b)(a * b)), rankingExpression(imported_ml_function_mnist_saved_dnn_hidden1_add), f(a,b)(max(a,b))), constant(mnist_saved_dnn_hidden2_weights_read), f(a,b)(a * b)), sum, d3), constant(mnist_saved_dnn_hidden2_bias_read), f(a,b)(a + b)), f(a)(1.0507009873554805 * if (a >= 0, a, 1.6732632423543772 * (exp(a) - 1)))), constant(mnist_saved_dnn_outputs_weights_read), f(a,b)(a * b)), sum, d2), constant(mnist_saved_dnn_outputs_bias_read), f(a,b)(a + b))\n" +
"rankingExpression(Placeholder).rankingScript: attribute(argument)\n" +
- "rankingExpression(Placeholder).type: tensor<float>(d0[],d1[784])\n" +
- "rankingExpression(mnist_softmax_tensorflow).rankingScript: join(reduce(join(rename(rankingExpression(Placeholder), (d0, d1), (d0, d2)), constant(mnist_softmax_saved_layer_Variable_read), f(a,b)(a * b)), sum, d2), constant(mnist_softmax_saved_layer_Variable_1_read), f(a,b)(a + b))\n" +
- "rankingExpression(mnist_softmax_onnx).rankingScript: join(reduce(join(rename(rankingExpression(Placeholder), (d0, d1), (d0, d2)), constant(mnist_softmax_Variable), f(a,b)(a * b)), sum, d2), constant(mnist_softmax_Variable_1), f(a,b)(a + b))\n" +
+ "rankingExpression(Placeholder).type: tensor<float>(d0[1],d1[784])\n" +
+ "rankingExpression(mnist_softmax_tensorflow).rankingScript: join(join(reduce(join(reduce(rename(rankingExpression(Placeholder), (d0, d1), (d0, d2)), sum, d0), constant(mnist_softmax_saved_layer_Variable_read), f(a,b)(a * b)), sum, d2), constant(mnist_softmax_saved_layer_Variable_1_read), f(a,b)(a + b)), tensor(d0[1])(1.0), f(a,b)(a * b))\n" +
+ "rankingExpression(mnist_softmax_onnx).rankingScript: join(join(reduce(join(reduce(rename(rankingExpression(Placeholder), (d0, d1), (d0, d2)), sum, d0), constant(mnist_softmax_Variable), f(a,b)(a * b)), sum, d2), constant(mnist_softmax_Variable_1), f(a,b)(a + b)), tensor<float>(d0[1])(1.0), f(a,b)(a * b))\n" +
"rankingExpression(my_xgboost).rankingScript: if (f29 < -0.1234567, if (!(f56 >= -0.242398), 1.71218, -1.70044), if (f109 < 0.8723473, -1.94071, 1.85965)) + if (!(f60 >= -0.482947), if (f29 < -4.2387498, 0.784718, -0.96853), -6.23624)\n" +
"rankingExpression(my_lightgbm).rankingScript: if (!(numerical_2 >= 0.46643291586559305), 2.1594397038037663, if (categorical_2 in [\"k\", \"l\", \"m\"], 2.235297305276056, 2.1792953471546546)) + if (categorical_1 in [\"d\", \"e\"], 0.03070842919354316, if (!(numerical_1 >= 0.5102250691730842), -0.04439151147520909, 0.005117411709368601)) + if (!(numerical_2 >= 0.668665477622446), if (!(numerical_2 >= 0.008118820676863816), -0.15361238490967524, -0.01192330846157292), 0.03499044894987518) + if (!(numerical_1 >= 0.5201391072644542), -0.02141000620783247, if (categorical_1 in [\"a\", \"b\"], -0.004121485787596721, 0.04534090904886873)) + if (categorical_2 in [\"k\", \"l\", \"m\"], if (!(numerical_2 >= 0.27283279016959255), -0.01924803254356527, 0.03643772842347651), -0.02701711918923075)\n" +
"vespa.rank.firstphase: rankingExpression(firstphase)\n" +
"rankingExpression(firstphase).rankingScript: rankingExpression(mnist_tensorflow) + rankingExpression(mnist_softmax_tensorflow) + rankingExpression(mnist_softmax_onnx) + rankingExpression(my_xgboost) + rankingExpression(my_lightgbm)\n" +
- "vespa.type.attribute.argument: tensor<float>(d0[],d1[784])\n";
+ "vespa.type.attribute.argument: tensor<float>(d0[1],d1[784])\n";
}