Implantar e consultar um ponto de extremidade de serviço de recurso

Este artigo mostra como implantar e consultar um ponto de extremidade de serviço de recurso em um processo passo a passo. Este artigo usa o SDK do Databricks. Algumas etapas também podem ser concluídas usando a API REST ou a interface do usuário do Databricks e incluem referências à documentação desses métodos.

Neste exemplo, você tem uma tabela de cidades com suas localizações (latitude e longitude) e um aplicativo de recomendação que leva em conta a distância atual do usuário dessas cidades. Como a localização do usuário muda constantemente, a distância entre o usuário e cada cidade deve ser calculada no momento da inferência. Este tutorial ilustra como executar esses cálculos com baixa latência usando Databricks Online Tables e Databricks Feature Serving. Para obter o conjunto completo de código de exemplo, consulte o bloco de anotações de exemplo.

Passo 1. Criar a tabela de origem

A tabela de origem contém valores de recursos pré-calculados e pode ser qualquer tabela Delta no Unity Catalog com uma chave primária. Neste exemplo, a tabela contém uma lista de cidades com sua latitude e longitude. A chave primária é destination_id. Os dados de exemplo são mostrados abaixo.

nome destination_id (pk) latitude longitude
Nashville, Tennessee 0 36.162663 -86.7816
Honolulu, Havai 1 21.309885 -157.85814
Las Vegas, Nevada 2 36.171562 -115.1391
Nova Iorque, Nova Iorque 3 40.712776 -74.005974

Passo 2. Criar uma tabela online

Uma tabela online é uma cópia somente leitura de uma tabela delta otimizada para acesso online. Para obter mais informações, consulte Usar tabelas online para serviço de recursos em tempo real.

Para criar uma tabela online, você pode usar a interface do usuário Criar uma tabela online usando a interface do usuário, a API REST ou o SDK do Databricks, como no exemplo a seguir:

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

Passo 3. Criar uma função no Catálogo Unity

Neste exemplo, a função calcula a distância entre o destino (cuja localização não muda) e o usuário (cuja localização muda frequentemente e não é conhecida até o momento da inferência).

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

Passo 4. Criar uma especificação de recurso no Catálogo Unity

A especificação do recurso especifica os recursos que o ponto de extremidade serve e suas chaves de pesquisa. Ele também especifica todas as funções necessárias a serem aplicadas aos recursos recuperados com suas associações. Para obter detalhes, consulte Criar um 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

Passo 5. Criar um ponto de extremidade de serviço de recurso

Para criar um ponto de extremidade de serviço de recurso, você pode usar a interface do usuário Criar um ponto de extremidade, a API REST ou o SDK do Databricks, mostrado aqui.

O ponto de extremidade de serviço de recurso usa o feature_spec que você criou na Etapa 4 como um parâmetro.

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)

Passo 6. Consultar o ponto de extremidade de serviço de recurso

Ao consultar o ponto de extremidade, você fornece a chave primária e, opcionalmente, todos os dados de contexto usados pela função. Neste exemplo, a função toma como entrada a localização atual do usuário (latitude e longitude). Como a localização do usuário está em constante mudança, ela deve ser fornecida à função no momento da inferência como um recurso de contexto.

Você também pode consultar o ponto de extremidade usando a interface do usuário Consultar um ponto de extremidade usando a interface do usuário ou a API REST.

Para simplificar, este exemplo calcula apenas a distância a duas cidades. Um cenário mais realista pode calcular a distância do usuário de cada local na tabela de recursos para determinar quais cidades recomendar.

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)

Exemplo de bloco de notas

Consulte este bloco de notas para obter uma ilustração completa dos passos:

Recurso Servindo bloco de anotações de exemplo com tabelas online

Obter o bloco de notas

Informações adicionais

Para obter detalhes sobre como usar a API Python de engenharia de recursos, consulte a documentação de referência.