// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.schema.parser; import com.yahoo.schema.OnnxModel; import com.yahoo.schema.RankProfile; import com.yahoo.schema.RankProfile.MatchPhaseSettings; import com.yahoo.schema.RankProfile.MutateOperation; import com.yahoo.searchlib.rankingexpression.FeatureList; import com.yahoo.searchlib.rankingexpression.Reference; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; /** * This class holds the extracted information after parsing a * rank-profile block in a schema (.sd) file, using simple data * structures as far as possible. Do not put advanced logic here! * * @author arnej27959 */ class ParsedRankProfile extends ParsedBlock { private boolean ignoreDefaultRankFeatures = false; private Double rankScoreDropLimit = null; private Double termwiseLimit = null; private Double postFilterThreshold = null; private Double approximateThreshold = null; private Double targetHitsMaxAdjustmentFactor = null; private final List matchFeatures = new ArrayList<>(); private final List rankFeatures = new ArrayList<>(); private final List summaryFeatures = new ArrayList<>(); private Integer keepRankCount = null; private Integer minHitsPerThread = null; private Integer numSearchPartitions = null; private Integer numThreadsPerSearch = null; private Integer reRankCount = null; private MatchPhaseSettings matchPhaseSettings = null; private String firstPhaseExpression = null; private String inheritedSummaryFeatures = null; private String inheritedMatchFeatures = null; private String secondPhaseExpression = null; private Boolean strict = null; private Boolean useSignificanceModel = null; private final List mutateOperations = new ArrayList<>(); private final List inherited = new ArrayList<>(); private final Map fieldsRankFilter = new LinkedHashMap<>(); private final Map fieldsRankWeight = new LinkedHashMap<>(); private final Map functions = new LinkedHashMap<>(); private final Map fieldsRankType = new LinkedHashMap<>(); private final Map> rankProperties = new LinkedHashMap<>(); private final Map constants = new LinkedHashMap<>(); private final Map inputs = new LinkedHashMap<>(); private final List onnxModels = new ArrayList<>(); private Integer globalPhaseRerankCount = null; private String globalPhaseExpression = null; ParsedRankProfile(String name) { super(name, "rank-profile"); } boolean getIgnoreDefaultRankFeatures() { return this.ignoreDefaultRankFeatures; } Optional getRankScoreDropLimit() { return Optional.ofNullable(this.rankScoreDropLimit); } Optional getTermwiseLimit() { return Optional.ofNullable(this.termwiseLimit); } Optional getPostFilterThreshold() { return Optional.ofNullable(this.postFilterThreshold); } Optional getApproximateThreshold() { return Optional.ofNullable(this.approximateThreshold); } Optional getTargetHitsMaxAdjustmentFactor() { return Optional.ofNullable(this.targetHitsMaxAdjustmentFactor); } List getMatchFeatures() { return List.copyOf(this.matchFeatures); } List getRankFeatures() { return List.copyOf(this.rankFeatures); } List getSummaryFeatures() { return List.copyOf(this.summaryFeatures); } Optional getKeepRankCount() { return Optional.ofNullable(this.keepRankCount); } Optional getMinHitsPerThread() { return Optional.ofNullable(this.minHitsPerThread); } Optional getNumSearchPartitions() { return Optional.ofNullable(this.numSearchPartitions); } Optional getNumThreadsPerSearch() { return Optional.ofNullable(this.numThreadsPerSearch); } Optional getReRankCount() { return Optional.ofNullable(this.reRankCount); } Optional getMatchPhaseSettings() { return Optional.ofNullable(this.matchPhaseSettings); } Optional getFirstPhaseExpression() { return Optional.ofNullable(this.firstPhaseExpression); } Optional getInheritedMatchFeatures() { return Optional.ofNullable(this.inheritedMatchFeatures); } List getFunctions() { return List.copyOf(functions.values()); } List getMutateOperations() { return List.copyOf(mutateOperations); } List getInherited() { return List.copyOf(inherited); } Optional getGlobalPhaseRerankCount() { return Optional.ofNullable(this.globalPhaseRerankCount); } Optional getGlobalPhaseExpression() { return Optional.ofNullable(this.globalPhaseExpression); } Map getFieldsWithRankFilter() { return Collections.unmodifiableMap(fieldsRankFilter); } Map getFieldsWithRankWeight() { return Collections.unmodifiableMap(fieldsRankWeight); } Map getFieldsWithRankType() { return Collections.unmodifiableMap(fieldsRankType); } Map> getRankProperties() { return Collections.unmodifiableMap(rankProperties); } Map getConstants() { return Collections.unmodifiableMap(constants); } Map getInputs() { return Collections.unmodifiableMap(inputs); } List getOnnxModels() { return List.copyOf(onnxModels); } Optional getInheritedSummaryFeatures() { return Optional.ofNullable(this.inheritedSummaryFeatures); } Optional getSecondPhaseExpression() { return Optional.ofNullable(this.secondPhaseExpression); } Optional isStrict() { return Optional.ofNullable(this.strict); } Optional isUseSignificanceModel() { return Optional.ofNullable(this.useSignificanceModel); } void addSummaryFeatures(FeatureList features) { this.summaryFeatures.add(features); } void addMatchFeatures(FeatureList features) { this.matchFeatures.add(features); } void addRankFeatures(FeatureList features) { this.rankFeatures.add(features); } void inherit(String other) { inherited.add(other); } void setInheritedSummaryFeatures(String other) { verifyThat(inheritedSummaryFeatures == null, "already inherits summary-features"); this.inheritedSummaryFeatures = other; } void add(RankProfile.Constant constant) { verifyThat(! constants.containsKey(constant.name()), "already has constant", constant.name()); constants.put(constant.name(), constant); } void addInput(Reference name, RankProfile.Input input) { verifyThat(! inputs.containsKey(name), "already has input", name); inputs.put(name, input); } void add(OnnxModel model) { onnxModels.add(model); } void addFieldRankFilter(String field, boolean filter) { fieldsRankFilter.put(field, filter); } void addFieldRankType(String field, String type) { verifyThat(! fieldsRankType.containsKey(field), "already has rank type for field", field); fieldsRankType.put(field, type); } void addFieldRankWeight(String field, int weight) { verifyThat(! fieldsRankType.containsKey(field), "already has weight for field", field); fieldsRankWeight.put(field, weight); } ParsedRankFunction addOrReplaceFunction(ParsedRankFunction func) { // allowed with warning // verifyThat(! functions.containsKey(func.name()), "already has function", func.name()); return functions.put(func.name(), func); } void addMutateOperation(MutateOperation.Phase phase, String attrName, String operation) { mutateOperations.add(new MutateOperation(phase, attrName, operation)); } void addRankProperty(String key, String value) { List values = rankProperties.computeIfAbsent(key, k -> new ArrayList()); values.add(value); } void setFirstPhaseRanking(String expression) { verifyThat(firstPhaseExpression == null, "already has first-phase expression"); this.firstPhaseExpression = expression; } void setIgnoreDefaultRankFeatures(boolean value) { this.ignoreDefaultRankFeatures = value; } void setInheritedMatchFeatures(String other) { this.inheritedMatchFeatures = other; } void setKeepRankCount(int count) { verifyThat(keepRankCount == null, "already has rerank-count"); this.keepRankCount = count; } void setMatchPhaseSettings(MatchPhaseSettings settings) { verifyThat(matchPhaseSettings == null, "already has match-phase"); this.matchPhaseSettings = settings; } void setMinHitsPerThread(int minHits) { verifyThat(minHitsPerThread == null, "already has min-hits-per-thread"); this.minHitsPerThread = minHits; } void setNumSearchPartitions(int numParts) { verifyThat(numSearchPartitions == null, "already has num-search-partitions"); this.numSearchPartitions = numParts; } void setNumThreadsPerSearch(int threads) { verifyThat(numThreadsPerSearch == null, "already has num-threads-per-search"); this.numThreadsPerSearch = threads; } void setRankScoreDropLimit(double limit) { verifyThat(rankScoreDropLimit == null, "already has rank-score-drop-limit"); this.rankScoreDropLimit = limit; } void setRerankCount(int count) { verifyThat(reRankCount == null, "already has rerank-count"); this.reRankCount = count; } void setSecondPhaseRanking(String expression) { verifyThat(secondPhaseExpression == null, "already has second-phase expression"); this.secondPhaseExpression = expression; } void setGlobalPhaseExpression(String expression) { verifyThat(globalPhaseExpression == null, "already has global-phase expression"); this.globalPhaseExpression = expression; } void setGlobalPhaseRerankCount(int count) { verifyThat(globalPhaseRerankCount == null, "already has global-phase rerank-count"); this.globalPhaseRerankCount = count; } void setStrict(boolean strict) { verifyThat(this.strict == null, "already has strict"); this.strict = strict; } void setUseSignificanceModel(boolean useSignificanceModel) { verifyThat(this.useSignificanceModel == null, "already has use-model"); this.useSignificanceModel = useSignificanceModel; } void setTermwiseLimit(double limit) { verifyThat(termwiseLimit == null, "already has termwise-limit"); this.termwiseLimit = limit; } void setPostFilterThreshold(double threshold) { verifyThat(postFilterThreshold == null, "already has post-filter-threshold"); this.postFilterThreshold = threshold; } void setApproximateThreshold(double threshold) { verifyThat(approximateThreshold == null, "already has approximate-threshold"); this.approximateThreshold = threshold; } void setTargetHitsMaxAdjustmentFactor(double factor) { verifyThat(targetHitsMaxAdjustmentFactor == null, "already has target-hits-max-adjustment-factor"); this.targetHitsMaxAdjustmentFactor = factor; } }