Condividi tramite


Distribuire ed eseguire query su un endpoint di gestione delle funzionalità

Questo articolo mostra come distribuire ed eseguire query su un endpoint di gestione delle funzionalità in un processo dettagliato. Questo articolo utilizza Databricks SDK. Alcuni passaggi possono essere completati anche usando l'API REST o l'interfaccia utente di Databricks e comprendono riferimenti alla documentazione per quei metodi.

In questo esempio è presente una tabella delle città con le relative posizioni (latitudine e longitudine) e un'app di raccomandazione che tiene conto della distanza corrente dell'utente da quelle città. Poiché la posizione dell'utente cambia costantemente, la distanza tra l'utente e ogni città deve essere calcolata al momento dell'inferenza. Questa esercitazione illustra come eseguire questi calcoli con bassa latenza utilizzando le tabelle online di Databricks e databricks Feature Serving. Per il set completo di codice di esempio, si veda il notebook di esempio.

Passaggio 1: Creare una tabella di origine

La tabella di origine contiene valori di funzionalità precompilate e può essere una qualsiasi tabella Delta nel catalogo Unity con una chiave primaria. In questo esempio la tabella contiene un elenco di città con la rispettiva latitudine e longitudine. la chiave primaria è destination_id. Di seguito sono riportati i dati di esempio.

name destination_id (pk) latitude longitude
Nashville, Tennessee 0 36.162663 -86.7816
Honolulu, Hawaii 1 21.309885 -157.85814
Las Vegas, Nevada 2 36.171562 -115.1391
New York, New York 3 40.712776 -74.005974

Passaggio 2. Creare una tabella online

Una tabella online è una copia di sola lettura di una tabella Delta, ottimizzata per l'accesso online. Per altre informazioni, si veda Usare tabelle online per la gestione delle funzionalità in tempo reale.

Per creare una tabella online, è possibile usare l'interfaccia utente Creare una tabella online usando l'interfaccia utente, l'API REST o Databricks SDK, come nell'esempio seguente:

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))

Passaggio 3. Creare una funzione in Unity Catalog

In questo esempio, la funzione calcola la distanza tra la destinazione (la cui posizione non cambia) e l'utente (la cui posizione cambia frequentemente e non è nota fino al momento dell'inferenza).

# 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
$$""")

Passaggio 4. Creare una specifica di funzionalità in Unity Catalog

La specifica di funzionalità definisce le funzionalità che l'endpoint gestisce e le relative chiavi di ricerca. Specifica inoltre le funzioni necessarie da applicare alle funzionalità recuperate con le relative associazioni. Per informazioni dettagliate, si veda Creare una specifica di funzionalità.

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

Passaggio 5. Creare un endpoint di gestione delle funzionalità

Per creare un endpoint di gestione delle funzionalità, è possibile usare l'interfaccia utente Creare un endpoint, l'API REST o Databricks SDK, come illustrato di seguito.

L'endpoint di gestione delle funzionalità considera come parametro l'oggetto feature_spec creato nel passaggio 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)

Passaggio 6. Eseguire query sull'endpoint di gestione delle funzionalità

Quando si esegue una query sull'endpoint, si specifica la chiave primaria e, facoltativamente, anche i dati di contesto usati dalla funzione. In questo esempio, la funzione considera come input la posizione corrente dell'utente (latitudine e longitudine). Poiché la posizione dell'utente cambia costantemente, deve essere fornita alla funzione in fase di inferenza come funzionalità di contesto.

È anche possibile eseguire query sull'endpoint usando l'interfaccia utente Eseguire query su un endpoint usando l'interfaccia utente o l'API REST.

Per semplicità, questo esempio calcola solo la distanza tra due città. In uno scenario più realistico potrebbe calcolare la distanza dell'utente da ogni posizione nella tabella delle funzionalità per determinare quali città consigliare.

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)

Notebook di esempio

Per una illustrazione completa dei passaggi, si veda questo notebook:

Notebook di esempio di Funzionalità di gestione delle funzionalità con tabelle online

Ottenere il notebook

Informazioni aggiuntive

Per informazioni dettagliate sull'uso dell'API Python di progettazione delle funzionalità, si veda la documentazione di riferimento.