summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@gmail.com>2023-03-02 21:18:03 +0100
committerGitHub <noreply@github.com>2023-03-02 21:18:03 +0100
commit3d3d8fbbfe3577c34039e22e51438415442da7d0 (patch)
tree3fed20816f0c44095fc88417f4a2d39c88697221
parente8843502782cf63a490fe9cd45c43329d509b0f5 (diff)
parent27f83008c0026108f9fc3a7cffa576897cb7a55d (diff)
Merge pull request #26270 from vespa-engine/arnej/ranking-expression-wrapping
Arnej/ranking expression wrapping
-rw-r--r--config-model/src/main/java/com/yahoo/schema/OnnxModel.java2
-rw-r--r--config-model/src/main/java/com/yahoo/schema/RankProfile.java2
-rw-r--r--config-model/src/main/java/com/yahoo/schema/derived/RawRankProfile.java11
-rw-r--r--config-model/src/test/derived/rankingmacros/rank-profiles.cfg83
-rw-r--r--config-model/src/test/derived/rankingmacros/rankingmacros.sd105
-rw-r--r--config-model/src/test/java/com/yahoo/schema/derived/RankProfilesTestCase.java5
-rw-r--r--container-search/src/main/java/com/yahoo/search/ranking/HitRescorer.java3
-rw-r--r--container-search/src/main/java/com/yahoo/search/result/FeatureData.java3
-rw-r--r--model-evaluation/src/main/java/ai/vespa/models/evaluation/FunctionReference.java4
-rw-r--r--model-evaluation/src/main/java/ai/vespa/models/evaluation/LazyArrayContext.java9
-rw-r--r--model-evaluation/src/test/java/ai/vespa/models/evaluation/RankProfileImportingTest.java5
-rw-r--r--searchlib/abi-spec.json6
-rwxr-xr-xsearchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java3
-rwxr-xr-xsearchlib/src/main/java/com/yahoo/searchlib/rankingexpression/RankingExpression.java3
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/Reference.java25
-rwxr-xr-xsearchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java3
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java5
17 files changed, 253 insertions, 24 deletions
diff --git a/config-model/src/main/java/com/yahoo/schema/OnnxModel.java b/config-model/src/main/java/com/yahoo/schema/OnnxModel.java
index 6baaea6ea05..272b668b5fb 100644
--- a/config-model/src/main/java/com/yahoo/schema/OnnxModel.java
+++ b/config-model/src/main/java/com/yahoo/schema/OnnxModel.java
@@ -55,7 +55,7 @@ public class OnnxModel extends DistributableResource {
return ref.toString();
}
// or a function (evaluated by backend)
- if (ref.isSimple() && "rankingExpression".equals(ref.name())) {
+ if (ref.isSimpleRankingExpressionWrapper()) {
var arg = ref.simpleArgument();
if (arg.isPresent()) {
return ref.toString();
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 7cb0a088f5f..a00bbb682a8 100644
--- a/config-model/src/main/java/com/yahoo/schema/RankProfile.java
+++ b/config-model/src/main/java/com/yahoo/schema/RankProfile.java
@@ -1169,7 +1169,7 @@ public class RankProfile implements Cloneable {
// Source is either a simple reference (query/attribute/constant/rankingExpression)...
Optional<Reference> reference = Reference.simple(source);
if (reference.isPresent()) {
- if (reference.get().name().equals("rankingExpression") && reference.get().simpleArgument().isPresent()) {
+ if (reference.get().isSimpleRankingExpressionWrapper()) {
source = reference.get().simpleArgument().get(); // look up function below
} else {
return Optional.of(context.getType(reference.get()));
diff --git a/config-model/src/main/java/com/yahoo/schema/derived/RawRankProfile.java b/config-model/src/main/java/com/yahoo/schema/derived/RawRankProfile.java
index 31a38752bec..acb125197d2 100644
--- a/config-model/src/main/java/com/yahoo/schema/derived/RawRankProfile.java
+++ b/config-model/src/main/java/com/yahoo/schema/derived/RawRankProfile.java
@@ -20,6 +20,7 @@ import com.yahoo.searchlib.rankingexpression.parser.ParseException;
import com.yahoo.searchlib.rankingexpression.rule.ReferenceNode;
import com.yahoo.searchlib.rankingexpression.rule.SerializationContext;
import com.yahoo.vespa.config.search.RankProfilesConfig;
+import static com.yahoo.searchlib.rankingexpression.Reference.wrapInRankingExpression;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
@@ -273,9 +274,9 @@ public class RawRankProfile implements RankProfilesConfig.Producer {
String propertyName = RankingExpression.propertyName(referenceNode.getName());
String expressionString = function.getBody().getRoot().toString(context).toString();
context.addFunctionSerialization(propertyName, expressionString);
- ReferenceNode backendReferenceNode = new ReferenceNode("rankingExpression(" + referenceNode.getName() + ")",
- referenceNode.getArguments().expressions(),
- referenceNode.getOutput());
+ var backendReferenceNode = new ReferenceNode(wrapInRankingExpression(referenceNode.getName()),
+ referenceNode.getArguments().expressions(),
+ referenceNode.getOutput());
// tell backend to map back to the name the user expects:
featureRenames.put(backendReferenceNode.toString(), referenceNode.toString());
functionFeatures.put(referenceNode.getName(), backendReferenceNode);
@@ -499,7 +500,7 @@ public class RawRankProfile implements RankProfilesConfig.Producer {
if (expression.getRoot() instanceof ReferenceNode) {
properties.add(new Pair<>("vespa.rank." + phase, expression.getRoot().toString()));
} else {
- properties.add(new Pair<>("vespa.rank." + phase, "rankingExpression(" + name + ")"));
+ properties.add(new Pair<>("vespa.rank." + phase, wrapInRankingExpression(name)));
properties.add(new Pair<>(RankingExpression.propertyName(name), expression.getRoot().toString()));
}
return properties;
@@ -520,7 +521,7 @@ public class RawRankProfile implements RankProfilesConfig.Producer {
for (Map.Entry<String, String> mapping : onnxModel.getInputMap().entrySet()) {
String source = mapping.getValue();
if (functionNames.contains(source)) {
- onnxModel.addInputNameMapping(mapping.getKey(), "rankingExpression(" + source + ")");
+ onnxModel.addInputNameMapping(mapping.getKey(), wrapInRankingExpression(source));
}
}
}
diff --git a/config-model/src/test/derived/rankingmacros/rank-profiles.cfg b/config-model/src/test/derived/rankingmacros/rank-profiles.cfg
new file mode 100644
index 00000000000..71b7bc7166c
--- /dev/null
+++ b/config-model/src/test/derived/rankingmacros/rank-profiles.cfg
@@ -0,0 +1,83 @@
+rankprofile[].name "default"
+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[].name "standalone"
+rankprofile[].fef.property[].name "rankingExpression(myfeature).rankingScript"
+rankprofile[].fef.property[].value "7 * attribute(num)"
+rankprofile[].fef.property[].name "rankingExpression(fourtimessum@2b1138e8965e7ff5.67f1e87166cfef86).rankingScript"
+rankprofile[].fef.property[].value "4 * (match + match)"
+rankprofile[].fef.property[].name "rankingExpression(macro_with_dollar$).rankingScript"
+rankprofile[].fef.property[].value "69"
+rankprofile[].fef.property[].name "rankingExpression(anotherfeature).rankingScript"
+rankprofile[].fef.property[].value "10 * rankingExpression(myfeature)"
+rankprofile[].fef.property[].name "rankingExpression(yetanotherfeature).rankingScript"
+rankprofile[].fef.property[].value "100 * rankingExpression(myfeature)"
+rankprofile[].fef.property[].name "rankingExpression(fourtimessum).rankingScript"
+rankprofile[].fef.property[].value "4 * (var1 + var2)"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "rankingExpression(firstphase)"
+rankprofile[].fef.property[].name "rankingExpression(firstphase).rankingScript"
+rankprofile[].fef.property[].value "match + fieldMatch(title) + rankingExpression(myfeature)"
+rankprofile[].fef.property[].name "vespa.rank.secondphase"
+rankprofile[].fef.property[].value "rankingExpression(secondphase)"
+rankprofile[].fef.property[].name "rankingExpression(secondphase).rankingScript"
+rankprofile[].fef.property[].value "rankingExpression(fourtimessum@2b1138e8965e7ff5.67f1e87166cfef86) + 0 * rankingExpression(macro_with_dollar$)"
+rankprofile[].fef.property[].name "vespa.summary.feature"
+rankprofile[].fef.property[].value "firstPhase"
+rankprofile[].fef.property[].name "vespa.summary.feature"
+rankprofile[].fef.property[].value "rankingExpression(myfeature)"
+rankprofile[].fef.property[].name "vespa.summary.feature"
+rankprofile[].fef.property[].value "rankingExpression(anotherfeature)"
+rankprofile[].fef.property[].name "vespa.summary.feature"
+rankprofile[].fef.property[].value "rankingExpression(yetanotherfeature)"
+rankprofile[].fef.property[].name "vespa.summary.feature"
+rankprofile[].fef.property[].value "rankingExpression(macro_with_dollar$)"
+rankprofile[].fef.property[].name "vespa.feature.rename"
+rankprofile[].fef.property[].value "rankingExpression(anotherfeature)"
+rankprofile[].fef.property[].name "vespa.feature.rename"
+rankprofile[].fef.property[].value "anotherfeature"
+rankprofile[].fef.property[].name "vespa.feature.rename"
+rankprofile[].fef.property[].value "rankingExpression(yetanotherfeature)"
+rankprofile[].fef.property[].name "vespa.feature.rename"
+rankprofile[].fef.property[].value "yetanotherfeature"
+rankprofile[].fef.property[].name "vespa.feature.rename"
+rankprofile[].fef.property[].value "rankingExpression(macro_with_dollar$)"
+rankprofile[].fef.property[].name "vespa.feature.rename"
+rankprofile[].fef.property[].value "macro_with_dollar$"
+rankprofile[].name "constantsAndMacro"
+rankprofile[].fef.property[].name "rankingExpression(c).rankingScript"
+rankprofile[].fef.property[].value "attribute(num)"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "rankingExpression(firstphase)"
+rankprofile[].fef.property[].name "rankingExpression(firstphase).rankingScript"
+rankprofile[].fef.property[].value "attribute(num) * 2.0 + 3.0"
+rankprofile[].fef.property[].name "vespa.summary.feature"
+rankprofile[].fef.property[].value "firstPhase"
+rankprofile[].name "doc"
+rankprofile[].fef.property[].name "rankingExpression(myfeature).rankingScript"
+rankprofile[].fef.property[].value "fieldMatch(title) + freshness(timestamp)"
+rankprofile[].fef.property[].name "rankingExpression(otherfeature@6b0a229a66fcaa04).rankingScript"
+rankprofile[].fef.property[].value "nativeRank(title,body)"
+rankprofile[].fef.property[].name "rankingExpression(otherfeature).rankingScript"
+rankprofile[].fef.property[].value "nativeRank(foo,body)"
+rankprofile[].fef.property[].name "vespa.rank.firstphase"
+rankprofile[].fef.property[].value "rankingExpression(firstphase)"
+rankprofile[].fef.property[].name "rankingExpression(firstphase).rankingScript"
+rankprofile[].fef.property[].value "rankingExpression(myfeature) * 10"
+rankprofile[].fef.property[].name "vespa.rank.secondphase"
+rankprofile[].fef.property[].value "rankingExpression(secondphase)"
+rankprofile[].fef.property[].name "rankingExpression(secondphase).rankingScript"
+rankprofile[].fef.property[].value "rankingExpression(otherfeature@6b0a229a66fcaa04) * rankingExpression(myfeature)"
+rankprofile[].fef.property[].name "vespa.summary.feature"
+rankprofile[].fef.property[].value "rankingExpression(myfeature)"
+rankprofile[].fef.property[].name "vespa.feature.rename"
+rankprofile[].fef.property[].value "rankingExpression(myfeature)"
+rankprofile[].fef.property[].name "vespa.feature.rename"
+rankprofile[].fef.property[].value "myfeature"
diff --git a/config-model/src/test/derived/rankingmacros/rankingmacros.sd b/config-model/src/test/derived/rankingmacros/rankingmacros.sd
new file mode 100644
index 00000000000..84598cb483a
--- /dev/null
+++ b/config-model/src/test/derived/rankingmacros/rankingmacros.sd
@@ -0,0 +1,105 @@
+# Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+schema rankingmacros {
+
+ document rankingmacros {
+ field title type string {
+ indexing: index
+ }
+ field timestamp type long {
+ indexing: attribute
+ }
+ field description type string {
+ indexing: index
+ }
+ field num type int {
+ indexing: attribute
+ }
+ field abstract type string {
+ indexing: index
+ }
+ field body type string {
+ indexing: index
+ }
+ field usstaticrank type string {
+ indexing: attribute
+ }
+ field boostmax type string {
+ indexing: index
+ }
+ field entitytitle type string {
+ indexing: index
+ }
+ }
+
+ rank-profile standalone {
+ macro fourtimessum(var1, var2) {
+ expression: 4*(var1+var2)
+ }
+ macro myfeature() {
+ expression {
+ 7 * attribute(num)
+ }
+ }
+ macro anotherfeature() {
+ expression: 10*myfeature
+ }
+ macro yetanotherfeature() {
+ expression: 100*rankingExpression(myfeature) # legacy form
+ }
+ macro macro_with_dollar$() { # Not allowed
+ expression: 69
+ }
+ first-phase {
+ expression: match + fieldMatch(title) + myfeature
+ }
+ second-phase {
+ expression: fourtimessum(match,match) + 0 * macro_with_dollar$
+ }
+ summary-features {
+ firstPhase
+ rankingExpression(myfeature)
+ anotherfeature
+ yetanotherfeature
+ macro_with_dollar$
+ }
+ }
+
+ # Profile with macro and constants
+ rank-profile constantsAndMacro {
+ macro c() {
+ expression: attribute(num)
+ }
+
+ constants {
+ a: 2
+ b: 3
+ }
+
+ first-phase {
+ expression: attribute(num) * a + b
+ }
+
+ summary-features {
+ firstPhase
+ }
+ }
+
+ # The example in the docs
+ rank-profile doc inherits default {
+ macro myfeature() {
+ expression: fieldMatch(title) + freshness(timestamp)
+ }
+ macro otherfeature(foo) {
+ expression{ nativeRank(foo, body) }
+ }
+
+ first-phase {
+ expression: myfeature * 10
+ }
+ second-phase {
+ expression: otherfeature(title) * myfeature
+ }
+ summary-features: myfeature
+ }
+
+}
diff --git a/config-model/src/test/java/com/yahoo/schema/derived/RankProfilesTestCase.java b/config-model/src/test/java/com/yahoo/schema/derived/RankProfilesTestCase.java
index 5c24b32e275..a4c03291ce2 100644
--- a/config-model/src/test/java/com/yahoo/schema/derived/RankProfilesTestCase.java
+++ b/config-model/src/test/java/com/yahoo/schema/derived/RankProfilesTestCase.java
@@ -17,4 +17,9 @@ public class RankProfilesTestCase extends AbstractExportingTestCase {
void testRankProfiles() throws IOException, ParseException {
assertCorrectDeriving("rankprofiles", null, new TestProperties(), new TestableDeployLogger());
}
+
+ @Test
+ void testMacrosInRankProfiles() throws IOException, ParseException {
+ assertCorrectDeriving("rankingmacros", null, new TestProperties(), new TestableDeployLogger());
+ }
}
diff --git a/container-search/src/main/java/com/yahoo/search/ranking/HitRescorer.java b/container-search/src/main/java/com/yahoo/search/ranking/HitRescorer.java
index ebdbbb693f1..cce6b42d323 100644
--- a/container-search/src/main/java/com/yahoo/search/ranking/HitRescorer.java
+++ b/container-search/src/main/java/com/yahoo/search/ranking/HitRescorer.java
@@ -3,6 +3,7 @@ package com.yahoo.search.ranking;
import com.yahoo.search.result.FeatureData;
import com.yahoo.search.result.Hit;
+import static com.yahoo.searchlib.rankingexpression.Reference.RANKING_EXPRESSION_WRAPPER;
import java.util.function.Supplier;
import java.util.logging.Logger;
@@ -42,7 +43,7 @@ class HitRescorer {
}
}
- private static final String RE_PREFIX = "rankingExpression(";
+ private static final String RE_PREFIX = RANKING_EXPRESSION_WRAPPER + "(";
private static final String RE_SUFFIX = ")";
private static final int RE_PRE_LEN = RE_PREFIX.length();
private static final int RE_SUF_LEN = RE_SUFFIX.length();
diff --git a/container-search/src/main/java/com/yahoo/search/result/FeatureData.java b/container-search/src/main/java/com/yahoo/search/result/FeatureData.java
index 421f19475a6..7e9fa3f748a 100644
--- a/container-search/src/main/java/com/yahoo/search/result/FeatureData.java
+++ b/container-search/src/main/java/com/yahoo/search/result/FeatureData.java
@@ -11,6 +11,7 @@ import com.yahoo.io.GrowableByteBuffer;
import com.yahoo.tensor.Tensor;
import com.yahoo.tensor.serialization.JsonFormat;
import com.yahoo.tensor.serialization.TypedBinaryFormat;
+import static com.yahoo.searchlib.rankingexpression.Reference.wrapInRankingExpression;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
@@ -144,7 +145,7 @@ public class FeatureData implements Inspectable, JsonProducer {
if (featureValue.valid()) return featureValue;
// Try to wrap by rankingExpression(name)
- return value.field("rankingExpression(" + featureName + ")");
+ return value.field(wrapInRankingExpression(featureName));
}
/** Returns the names of the features available in this */
diff --git a/model-evaluation/src/main/java/ai/vespa/models/evaluation/FunctionReference.java b/model-evaluation/src/main/java/ai/vespa/models/evaluation/FunctionReference.java
index 46134074137..34e34a3341d 100644
--- a/model-evaluation/src/main/java/ai/vespa/models/evaluation/FunctionReference.java
+++ b/model-evaluation/src/main/java/ai/vespa/models/evaluation/FunctionReference.java
@@ -2,6 +2,7 @@
package ai.vespa.models.evaluation;
import com.yahoo.collections.Pair;
+import static com.yahoo.searchlib.rankingexpression.Reference.wrapInRankingExpression;
import java.util.Objects;
import java.util.Optional;
@@ -51,7 +52,8 @@ class FunctionReference {
}
String serialForm() {
- return "rankingExpression(" + name + (instance != null ? instance : "") + ")";
+ String extra = (instance != null ? instance : "");
+ return wrapInRankingExpression(name + extra);
}
@Override
diff --git a/model-evaluation/src/main/java/ai/vespa/models/evaluation/LazyArrayContext.java b/model-evaluation/src/main/java/ai/vespa/models/evaluation/LazyArrayContext.java
index 81325740218..47c246c008e 100644
--- a/model-evaluation/src/main/java/ai/vespa/models/evaluation/LazyArrayContext.java
+++ b/model-evaluation/src/main/java/ai/vespa/models/evaluation/LazyArrayContext.java
@@ -16,6 +16,7 @@ import com.yahoo.searchlib.rankingexpression.rule.ReferenceNode;
import com.yahoo.stream.CustomCollectors;
import com.yahoo.tensor.Tensor;
import com.yahoo.tensor.TensorType;
+import static com.yahoo.searchlib.rankingexpression.Reference.RANKING_EXPRESSION_WRAPPER;
import java.util.Arrays;
import java.util.HashMap;
@@ -233,7 +234,11 @@ public final class LazyArrayContext extends Context implements ContextIndex {
List<OnnxModel> onnxModels,
Map<String, OnnxModel> onnxModelsInUse) {
if (isFunctionReference(node)) {
- FunctionReference reference = FunctionReference.fromSerial(node.toString()).get();
+ var opt = FunctionReference.fromSerial(node.toString());
+ if (opt.isEmpty()) {
+ throw new IllegalArgumentException("Could not extract function " + node + " from serialized form '" + node.toString() +"'");
+ }
+ FunctionReference reference = opt.get();
bindTargets.add(reference.serialForm());
ExpressionFunction function = functions.get(reference);
@@ -313,7 +318,7 @@ public final class LazyArrayContext extends Context implements ContextIndex {
private boolean isFunctionReference(ExpressionNode node) {
if ( ! (node instanceof ReferenceNode reference)) return false;
- return reference.getName().equals("rankingExpression") && reference.getArguments().size() == 1;
+ return reference.getName().equals(RANKING_EXPRESSION_WRAPPER) && reference.getArguments().size() == 1;
}
private boolean isOnnx(ExpressionNode node) {
diff --git a/model-evaluation/src/test/java/ai/vespa/models/evaluation/RankProfileImportingTest.java b/model-evaluation/src/test/java/ai/vespa/models/evaluation/RankProfileImportingTest.java
index 1a6f6925caf..c5084166c1f 100644
--- a/model-evaluation/src/test/java/ai/vespa/models/evaluation/RankProfileImportingTest.java
+++ b/model-evaluation/src/test/java/ai/vespa/models/evaluation/RankProfileImportingTest.java
@@ -49,4 +49,9 @@ public class RankProfileImportingTest {
assertEquals("tensor()", rt.get().toString());
}
+ @Test
+ public void testImportingExpressionsAsArguments() {
+ ModelTester tester = new ModelTester("src/test/resources/config/expressions-as-arguments/");
+ assertEquals(3, tester.models().size());
+ }
}
diff --git a/searchlib/abi-spec.json b/searchlib/abi-spec.json
index 5413907e967..be0414421fe 100644
--- a/searchlib/abi-spec.json
+++ b/searchlib/abi-spec.json
@@ -364,6 +364,8 @@
"public boolean equals(java.lang.Object)",
"public int hashCode()",
"public java.lang.String toString()",
+ "public static java.lang.String wrapInRankingExpression(java.lang.String)",
+ "public boolean isSimpleRankingExpressionWrapper()",
"public java.lang.StringBuilder toString(java.lang.StringBuilder, com.yahoo.searchlib.rankingexpression.rule.SerializationContext, java.util.Deque, com.yahoo.searchlib.rankingexpression.rule.CompositeNode)",
"public int compareTo(com.yahoo.searchlib.rankingexpression.Reference)",
"public static com.yahoo.searchlib.rankingexpression.Reference fromIdentifier(java.lang.String)",
@@ -371,7 +373,9 @@
"public static java.util.Optional simple(java.lang.String)",
"public bridge synthetic int compareTo(java.lang.Object)"
],
- "fields" : [ ]
+ "fields" : [
+ "public static final java.lang.String RANKING_EXPRESSION_WRAPPER"
+ ]
},
"com.yahoo.searchlib.rankingexpression.evaluation.AbstractArrayContext" : {
"superClass" : "com.yahoo.searchlib.rankingexpression.evaluation.Context",
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java
index 171151bfdf4..c7d69d7a36a 100755
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java
@@ -10,6 +10,7 @@ import com.yahoo.searchlib.rankingexpression.rule.ReferenceNode;
import com.yahoo.searchlib.rankingexpression.rule.SerializationContext;
import com.yahoo.tensor.TensorType;
import com.yahoo.text.Utf8;
+import static com.yahoo.searchlib.rankingexpression.Reference.wrapInRankingExpression;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -142,7 +143,7 @@ public class ExpressionFunction {
if (shouldGenerateFeature(expr)) {
String funcName = "autogenerated_ranking_feature@" + Long.toHexString(symbolCode(key + "=" + binding));
context.addFunctionSerialization(RankingExpression.propertyName(funcName), binding);
- binding = "rankingExpression(" + funcName + ")";
+ binding = wrapInRankingExpression(funcName);
}
argumentBindings.put(key, binding);
}
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/RankingExpression.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/RankingExpression.java
index c9f818544e3..c6de04ed755 100755
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/RankingExpression.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/RankingExpression.java
@@ -11,6 +11,7 @@ import com.yahoo.searchlib.rankingexpression.rule.SerializationContext;
import com.yahoo.tensor.TensorType;
import com.yahoo.tensor.evaluation.TypeContext;
import com.yahoo.text.Text;
+import static com.yahoo.searchlib.rankingexpression.Reference.RANKING_EXPRESSION_WRAPPER;
import java.io.File;
import java.io.FileNotFoundException;
@@ -80,7 +81,7 @@ public class RankingExpression implements Serializable {
private String name = "";
private ExpressionNode root;
- private final static String RANKEXPRESSION = "rankingExpression(";
+ private final static String RANKEXPRESSION = RANKING_EXPRESSION_WRAPPER + "(";
private final static String RANKINGSCRIPT = ").rankingScript";
private final static String EXPRESSION_NAME = ").expressionName";
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/Reference.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/Reference.java
index eaecdf78162..64b251c0cd4 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/Reference.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/Reference.java
@@ -120,17 +120,30 @@ public class Reference extends Name implements Comparable<Reference> {
return toString(new StringBuilder(), new SerializationContext(), null, null).toString();
}
+ public static final String RANKING_EXPRESSION_WRAPPER = "rankingExpression";
+
+ public static String wrapInRankingExpression(String name) {
+ return RANKING_EXPRESSION_WRAPPER + "(" + name + ")";
+ }
+
+ public boolean isSimpleRankingExpressionWrapper() {
+ return name().equals(RANKING_EXPRESSION_WRAPPER) && isSimple();
+ }
+
public StringBuilder toString(StringBuilder b, SerializationContext context, Deque<String> path, CompositeNode parent) {
b.append(name());
if (arguments.expressions().size() > 0) {
b.append("(");
- for (int i = 0; i < arguments.expressions().size(); i++) {
- ExpressionNode e = arguments.expressions().get(i);
- e.toString(b, context, path, parent);
- if (i+1 < arguments.expressions().size()) {
- b.append(',');
+ if (isSimpleRankingExpressionWrapper()) {
+ b.append(simpleArgument().get());
+ } else {
+ for (int i = 0; i < arguments.expressions().size(); i++) {
+ ExpressionNode e = arguments.expressions().get(i);
+ e.toString(b, context, path, parent);
+ if (i+1 < arguments.expressions().size()) {
+ b.append(',');
+ }
}
-
}
b.append(")");
}
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java
index 85a12a49958..ec377c6f5d9 100755
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java
@@ -8,6 +8,7 @@ import com.yahoo.searchlib.rankingexpression.evaluation.Context;
import com.yahoo.searchlib.rankingexpression.evaluation.Value;
import com.yahoo.tensor.TensorType;
import com.yahoo.tensor.evaluation.TypeContext;
+import static com.yahoo.searchlib.rankingexpression.Reference.wrapInRankingExpression;
import java.util.ArrayDeque;
import java.util.Deque;
@@ -95,7 +96,7 @@ public final class ReferenceNode extends CompositeNode {
context.addFunctionTypeSerialization(functionName, function.returnType().get());
}
path.removeLast();
- return string.append("rankingExpression(").append(functionName).append(')');
+ return string.append(wrapInRankingExpression(functionName));
}
// Not resolved in this context: output as-is
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java
index 7d0c0b98910..e2fffd824b9 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java
@@ -6,6 +6,7 @@ import com.yahoo.searchlib.rankingexpression.RankingExpression;
import com.yahoo.searchlib.rankingexpression.Reference;
import com.yahoo.tensor.TensorType;
import com.yahoo.tensor.evaluation.TypeContext;
+import static com.yahoo.searchlib.rankingexpression.Reference.wrapInRankingExpression;
import java.util.Collection;
import java.util.Collections;
@@ -97,13 +98,13 @@ public class SerializationContext extends FunctionReferenceContext {
/** Adds the serialization of the argument type to a function */
public void addArgumentTypeSerialization(String functionName, String argumentName, TensorType type) {
- serializedFunctions.put("rankingExpression(" + functionName + ")." + argumentName + ".type", type.toString());
+ serializedFunctions.put(wrapInRankingExpression(functionName) + "." + argumentName + ".type", type.toString());
}
/** Adds the serialization of the return type of a function */
public void addFunctionTypeSerialization(String functionName, TensorType type) {
if (type.rank() == 0) return; // no explicit type implies scalar (aka rank 0 tensor)
- serializedFunctions.put("rankingExpression(" + functionName + ").type", type.toString());
+ serializedFunctions.put(wrapInRankingExpression(functionName) + ".type", type.toString());
}
@Override