Score Modifier Best Practices
Score modifiers are a way to influence the ranking of search results. Score modifiers let you adjust the score of each document in the result set based on the value of a scalar field in the document (int
, float
, double
, long
).
Typical use cases include:
- Boosting documents based on some measure of "goodness" (e.g. popularity, previous sales, aesthetic score).
- Reducing duplication in search results for user generated content (e.g. users copy each other but copies score worse that originals).
Score Modifiers Under the Hood
Score modifiers are only applied to your limit
results. This means that if you have a limit
of 10 then the score modifiers will only be applied to the 10 results (changing their ranking).
This is important to know because changing your limit
later on can have a significant impact on the ranking of your results.
Using Score Modifiers
Marqo provides two modifications: "multiply_score_by"
and "add_to_score"
. For almost all use cases we recommend using "add_to_score"
as it has much more intuitive behavior.
Score modifiers as specified in search requests can be be different for each request:
mq.index("my-first-index").search(
q="T-shirts with a cartoon character",
score_modifiers={
"multiply_score_by": [{"field_name": "itemPopularity", "weight": 1.8}],
"add_to_score": [{"field_name": "sellerScore", "weight": 0.01}],
},
)
Best Practices with "add_to_score"
While variables in your documents which are used for score modifiers can be of any magnitude it is recommended to use values in the 0-1 range for simplicity.
For "add_to_score"
tje final score for a document (_score
in the response) is calculated as:
_score = _score + (field_value * weight)
Where _score
is the distance between the query vector and the document vector and field_value
is the value of the field used for score modification. For a document like:
{
"_id": "document1",
"sellerScore": 0.7,
"title": "this is a t-shirt"
}
With a search request like:
mq.index("my-first-index").search(
q="T-shirts with a cartoon character",
score_modifiers={"add_to_score": [{"field_name": "sellerScore", "weight": 0.01}]},
)
Would result in a score of 0.7 * 0.01
being added to the score of the document.
Deciding on an amount to add
The amount to add ("weight"
) will largerly depend on your data, the range of values in the field and your desired effect. Typically lower weights such as 0.01
are a sensible starting point as this does not overpower the original ranking entirely.
Best Practices with "multiply_score_by"
For "multiply_score_by"
the final score for a document (_score
in the response) is calculated as:
_score = _score * (field_value * weight)
Where _score
is the distance between the query vector and the document vector and field_value
is the value of the field used for score modification. For a document like:
{
"_id": "document1",
"itemPopularity": 0.7,
"title": "this is a t-shirt"
}
With a search request like:
mq.index("my-first-index").search(
q="T-shirts with a cartoon character",
score_modifiers={
"multiply_score_by": [{"field_name": "itemPopularity", "weight": 1.2}]
},
)
The score of the document would be multiplied by 0.7 * 1.2
. This might make sense in some use cases but can have unintuitive effects on the ranking of results if your data is not well understood.
Because documents with no value in the field will have this treated as a value of 0
this will mean that all these documents receive a score of 0
which can be undesirable.
Multiply score modifiers for positive weight and field values are not strictly increasing as this depends on which side of 1
the field value multiplied by the weight falls. This can make it harder to reason about the effect of the score modifier.
That being said, "multiply_score_by"
can work well in cases where your score modifier values are greater than 1
as for prenormalized-angular
vector spaces the original score is in the range [0, 1]
and so this will weight the modifier value by the similarity of the document to the query.
Score Modifiers in Scaled Deployments
If you are running Marqo with a scaled deployment where there are multiple shards for the index then the score modifiers will be applied to the results from each shard. This means that if you set limit=10
and have 3 shards then the score modifiers will be applied to all 30 results before the top 10 are selected from all shards.
This means that the impact of score modifiers can be very different for deployments with many shards compared to deployments with fewer shards. Keep this in mind when comparing smaller dev/test/staging configurations with larger production configurations.