SOLR-15149: model creation errors fixes (#2350)

SOLR-15149: model loading errors fix + tests
This commit is contained in:
Alessandro Benedetti 2021-02-15 18:02:25 +01:00 committed by GitHub
parent f993c392f1
commit 227ef3b397
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 231 additions and 8 deletions

View File

@ -239,6 +239,8 @@ Optimizations
Bug Fixes
---------------------
* SOLR-15078: Fix ExpandComponent behavior when expanding on numeric fields to differentiate '0' group from null group (hossman)
* SOLR-15149: Better exception handling for LTR model creation errors (Alessandro Benedetti, Christine Poerschke)
Other Changes
---------------------

View File

@ -108,7 +108,7 @@ public abstract class LTRScoringModel implements Accountable {
SolrPluginUtils.invokeSetters(model, params.entrySet());
}
} catch (final Exception e) {
throw new ModelException("Model type does not exist " + className, e);
throw new ModelException("Model loading failed for " + className, e);
}
model.validate();
return model;

View File

@ -80,10 +80,10 @@ public class LinearModel extends LTRScoringModel {
public void setWeights(Object weights) {
@SuppressWarnings({"unchecked"})
final Map<String,Double> modelWeights = (Map<String,Double>) weights;
final Map<String,Number> modelWeights = (Map<String, Number>) weights;
for (int ii = 0; ii < features.size(); ++ii) {
final String key = features.get(ii).getName();
final Double val = modelWeights.get(key);
final Number val = modelWeights.get(key);
featureToWeight[ii] = (val == null ? null : val.floatValue());
}
}

View File

@ -294,11 +294,18 @@ public class ManagedModelStore extends ManagedResource implements ManagedResourc
return modelMap;
}
private static Feature lookupFeatureFromFeatureMap(Map<String,Object> featureMap,
FeatureStore featureStore) {
final String featureName = (String)featureMap.get(NAME_KEY);
return (featureName == null ? null
: featureStore.get(featureName));
private static Feature lookupFeatureFromFeatureMap(Map<String, Object> featureMap, FeatureStore featureStore)
{
final String featureName = (String) featureMap.get(NAME_KEY);
Feature extractedFromStore = featureName == null ? null : featureStore.get(featureName);
if (extractedFromStore == null) {
if (featureStore.getFeatures().isEmpty()) {
throw new ModelException("Missing or empty feature store: " + featureStore.getName());
} else {
throw new ModelException("Feature: " + featureName + " not found in store: " + featureStore.getName());
}
}
return extractedFromStore;
}
@SuppressWarnings("unchecked")

View File

@ -0,0 +1,19 @@
{
"class": "org.apache.solr.ltr.model.LinearModel",
"name": "6029760550880411648",
"store": "test",
"features": [
{
"name": "notExist1"
},
{
"name": "notExist2"
}
],
"params": {
"weights": {
"notExist1": 0.0000000000,
"notExist2": 0.1000000000
}
}
}

View File

@ -0,0 +1,46 @@
{
"class": "org.apache.solr.ltr.model.LinearModel",
"name": "6029760550880411648",
"store": "not_existent_store",
"features": [
{
"name": "title"
},
{
"name": "description"
},
{
"name": "keywords"
},
{
"name": "popularity",
"norm": {
"class": "org.apache.solr.ltr.norm.MinMaxNormalizer",
"params": {
"min": "0.0f",
"max": "10.0f"
}
}
},
{
"name": "text"
},
{
"name": "queryIntentPerson"
},
{
"name": "queryIntentCompany"
}
],
"params": {
"weights": {
"title": 0.0000000000,
"description": 0.1000000000,
"keywords": 0.2000000000,
"popularity": 0.3000000000,
"text": 0.4000000000,
"queryIntentPerson": 0.1231231,
"queryIntentCompany": 0.12121211
}
}
}

View File

@ -0,0 +1,39 @@
{
"class":"org.apache.solr.ltr.model.MultipleAdditiveTreesModel",
"name":"multipleadditivetreesmodel",
"store": "not_existent_store",
"features":[
{ "name": "matchedTitle"},
{ "name": "constantScoreToForceMultipleAdditiveTreesScoreAllDocs"}
],
"params":{
"trees": [
{
"weight" : "1f",
"root": {
"feature": "matchedTitle",
"threshold": "0.5f",
"left" : {
"value" : "-100"
},
"right": {
"feature" : "constantScoreToForceMultipleAdditiveTreesScoreAllDocs",
"threshold": "10.0f",
"left" : {
"value" : "50"
},
"right" : {
"value" : "75"
}
}
}
},
{
"weight" : "2f",
"root": {
"value" : "-10"
}
}
]
}
}

View File

@ -0,0 +1,38 @@
{
"class":"org.apache.solr.ltr.model.MultipleAdditiveTreesModel",
"name":"multipleadditivetreesmodel",
"features":[
{ "name": "notExist1"},
{ "name": "notExist2"}
],
"params":{
"trees": [
{
"weight" : "1f",
"root": {
"feature": "notExist1",
"threshold": "0.5f",
"left" : {
"value" : "-100"
},
"right": {
"feature" : "notExist2",
"threshold": "10.0f",
"left" : {
"value" : "50"
},
"right" : {
"value" : "75"
}
}
}
},
{
"weight" : "2f",
"root": {
"value" : "-10"
}
}
]
}
}

View File

@ -184,6 +184,29 @@ public class TestLinearModel extends TestRerankBase {
assertEquals(expectedException.toString(), ex.toString());
}
@Test
public void integerAndLongFeatureWeights_shouldCreateModel() {
final List<Feature> features = getFeatures(new String[]
{"constant1", "constant5"});
final List<Normalizer> norms =
new ArrayList<>(Collections.nCopies(features.size(),IdentityNormalizer.INSTANCE));
final Map<String,Object> weights = new HashMap<>();
weights.put("constant1", 100L);
weights.put("constant5", 1);
Map<String,Object> params = new HashMap<>();
params.put("weights", weights);
final LTRScoringModel ltrScoringModel = createLinearModel("test6",
features, norms, "test", fstore.getFeatures(),
params);
store.addModel(ltrScoringModel);
final LTRScoringModel m = store.getModel("test6");
assertEquals(ltrScoringModel, m);
}
@Test
public void emptyFeaturesTest() {
final ModelException expectedException =
@ -206,4 +229,28 @@ public class TestLinearModel extends TestRerankBase {
assertEquals(expectedException.toString(), ex.toString());
}
@Test
public void notExistentStore_shouldThrowMeaningFulException(){
final ModelException expectedException =
new ModelException("Feature Store not found: not_existent_store");
ModelException ex = expectThrows(ModelException.class, () -> {
createModelFromFiles("linear-model_notExistentStore.json",
"features-store-test-model.json");
});
assertEquals(expectedException.toString(), ex.toString());
}
@Test
public void notExistentFeature_shouldThrowMeaningFulException(){
final ModelException expectedException =
new ModelException("Feature:notExist1 not found in store: test");
ModelException ex = expectThrows(ModelException.class, () -> {
createModelFromFiles("linear-model_notExistentFeature.json",
"features-store-test-model.json");
});
assertEquals(expectedException.toString(), ex.toString());
}
}

View File

@ -225,4 +225,29 @@ public class TestMultipleAdditiveTreesModel extends TestRerankBase {
});
assertEquals(expectedException.toString(), ex.toString());
}
@Test
public void multipleAdditiveTreesTestMissingFeatureStore(){
final ModelException expectedException =
new ModelException("Feature Store not found: not_existent_store");
ModelException ex = expectThrows(ModelException.class, () -> {
createModelFromFiles("multipleadditivetreesmodel_notExistentStore.json",
"multipleadditivetreesmodel_features.json");
});
assertEquals(expectedException.toString(), ex.toString());
}
@Test
public void multipleAdditiveTreesTestUnknownFeature(){
final ModelException expectedException =
new ModelException("Feature:notExist1 not found in store: _DEFAULT_");
ModelException ex = expectThrows(ModelException.class, () -> {
createModelFromFiles("multipleadditivetreesmodel_unknownFeature.json",
"multipleadditivetreesmodel_features.json");
});
assertEquals(expectedException.toString(), ex.toString());
}
}