From 97eff1f15dcafe4a8d0229fa36b3e0448de2f4d6 Mon Sep 17 00:00:00 2001 From: Arne Juul Date: Wed, 21 Feb 2024 14:31:27 +0000 Subject: allow inputs { query(foo) string } --- .../main/java/com/yahoo/schema/RankProfile.java | 16 +++++++++----- .../com/yahoo/schema/derived/RawRankProfile.java | 4 ++-- config-model/src/main/javacc/SchemaParser.jj | 25 +++++++++++++--------- .../derived/rankingexpression/rank-profiles.cfg | 11 ++++++++++ .../derived/rankingexpression/rankexpression.sd | 13 ++++++++++- .../src/test/derived/rankingexpression/summary.cfg | 9 +++++--- 6 files changed, 57 insertions(+), 21 deletions(-) (limited to 'config-model') 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 9b3e236612a..22bf1880cd7 100644 --- a/config-model/src/main/java/com/yahoo/schema/RankProfile.java +++ b/config-model/src/main/java/com/yahoo/schema/RankProfile.java @@ -17,6 +17,7 @@ import com.yahoo.schema.expressiontransforms.ExpressionTransforms; import com.yahoo.schema.expressiontransforms.RankProfileTransformContext; import com.yahoo.schema.expressiontransforms.InputRecorder; import com.yahoo.schema.parser.ParseException; +import com.yahoo.search.schema.RankProfile.InputType; import com.yahoo.searchlib.rankingexpression.ExpressionFunction; import com.yahoo.searchlib.rankingexpression.FeatureList; import com.yahoo.searchlib.rankingexpression.RankingExpression; @@ -841,7 +842,7 @@ public class RankProfile implements Cloneable { if (inputs.containsKey(reference)) { Input existing = inputs().get(reference); if (! input.equals(existing)) - throw new IllegalArgumentException("Duplicate input: Has both " + input + " and existing"); + throw new IllegalArgumentException("Duplicate input: Has both " + input + " and existing " + existing); } inputs.put(reference, input); } @@ -1177,7 +1178,8 @@ public class RankProfile implements Cloneable { private Map featureTypes() { Map featureTypes = inputs().values().stream() - .collect(Collectors.toMap(input -> input.name(), input -> input.type())); + .collect(Collectors.toMap(input -> input.name(), + input -> input.type().tensorType())); allFields().forEach(field -> addAttributeFeatureTypes(field, featureTypes)); allImportedFields().forEach(field -> addAttributeFeatureTypes(field, featureTypes)); return featureTypes; @@ -1545,17 +1547,21 @@ public class RankProfile implements Cloneable { public static final class Input { private final Reference name; - private final TensorType type; + private final InputType type; private final Optional defaultValue; - public Input(Reference name, TensorType type, Optional defaultValue) { + public Input(Reference name, InputType type, Optional defaultValue) { this.name = name; this.type = type; this.defaultValue = defaultValue; } + public Input(Reference name, TensorType tType, Optional defaultValue) { + this(name, new InputType(tType, false), defaultValue); + } + public Reference name() { return name; } - public TensorType type() { return type; } + public InputType type() { return type; } public Optional defaultValue() { return defaultValue; } @Override 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 33a363312d6..db76d6397fc 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 @@ -519,12 +519,12 @@ public class RawRankProfile implements RankProfilesConfig.Producer { for (var input : inputs.values()) { if (FeatureNames.isQueryFeature(input.name())) { - if (input.type().rank() > 0) // Proton does not like representing the double type as a rank 0 tensor + if (input.type().tensorType().rank() > 0) // Proton does not like representing the double type as a rank 0 tensor properties.add(new Pair<>("vespa.type.query." + input.name().arguments().expressions().get(0), input.type().toString())); if (input.defaultValue().isPresent()) { properties.add(new Pair<>(input.name().toString(), - input.type().rank() == 0 ? + input.type().tensorType().rank() == 0 ? String.valueOf(input.defaultValue().get().asDouble()) : input.defaultValue().get().toString(true, false))); } diff --git a/config-model/src/main/javacc/SchemaParser.jj b/config-model/src/main/javacc/SchemaParser.jj index f298293ed57..d769f6208aa 100644 --- a/config-model/src/main/javacc/SchemaParser.jj +++ b/config-model/src/main/javacc/SchemaParser.jj @@ -34,6 +34,7 @@ import com.yahoo.schema.document.Stemming; import com.yahoo.schema.document.SDField; import com.yahoo.schema.FeatureNames; import com.yahoo.schema.fieldoperation.IndexingOperation; +import com.yahoo.search.schema.RankProfile.InputType; import com.yahoo.searchlib.rankingexpression.FeatureList; import com.yahoo.searchlib.rankingexpression.Reference; import com.yahoo.searchlib.rankingexpression.evaluation.TensorValue; @@ -298,6 +299,7 @@ TOKEN : | < HNSW: "hnsw" > | < MAX_LINKS_PER_NODE: "max-links-per-node" > | < DOUBLE_KEYWORD: "double" > +| < STRING_KEYWORD: "string" > | < DISTANCE_METRIC: "distance-metric" > | < NEIGHBORS_TO_EXPLORE_AT_INSERT: "neighbors-to-explore-at-insert" > | < MULTI_THREADED_INDEXING: "multi-threaded-indexing" > @@ -2012,11 +2014,11 @@ void inputs(ParsedRankProfile profile) : void input(ParsedRankProfile profile) : { Reference reference; - TensorType type = TensorType.empty; + InputType type = new InputType(TensorType.empty, false); Tensor defaultValue = null; } { - reference = inputName() ( type = valueType(reference))? ( ()* defaultValue = tensorValue(type) )? + reference = inputName() ( type = valueType(reference))? ( ()* defaultValue = tensorValue(type.tensorType()) )? { profile.addInput(reference, new RankProfile.Input(reference, type, Optional.ofNullable(defaultValue))); } } @@ -2034,18 +2036,20 @@ Reference inputName() : { return FeatureNames.asQueryFeature(name); } } -TensorType valueType(Reference reference) : +InputType valueType(Reference reference) : { TensorType type; - + InputType result; } { ( - ( type = tensorType("Type of " + reference) ) + ( type = tensorType("Type of " + reference) { result = new InputType(type, false); } ) + | + ( { result = new InputType(TensorType.empty, false); } ) | - ( { type = TensorType.empty; } ) + ( { result = new InputType(TensorType.empty, true); } ) ) - { return type; } + { return result; } } /** @@ -2329,7 +2333,7 @@ void constants(ParsedSchema schema, ParsedRankProfile profile) : void constant(ParsedSchema schema, ParsedRankProfile profile) : { Reference name = null; - TensorType type = TensorType.empty; + InputType type = new InputType(TensorType.empty, false); Tensor value = null; String valuePath = null; } @@ -2337,12 +2341,12 @@ void constant(ParsedSchema schema, ParsedRankProfile profile) : ( name = constantName() ( - LOOKAHEAD(4) ( ( type = valueType(name) )? ()* ( value = tensorValue(type) | valuePath = fileItem()) + LOOKAHEAD(4) ( ( type = valueType(name) )? ()* ( value = tensorValue(type.tensorType()) | valuePath = fileItem()) { if (value != null) profile.add(new RankProfile.Constant(name, value)); else - profile.add(new RankProfile.Constant(name, type, valuePath)); + profile.add(new RankProfile.Constant(name, type.tensorType(), valuePath)); } ) | // Deprecated forms (TODO: Vespa > 8: Add warning): @@ -2710,6 +2714,7 @@ String identifier() : { } | | | + | | | | diff --git a/config-model/src/test/derived/rankingexpression/rank-profiles.cfg b/config-model/src/test/derived/rankingexpression/rank-profiles.cfg index 87882eef273..8b769360053 100644 --- a/config-model/src/test/derived/rankingexpression/rank-profiles.cfg +++ b/config-model/src/test/derived/rankingexpression/rank-profiles.cfg @@ -670,3 +670,14 @@ rankprofile[].fef.property[].name "vespa.feature.rename" rankprofile[].fef.property[].value "useAttr(t1,42)" rankprofile[].fef.property[].name "vespa.type.attribute.t1" rankprofile[].fef.property[].value "tensor(m{},v[3])" +rankprofile[].name "withstringcompare" +rankprofile[].fef.property[].name "vespa.rank.firstphase" +rankprofile[].fef.property[].value "rankingExpression(firstphase)" +rankprofile[].fef.property[].name "rankingExpression(firstphase).rankingScript" +rankprofile[].fef.property[].value "if (attribute(surl) == query(myquerystring), 0.75, 0.25)" +rankprofile[].fef.property[].name "vespa.rank.secondphase" +rankprofile[].fef.property[].value "rankingExpression(secondphase)" +rankprofile[].fef.property[].name "rankingExpression(secondphase).rankingScript" +rankprofile[].fef.property[].value "if (attribute(surl) == query(undeclaredinput), 0.75, 0.25)" +rankprofile[].fef.property[].name "vespa.type.attribute.t1" +rankprofile[].fef.property[].value "tensor(m{},v[3])" diff --git a/config-model/src/test/derived/rankingexpression/rankexpression.sd b/config-model/src/test/derived/rankingexpression/rankexpression.sd index 1ccf74bfe17..76672906252 100644 --- a/config-model/src/test/derived/rankingexpression/rankexpression.sd +++ b/config-model/src/test/derived/rankingexpression/rankexpression.sd @@ -20,7 +20,7 @@ schema rankexpression { } field surl type string { - indexing: summary + indexing: summary | attribute } field year type int { @@ -507,4 +507,15 @@ schema rankexpression { } } + rank-profile withstringcompare { + inputs { + query(myquerystring) string + } + first-phase { + expression: if (attribute(surl) == query(myquerystring), 0.75, 0.25) + } + second-phase { + expression: if (attribute(surl) == query(undeclaredinput), 0.75, 0.25) + } + } } diff --git a/config-model/src/test/derived/rankingexpression/summary.cfg b/config-model/src/test/derived/rankingexpression/summary.cfg index b52cb055164..9f96f5ab4a7 100644 --- a/config-model/src/test/derived/rankingexpression/summary.cfg +++ b/config-model/src/test/derived/rankingexpression/summary.cfg @@ -10,8 +10,8 @@ classes[].fields[].name "title" classes[].fields[].command "" classes[].fields[].source "" classes[].fields[].name "surl" -classes[].fields[].command "" -classes[].fields[].source "" +classes[].fields[].command "attribute" +classes[].fields[].source "surl" classes[].fields[].name "year" classes[].fields[].command "attribute" classes[].fields[].source "year" @@ -24,7 +24,7 @@ classes[].fields[].source "" classes[].fields[].name "documentid" classes[].fields[].command "documentid" classes[].fields[].source "" -classes[].id 399614584 +classes[].id 799304810 classes[].name "attributeprefetch" classes[].omitsummaryfeatures false classes[].fields[].name "nrtgmp" @@ -33,6 +33,9 @@ classes[].fields[].source "nrtgmp" classes[].fields[].name "glmpfw" classes[].fields[].command "attribute" classes[].fields[].source "glmpfw" +classes[].fields[].name "surl" +classes[].fields[].command "attribute" +classes[].fields[].source "surl" classes[].fields[].name "year" classes[].fields[].command "attribute" classes[].fields[].source "year" -- cgit v1.2.3