Webhooks de registro de modelo MLflow em Databricks

Visualização

Este recurso está em visualização pública.

Webhooks permitem que você escute eventos de Model Registry para que suas integrações possam acionar ações automaticamente. Você pode usar webhooks para automatizar e integrar seu pipeline machine learning com ferramentas CI/CD existentes e fluxo de trabalho. Por exemplo, você pode acionar builds de CI quando uma nova versão de modelo é criada ou notificar os membros de sua equipe por meio do Slack sempre que uma transição de modelo para produção é solicitada.

Os webhooks estão disponíveis por meio da API REST do Databricks ou do cliente Python databricks-registry-webhooks no PyPI.

Observação

Os webhooks não estão disponíveis quando o senhor usa Models no Unity Catalog. Para obter uma alternativa, consulte Posso usar solicitações de transição de estágio ou acionar webhooks em eventos?

Eventos de webhook

Você pode especificar um webhook para ser acionado em um ou mais destes eventos:

  • MODEL_VERSION_CREATED: Uma nova versão de modelo foi criada para o modelo associado.

  • MODEL_VERSION_TRANSITIONED_STAGE: O estágio de uma versão do modelo foi alterado.

  • TRANSITION_REQUEST_CREATED: um usuário solicitou que o estágio de uma versão do modelo fosse transferido.

  • COMMENT_CREATED: Um usuário escreveu um comentário em um modelo registrado.

  • REGISTERED_MODEL_CREATED: Um novo modelo registrado foi criado. Esse tipo de evento só pode ser especificado para um webhook em todo o registro, que pode ser criado não especificando um nome de modelo na solicitação de criação.

  • MODEL_VERSION_TAG_SET: um usuário definiu tags na versão do modelo.

  • MODEL_VERSION_TRANSITIONED_TO_STAGING: uma versão de modelo foi transferida para teste.

  • MODEL_VERSION_TRANSITIONED_TO_PRODUCTION: uma versão de modelo foi transferida para produção.

  • MODEL_VERSION_TRANSITIONED_TO_ARCHIVED: uma versão de modelo foi arquivada.

  • TRANSITION_REQUEST_TO_STAGING_CREATED: um usuário solicitou que uma versão de modelo fosse transferida para teste.

  • TRANSITION_REQUEST_TO_PRODUCTION_CREATED: um usuário solicitou que uma versão de modelo fosse transferida para produção.

  • TRANSITION_REQUEST_TO_ARCHIVED_CREATED: um usuário solicitou que uma versão de modelo fosse arquivada.

Tipos de webhooks

Existem dois tipos de webhooks com base em seus destinos de acionamento:

  • Webhooks com endpoints HTTP (webhooks de registro HTTP): envie gatilhos para um endpoint HTTP.

  • Webhooks com gatilhos Job (webhooks de registro de Job ): acione um Job em um workspace Databricks. Se a lista de permissões de IP estiver habilitada no workspace do Job, você deverá permitir os IPs do workspace do registro de modelo. Consulte lista de permissões de IP para webhooks de registro Job para obter mais informações.

Existem também dois tipos de webhooks com base em seu escopo, com diferentes requisitos de controle de acesso:

  • Webhooks específicos do modelo: O webhook se aplica a um modelo específico registrado. O senhor deve ter permissões de gerenciar o CAN no modelo registrado para criar, modificar, excluir ou testar webhooks específicos do modelo.

  • Webhooks de todo o registro: o webhook é acionado por eventos em qualquer modelo registrado no workspace, incluindo a criação de um novo modelo registrado. Para criar um webhook em todo o registro, omita o campo model_name na criação. Você deve ter permissões de administrador workspace para criar, modificar, excluir ou testar webhooks em todo o registro.

Carga útil do webhook

Cada acionador de evento tem campos mínimos incluídos na carga da solicitação de saída para o endpoint do webhook.

  • Informações confidenciais, como localização do caminho do artefato, são excluídas. Usuários e principais com ACLs apropriados podem usar o cliente ou APIs REST para query o Model Registry para esta informação.

  • As cargas não são criptografadas. Consulte Segurança para obter informações sobre como validar que Databricks é a origem do webhook.

  • O campo text facilita a integração do Slack. Para enviar uma mensagem do Slack, forneça um endpoint de webhook do Slack como o URL do webhook.

Carga útil do webhook de registro Job

A carga de um webhook de registro Job depende do tipo de Job e é enviada para o endpoint jobs/run-now no workspace de destino.

Jobde tarefa única

Job de tarefa única tem uma das três cargas úteis com base no tipo de tarefa.

Job de Notebook e Python wheel

Job de Notebook e Python wheel têm uma carga útil JSON com um dicionário de parâmetros que contém um campo event_message.

{
  "job_id": 1234567890,
  "notebook_params": {
    "event_message": "<Webhook Payload>"
  }
}
Jobde envio de Python, JAR e Spark

Python, JAR e Spark submit Job têm uma carga JSON com uma lista de parâmetros.

{
  "job_id": 1234567890,
  "python_params": ["<Webhook Payload>"]
}
Todos os outros Job

Todos os outros tipos de Job têm uma carga JSON sem parâmetros.

{
  "job_id": 1234567890
}

Jobmultitarefa

Job multitarefa tem uma carga útil JSON com todos os parâmetros preenchidos para account diferentes tipos de tarefa.

{
  "job_id": 1234567890,
  "notebook_params": {
    "event_message": "<Webhook Payload>"
  },
  "python_named_params": {
    "event_message": "<Webhook Payload>"
  },
  "jar_params": ["<Webhook Payload>"],
  "python_params": ["<Webhook Payload>"],
  "spark_submit_params": ["<Webhook Payload>"]
}

Exemplo de cargas úteis

evento: MODEL_VERSION_TRANSITIONED_STAGE

Resposta

POST
/your/endpoint/for/event/model-versions/stage-transition
--data {
  "event": "MODEL_VERSION_TRANSITIONED_STAGE",
  "webhook_id": "c5596721253c4b429368cf6f4341b88a",
  "event_timestamp": 1589859029343,
  "model_name": "Airline_Delay_SparkML",
  "version": "8",
  "to_stage": "Production",
  "from_stage": "None",
  "text": "Registered model 'someModel' version 8 transitioned from None to Production."
}

evento: MODEL_VERSION_TAG_SET

Resposta

POST
/your/endpoint/for/event/model-versions/tag-set
--data {
  "event": "MODEL_VERSION_TAG_SET",
  "webhook_id": "8d7fc634e624474f9bbfde960fdf354c",
  "event_timestamp": 1589859029343,
  "model_name": "Airline_Delay_SparkML",
  "version": "8",
  "tags": [{"key":"key1","value":"value1"},{"key":"key2","value":"value2"}],
  "text": "example@yourdomain.com set version tag(s) 'key1' => 'value1', 'key2' => 'value2' for registered model 'someModel' version 8."
}

evento: COMMENT_CREATED

Resposta

POST
/your/endpoint/for/event/comments/create
--data {
  "event": "COMMENT_CREATED",
  "webhook_id": "8d7fc634e624474f9bbfde960fdf354c",
  "event_timestamp": 1589859029343,
  "model_name": "Airline_Delay_SparkML",
  "version": "8",
  "comment": "Raw text content of the comment",
  "text": "A user commented on registered model 'someModel' version 8."
}

Segurança

Por segurança, o Databricks inclui o X-Databricks-Signature no compute do cabeçalho da carga útil e a key secreta compartilhada associada ao webhook usando o algoritmo HMAC com SHA-256.

Além disso, você pode incluir um cabeçalho de autorização padrão na solicitação de saída especificando um no HttpUrlSpec do webhook.

verificação do cliente

Se um segredo compartilhado for definido, o destinatário da carga útil deverá verificar a origem da solicitação HTTP usando o segredo compartilhado para codificar HMAC a carga útil e, em seguida, comparar o valor codificado com o X-Databricks-Signature do cabeçalho. Isso é particularmente importante se a validação do certificado SSL estiver desativada (ou seja, se o campo enable_ssl_verification estiver definido como false).

Observação

enable_ssl_verification é true por default. Para certificados autoassinados, este campo deve ser false e o servidor de destino deve desabilitar a validação do certificado.

Para fins de segurança, o Databricks recomenda que você execute a validação secreta com a parte codificada em HMAC da carga útil. Se você desativar a validação do nome do host, aumentará o risco de uma solicitação ser roteada de forma maliciosa para um host indesejado.

import hmac
import hashlib
import json

secret = shared_secret.encode('utf-8')
signature_key = 'X-Databricks-Signature'

def validate_signature(request):
  if not request.headers.has_key(signature_key):
    raise Exception('No X-Signature. Webhook not be trusted.')

  x_sig = request.headers.get(signature_key)
  body = request.body.encode('utf-8')
  h = hmac.new(secret, body, hashlib.sha256)
  computed_sig = h.hexdigest()

  if not hmac.compare_digest(computed_sig, x_sig.encode()):
    raise Exception('X-Signature mismatch. Webhook not be trusted.')

Cabeçalho de autorização para webhooks de registro HTTP

Se um cabeçalho de autorização for definido, os clientes devem verificar a origem da solicitação HTTP verificando os tokens do portador ou as credenciais de autorização no cabeçalho de autorização.

Lista de permissões de IP para webhooks de registro Job

Para usar um webhook que aciona a execução Job em um espaço de trabalho diferente que tenha a lista de permissões de IP habilitada, você deve colocar na lista de permissões o IP NAT da região onde o webhook está localizado para aceitar solicitações recebidas.

Se o webhook e o Job estiverem no mesmo workspace, você não precisará adicionar nenhum IP à sua lista de permissões.

Entre em contato com a equipe da sua account para identificar os IPs que você precisa incluir na lista de permissões.

Log de auditoria

Se o log de auditoria estiver habilitado para seu workspace, os seguintes eventos serão incluídos nos logs de auditoria:

  • Criar webhook

  • Atualizar webhook

  • Listar webhook

  • Excluir webhook

  • webhook de teste

  • Gatilho de webhook

Log de auditoria de gatilho de webhook

Para webhooks com endpoints HTTP, a solicitação HTTP enviada para a URL especificada para o webhook junto com a URL e os valores enable_ssl_verification são logs.

Para webhooks com acionadores Job , os valores job_id e workspace_url são logs.

Exemplos

Esta seção inclui:

Exemplo de webhook de registro HTTP fluxo de trabalho

1. Crie um webhook

Quando um endpoint HTTPS está pronto para receber a solicitação de evento de webhook, você pode criar um webhook usando a API REST Databricks webhooks. Por exemplo, o URL do webhook pode apontar para o Slack para postar mensagens em um canal.

$ curl -X POST -H "Authorization: Bearer <access-token>" -d \
'{"model_name": "<model-name>",
  "events": ["MODEL_VERSION_CREATED"],
  "description": "Slack notifications",
  "status": "TEST_MODE",
  "http_url_spec": {
    "url": "https://hooks.slack.com/services/...",
    "secret": "anyRandomString"
    "authorization": "Bearer AbcdEfg1294"}}' https://<databricks-instance>/api/2.0/mlflow/registry-webhooks/create
from databricks_registry_webhooks import RegistryWebhooksClient, HttpUrlSpec

http_url_spec = HttpUrlSpec(
  url="https://hooks.slack.com/services/...",
  secret="secret_string",
  authorization="Bearer AbcdEfg1294"
)
http_webhook = RegistryWebhooksClient().create_webhook(
  model_name="<model-name>",
  events=["MODEL_VERSION_CREATED"],
  http_url_spec=http_url_spec,
  description="Slack notifications",
  status="TEST_MODE"
)

Resposta

{"webhook": {
   "id":"1234567890",
   "creation_timestamp":1571440826026,
   "last_updated_timestamp":1582768296651,
   "status":"TEST_MODE",
   "events":["MODEL_VERSION_CREATED"],
   "http_url_spec": {
     "url": "https://hooks.slack.com/services/...",
     "enable_ssl_verification": True
}}}

Você também pode criar um webhook de registro HTTP com o provedor Databricks Terraform e databricks_mlflow_webhook.

2. Teste o webhook

O webhook anterior foi criado em TEST_MODE, portanto, um evento simulado pode ser acionado para enviar uma solicitação ao URL especificado. No entanto, o webhook não é acionado em um evento real. O endpoint de teste retorna o código de status recebido e o corpo da URL especificada.

$ curl -X POST -H "Authorization: Bearer <access-token>" -d \
'{"id": "1234567890"}' \
https://<databricks-instance>/api/2.0/mlflow/registry-webhooks/test
from databricks_registry_webhooks import RegistryWebhooksClient

http_webhook = RegistryWebhooksClient().test_webhook(
  id="1234567890"
)

Resposta

{
 "status":200,
 "body":"OK"
}

3. Atualize o webhook para o status ativo

Para ativar o webhook para eventos reais, defina seu status como ACTIVE por meio de uma chamada de atualização, que também pode ser usada para alterar qualquer uma de suas outras propriedades.

$ curl -X PATCH -H "Authorization: Bearer <access-token>" -d \
'{"id": "1234567890", "status": "ACTIVE"}' \
https://<databricks-instance>/api/2.0/mlflow/registry-webhooks/update
from databricks_registry_webhooks import RegistryWebhooksClient

http_webhook = RegistryWebhooksClient().update_webhook(
  id="1234567890",
  status="ACTIVE"
)

Resposta

{"webhook": {
   "id":"1234567890",
   "creation_timestamp":1571440826026,
   "last_updated_timestamp":1582768296651,
   "status": "ACTIVE",
   "events":["MODEL_VERSION_CREATED"],
   "http_url_spec": {
     "url": "https://hooks.slack.com/services/...",
     "enable_ssl_verification": True
}}}

4. Exclua o webhook

Para desativar o webhook, defina seu status como DISABLED (usando um comando de atualização semelhante ao acima) ou exclua-o.

$ curl -X DELETE -H "Authorization: Bearer <access-token>" -d \
'{"id": "1234567890"}' \
https://<databricks-instance>/api/2.0/mlflow/registry-webhooks/delete
from databricks_registry_webhooks import RegistryWebhooksClient

http_webhook = RegistryWebhooksClient().delete_webhook(
  id="1234567890"
)

Resposta

{}

Exemplo de webhook de registro Job fluxo de trabalho

O fluxo de trabalho para gerenciar webhooks de registro Job é semelhante aos webhooks de registro HTTP, com a única diferença sendo o campo job_spec que substitui o campo http_url_spec.

Com webhooks, você pode acionar Job no mesmo workspace ou em um workspace diferente. A workspace é especificada usando o parâmetro opcional workspace_url. Se nenhum workspace_url estiver presente, o comportamento default é acionar um Job no mesmo workspace que o webhook.

Requisitos

  • Um Job existente.

  • Um access tokenpessoal. Observe que access token não está incluído no objeto webhook retornado pelas APIs.

Observação

Como prática recomendada de segurança, ao autenticar com ferramentas, sistemas, scripts e aplicativos automatizados, a Databricks recomenda que você use access token pessoal pertencente à entidade de serviço em vez de usuários do espaço de trabalho. Para criar tokens para entidades de serviço, consulte gerenciar tokens para uma entidade de serviço.

Criar um webhook de registro Job

$ curl -X POST -H "Authorization: Bearer <access-token>" -d \ '{"model_name": "<model-name>",
  "events": ["TRANSITION_REQUEST_CREATED"],
  "description": "Job webhook trigger",
  "status": "TEST_MODE",
  "job_spec": {
    "job_id": "1",
    "workspace_url": "https://my-databricks-workspace.com",
    "access_token": "dapi12345..."}}'
https://<databricks-instance>/api/2.0/mlflow/registry-webhooks/create
from databricks_registry_webhooks import RegistryWebhooksClient, JobSpec

job_spec = JobSpec(
  job_id="1",
  workspace_url="https://my-databricks-workspace.com",
  access_token="dapi12345..."
)
job_webhook = RegistryWebhooksClient().create_webhook(
  model_name="<model-name>",
  events=["TRANSITION_REQUEST_CREATED"],
  job_spec=job_spec,
  description="Job webhook trigger",
  status="TEST_MODE"
)

Resposta

{"webhook": {
   "id":"1234567891",
   "creation_timestamp":1591440826026,
   "last_updated_timestamp":1591440826026,
   "status":"TEST_MODE",
   "events":["TRANSITION_REQUEST_CREATED"],
   "job_spec": {
     "job_id": "1",
     "workspace_url": "https://my-databricks-workspace.com"
}}}

Você também pode criar um webhook de registro Job com o provedor Databricks Terraform e databricks_mlflow_webhook.

Exemplo de webhooks de registro de lista

$ curl -X GET -H "Authorization: Bearer <access-token>" -d \ '{"model_name": "<model-name>"}'
https://<databricks-instance>/api/2.0/mlflow/registry-webhooks/list
from databricks_registry_webhooks import RegistryWebhooksClient

webhooks_list = RegistryWebhooksClient().list_webhooks(model_name="<model-name>")

Resposta

{"webhooks": [{
   "id":"1234567890",
   "creation_timestamp":1571440826026,
   "last_updated_timestamp":1582768296651,
   "status": "ACTIVE",
   "events":["MODEL_VERSION_CREATED"],
   "http_url_spec": {
     "url": "https://hooks.slack.com/services/...",
     "enable_ssl_verification": True
}},
{
   "id":"1234567891",
   "creation_timestamp":1591440826026,
   "last_updated_timestamp":1591440826026,
   "status":"TEST_MODE",
   "events":["TRANSITION_REQUEST_CREATED"],
   "job_spec": {
     "job_id": "1",
     "workspace_url": "https://my-databricks-workspace.com"
}}]}

Notebook

Webhooks de MLflow Model Registry Exemplo de API REST Notebook

Abra o bloco de anotações em outra guia

Webhooks de MLflow Model Registry exemplo de cliente Python Notebook

Abra o bloco de anotações em outra guia