Model Serving dans Snowpark Container Services¶
Note
La possibilité d’exécuter des modèles dans Snowpark Container Services (SPCS) décrite dans cette rubrique est disponible dans snowflake-ml-python
version 1.6.4 et ultérieure.
Le Snowflake Model Registry vous permet d’exécuter des modèles soit dans un entrepôt (par défaut), soit dans un pool de calcul Snowpark Container Services (SPCS) via Model Serving. L’exécution de modèles dans un entrepôt impose quelques limitations sur la taille et les types de modèles que vous pouvez utiliser (en particulier, les modèles ayant des CPU de petite à moyenne taille dont les dépendances peuvent être satisfaites par les paquets disponibles dans le canal Snowflake conda).
L’exécution de modèles sur Snowpark Container Services (SPCS) assouplit ces restrictions, voire les élimine complètement. Vous pouvez utiliser tous les paquets de votre choix, y compris ceux du Python Package Index (PyPI) ou d’autres sources. Les grands modèles peuvent être exécutés sur des clusters distribués de GPUs. Et vous n’avez pas besoin de connaître quoi que ce soit sur les technologies de conteneurs, telles que Docker ou Kubernetes. Snowflake Model Serving s’occupe de tous les détails.
Concepts clés¶
Un aperçu simplifié de haut niveau de l’architecture d’inférence de Snowflake Model Serving est présenté ci-dessous.

Les principaux composants de l’architecture sont les suivants :
Serveur d’inférence : le serveur qui exécute le modèle et fournit des prédictions. Le serveur d’inférence peut utiliser plusieurs processus d’inférence pour exploiter pleinement les capacités du nœud. Les requêtes adressées au modèle sont expédiées par le contrôle d’admission, qui gère la file d’attente des requêtes entrantes pour éviter les conditions de manque de mémoire, rejetant les clients lorsque le serveur est surchargé. Aujourd’hui, Snowflake fournit un serveur d’inférence simple et flexible basé sur Python qui peut exécuter des inférences pour tous les types de modèles. Progressivement, Snowflake prévoit de proposer des serveurs d’inférence optimisés pour des types de modèles spécifiques.
Environnement Python spécifique au modèle : pour réduire la latence de démarrage d’un modèle, qui inclut le temps nécessaire au téléchargement des dépendances et au chargement du modèle, Snowflake crée un conteneur qui encapsule les dépendances du modèle spécifique. Cela peut nécessiter une intégration d’accès externe pour permettre au processus de construction du conteneur de télécharger les dépendances nécessaires à l’aide de
pip
ouconda
.Note
Les intégrations d’accès externe ne sont requises que lorsque les dépendances doivent être téléchargées à partir d’un référentiel externe, tel que conda-forge ou PyPI. Snowflake a l’intention de supprimer cette exigence dans une future version.
Fonctions de service : pour communiquer avec le serveur d’inférence à partir du code exécuté dans un entrepôt, Snowflake Model Serving crée des fonctions qui ont la même signature que le modèle, mais qui appellent à la place le serveur d’inférence via le protocole de fonction externe.
Point de terminaison d’entrée : pour permettre aux applications extérieures à Snowflake d’appeler le modèle, Snowflake Model Serving peut provisionner un point de terminaison HTTP facultatif, accessible à l’Internet public.
Comment cela fonctionne-t-il ?¶
Le diagramme suivant montre comment Snowflake Model Serving déploie et sert des modèles dans un entrepôt ou sur SPCS.

Comme vous pouvez le voir, le chemin vers le déploiement SPCS est plus complexe que le chemin vers le déploiement de l’entrepôt, mais Snowflake Model Serving fait tout le travail pour vous, y compris la création de l’image de conteneur qui contient le modèle et ses dépendances, et la création du serveur d’inférence qui exécute le modèle.
Conditions préalables¶
Avant de commencer, assurez-vous de disposer des éléments suivants :
Un compte Snowflake dans n’importe quelle région AWS commerciale. Les régions gouvernementales ne sont pas prises en charge. Contactez votre représentant de compte si votre compte est dans Azure.
Version 1.6.4 ou ultérieure du paquet Python
snowflake-ml-python
.Un modèle que vous souhaitez exécuter sur Snowpark Container Services.
Connaissances de Snowflake Model Registry.
Connaissances de Snowpark Container Services. Plus précisément, vous devez comprendre ce que sont les pools de calcul, les référentiels d’images, et les privilèges associés.
Créer un pool de calcul¶
Snowpark Container Services (SPCS) exécute des images de conteneurs dans des pools de calcul. Si vous ne disposez pas encore d’un pool de calcul approprié, créez-en un comme suit :
CREATE COMPUTE POOL IF NOT EXISTS mypool
MIN_NODES = 2
MAX_NODES = 4
INSTANCE_FAMILY = 'CPU_X64_M'
AUTO_RESUME = TRUE;
Voir le tableau des noms de famille pour une liste de familles d’instances valides.
Assurez-vous que le rôle qui exécutera le modèle est le propriétaire du pool de calcul ou qu’il dispose des privilèges USAGE ou OPERATE sur le pool.
Créer un référentiel d’images¶
Snowflake Model Serving crée une image de conteneur qui contient le modèle et ses dépendances. Pour stocker cette image, vous avez besoin d’un référentiel d’images. Si vous n’en avez pas déjà un, créez-en un comme suit :
CREATE IMAGE REPOSITORY IF NOT EXISTS my_inference_images
Si vous utilisez un référentiel d’images dont vous n’êtes pas propriétaire, assurez-vous que le rôle qui créera l’image du conteneur dispose des privilèges SERVICE READ, SERVICE WRITE, READ, et WRITE sur le référentiel. Accordez ces privilèges comme suit :
GRANT WRITE ON IMAGE REPOSITORY my_inference_images TO ROLE myrole;
GRANT READ ON IMAGE REPOSITORY my_inference_images TO ROLE myrole;
GRANT SERVICE WRITE ON IMAGE REPOSITORY my_inference_images TO ROLE myrole;
GRANT SERVICE READ ON IMAGE REPOSITORY my_inference_images TO ROLE myrole;
Créer une intégration d’accès externe¶
Le processus de création de conteneurs nécessite l’accès à divers sites Internet pour télécharger les dépendances depuis conda-forge, PyPI, ou d’autres référentiels ou sites. Ceux-ci doivent être configurés comme des intégrations d’accès externes (EAIs) par le rôle ACCOUNTADMIN.
Note
Les intégrations d’accès externe ne sont requises que lorsque les dépendances doivent être téléchargées à partir d’un référentiel externe, tel que conda-forge ou PyPI. Snowflake a l’intention de supprimer cette exigence dans une future version.
Les intégrations d’accès externe sont des objets au niveau du compte et ne peuvent pas être partagées.
Tout d’abord, créez les règles réseau nécessaires. L’accès à conda-forge est toujours nécessaire ; si vous n’avez pas besoin d’accéder à d’autres référentiels de paquets, créez cette règle.
CREATE OR REPLACE NETWORK RULE conda_forge_rule
MODE = 'EGRESS'
TYPE = 'HOST_PORT'
VALUE_LIST = ('conda.anaconda.org:443')
Note
Vous ne pouvez pas utiliser le canal conda snowflake
avec Snowpark Container Services. Tous les paquets conda sont installés à partir de conda-forge lors de la construction d’une image de conteneur SPCS.
Si vous devez installer des paquets à partir de PyPI, créez également la règle suivante. Les quatre hôtes répertoriés sont nécessaires pour que pip
fonctionne.
CREATE OR REPLACE NETWORK RULE pypi_rule
MODE = 'EGRESS'
TYPE = 'HOST_PORT'
VALUE_LIST = ('pypi.org:443', 'pypi.python.org:443', 'pythonhosted.org:443',
'files.pythonhosted.org:443');
Si vous avez besoin d’accéder à de nombreux autres sites, vous pouvez créer une règle qui autorise un accès large à Internet. Le risque de sécurité est minime tant que cette règle s’applique uniquement au rôle utilisé pour créer des images de conteneur.
CREATE OR REPLACE NETWORK RULE all_access_rule
MODE = 'EGRESS'
TYPE = 'HOST_PORT'
VALUE_LIST = ('0.0.0.0:443', '0.0.0.0:80')
Créez l’intégration d’accès externe à l’aide d’une ou plusieurs de vos règles. Dans l’exemple ci-dessous, nous utilisons à la fois les règles conda_forge_rule
et pypi_rule
définies précédemment, permettant l’accès uniquement à conda-forge et PyPI.
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION model_service_build_access
ALLOWED_NETWORK_RULES = (conda_forge_rule, pypi_rule)
ENABLED = true;
Enfin, accordez USAGE sur EAI au rôle qui va construire les images de conteneurs.
GRANT USAGE ON INTEGRATION model_service_build_access TO ROLE model_users;
Limitations¶
Bien que cette fonctionnalité soit en version préliminaire, les limitations suivantes s’appliquent. Snowflake a l’intention de remédier à ces limitations avant la disponibilité générale.
Seul le propriétaire d’un modèle peut le déployer sur Snowpark Container Services
La taille du cluster de calcul ne s’adapte pas automatiquement. Vous pouvez modifier manuellement le nombre d’instances lors de l’exécution à l’aide de
ALTER SERVICE myservice MIN_INSTANCES = n
. Dans certains cas, cela entraîne la défaillance des nœuds existants.La mise à l’échelle des services et des pools de calcul est plus lente que prévu. Cela devrait être amélioré avant la disponibilité générale.
La suspension automatique d’un service de conteneur n’est pas prise en charge. Si vous prévoyez une utilisation sporadique, vous souhaiterez peut-être suspendre manuellement le service après chaque utilisation.
La méthode Python
create_service
ne permet pas de spécifier plusieurs intégrations d’accès externes (EAIs). Si un modèle nécessite à la fois conda et pip, créez une seule EAI qui permet les deux. (Notez que vous pouvez créer une EAI avec plusieurs règles de réseau.)La construction d’une image échoue si elle dure plus d’une heure.
Les fonctions de table ne sont pas prises en charge. Les modèles sans fonction régulière ne peuvent actuellement pas être déployés sur Snowpark Container Services.
Déploiement d’un modèle sur SPCS¶
Soit vous enregistrez une nouvelle version du modèle (en utilisant reg.log_model
) soit vous obtenez une référence à une version de modèle existante (reg.get_model(...).version()
). Dans les deux cas, vous vous retrouvez avec une référence à un objet ModelVersion
.
Dépendances et éligibilité du modèle¶
Les dépendances d’un modèle déterminent s’il peut s’exécuter dans un entrepôt, dans un service SPCS, ou les deux. Vous pouvez, si nécessaire, spécifier intentionnellement des dépendances pour rendre un modèle inéligible à l’exécution dans l’un de ces environnements.
Le canal Snowflake conda est disponible uniquement dans les entrepôts et constitue la seule source de dépendances d’entrepôt. Par défaut, les dépendances de conda pour les modèles SPCS obtiennent leurs dépendances de conda-forge.
Lorsque vous enregistrez une version de modèle, les dépendances conda du modèle sont validées par rapport au canal conda Snowflake. Si toutes les dépendances conda du modèle y sont disponibles, le modèle est considéré comme éligible pour être exécuté dans un entrepôt. Il peut également être éligible pour se présenter à un service SPCS si toutes ses dépendances sont disponibles depuis conda-forge, bien que cela ne soit pas vérifié tant que vous n’avez pas créé un service.
Les modèles connectés avec les dépendances PyPI doivent être exécutés sur SPCS. Spécifier au moins une dépendance PyPI est un moyen de rendre un modèle inéligible à l’exécution dans un entrepôt. Si votre modèle n’a que des dépendances conda, spécifiez-en au moins une avec un canal explicite (même conda-forge), comme indiqué dans l’exemple suivant.
reg.log_model(
model_name="my_model",
version_name="v1",
model=model,
conda_dependencies=["conda-forge::scikit-learn"])
Pour les modèles déployés avec SPCS, les dépendances conda, le cas échéant, sont installées en premier, puis toutes les dépendances PyPI sont installées dans l’environnement conda à l’aide de pip
.
Créez un service¶
Pour créer un service SPCS et y déployer le modèle, appelez la méthode create_service
de la version du modèle, comme illustré dans l’exemple suivant.
mv.create_service(service_name="myservice",
service_compute_pool="my_compute_pool",
image_repo="mydb.myschema.my_image_repo",
build_external_access_integration="my_external_access",
ingress_enabled=True,
gpu_requests=None)
Voici les arguments requis pour create_service
:
service_name : le nom du service à créer. Ce nom doit être unique au sein du compte.
service_compute_pool : le nom du pool de calcul à utiliser pour exécuter le modèle. Le pool de calcul doit déjà exister.
image_repo : le nom du référentiel d’images à utiliser pour stocker l’image du conteneur. Le référentiel doit déjà exister et l’utilisateur doit avoir le privilège SERVICE WRITE sur celui-ci (ou OWNERSHIP).
build_external_access_integration : le nom de l’intégration d’accès externe à utiliser lors du téléchargement des dépendances. Cette EA devrait toujours autoriser l’accès à conda-forge et devrait également inclure des hôtes PyPI si des dépendances sont installées avec
pip
.ingress_enabled : si True, le service est rendu accessible via un point de terminaison HTTP. Pour créer le point de terminaison, l’utilisateur doit disposer du privilège BIND SERVICE ENDPOINT.
gpu_requests : une chaîne spécifiant le nombre de GPUs. Pour un modèle qui peut être exécuté sur l’un ou l’autre CPU ou GPU, cet argument détermine si le modèle sera exécuté sur le CPU ou sur les GPUs. Si le modèle est d’un type connu qui ne peut être exécuté que sur CPU (par exemple, les modèles scikit-learn), la création de l’image échoue si des GPUs sont demandés.
Cet exemple montre uniquement les arguments obligatoires et les plus couramment utilisés. Voir la référence d’API ModelVersion pour une liste complète des arguments.
Configuration de service par défaut¶
Par défaut, un modèle alimenté par CPU utilise deux fois le nombre de CPUs, plus un, pour les processus de travail. Les modèles alimentés par GPU utilisent un seul processus de travail. Vous pouvez contourner cela en utilisant l’argument num_workers
.
Certains modèles ne sont pas « thread-safe ». Par conséquent, le service charge une copie distincte du modèle pour chaque processus de travail. Cela peut entraîner un épuisement des ressources pour les grands modèles.
Par défaut, le serveur d’inférence optimise l’exécution d’une seule inférence à la fois, dans le but d’exploiter pleinement toutes les ressources de CPU et la mémoire de chaque nœud.
Comportement de création d’image de conteneur¶
Par défaut, Snowflake Model Serving crée l’image du conteneur à l’aide du même pool de calcul qui sera utilisé pour exécuter le modèle. Ce pool de calcul d’inférence est probablement surpuissant pour cette tâche (par exemple, les GPUs ne sont pas utilisés dans la création d’images de conteneurs). Dans la plupart des cas, cela n’aura pas d’impact significatif sur les coûts de calcul, mais si cela constitue un problème, vous pouvez choisir un pool de calcul moins puissant pour créer des images en spécifiant l’argument image_build_compute_pool
.
create_service
est une fonction idempotente. L’appeler plusieurs fois ne déclenche pas la création d’image à chaque fois. Cependant, les images de conteneurs peuvent être reconstruites en fonction des mises à jour du service d’inférence, y compris des correctifs pour les vulnérabilités des paquets dépendants. Lorsque cela se produit, create_service
déclenche automatiquement une reconstruction de l’image. Par conséquent, vous ne devez pas désactiver l’intégration d’accès externe après le premier appel à create_service
.
Utilisation d’un modèle déployé dans SPCS¶
Vous pouvez appeler les méthodes d’un modèle en utilisant SQL, Python, ou un point de terminaison HTTP.
SQL¶
Snowflake Model Serving crée des fonctions de service lors du déploiement d’un modèle dans SPCS. Ces fonctions servent de passerelle entre SQL et le modèle exécuté dans le pool de calcul du SPCS. Une fonction de service est créée pour chaque méthode du modèle, et elles sont nommées comme model_name_method_name
. Par exemple, si le modèle a deux méthodes nommées PREDICT
et EXPLAIN
est qu’il est en cours de déploiement sur un service nommé MY_SERVICE
, les fonctions de service résultantes sont MY_SERVICE_PREDICT
et MY_SERVICE_EXPLAIN
.
Note
Les fonctions de service sont contenues dans le service. Pour cette raison, elles ne disposent que d’un seul point de contrôle d’accès, le service. Vous ne pouvez pas avoir différents privilèges de contrôle d’accès pour différentes fonctions dans un même service.
L’appel des fonctions de service d’un modèle en SQL se fait en utilisant un code comme celui-ci :
SELECT MY_SERVICE_PREDICT(...) FROM ...;
Python¶
Appeler les méthodes d’un service à l’aide de la méthode run
d’un objet de version de modèle, y compris l’argument service_name
pour spécifier le service où la méthode sera exécutée. Par exemple :
service_prediction = mv.run(
test_df,
function_name="predict",
service_name="my_service")
Si vous n’incluez pas l’argument service_name
, le modèle s’exécute dans un entrepôt.
Point de terminaison HTTP¶
Après avoir déployé un service avec l’entrée activée, un nouveau point de terminaison HTTP est disponible pour le service. Vous pouvez trouver le point de terminaison en utilisant la commande ShOW ENDPOINTS IN SERVICE.
SHOW ENDPOINTS IN SERVICE my_service;
Prenez note de la colonne ingress_url
, qui devrait ressembler à random_str-account-id.snowflakecomputing.app
.
Pour en savoir plus sur l’utilisation de ce point de terminaison, consultez le tutoriel SPCS Créer un service Snowpark Container Services et le sujet Utiliser un service extérieur à Snowflake dans le Guide du développeur. Pour plus d’informations sur le format de données requis, voir Formats des données d’entrée et de sortie des services à distance.
Voir Déploiement d’un transformateur de phrases Hugging Face pour inférence alimentée par GPU pour un exemple d’utilisation d’un point de terminaison de service de modèle HTTP.
Gestion des services¶
Snowpark Container Services propose une interface SQL de gestion des services. Vous pouvez utiliser les commandes DESCRIBE SERVICE et ALTER SERVICE avec les services SPCS créés par Snowflake Model Serving comme vous le feriez pour gérer n’importe quel autre service SPCS. Par exemple, vous pouvez :
Changer MIN_INSTANCES et d’autres propriétés d’un service
Supprimer un service
Partager un service avec un autre compte
Changer la propriété d’un service (le nouveau propriétaire doit avoir accès au modèle)
Note
Si le propriétaire d’un service perd l’accès au modèle sous-jacent pour une raison quelconque, le service cesse de fonctionner après un redémarrage. Il continuera à fonctionner jusqu’à ce qu’il soit redémarré.
Pour garantir la reproductibilité et la débogabilité, vous ne pouvez pas modifier la spécification d’un service d’inférence existant. Vous pouvez cependant copier la spécification, la personnaliser et utiliser la spécification personnalisée pour créer votre propre service pour héberger le modèle. Cependant, cette méthode ne protège pas le modèle sous-jacent contre la suppression. Il est généralement préférable de permettre à Snowflake Model Serving de créer des services.
Suspension de services¶
Une fois que vous avez fini d’utiliser un modèle, ou s’il n’est pas utilisé, il est recommandé de suspendre le service pour réduire les coûts. Vous pouvez le faire en utilisant la commande ALTER SERVICE.
ALTER SERVICE my_service SUSPEND;
Le service redémarre automatiquement lorsqu’il reçoit une demande, sous réserve des délais de planification et de démarrage. Le délai de planification dépend de la disponibilité du pool de calcul et le délai de démarrage dépend de la taille du modèle.
Suppression de modèles¶
Vous pouvez gérer les modèles et les versions de modèles comme d’habitude avec l’interface SQL ou l’API Python, à la condition qu’un modèle ou une version de modèle utilisé(e) par un service (qu’il soit en cours d’exécution ou suspendu) ne puisse pas être supprimé(e). Pour supprimer un modèle ou une version de modèle, supprimez d’abord le service.
Exemples¶
Ces exemples supposent que vous avez déjà créé un pool de calcul, un référentiel d’images et une intégration d’accès externe, et que vous avez accordé les privilèges nécessaires. Voir Conditions préalables pour plus de détails.
Déploiement d’un modèle XGBoost pour une inférence alimentée par CPU¶
Le code suivant illustre les étapes clés du déploiement d’un modèle XGBoost pour l’inférence dans SPCS, puis en utilisant le modèle déployé pour l’inférence. Un notebook pour cet exemple est disponible.
from snowflake.ml.registry import registry
from snowflake.ml.utils.connection_params import SnowflakeLoginOptions
from snowflake.snowpark import Session
from snowflake.ml.modeling.xgboost import XGBRegressor
# your model training code here output of which is a trained xgb_model
# Open model registry
reg = registry.Registry(session=session, database_name='my_registry_db', schema_name='my_registry_schema')
# Log the model in Snowflake Model Registry
model_ref = reg.log_model(
model_name="my_xgb_forecasting_model",
version_name="v1",
model=xgb_model,
conda_dependencies=["scikit-learn","xgboost"],
sample_input_data=train,
comment="XGBoost model for forecasting customer demand"
)
# Deploy the model to SPCS
reg_model.create_service(
service_name="ForecastModelServicev1",
service_compute_pool="my_cpu_pool",
image_repo="my_db.data.my_images",
build_external_access_integration="my_egress_access_integration_for_conda_pip",
ingress_enabled=True)
# See all services running a model
reg_model.list_services()
# Run on SPCS
reg_model.run(input_data, function_name="predict", service_name="ForecastModelServicev1")
# Delete the service
reg_model.delete_service("ForecastModelServicev1")
Déploiement d’un transformateur de phrases Hugging Face pour inférence alimentée par GPU¶
Ce code entraîne et déploie un transformateur de phrases Hugging Face, y compris un point de terminaison HTTP.
from snowflake.ml.registry import registry
from snowflake.ml.utils.connection_params import SnowflakeLoginOptions
from snowflake.snowpark import Session
from sentence_transformers import SentenceTransformer
session = Session.builder.configs(SnowflakeLoginOptions("connection_name")).create()
reg = registry.Registry(session=session, database_name='my_registry_db', schema_name='my_registry_schema')
# Take an example sentence transformer from HF
embed_model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
# Have some sample input data
input_data = [
"This is the first sentence.",
"Here's another sentence for testing.",
"The quick brown fox jumps over the lazy dog.",
"I love coding and programming.",
"Machine learning is an exciting field.",
"Python is a popular programming language.",
"I enjoy working with data.",
"Deep learning models are powerful.",
"Natural language processing is fascinating.",
"I want to improve my NLP skills.",
]
# Log the model with pip dependencies
pip_model = reg.log_model(
embed_model,
model_name="sentence_transformer_minilm",
version_name='pip',
sample_input_data=input_data, # Needed for determining signature of the model
pip_requirements=["sentence-transformers", "torch", "transformers"], # If you want to run this model in the Warehouse, you can use conda_dependencies instead
)
# Force Snowflake to not try to check warehouse
conda_forge_model = reg.log_model(
embed_model,
model_name="sentence_transformer_minilm",
version_name='conda_forge_force',
sample_input_data=input_data,
# setting any package from conda-forge is sufficient to know that it can't be run in warehouse
conda_dependencies=["sentence-transformers", "conda-forge::pytorch", "transformers"]
)
# Deploy the model to SPCS
pip_model.create_service(
service_name="my_minilm_service",
service_compute_pool="my_gpu_pool", # Using GPU_NV_S - smallest GPU node that can run the model
image_repo="my_db.data.my_images",
ingress_enabled=True,
build_external_access_integration="my_egress_access_integration_for_conda_pip",
gpu_requests="1", # Model fits in GPU memory; only needed for GPU pool
max_instances=4, # 4 instances were able to run 10M inferences from an XS warehouse
)
# See all services running a model
pip_model.list_services()
# Run on SPCS
pip_model.run(input_data, function_name="encode", service_name="my_minilm_service")
# Delete the service
pip_model.delete_service("my_minilm_service")
Étant donné que l’entrée est activée sur ce modèle, vous pouvez appeler son point de terminaison HTTP comme suit.
import json
from pprint import pprint
import requests
import snowflake.connector
# Generate right header
# Note that, ideally user should use key-pair authentication for API access (see this).
def initiate_snowflake_connection():
connection_parameters = SnowflakeLoginOptions("connection_name")
connection_parameters["session_parameters"] = {"PYTHON_CONNECTOR_QUERY_RESULT_FORMAT": "json"}
snowflake_conn = snowflake.connector.connect(**connection_parameters)
return snowflake_conn
def get_headers(snowflake_conn):
token = snowflake_conn._rest._token_request('ISSUE')
headers = {'Authorization': f'Snowflake Token=\"{token["data"]["sessionToken"]}\"'}
return headers
headers = get_headers(initiate_snowflake_connection())
# Put the endpoint url with method name
URL='https://<random_str>-<account>.snowflakecomputing.app/encode'
# Prepare data to be sent
data = {
'data': []
}
for idx, x in enumerate(input_data):
data['data'].append([idx, x])
# Send over HTTP
def send_request(data: dict):
output = requests.post(URL, json=data, headers=headers)
assert (output.status_code == 200), f"Failed to get response from the service. Status code: {output.status_code}"
return output.content
# Test
results = send_request(data=data)
pprint(json.loads(results))
Déploiement d’un modèle PyTorch pour inférence alimentée par GPU¶
Voir ce démarrage rapide pour un exemple d’entraînement et de déploiement d’un modèle de recommandation d’apprentissage profond PyTorch (DLRM) dans SPCS pour une inférence par GPU.
Meilleures pratiques¶
- Partage d’un référentiel d’images
Il est courant que plusieurs utilisateurs ou rôles utilisent le même modèle. L’utilisation d’un référentiel d’images unique permet de créer l’image une seule fois et de la réutiliser par tous les utilisateurs, ce qui permet d’économiser du temps et de l’argent. Tous les rôles qui utiliseront le référentiel ont besoin de privilèges SERVICE READ, SERVICE WRITE, READ, et WRITE sur le référentiel. Étant donné que l’image peut avoir besoin d’être reconstruite pour mettre à jour les dépendances, vous devez conserver les privilèges d’écriture ; ne les révoquez pas une fois l’image initialement créée.
- Mise à l’échelle du service d’inférence
La mise à l’échelle automatique de Snowpark Container Services est très conservatrice et ne s’adapte pas assez rapidement à la plupart des charges de travail de ML. Pour cette raison, Snowflake vous recommande de définir les deux MIN_INSTANCES et MAX_INSTANCES sur la même valeur, en choisissant ces valeurs pour obtenir les performances dont vous avez besoin pour vos charges de travail typiques. Utilisez SQL comme ce qui suit :
ALTER SERVICE myservice SET MIN_INSTANCES = <new_num> MAX_INSTANCES = <new_num>;
Pour la même raison, lors de la création initiale du service à l’aide de l’API Python, la méthode
create_service
accepte uniquementmax_instances
et utilise cette même valeur pourmin_instances
.- Choix du type de nœud et du nombre d’instances
Utilisez le plus petit nœud de GPU où le modèle s’insère dans la mémoire. Dimensionnez en augmentant le nombre d’instances, plutôt qu’en augmentant
num_workers
dans un nœud de GPU plus grand. Par exemple, si le modèle s’inscrit dans le type d’instance GPU_NV_S, utilisezgpu_requests=1
et adaptez en augmentantmax_instances
plutôt qu’en utilisant une combinaison degpu_requests
etnum_workers
sur une instance de GPU plus grande.- Sélection d’une taille d’entrepôt
Plus l’entrepôt est grand, plus les requêtes parallèles sont envoyées aux serveurs d’inférence. L’inférence est une opération coûteuse, utilisez donc un entrepôt plus petit lorsque cela est possible. L’utilisation d’une taille d’entrepôt supérieure à la moyenne n’accélère pas les performances des requêtes et entraîne des coûts supplémentaires.
- Schéma distinct pour les déploiements de modèles
La création d’un service crée plusieurs objets au niveau du schéma (le service lui-même et une fonction de service par fonction de modèle). Pour éviter l’encombrement, utilisez des schémas distincts pour stocker les modèles (Snowflake Model Registry) et les déployer (Snowflake Model Serving).
Résolution des problèmes¶
Surveillance de déploiements SPCS¶
Vous pouvez surveiller le déploiement en inspectant les services lancés à l’aide de la requête SQL suivante.
SHOW SERVICES IN COMPUTE POOL my_compute_pool;
Deux tâches sont lancées :
MODEL_BUILD_xxxxx : les derniers caractères du nom sont choisis de façon aléatoire pour éviter les conflits de noms. Cette tâche construit l’image et se termine une fois l’image construite. Si une image existe déjà, la tâche est ignorée.
Les journaux sont utiles pour déboguer les conflits dans les dépendances des paquets ou les problèmes d’intégration d’accès externe qui empêchent l’accès aux référentiels de paquets, entre autres problèmes potentiels. Pour voir les journaux de cette tâche, exécutez la commande SQL ci-dessous, en veillant à utiliser les mêmes caractères finaux :
CALL SYSTEM$GET_SERVICE_LOGS('MODEL_BUILD_xxxxx', 0, 'model-build');MYSERVICE : le nom du service tel que spécifié dans l’appel à
create_service
. Cette tâche est démarrée si la tâche MODEL_BUILD aboutit ou est ignorée. Pour voir les journaux de cette tâche, exécutez la commande SQL ci-dessous :CALL SYSTEM$GET_SERVICE_LOGS('MYSERVICE', 0, 'model-inference');
Conflits de paquets¶
Deux systèmes dictent les paquets installés dans le conteneur de services : le modèle lui-même et le serveur d’inférence. Pour atténuer les conflits entre les dépendances de votre modèle, le serveur d’inférence nécessite uniquement les paquets suivants :
gunicorn<24.0.0
starlette<1.0.0
uvicorn-standard<1.0.0
Assurez-vous que les dépendances de votre modèle, ainsi que celles ci-dessus, peuvent être résolues par pip
ou conda
, quel que soit votre choix.
Si un modèle possède à la fois conda_dependencies
et pip_requirements
, elles seront installées comme suit via conda :
Canaux :
conda-forge
nodefaults
Dépendances :
all_conda_packages
- pip :
all_pip_packages
Par défaut, Snowflake utilise conda-forge pour les paquets Anaconda, car le canal Snowflake conda est disponible dans les entrepôts et le canal defaults
exige que les utilisateurs acceptent les conditions d’utilisation d’Anaconda. Pour spécifier les paquets du canal par défaut, incluez le nom du paquet : defaults::pkg_name
.
Service à court de mémoire¶
Certains modèles ne sont pas thread-safe, donc Snowflake charge une copie du modèle en mémoire pour chaque processus de travail. Cela peut entraîner des conditions de pénurie de mémoire pour les grands modèles avec un nombre plus élevé de workers. Essayez de réduire num_workers
.
Performances de requête insatisfaisantes¶
En général, l’inférence est limitée par le nombre d’instances dans le service d’inférence. Essayez de transmettre une valeur plus élevée pour max_instances
lors du déploiement du modèle.
Impossible de modifier les spécifications du service¶
Les spécifications des services de création de modèles et d’inférence ne peuvent pas être modifiées à l’aide de ALTER SERVICE. Vous ne pouvez modifier que des attributs tels que TAG, MIN_INSTANCES, et ainsi de suite.
Cependant, étant donné que l’image est publiée dans le référentiel d’images, vous pouvez copier la spécification, la modifier et créer un nouveau service à partir de celle-ci, que vous pouvez démarrer manuellement.