summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@gmail.com>2023-03-20 11:24:14 +0100
committerGitHub <noreply@github.com>2023-03-20 11:24:14 +0100
commit24b297f12cdb8707d15ad554554eaaff76bcbdd3 (patch)
tree1a1a64b6224b296b5d79b06b110bcf03665be86f
parent722ea7f065eaf28cbe3c27e0e8cafb53a7799980 (diff)
parent8ab3f0d995666384080e9d1a44df2eac01efca31 (diff)
Merge pull request #26489 from vespa-engine/arnej/deterministic-rank-properties
Arnej/deterministic rank properties
-rw-r--r--config-model/src/main/java/com/yahoo/schema/RankProfile.java21
-rw-r--r--config-model/src/main/java/com/yahoo/schema/expressiontransforms/RankProfileTransformContext.java4
-rw-r--r--config-model/src/test/derived/globalphase_onnx_inside/rank-profiles.cfg106
-rw-r--r--config-model/src/test/derived/globalphase_onnx_inside/test.sd74
-rw-r--r--config-model/src/test/derived/rankproperties/rank-profiles.cfg46
-rw-r--r--config-model/src/test/derived/rankproperties/rankproperties.sd24
-rw-r--r--config-model/src/test/java/com/yahoo/schema/processing/VespaMlModelTestCase.java2
7 files changed, 262 insertions, 15 deletions
diff --git a/config-model/src/main/java/com/yahoo/schema/RankProfile.java b/config-model/src/main/java/com/yahoo/schema/RankProfile.java
index f9b3bc77040..639930041c3 100644
--- a/config-model/src/main/java/com/yahoo/schema/RankProfile.java
+++ b/config-model/src/main/java/com/yahoo/schema/RankProfile.java
@@ -683,6 +683,25 @@ public class RankProfile implements Cloneable {
addRankProperty(new RankProperty(name, parameter));
}
+ /*
+ * set a rank-property that should be a single-value parameter;
+ * if the same name is used multiple times, that parameter must be identical each time.
+ */
+ public void setRankProperty(String name, String parameter) {
+ var old = rankProperties.get(name);
+ if (old != null) {
+ if (old.size() != 1) {
+ throw new IllegalStateException("setRankProperty used for multi-valued property " + name);
+ }
+ var oldVal = old.get(0).getValue();
+ if (! oldVal.equals(parameter)) {
+ throw new IllegalArgumentException("setRankProperty would change property " + name + " from " + oldVal + " to " + parameter);
+ }
+ } else {
+ addRankProperty(new RankProperty(name, parameter));
+ }
+ }
+
private void addRankProperty(RankProperty rankProperty) {
// Just the usual multimap semantics here
rankProperties.computeIfAbsent(rankProperty.getName(), (String key) -> new ArrayList<>(1)).add(rankProperty);
@@ -1091,7 +1110,7 @@ public class RankProfile implements Cloneable {
inlineFunctions);
RankingExpression expression = expressionTransforms.transform(function.function().getBody(), context);
for (Map.Entry<String, String> rankProperty : context.rankProperties().entrySet()) {
- addRankProperty(rankProperty.getKey(), rankProperty.getValue());
+ setRankProperty(rankProperty.getKey(), rankProperty.getValue());
}
return function.withExpression(expression);
}
diff --git a/config-model/src/main/java/com/yahoo/schema/expressiontransforms/RankProfileTransformContext.java b/config-model/src/main/java/com/yahoo/schema/expressiontransforms/RankProfileTransformContext.java
index cfc859345ad..890fa5e7a10 100644
--- a/config-model/src/main/java/com/yahoo/schema/expressiontransforms/RankProfileTransformContext.java
+++ b/config-model/src/main/java/com/yahoo/schema/expressiontransforms/RankProfileTransformContext.java
@@ -12,7 +12,7 @@ import com.yahoo.searchlib.rankingexpression.transform.TransformContext;
import com.yahoo.tensor.Tensor;
import com.yahoo.tensor.TensorType;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
@@ -27,7 +27,7 @@ public class RankProfileTransformContext extends TransformContext {
private final QueryProfileRegistry queryProfiles;
private final ImportedMlModels importedModels;
private final Map<String, RankProfile.RankingExpressionFunction> inlineFunctions;
- private final Map<String, String> rankProperties = new HashMap<>();
+ private final Map<String, String> rankProperties = new LinkedHashMap<>();
public RankProfileTransformContext(RankProfile rankProfile,
QueryProfileRegistry queryProfiles,
diff --git a/config-model/src/test/derived/globalphase_onnx_inside/rank-profiles.cfg b/config-model/src/test/derived/globalphase_onnx_inside/rank-profiles.cfg
index e456dec58ed..58be9b400aa 100644
--- a/config-model/src/test/derived/globalphase_onnx_inside/rank-profiles.cfg
+++ b/config-model/src/test/derived/globalphase_onnx_inside/rank-profiles.cfg
@@ -1,10 +1,49 @@
rankprofile[].name "default"
+rankprofile[].fef.property[].name "vespa.type.attribute.aa"
+rankprofile[].fef.property[].value "tensor(d1[3])"
+rankprofile[].fef.property[].name "vespa.type.query.bb"
+rankprofile[].fef.property[].value "tensor(d0[2])"
+rankprofile[].fef.property[].name "vespa.type.query.yy"
+rankprofile[].fef.property[].value "tensor(d0[2])"
+rankprofile[].name "unranked"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "value(0)"
+rankprofile[].fef.property[].name "vespa.hitcollector.heapsize"
+rankprofile[].fef.property[].value "0"
+rankprofile[].fef.property[].name "vespa.hitcollector.arraysize"
+rankprofile[].fef.property[].value "0"
+rankprofile[].fef.property[].name "vespa.dump.ignoredefaultfeatures"
+rankprofile[].fef.property[].value "true"
+rankprofile[].fef.property[].name "vespa.type.attribute.aa"
+rankprofile[].fef.property[].value "tensor(d1[3])"
+rankprofile[].name "simple"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "rankingExpression(firstphase)"
+rankprofile[].fef.property[].name "rankingExpression(firstphase).rankingScript"
+rankprofile[].fef.property[].value "reduce(attribute(aa), sum)"
+rankprofile[].fef.property[].name "vespa.rank.globalphase"
+rankprofile[].fef.property[].value "rankingExpression(globalphase)"
+rankprofile[].fef.property[].name "rankingExpression(globalphase).rankingScript"
+rankprofile[].fef.property[].value "onnx(direct).out{d0:(attribute(extra))}"
+rankprofile[].fef.property[].name "vespa.match.feature"
+rankprofile[].fef.property[].value "attribute(aa)"
+rankprofile[].fef.property[].name "vespa.match.feature"
+rankprofile[].fef.property[].value "attribute(extra)"
+rankprofile[].fef.property[].name "vespa.globalphase.rerankcount"
+rankprofile[].fef.property[].value "13"
+rankprofile[].fef.property[].name "vespa.type.attribute.aa"
+rankprofile[].fef.property[].value "tensor(d1[3])"
+rankprofile[].fef.property[].name "vespa.type.query.bb"
+rankprofile[].fef.property[].value "tensor(d0[2])"
+rankprofile[].fef.property[].name "vespa.type.query.yy"
+rankprofile[].fef.property[].value "tensor(d0[2])"
+rankprofile[].name "one"
rankprofile[].fef.property[].name "rankingExpression(handicap).rankingScript"
rankprofile[].fef.property[].value "query(yy)"
rankprofile[].fef.property[].name "rankingExpression(handicap).type"
rankprofile[].fef.property[].value "tensor(d0[2])"
rankprofile[].fef.property[].name "rankingExpression(indirect_a).rankingScript"
-rankprofile[].fef.property[].value "attribute(aa) + tensor(d1[3])((d1 + attribute(extra)))"
+rankprofile[].fef.property[].value "attribute(aa)"
rankprofile[].fef.property[].name "rankingExpression(indirect_a).type"
rankprofile[].fef.property[].value "tensor(d1[3])"
rankprofile[].fef.property[].name "rankingExpression(indirect_x).rankingScript"
@@ -25,24 +64,71 @@ rankprofile[].fef.property[].name "rankingExpression(globalphase).rankingScript"
rankprofile[].fef.property[].value "reduce(constant(ww) * (onnx(inside).foobar - rankingExpression(handicap)), sum)"
rankprofile[].fef.property[].name "vespa.match.feature"
rankprofile[].fef.property[].value "attribute(aa)"
+rankprofile[].fef.property[].name "vespa.globalphase.rerankcount"
+rankprofile[].fef.property[].value "13"
+rankprofile[].fef.property[].name "vespa.type.attribute.aa"
+rankprofile[].fef.property[].value "tensor(d1[3])"
+rankprofile[].fef.property[].name "vespa.type.query.bb"
+rankprofile[].fef.property[].value "tensor(d0[2])"
+rankprofile[].fef.property[].name "vespa.type.query.yy"
+rankprofile[].fef.property[].value "tensor(d0[2])"
+rankprofile[].name "two"
+rankprofile[].fef.property[].name "rankingExpression(indirect_a).rankingScript"
+rankprofile[].fef.property[].value "tensor(d1[3])((d1 + attribute(extra)))"
+rankprofile[].fef.property[].name "rankingExpression(indirect_a).type"
+rankprofile[].fef.property[].value "tensor(d1[3])"
+rankprofile[].fef.property[].name "rankingExpression(indirect_x).rankingScript"
+rankprofile[].fef.property[].value "constant(xx)"
+rankprofile[].fef.property[].name "rankingExpression(indirect_x).type"
+rankprofile[].fef.property[].value "tensor(d0[2],d1[3])"
+rankprofile[].fef.property[].name "rankingExpression(indirect_b).rankingScript"
+rankprofile[].fef.property[].value "query(bb)"
+rankprofile[].fef.property[].name "rankingExpression(indirect_b).type"
+rankprofile[].fef.property[].value "tensor(d0[2])"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "rankingExpression(firstphase)"
+rankprofile[].fef.property[].name "rankingExpression(firstphase).rankingScript"
+rankprofile[].fef.property[].value "reduce(attribute(aa), sum)"
+rankprofile[].fef.property[].name "vespa.rank.globalphase"
+rankprofile[].fef.property[].value "rankingExpression(globalphase)"
+rankprofile[].fef.property[].name "rankingExpression(globalphase).rankingScript"
+rankprofile[].fef.property[].value "reduce(constant(ww) * onnx(twoside).foobar, sum)"
rankprofile[].fef.property[].name "vespa.match.feature"
rankprofile[].fef.property[].value "attribute(extra)"
rankprofile[].fef.property[].name "vespa.globalphase.rerankcount"
-rankprofile[].fef.property[].value "13"
+rankprofile[].fef.property[].value "42"
rankprofile[].fef.property[].name "vespa.type.attribute.aa"
rankprofile[].fef.property[].value "tensor(d1[3])"
rankprofile[].fef.property[].name "vespa.type.query.bb"
rankprofile[].fef.property[].value "tensor(d0[2])"
rankprofile[].fef.property[].name "vespa.type.query.yy"
rankprofile[].fef.property[].value "tensor(d0[2])"
-rankprofile[].name "unranked"
+rankprofile[].name "three"
+rankprofile[].fef.property[].name "rankingExpression(indirect_a).rankingScript"
+rankprofile[].fef.property[].value "tensor(d1[3]):{{d1:0}:0.25,{d1:1}:(attribute(extra)),{d1:2}:0.75}"
+rankprofile[].fef.property[].name "rankingExpression(indirect_a).type"
+rankprofile[].fef.property[].value "tensor(d1[3])"
+rankprofile[].fef.property[].name "rankingExpression(indirect_x).rankingScript"
+rankprofile[].fef.property[].value "constant(xx)"
+rankprofile[].fef.property[].name "rankingExpression(indirect_x).type"
+rankprofile[].fef.property[].value "tensor(d0[2],d1[3])"
+rankprofile[].fef.property[].name "rankingExpression(indirect_b).rankingScript"
+rankprofile[].fef.property[].value "query(bb)"
+rankprofile[].fef.property[].name "rankingExpression(indirect_b).type"
+rankprofile[].fef.property[].value "tensor(d0[2])"
rankprofile[].fef.property[].name "vespa.rank.firstphase"
-rankprofile[].fef.property[].value "value(0)"
-rankprofile[].fef.property[].name "vespa.hitcollector.heapsize"
-rankprofile[].fef.property[].value "0"
-rankprofile[].fef.property[].name "vespa.hitcollector.arraysize"
-rankprofile[].fef.property[].value "0"
-rankprofile[].fef.property[].name "vespa.dump.ignoredefaultfeatures"
-rankprofile[].fef.property[].value "true"
+rankprofile[].fef.property[].value "rankingExpression(firstphase)"
+rankprofile[].fef.property[].name "rankingExpression(firstphase).rankingScript"
+rankprofile[].fef.property[].value "reduce(attribute(aa), sum)"
+rankprofile[].fef.property[].name "vespa.rank.globalphase"
+rankprofile[].fef.property[].value "rankingExpression(globalphase)"
+rankprofile[].fef.property[].name "rankingExpression(globalphase).rankingScript"
+rankprofile[].fef.property[].value "reduce(constant(ww) * onnx(another).foobar, sum)"
+rankprofile[].fef.property[].name "vespa.globalphase.rerankcount"
+rankprofile[].fef.property[].value "1001"
rankprofile[].fef.property[].name "vespa.type.attribute.aa"
rankprofile[].fef.property[].value "tensor(d1[3])"
+rankprofile[].fef.property[].name "vespa.type.query.bb"
+rankprofile[].fef.property[].value "tensor(d0[2])"
+rankprofile[].fef.property[].name "vespa.type.query.yy"
+rankprofile[].fef.property[].value "tensor(d0[2])"
diff --git a/config-model/src/test/derived/globalphase_onnx_inside/test.sd b/config-model/src/test/derived/globalphase_onnx_inside/test.sd
index f5788611b0a..3e48f912931 100644
--- a/config-model/src/test/derived/globalphase_onnx_inside/test.sd
+++ b/config-model/src/test/derived/globalphase_onnx_inside/test.sd
@@ -23,6 +23,26 @@ schema test {
query(bb) tensor(d0[2])
query(yy) tensor(d0[2])
}
+ }
+
+ rank-profile simple inherits default {
+ onnx-model direct {
+ file: files/ax_plus_b.onnx
+ input vector_A: attribute(aa)
+ input matrix_X: constant(xx)
+ input vector_B: query(bb)
+ output vector_Y: out
+ }
+ first-phase {
+ expression: sum(attribute(aa))
+ }
+ global-phase {
+ rerank-count: 13
+ expression: onnx(direct).out{d0:attribute(extra)}
+ }
+ }
+
+ rank-profile one inherits default {
onnx-model inside {
file: files/ax_plus_b.onnx
input vector_A: indirect_a
@@ -41,7 +61,59 @@ schema test {
expression: sum(constant(ww) * (onnx(inside).foobar - handicap))
}
function indirect_a() {
- expression: attribute(aa) + tensor(d1[3])(d1+attribute(extra))
+ expression: attribute(aa)
+ }
+ function indirect_x() {
+ expression: constant(xx)
+ }
+ function indirect_b() {
+ expression: query(bb)
+ }
+ }
+
+ rank-profile two inherits default {
+ onnx-model twoside {
+ file: files/ax_plus_b.onnx
+ input vector_A: indirect_a
+ input matrix_X: indirect_x
+ input vector_B: indirect_b
+ output vector_Y: foobar
+ }
+ first-phase {
+ expression: sum(attribute(aa))
+ }
+ global-phase {
+ rerank-count: 42
+ expression: sum(constant(ww) * onnx(twoside).foobar)
+ }
+ function indirect_a() {
+ expression: tensor(d1[3])(d1+attribute(extra))
+ }
+ function indirect_x() {
+ expression: constant(xx)
+ }
+ function indirect_b() {
+ expression: query(bb)
+ }
+ }
+
+ rank-profile three inherits default {
+ onnx-model another {
+ file: files/ax_plus_b.onnx
+ input vector_A: indirect_a
+ input matrix_X: indirect_x
+ input vector_B: indirect_b
+ output vector_Y: foobar
+ }
+ first-phase {
+ expression: sum(attribute(aa))
+ }
+ global-phase {
+ rerank-count: 1001
+ expression: sum(constant(ww) * onnx(another).foobar)
+ }
+ function indirect_a() {
+ expression: tensor(d1[3]):[0.25, attribute(extra), 0.75]
}
function indirect_x() {
expression: constant(xx)
diff --git a/config-model/src/test/derived/rankproperties/rank-profiles.cfg b/config-model/src/test/derived/rankproperties/rank-profiles.cfg
index 3ca44288282..b6f51a88197 100644
--- a/config-model/src/test/derived/rankproperties/rank-profiles.cfg
+++ b/config-model/src/test/derived/rankproperties/rank-profiles.cfg
@@ -50,3 +50,49 @@ rankprofile[].fef.property[].name "vespa.fieldweight.description"
rankprofile[].fef.property[].value "35"
rankprofile[].fef.property[].name "vespa.fieldweight.tag"
rankprofile[].fef.property[].value "88"
+rankprofile[].name "withconstants1"
+rankprofile[].fef.property[].name "constant(a).value"
+rankprofile[].fef.property[].value "tensor(x[2]):[1.0, 2.0]"
+rankprofile[].fef.property[].name "constant(a).type"
+rankprofile[].fef.property[].value "tensor(x[2])"
+rankprofile[].fef.property[].name "constant(b).value"
+rankprofile[].fef.property[].value "tensor(y[3]):[3.0, 4.0, 5.0]"
+rankprofile[].fef.property[].name "constant(b).type"
+rankprofile[].fef.property[].value "tensor(y[3])"
+rankprofile[].fef.property[].name "rankingExpression(usea).rankingScript"
+rankprofile[].fef.property[].value "constant(a) * 1.0"
+rankprofile[].fef.property[].name "rankingExpression(usea).type"
+rankprofile[].fef.property[].value "tensor(x[2])"
+rankprofile[].fef.property[].name "rankingExpression(useb).rankingScript"
+rankprofile[].fef.property[].value "constant(a) * 1.0 + constant(b)"
+rankprofile[].fef.property[].name "rankingExpression(useb).type"
+rankprofile[].fef.property[].value "tensor(x[2],y[3])"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "rankingExpression(firstphase)"
+rankprofile[].fef.property[].name "rankingExpression(firstphase).rankingScript"
+rankprofile[].fef.property[].value "reduce(nativeFieldMatch + constant(a) * 1.0 + constant(b), sum)"
+rankprofile[].name "withconstants2"
+rankprofile[].fef.property[].name "constant(a).value"
+rankprofile[].fef.property[].value "tensor(x[2]):[1.0, 2.0]"
+rankprofile[].fef.property[].name "constant(a).type"
+rankprofile[].fef.property[].value "tensor(x[2])"
+rankprofile[].fef.property[].name "constant(b).value"
+rankprofile[].fef.property[].value "tensor(y[3]):[3.0, 4.0, 5.0]"
+rankprofile[].fef.property[].name "constant(b).type"
+rankprofile[].fef.property[].value "tensor(y[3])"
+rankprofile[].fef.property[].name "rankingExpression(usea).rankingScript"
+rankprofile[].fef.property[].value "constant(a) * 1.0"
+rankprofile[].fef.property[].name "rankingExpression(usea).type"
+rankprofile[].fef.property[].value "tensor(x[2])"
+rankprofile[].fef.property[].name "rankingExpression(useb).rankingScript"
+rankprofile[].fef.property[].value "constant(a) * 1.0 + constant(b)"
+rankprofile[].fef.property[].name "rankingExpression(useb).type"
+rankprofile[].fef.property[].value "tensor(x[2],y[3])"
+rankprofile[].fef.property[].name "rankingExpression(usec).rankingScript"
+rankprofile[].fef.property[].value "constant(a) + constant(b)"
+rankprofile[].fef.property[].name "rankingExpression(usec).type"
+rankprofile[].fef.property[].value "tensor(x[2],y[3])"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "rankingExpression(firstphase)"
+rankprofile[].fef.property[].name "rankingExpression(firstphase).rankingScript"
+rankprofile[].fef.property[].value "reduce(nativeFieldMatch + constant(a) + constant(b), sum)"
diff --git a/config-model/src/test/derived/rankproperties/rankproperties.sd b/config-model/src/test/derived/rankproperties/rankproperties.sd
index a2eb987d4ff..a13b3081ca7 100644
--- a/config-model/src/test/derived/rankproperties/rankproperties.sd
+++ b/config-model/src/test/derived/rankproperties/rankproperties.sd
@@ -59,4 +59,28 @@ schema rankproperties {
}
}
+ rank-profile withconstants1 {
+ constants {
+ constant(a) tensor(x[2]) : [1,2]
+ constant(b) tensor(y[3]) : [3,4,5]
+ }
+ function inline usea() {
+ expression: constant(a)*1.0
+ }
+ function inline useb() {
+ expression: usea + constant(b)
+ }
+ first-phase {
+ expression: sum(nativeFieldMatch + useb)
+ }
+ }
+
+ rank-profile withconstants2 inherits withconstants1 {
+ function inline usec() {
+ expression: constant(a)+constant(b)
+ }
+ first-phase {
+ expression: sum(nativeFieldMatch + usec)
+ }
+ }
}
diff --git a/config-model/src/test/java/com/yahoo/schema/processing/VespaMlModelTestCase.java b/config-model/src/test/java/com/yahoo/schema/processing/VespaMlModelTestCase.java
index 01e80e0f47a..664cfaf4ad7 100644
--- a/config-model/src/test/java/com/yahoo/schema/processing/VespaMlModelTestCase.java
+++ b/config-model/src/test/java/com/yahoo/schema/processing/VespaMlModelTestCase.java
@@ -25,8 +25,8 @@ public class VespaMlModelTestCase {
private final Path applicationDir = Path.fromString("src/test/integration/vespa/");
private final String expectedRankConfig =
- "constant(constant1).type : tensor(x[3])\n" +
"constant(constant1).value : tensor(x[3]):[0.5, 1.5, 2.5]\n" +
+ "constant(constant1).type : tensor(x[3])\n" +
"rankingExpression(foo1).rankingScript : reduce(reduce(input1 * input2, sum, name) * constant(constant1), max, x) * 3.0\n" +
"rankingExpression(foo1).input1.type : tensor(name{},x[3])\n" +
"rankingExpression(foo1).input2.type : tensor(x[3])\n" +