summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java5
-rw-r--r--model-inference/src/main/java/ai/vespa/models/evaluation/Model.java23
-rw-r--r--model-inference/src/main/java/ai/vespa/models/evaluation/ModelsEvaluator.java1
-rw-r--r--model-inference/src/main/java/ai/vespa/models/evaluation/RankProfilesConfigImporter.java82
-rw-r--r--model-inference/src/main/java/ai/vespa/models/evaluation/config/RankProfilesConfigImporter.java55
-rw-r--r--model-inference/src/test/java/ai/vespa/models/evaluation/RankProfilesImporterTest.java (renamed from model-inference/src/test/java/ai/vespa/models/evaluation/config/RankProfilesImporterTest.java)31
6 files changed, 121 insertions, 76 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 a69c524e863..5855dedc415 100644
--- a/config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java
+++ b/config-model/src/main/java/com/yahoo/searchdefinition/RankProfile.java
@@ -932,8 +932,8 @@ public class RankProfile implements Serializable, Cloneable {
public static class Macro implements Serializable, Cloneable {
private final String name;
- private String textualExpression=null;
- private RankingExpression expression=null;
+ private String textualExpression = null;
+ private RankingExpression expression = null;
private List<String> formalParams = new ArrayList<>();
/** True if this should be inlined into calling expressions. Useful for very cheap macros. */
@@ -998,6 +998,7 @@ public class RankProfile implements Serializable, Cloneable {
}
public static final class DiversitySettings {
+
private String attribute = null;
private int minGroups = 0;
private double cutoffFactor = 10;
diff --git a/model-inference/src/main/java/ai/vespa/models/evaluation/Model.java b/model-inference/src/main/java/ai/vespa/models/evaluation/Model.java
index 76d990a493e..b2eb8546a7c 100644
--- a/model-inference/src/main/java/ai/vespa/models/evaluation/Model.java
+++ b/model-inference/src/main/java/ai/vespa/models/evaluation/Model.java
@@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableList;
import com.yahoo.searchlib.rankingexpression.ExpressionFunction;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
/**
@@ -16,18 +17,38 @@ public class Model {
private final String name;
+ /** Free functions */
private final ImmutableList<ExpressionFunction> functions;
+ /** An instance of each usage of the above function, where variables are replaced by their bindings */
+ private final ImmutableList<ExpressionFunction> boundFunctions;
+
public Model(String name, Collection<ExpressionFunction> functions) {
+ this(name, functions, Collections.emptyList());
+ }
+
+ Model(String name, Collection<ExpressionFunction> functions, Collection<ExpressionFunction> boundFunctions) {
this.name = name;
this.functions = ImmutableList.copyOf(functions);
+ this.boundFunctions = ImmutableList.copyOf(boundFunctions);
}
public String name() { return name; }
- /** Returns an immutable list of the expression functions of this */
+ /** Returns an immutable list of the free (callable) functions of this */
public List<ExpressionFunction> functions() { return functions; }
+ /** Returns an immutable list of the bound function instances of this */
+ List<ExpressionFunction> boundFunctions() { return functions; }
+
+ /** Returns the function withe the given name, or null if none */ // TODO: Parameter overloading?
+ ExpressionFunction function(String name) {
+ for (ExpressionFunction function : functions)
+ if (function.getName().equals(name))
+ return function;
+ return null;
+ }
+
@Override
public String toString() { return "Model '" + name + "'"; }
diff --git a/model-inference/src/main/java/ai/vespa/models/evaluation/ModelsEvaluator.java b/model-inference/src/main/java/ai/vespa/models/evaluation/ModelsEvaluator.java
index c1a22a361e9..3532409766b 100644
--- a/model-inference/src/main/java/ai/vespa/models/evaluation/ModelsEvaluator.java
+++ b/model-inference/src/main/java/ai/vespa/models/evaluation/ModelsEvaluator.java
@@ -1,7 +1,6 @@
// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package ai.vespa.models.evaluation;
-import ai.vespa.models.evaluation.config.RankProfilesConfigImporter;
import com.yahoo.vespa.config.search.RankProfilesConfig;
/**
diff --git a/model-inference/src/main/java/ai/vespa/models/evaluation/RankProfilesConfigImporter.java b/model-inference/src/main/java/ai/vespa/models/evaluation/RankProfilesConfigImporter.java
new file mode 100644
index 00000000000..30eabb6f8a4
--- /dev/null
+++ b/model-inference/src/main/java/ai/vespa/models/evaluation/RankProfilesConfigImporter.java
@@ -0,0 +1,82 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package ai.vespa.models.evaluation;
+
+import ai.vespa.models.evaluation.Model;
+import com.yahoo.searchlib.rankingexpression.ExpressionFunction;
+import com.yahoo.searchlib.rankingexpression.RankingExpression;
+import com.yahoo.vespa.config.search.RankProfilesConfig;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Converts RankProfilesConfig instances to RankingExpressions for evaluation
+ *
+ * @author bratseth
+ */
+class RankProfilesConfigImporter {
+
+ private static final Pattern expressionPattern =
+ Pattern.compile("rankingExpression\\(([a-zA-Z0-9_]+)(@[a-f0-9]+\\.[a-f0-9]+)?\\)\\.rankingScript");
+
+ /**
+ * Returns a map of the models contained in this config, indexed on name.
+ * The map is modifiable and owned by the caller.
+ */
+ public Map<String, Model> importFrom(RankProfilesConfig config) {
+ Map<String, Model> models = new HashMap<>();
+ for (RankProfilesConfig.Rankprofile profile : config.rankprofile()) {
+ Model model = importProfile(profile);
+ models.put(model.name(), model);
+ }
+ return models;
+ }
+
+ private Model importProfile(RankProfilesConfig.Rankprofile profile) {
+ System.out.println("Importing " + profile.name());
+ List<ExpressionFunction> functions = new ArrayList<>();
+ List<ExpressionFunction> boundFunctions = new ArrayList<>();
+ ExpressionFunction firstPhase = null;
+ ExpressionFunction secondPhase = null;
+ for (RankProfilesConfig.Rankprofile.Fef.Property property : profile.fef().property()) {
+ Matcher expressionMatcher = expressionPattern.matcher(property.name());
+ if ( expressionMatcher.matches()) {
+ String name = expressionMatcher.group(1);
+ String instance = expressionMatcher.group(2);
+ List<String> arguments = new ArrayList<>();
+ RankingExpression expression = RankingExpression.from(property.value());
+
+ if (instance == null) {
+ System.out.println(" " + name + ": " + expression);
+ functions.add(new ExpressionFunction(name, arguments, expression));
+ } else {
+ System.out.println(" Binding of " + name + ": " + expression);
+ boundFunctions.add(new ExpressionFunction(name + instance, arguments, expression));
+ }
+ }
+ else if (property.name().equals("vespa.rank.firstphase")) { // Include in addition to macros
+ firstPhase = new ExpressionFunction("firstphase", new ArrayList<>(), RankingExpression.from(property.value()));
+ }
+ else if (property.name().equals("vespa.rank.secondphase")) { // Include in addition to macros
+ secondPhase = new ExpressionFunction("secondphase", new ArrayList<>(), RankingExpression.from(property.value()));
+ }
+ }
+ if (functionByName("firstphase", functions) == null && firstPhase != null) // may be already included, depending on body
+ functions.add(firstPhase);
+ if (functionByName("secondphase", functions) == null && secondPhase != null) // may be already included, depending on body
+ functions.add(secondPhase);
+ return new Model(profile.name(), functions, boundFunctions);
+ }
+
+ private ExpressionFunction functionByName(String name, List<ExpressionFunction> functions) {
+ for (ExpressionFunction function : functions)
+ if (function.getName().equals(name))
+ return function;
+ return null;
+ }
+
+}
diff --git a/model-inference/src/main/java/ai/vespa/models/evaluation/config/RankProfilesConfigImporter.java b/model-inference/src/main/java/ai/vespa/models/evaluation/config/RankProfilesConfigImporter.java
deleted file mode 100644
index a81006d526e..00000000000
--- a/model-inference/src/main/java/ai/vespa/models/evaluation/config/RankProfilesConfigImporter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package ai.vespa.models.evaluation.config;
-
-import ai.vespa.models.evaluation.Model;
-import com.yahoo.searchlib.rankingexpression.ExpressionFunction;
-import com.yahoo.searchlib.rankingexpression.RankingExpression;
-import com.yahoo.vespa.config.search.RankProfilesConfig;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Converts RankProfilesConfig instances to RankingExpressions for evaluation
- *
- * @author bratseth
- */
-public class RankProfilesConfigImporter {
-
- private static final Pattern expressionPattern = Pattern.compile("rankingExpression\\(([a-zA-Z0-9_]+)\\)\\.rankingScript");
-
- /**
- * Returns a map of the models contained in this config, indexed on name.
- * The map is modifiable and owned by the caller.
- */
- public Map<String, Model> importFrom(RankProfilesConfig config) {
- Map<String, Model> models = new HashMap<>();
- for (RankProfilesConfig.Rankprofile profile : config.rankprofile()) {
- Model model = importProfile(profile);
- models.put(model.name(), model);
- }
- return models;
- }
-
- private Model importProfile(RankProfilesConfig.Rankprofile profile) {
- System.out.println("Importing " + profile.name());
- List<ExpressionFunction> functions = new ArrayList<>();
- for (RankProfilesConfig.Rankprofile.Fef.Property property : profile.fef().property()) {
- Matcher expressionMatcher = expressionPattern.matcher(property.name());
- if ( ! expressionMatcher.matches()) continue;
-
- System.out.println(" Importing " + expressionMatcher.group(0));
-
- String name = expressionMatcher.group(0);
- List<String> arguments = new ArrayList<>();
- RankingExpression expression = RankingExpression.from(property.value());
- functions.add(new ExpressionFunction(name, arguments, expression));
- }
- return new Model(profile.name(), functions);
- }
-
-}
diff --git a/model-inference/src/test/java/ai/vespa/models/evaluation/config/RankProfilesImporterTest.java b/model-inference/src/test/java/ai/vespa/models/evaluation/RankProfilesImporterTest.java
index 2e93a1a138d..16ae433b958 100644
--- a/model-inference/src/test/java/ai/vespa/models/evaluation/config/RankProfilesImporterTest.java
+++ b/model-inference/src/test/java/ai/vespa/models/evaluation/RankProfilesImporterTest.java
@@ -1,7 +1,6 @@
// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package ai.vespa.models.evaluation.config;
+package ai.vespa.models.evaluation;
-import ai.vespa.models.evaluation.Model;
import com.yahoo.config.subscription.ConfigGetter;
import com.yahoo.config.subscription.FileSource;
import com.yahoo.searchlib.rankingexpression.ExpressionFunction;
@@ -13,7 +12,6 @@ import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
/**
* Tests instantiating models from rank-profiles configs.
@@ -23,7 +21,7 @@ import static org.junit.Assert.assertTrue;
public class RankProfilesImporterTest {
@Test
- public void testRankexpression() {
+ public void testImporting() {
String configPath = "src/test/resources/config/rankexpression/rank-profiles.cfg";
RankProfilesConfig config = new ConfigGetter<>(new FileSource(new File(configPath)), RankProfilesConfig.class).getConfig("");
Map<String, Model> models = new RankProfilesConfigImporter().importFrom(config);
@@ -31,21 +29,20 @@ public class RankProfilesImporterTest {
Model macros = models.get("macros");
assertNotNull(macros);
assertEquals(4, macros.functions().size());
- ExpressionFunction function = functionByName("fourtimessum", macros);
- assertNotNull(function);
-
- }
-
- @Test
- public void testRegexp() {
- assertTrue("a(foo)".matches("a\\([a-zA-Z0-9_]+\\)"));
+ assertFunction("fourtimessum", "4 * (var1 + var2)", macros);
+ assertFunction("firstphase", "match + fieldMatch(title) + rankingExpression(myfeature)", macros);
+ assertFunction("secondphase", "rankingExpression(fourtimessum@5cf279212355b980.67f1e87166cfef86)", macros);
+ assertFunction("myfeature",
+ "70 * fieldMatch(title).completeness * pow(0 - fieldMatch(title).earliness,2) + " +
+ "30 * pow(0 - fieldMatch(description).earliness,2)",
+ macros);
}
- private ExpressionFunction functionByName(String name, Model model) {
- for (ExpressionFunction function : model.functions())
- if (function.getName().equals(name))
- return function;
- return null;
+ private void assertFunction(String name, String expression, Model model) {
+ ExpressionFunction function = model.function(name);
+ assertNotNull(function);
+ assertEquals(name, function.getName());
+ assertEquals(expression, function.getBody().toString());
}
}