Utiliser un conteneur personnalisé pour la prédiction

Pour personnaliser la façon dont Vertex AI diffuse les prédictions en ligne à partir de votre modèle personnalisé, vous pouvez spécifier un conteneur personnalisé au lieu d'un conteneur prédéfini lorsque vous créez une ressource Model. Lorsque vous utilisez un conteneur personnalisé, Vertex AI exécute un conteneur Docker de votre choix sur chaque nœud de prédiction.

Nous vous recommandons d'utiliser un conteneur personnalisé pour l'une des raisons suivantes :

  • Pour diffuser des prédictions à partir d'un modèle de ML entraîné à l'aide d'un framework autre que TensorFlow, scikit-learn ou XGBoost
  • Pour prétraiter les requêtes de prédiction ou post-traiter les prédictions générées par votre modèle
  • Pour exécuter un serveur de prédiction écrit dans le langage de programmation de votre choix
  • Pour installer des dépendances que vous souhaitez utiliser pour personnaliser la prédiction

Ce guide explique comment créer un fichier Model utilisant un conteneur personnalisé. Il ne fournit pas d'instructions détaillées concernant la conception et la création d'une image de conteneur Docker.

Préparer une image de conteneur

Pour créer un Model qui utilise un conteneur personnalisé, vous devez fournir une image de conteneur Docker comme base de ce conteneur. Cette image de conteneur doit répondre aux exigences décrites dans la section Exigences relatives aux conteneurs personnalisés.

Si vous envisagez d'utiliser une image de conteneur existante créée par un tiers de confiance, vous pouvez ignorer l'une des sections suivantes, ou les deux.

Créer une image de conteneur

Concevez et créez une image de conteneur Docker répondant aux exigences relatives aux images de conteneur.

Pour apprendre les bases de la conception et de la création d'une image de conteneur Docker, consultez le guide de démarrage rapide de la documentation Docker.

Transférer l'image de conteneur vers Artifact Registry ou Container Registry

Transférez l'image de conteneur vers un dépôt Artifact Registry ouContainer Registry respectant les Exigences relatives à la publication d'images de conteneurs.

Découvrez comment transférer une image de conteneur vers Artifact Registry ou transférer une image de conteneur vers Container Registry.

Créer un objet Model

Pour créer un Model qui utilise un conteneur personnalisé, effectuez l'une des opérations suivantes :

Les sections suivantes montrent comment configurer les champs d'API associés aux conteneurs personnalisés lors de la création d'un objet Model de l'une de ces manières.

Champs d'API liés au conteneur

Lorsque vous créez le Model, assurez-vous de configurer le champ containerSpec avec les informations de votre conteneur personnalisé plutôt qu'avec un conteneur prédéfini.

Vous devez spécifier un message ModelContainerSpec dans le champ Model.containerSpec. Dans ce message, vous pouvez spécifier les sous-champs suivants :

imageUri (obligatoire)

URI Artifact Registry ou Container Registry de votre image de conteneur.

Si vous exécutez la commande gcloud ai models upload, vous pouvez utiliser l'option --container-image-uri pour spécifier ce champ.

command (facultatif)

Tableau d'un fichier exécutable et d'arguments pour remplacer le ENTRYPOINT du conteneur. Pour en savoir plus sur la mise en forme de ce champ et son interaction avec le champ args, consultez la documentation de référence de l'API pour ModelContainerSpec.

Si vous exécutez la commande gcloud ai models upload, vous pouvez utiliser l'option --container-command pour spécifier ce champ.

args (facultatif)

Tableau d'un fichier exécutable et d'arguments pour remplacer le CMD du conteneur. Pour en savoir plus sur la mise en forme de ce champ et son interaction avec command, lisez la documentation de référence de l'API pour ModelContainerSpec.

Si vous exécutez la commande gcloud ai models upload, vous pouvez utiliser l'option --container-args pour spécifier ce champ.

ports (facultatif)

Tableau de ports : Vertex AI envoie par défaut des vérifications d'activité, des vérifications d'état et des requêtes de prédiction à votre conteneur sur le premier port répertorié, ou sur le port 8080 par défaut. Spécifier des ports supplémentaires n'a aucun effet.

Si vous exécutez la commande gcloud ai models upload, vous pouvez utiliser l'option --container-ports pour spécifier ce champ.

env (facultatif)

Tableau de variables d'environnement que la commande entrypoint du conteneur, ainsi que les champs command et args, peuvent référencer. Pour en savoir plus sur la manière dont d'autres champs peuvent faire référence à ces variables d'environnement, consultez la documentation de référence de l'API pour ModelContainerSpec.

Si vous exécutez la commande gcloud ai models upload, vous pouvez utiliser l'option --container-env-vars pour spécifier ce champ.

healthRoute (facultatif)

Chemin d'accès sur le serveur HTTP du conteneur, vers lequel vous souhaitez que l'IA Vertex envoie des vérifications d'état.

Si vous ne spécifiez pas ce champ, la valeur par défaut /v1/endpoints/ENDPOINT/deployedModels/DEPLOYED_MODEL est utilisée lors du déploiement du Model en tant que DeployedModel sur une ressource Endpoint, où ENDPOINT est remplacé par le dernier segment du champ name du Endpoint (précédé par endpoints/) et DEPLOYED_MODEL est remplacé par le champ id de DeployedModel.

Si vous exécutez la commande gcloud ai models upload, vous pouvez utiliser l'option --container-health-route pour spécifier ce champ.

predictRoute (facultatif)

Chemin d'accès sur le serveur HTTP du conteneur, vers lequel vous souhaitez que l'IA Vertex transfère les requêtes de prédiction.

Si vous ne spécifiez pas ce champ, la valeur par défaut /v1/endpoints/ENDPOINT/deployedModels/DEPLOYED_MODEL est utilisée lors du déploiement du Model en tant que DeployedModel sur une ressource Endpoint, où ENDPOINT est remplacé par le dernier segment du champ name du Endpoint (précédé par endpoints/) et DEPLOYED_MODEL est remplacé par le champ id de DeployedModel.

Si vous exécutez la commande gcloud ai models upload, vous pouvez utiliser l'option --container-predict-route pour spécifier ce champ.

Outre les variables que vous avez définies dans le champ Model.containerSpec.env, Vertex AI définit plusieurs autres variables en fonction de votre configuration. Apprenez-en plus sur l'utilisation de ces variables d'environnement dans ces champs et dans la commande entrypoint du conteneur.

Exemples d'importation de modèle

Les exemples suivants montrent comment spécifier des champs d'API liés au conteneur lorsque vous importez un modèle.

gcloud

L'exemple suivant utilise la commande gcloud ai models upload :

gcloud ai models upload \
  --region=LOCATION \
  --display-name=MODEL_NAME \
  --container-image-uri=IMAGE_URI \
  --container-command=COMMAND \
  --container-args=ARGS \
  --container-ports=PORTS \
  --container-env-vars=ENV \
  --container-health-route=HEATLH_ROUTE \
  --container-predict-route=PREDICT_ROUTE \
  --artifact-uri=PATH_TO_MODEL_ARTIFACT_DIRECTORY

L'option --container-image-uri est obligatoire et toutes les autres options commençant par --container- sont facultatives. Pour en savoir plus sur les valeurs de ces champs, consultez la section précédente du présent guide.

Java


import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.aiplatform.v1.LocationName;
import com.google.cloud.aiplatform.v1.Model;
import com.google.cloud.aiplatform.v1.ModelContainerSpec;
import com.google.cloud.aiplatform.v1.ModelServiceClient;
import com.google.cloud.aiplatform.v1.ModelServiceSettings;
import com.google.cloud.aiplatform.v1.UploadModelOperationMetadata;
import com.google.cloud.aiplatform.v1.UploadModelResponse;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class UploadModelSample {
  public static void main(String[] args)
      throws InterruptedException, ExecutionException, TimeoutException, IOException {
    // TODO(developer): Replace these variables before running the sample.
    String project = "YOUR_PROJECT_ID";
    String modelDisplayName = "YOUR_MODEL_DISPLAY_NAME";
    String metadataSchemaUri =
        "gs://google-cloud-aiplatform/schema/trainingjob/definition/custom_task_1.0.0.yaml";
    String imageUri = "YOUR_IMAGE_URI";
    String artifactUri = "gs://your-gcs-bucket/artifact_path";
    uploadModel(project, modelDisplayName, metadataSchemaUri, imageUri, artifactUri);
  }

  static void uploadModel(
      String project,
      String modelDisplayName,
      String metadataSchemaUri,
      String imageUri,
      String artifactUri)
      throws IOException, InterruptedException, ExecutionException, TimeoutException {
    ModelServiceSettings modelServiceSettings =
        ModelServiceSettings.newBuilder()
            .setEndpoint("us-central1-aiplatform.googleapis.com:443")
            .build();

    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the "close" method on the client to safely clean up any remaining background resources.
    try (ModelServiceClient modelServiceClient = ModelServiceClient.create(modelServiceSettings)) {
      String location = "us-central1";
      LocationName locationName = LocationName.of(project, location);

      ModelContainerSpec modelContainerSpec =
          ModelContainerSpec.newBuilder().setImageUri(imageUri).build();

      Model model =
          Model.newBuilder()
              .setDisplayName(modelDisplayName)
              .setMetadataSchemaUri(metadataSchemaUri)
              .setArtifactUri(artifactUri)
              .setContainerSpec(modelContainerSpec)
              .build();

      OperationFuture<UploadModelResponse, UploadModelOperationMetadata> uploadModelResponseFuture =
          modelServiceClient.uploadModelAsync(locationName, model);
      System.out.format(
          "Operation name: %s\n", uploadModelResponseFuture.getInitialFuture().get().getName());
      System.out.println("Waiting for operation to finish...");
      UploadModelResponse uploadModelResponse = uploadModelResponseFuture.get(5, TimeUnit.MINUTES);

      System.out.println("Upload Model Response");
      System.out.format("Model: %s\n", uploadModelResponse.getModel());
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment these variables before running the sample.\
 */

// const modelDisplayName = 'YOUR_MODEL_DISPLAY_NAME';
// const metadataSchemaUri = 'YOUR_METADATA_SCHEMA_URI';
// const imageUri = 'YOUR_IMAGE_URI';
// const artifactUri = 'YOUR_ARTIFACT_URI';
// const project = 'YOUR_PROJECT_ID';
// const location = 'YOUR_PROJECT_LOCATION';

// Imports the Google Cloud Model Service Client library
const {ModelServiceClient} = require('@google-cloud/aiplatform');

// Specifies the location of the api endpoint
const clientOptions = {
  apiEndpoint: 'us-central1-aiplatform.googleapis.com',
};

// Instantiates a client
const modelServiceClient = new ModelServiceClient(clientOptions);

async function uploadModel() {
  // Configure the parent resources
  const parent = `projects/${project}/locations/${location}`;
  // Configure the model resources
  const model = {
    displayName: modelDisplayName,
    metadataSchemaUri: '',
    artifactUri: artifactUri,
    containerSpec: {
      imageUri: imageUri,
      command: [],
      args: [],
      env: [],
      ports: [],
      predictRoute: '',
      healthRoute: '',
    },
  };
  const request = {
    parent,
    model,
  };

  console.log('PARENT AND MODEL');
  console.log(parent, model);
  // Upload Model request
  const [response] = await modelServiceClient.uploadModel(request);
  console.log(`Long running operation : ${response.name}`);

  // Wait for operation to complete
  await response.promise();
  const result = response.result;

  console.log('Upload model response ');
  console.log(`\tModel : ${result.model}`);
}
uploadModel();

Python

def upload_model_sample(
    project: str,
    location: str,
    display_name: str,
    serving_container_image_uri: str,
    artifact_uri: Optional[str] = None,
    serving_container_predict_route: Optional[str] = None,
    serving_container_health_route: Optional[str] = None,
    description: Optional[str] = None,
    serving_container_command: Optional[Sequence[str]] = None,
    serving_container_args: Optional[Sequence[str]] = None,
    serving_container_environment_variables: Optional[Dict[str, str]] = None,
    serving_container_ports: Optional[Sequence[int]] = None,
    instance_schema_uri: Optional[str] = None,
    parameters_schema_uri: Optional[str] = None,
    prediction_schema_uri: Optional[str] = None,
    explanation_metadata: Optional[explain.ExplanationMetadata] = None,
    explanation_parameters: Optional[explain.ExplanationParameters] = None,
    sync: bool = True,
):

    aiplatform.init(project=project, location=location)

    model = aiplatform.Model.upload(
        display_name=display_name,
        artifact_uri=artifact_uri,
        serving_container_image_uri=serving_container_image_uri,
        serving_container_predict_route=serving_container_predict_route,
        serving_container_health_route=serving_container_health_route,
        instance_schema_uri=instance_schema_uri,
        parameters_schema_uri=parameters_schema_uri,
        prediction_schema_uri=prediction_schema_uri,
        description=description,
        serving_container_command=serving_container_command,
        serving_container_args=serving_container_args,
        serving_container_environment_variables=serving_container_environment_variables,
        serving_container_ports=serving_container_ports,
        explanation_metadata=explanation_metadata,
        explanation_parameters=explanation_parameters,
        sync=sync,
    )

    model.wait()

    print(model.display_name)
    print(model.resource_name)
    return model

Pour davantage de contexte, consultez le guide d'importation de modèles.

Envoyer des requêtes de prédiction

Pour envoyer une requête de prédiction en ligne à votre Model, suivez les guides pour déployer votre Model sur un Endpoint et obtenir des prédictions en ligne à partir de modèles personnalisés. Le processus est identique, que vous utilisiez un conteneur personnalisé ou non.

Apprenez-en plus sur les exigences concernant les requêtes et les réponses pour les conteneurs personnalisés.

Étape suivante