Déployer et interroger un point de terminaison de mise à disposition de caractéristiques
Cet article montre comment déployer et interroger un point de terminaison de mise à disposition de caractéristiques dans un processus pas à pas. Cet article utilise le kit SDK Databricks. Certaines étapes peuvent également être effectuées à l’aide de l’API REST ou de l’IU Databricks. Elles incluent des références à la documentation de ces méthodes.
Dans cet exemple, vous disposez d’une table de villes avec leurs emplacements (latitude et longitude), et d’une application de recommandation qui prend en compte la distance actuelle de l’utilisateur par rapport à ces villes. Dans la mesure où la localisation de l’utilisateur change constamment, la distance entre l’utilisateur et chaque ville doit être calculée au moment de l’inférence. Ce tutoriel montre comment effectuer ces calculs avec une faible latence à l’aide des tables en ligne et du Feature Serving de Databricks. Pour obtenir l’ensemble complet des exemples de code, consultez l’exemple de notebook.
Étape 1. Créer la table source
La table source contient des valeurs de caractéristiques précalculées, et peut représenter n’importe quelle table Delta dans Unity Catalog ayant une clé primaire. Dans cet exemple, la table contient une liste de villes avec leur latitude et leur longitude. La clé primaire est destination_id
. Des exemples de données sont présentés ci-dessous.
name | destination_id (clé primaire) | latitude | longitude |
---|---|---|---|
Nashville, Tennessee | 0 | 36,162663 | -86,7816 |
Honolulu, Hawaï | 1 | 21,309885 | -157,85814 |
Las Vegas, Nevada | 2 | 36,171562 | -115,1391 |
New York, New York | 3 | 40,712776 | -74,005974 |
Étape 2. Créer une table en ligne
Une table en ligne est une copie en lecture seule d’une table Delta optimisée pour l’accès en ligne. Pour plus d’informations, consultez Utiliser des tables en ligne pour la mise à disposition de caractéristiques en temps réel.
Pour créer une table en ligne, vous pouvez utiliser l’IU Créer une table en ligne à l’aide de l’IU, l’API REST ou le kit SDK Databricks, comme dans l’exemple suivant :
from pprint import pprint
from databricks.sdk import WorkspaceClient
from databricks.sdk.service.catalog import *
import mlflow
workspace = WorkspaceClient()
# Create an online table
feature_table_name = f"main.on_demand_demo.location_features"
online_table_name=f"main.on_demand_demo.location_features_online"
spec = OnlineTableSpec(
primary_key_columns=["destination_id"],
source_table_full_name = feature_table_name,
run_triggered=OnlineTableSpecTriggeredSchedulingPolicy.from_dict({'triggered': 'true'}),
perform_full_copy=True)
# ignore "already exists" error
try:
online_table_pipeline = workspace.online_tables.create(name=online_table_name, spec=spec)
except Exception as e:
if "already exists" in str(e):
pass
else:
raise e
pprint(workspace.online_tables.get(online_table_name))
Étape 3. Créer une fonction dans Unity Catalog
Dans cet exemple, la fonction calcule la distance entre la destination (dont la localisation ne change pas), et l’utilisateur (dont la localisation change fréquemment, et n’est connue qu’au moment de l’inférence).
# Define the function. This function calculates the distance between two locations.
function_name = f"main.on_demand_demo.distance"
spark.sql(f"""
CREATE OR REPLACE FUNCTION {function_name}(latitude DOUBLE, longitude DOUBLE, user_latitude DOUBLE, user_longitude DOUBLE)
RETURNS DOUBLE
LANGUAGE PYTHON AS
$$
import math
lat1 = math.radians(latitude)
lon1 = math.radians(longitude)
lat2 = math.radians(user_latitude)
lon2 = math.radians(user_longitude)
# Earth's radius in kilometers
radius = 6371
# Haversine formula
dlat = lat2 - lat1
dlon = lon2 - lon1
a = math.sin(dlat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2)**2
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
distance = radius * c
return distance
$$""")
Étape 4. Créer une spécification de caractéristiques dans Unity Catalog
La spécification de caractéristiques permet de spécifier les caractéristiques mises à disposition par le point de terminaison ainsi que leurs clés de recherche. Elle permet également de spécifier toutes les fonctions nécessaires à appliquer aux caractéristiques récupérées avec leurs liaisons. Pour plus d’informations, consultez Créer un FeatureSpec.
from databricks.feature_engineering import FeatureLookup, FeatureFunction, FeatureEngineeringClient
fe = FeatureEngineeringClient()
features=[
FeatureLookup(
table_name=feature_table_name,
lookup_key="destination_id"
),
FeatureFunction(
udf_name=function_name,
output_name="distance",
input_bindings={
"latitude": "latitude",
"longitude": "longitude",
"user_latitude": "user_latitude",
"user_longitude": "user_longitude"
},
),
]
feature_spec_name = f"main.on_demand_demo.travel_spec"
# The following code ignores errors raised if a feature_spec with the specified name already exists.
try:
fe.create_feature_spec(name=feature_spec_name, features=features, exclude_columns=None)
except Exception as e:
if "already exists" in str(e):
pass
else:
raise e
Étape 5. Créer un point de terminaison de mise à disposition de caractéristiques
Pour créer un point de terminaison de mise à disposition de caractéristiques, vous pouvez utiliser l’IU Créer un point de terminaison, l’API REST ou le kit SDK Databricks, indiqué ici.
Le point de terminaison de mise à disposition de caractéristiques accepte en tant que paramètre le feature_spec
que vous avez créé à l’étape 4.
from databricks.sdk import WorkspaceClient
from databricks.sdk.service.serving import EndpointCoreConfigInput, ServedEntityInput
# Create endpoint
endpoint_name = "fse-location"
try:
status = workspace.serving_endpoints.create_and_wait(
name=endpoint_name,
config = EndpointCoreConfigInput(
served_entities=[
ServedEntityInput(
entity_name=feature_spec_name,
scale_to_zero_enabled=True,
workload_size="Small"
)
]
)
)
print(status)
# Get the status of the endpoint
status = workspace.serving_endpoints.get(name=endpoint_name)
print(status)
Étape 6. Interroger le point de terminaison de mise à disposition de caractéristiques
Quand vous interrogez le point de terminaison, vous fournissez la clé primaire et éventuellement les données de contexte utilisées par la fonction. Dans cet exemple, la fonction accepte en entrée la localisation actuelle de l’utilisateur (latitude et longitude). Dans la mesure où la localisation de l’utilisateur change constamment, elle doit être fournie à la fonction au moment de l’inférence, en tant que caractéristique de contexte.
Vous pouvez également interroger le point de terminaison en utilisant l’IU Interroger un point de terminaison à l’aide de l’IU ou l’API REST.
Pour des raisons de simplicité, cet exemple calcule uniquement la distance entre deux villes. Un scénario plus réaliste peut consister à calculer la distance séparant l’utilisateur de chaque localisation présente dans la table de caractéristiques pour déterminer les villes à recommander.
import mlflow.deployments
client = mlflow.deployments.get_deploy_client("databricks")
response = client.predict(
endpoint=endpoint_name,
inputs={
"dataframe_records": [
{"destination_id": 1, "user_latitude": 37, "user_longitude": -122},
{"destination_id": 2, "user_latitude": 37, "user_longitude": -122},
]
},
)
pprint(response)
Exemple de notebook
Consultez ce notebook pour une illustration complète des étapes :
Exemple de notebook Feature Serving avec des tables en ligne
Informations supplémentaires
Pour plus d’informations sur l’utilisation de l’API Python d’ingénierie de caractéristiques, consultez la documentation de référence.