Partager via


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

Obtenir le notebook

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.