Ranking Signals Quickstart
Objective’s AI-native search ranks search results by a relevance score. Ranking Signals enable you to adjust the score, and therefore the final ranking of search results at query-time through the new ranking_expr
query parameter.
The most common use case for Ranking Signals is for query-time “boosting” or “de-boosting”. Boosting increases the rank of results based on specific criteria. Boosting is commonly used for personalization based on user preferences or other contextual information that depends on external factors outside of the core, intrinsic relevancy of your search system.
In this Quickstart, we'll walk through a common scenario in e-commerce. We'll use Ranking Signals to promote products within search results that a fictional user would be more likely to purchase.
We'll follow these steps:
- Add data: Add e-commerce data to the Object Store.
- Create Index: Build an Index on the data.
- Search the Index: Search the index for "t-shirt".
- Compare results: Add a Ranking Expression to the "t-shirt" search.
Setup
Begin by obtaining an API key and installing the SDK:
To get an API key, sign up.
pip3 install --upgrade "objective-sdk==5.6.0" requests
Adding Data
Next we will add Objects to the Object Store. The code below will download 10,000 example e-commerce products and upsert them to the Object Store. In this example we are building an e-commerce search platform:
import json
import requests
from objective import Objective
client = Objective(api_key='YOUR_API_KEY')
data = json.loads(requests.get("https://d11p8vtjlacpl4.cloudfront.net/demos/ecommerce/hm-10k.json").text)
batch_size = 100
for i in range(0, len(data), batch_size):
batch = data[i:i+batch_size]
client.objects.batch(
operations=[{"method": "PUT", "object_id": str(obj.get("article_id")), "object": obj} for obj in batch]
)
print(f"\rUpserted {i+batch_size} objects...", end="", flush=True)
print("\nUpsert complete!")
Building an Index
Build a multimodal
index out of the Objects pushed to the API with searchable
and filterable
fields:
import time
from objective import Objective
from objective.types.index_create_params import Configuration, ConfigurationIndexType, ConfigurationFields
client = Objective(api_key='YOUR_API_KEY')
index = client.indexes.create(
configuration=Configuration(
index_type=ConfigurationIndexType(
name="multimodal",
),
fields=ConfigurationFields(
searchable={
"allow": [
"prod_name",
"colour_group_name",
"detail_desc",
"department_name",
"garment_group_name",
"index_group_name",
"perceived_colour_master_name",
"perceived_colour_value_name",
"product_type_name",
"product_group_name",
"section_name"
],
},
crawlable={
"allow":[
"image_url"
]
},
filterable={
"allow": [
"department_name",
"price"
]
},
types={
"department_name": "string",
"price": "int",
},
)
),
)
while not client.indexes.status(index_id=index.id).status.ready:
time.sleep(1)
print(f"Index {index.id} is ready for queries!")
Create a Function for Displaying Results
Create a function called display_results
. We'll use this to help visualize search results as we add ranking expressions.
def display_results(results):
for obj in results['results']:
from IPython.display import Image, display, HTML
data = obj["object"]
image_html = f'<div style="display: flex; align-items: center;">' \
f'<div style="flex: 1;"><img src="{data["image_url"]}" height="120" width="85"></div>' \
f'<div style="flex: 2;">' \
f'<p>ID: {obj["id"]}</p>' \
f'<p>Product Name: {data["prod_name"]}</p>' \
f'<p>{data["index_name"]} » {data["product_group_name"]} » {data["product_type_name"]}</p>' \
f'<p>Color: {data["colour_group_name"]} - {data["colour_group_code"]}</p>'\
f'<p>Rating: {data["rating"]}'\
f'</div></div>'
display(HTML(image_html))
Query and Display Results for "t-shirt"
Let's start with a query for "t-shirt". After executing this search, we will add a ranking expression to it and then run it again in order to compare the 2 result sets.
results = client.indexes.search(
index_id=index.id,
query="t-shirt",
object_fields="*"
)
display_results(results.to_dict())
Create a Ranking Expression to Boost Menswear
Let's assume that a user is searching the product catalog and that the user is a male who prefers shopping in the Menswear
department. How can we express this with Ranking Signals?
In our data we have a field called field called index_group_name
and it contains values like Menswear
and Ladieswear
. Let's construct a ranking expression that gives a 2% boost to all products in the Menswear
department.
Why only 2%? - When using Ranking Signals, it is important to consider their impact on overall relevancy. For example. If the boost for Menswear
is too strong, a search result for "ladies t-shirt"
would be full of Menswear
.
Let's rerun the t-shirt
search with the 2% boost on Menswear
. Then we'll examine the ranking expression in more detail.
ranking_expr = 'uncalibrated_relevance * if(object.index_group_name == "Menswear", 1.02, 1)'
results = client.indexes.search(
index_id=index.id,
query="t-shirt",
object_fields="*",
ranking_expr=ranking_expr
)
display_results(results.to_dict())
Let's take a closer look at the ranking expression:
uncalibrated_relevance * if(object.index_group_name == "Menswear", 1.02, 1)
uncalibrated_relevance
is a primitive in Ranking Signals that represents the relevance score computed by the index before any ranking expression is applied. A ranking expression must return a new score.
The if(object.index_group_name == "Menswear", 1.02, 1)
part of the expression is saying if the index_group_name
equals Menswear
, return 1.02
, else return 1
.
Finally, we are multiplying the result of the if
statement and the uncalibrated_relevance
.
To see more examples and a full list of the available functions in Ranking Expressions, see our docs.
Add Another Signal
Our objects also have a rating
attribute with values from 1 to 5. Let's extend our ranking signal
so that we give a 2% boost to any objects having a rating equal to or greater than 4. To accomplis
this, we'll follow the same pattern as our Menswear
boost but we will add it to the existing expression
by multiplying them together. This means that any object that is in the Menswear
category with a rating
of over 4 or more will receive a 4%
boost.
ranking_expr = 'uncalibrated_relevance * (if(object.index_group_name == "Menswear", 1.02, 1) * if(object.rating >= 4, 1.02, 1))'
results = client.indexes.search(
index_id=index.id,
query="t-shirt",
object_fields="*",
ranking_expr=ranking_expr
)
display_results(results.to_dict())
The top 10 results are now only populated with products that have a rating of 4 or better!
Congratulations! 🎉 You've just successfully learned how to use Ranking Signals to promote results based on extrinsic factors. Use Ranking Signals when you want to personalize or adjust search results based contextual data.
To learn more about Ranking Signals, see our docs.