Model Serving in Snowpark Container Services

Bemerkung

Die in diesem Thema beschriebene Möglichkeit, Modelle in Snowpark Container Services (SPCS) auszuführen, ist ab der Version 1.6.4 von snowflake-ml-python verfügbar.

Die Snowflake Model Registry ermöglicht es Ihnen, Modelle entweder in einem Warehouse (die Standardeinstellung) oder in einem Snowpark Container Services (SPCS) Computepool über Model Serving auszuführen. Die Ausführung von Modellen in einem Warehouse bringt einige Beschränkungen in Bezug auf die Größe und die Art der Modelle mit sich, die Sie verwenden können (insbesondere kleine bis mittelgroße nur-CPU-Modelle, deren Abhängigkeiten von Paketen erfüllt werden können, die im Snowflake conda-Kanal verfügbar sind).

Die Ausführung von Modellen auf Snowpark Container Services (SPCS) erleichtert diese Einschränkungen oder beseitigt sie ganz. Sie können alle Pakete verwenden, die Sie möchten, auch die aus dem Python Package Index (PyPI) oder aus anderen Quellen. Große Modelle können auf verteilten Clustern von GPUs ausgeführt werden. Und Sie müssen nichts über Container-Technologien wie Docker oder Kubernetes wissen. Snowflake Model Serving kümmert sich um alle Details.

Die wichtigsten Konzepte

Nachfolgend finden Sie einen vereinfachten Überblick über die Architektur des Snowflake Modells Serving Inference.

Modellinferenz auf Snowpark Container Services-Architektur

Die Hauptkomponenten der Architektur sind:

  • Inferenzserver: Der Server, der das Modell ausführt und Vorhersagen liefert. Der Inferenzserver kann mehrere Inferenzprozesse verwenden, um die Fähigkeiten des Knotens voll auszuschöpfen. Anfragen an das Modell werden über die Zulassungskontrolle abgewickelt, die die Warteschlange für eingehende Anfragen verwaltet, um zu verhindern, dass der Speicher überlastet wird, und die Clients abweist, wenn der Server überlastet ist. Heute bietet Snowflake einen einfachen und flexiblen Inferenzserver auf Python-Basis, der Inferenzen für alle Arten von Modellen durchführen kann. Snowflake plant, im Laufe der Zeit InferenzsServer anzubieten, die für bestimmte Modelle optimiert sind.

  • Modellspezifische Python-Umgebung: Um die Latenzzeit beim Starten eines Modells zu verringern, zu der auch die Zeit gehört, die für das Herunterladen der Abhängigkeiten und das Laden des Modells benötigt wird, erstellt Snowflake einen Container, der die Abhängigkeiten des spezifischen Modells kapselt. Dies kann eine Integration für den externen Zugriff erfordern, damit der Container-Erstellungsprozess die erforderlichen Abhängigkeiten über pip oder conda herunterladen kann.

    Bemerkung

    Integrationen für den externen Zugriff sind nur dann erforderlich, wenn Abhängigkeiten von einem externen Repository, wie conda-forge oder PyPI, heruntergeladen werden müssen. Snowflake beabsichtigt, diese Anforderung in einem zukünftigen Release zu entfernen.

  • Dienstfunktionen: Um von einem im Warehouse ausgeführten Code aus mit dem Inferenzserver zu kommunizieren, erstellt Snowflake Model Serving-Funktionen, die dieselbe Signatur wie das Modell haben, aber stattdessen den Inferenzserver über das externe Funktionsprotokoll aufrufen.

  • Ingress-Endpunkt: Damit Anwendungen außerhalb von Snowflake das Modell aufrufen können, kann Snowflake Model Serving einen optionalen HTTP Endpunkt bereitstellen, der über das öffentliche Internet zugänglich ist.

Wie funktioniert das?

Das folgende Diagramm zeigt, wie das Snowflake Model Serving Modelle entweder in einem Warehouse oder auf SPCS bereitstellt und bedient.

Modell für den Einsatz auf Snowpark Container Services

Wie Sie sehen, ist der Pfad zur Bereitstellung von SPCS komplexer als der Pfad zur Bereitstellung des Warehouse, aber Snowflake Model Serving übernimmt die gesamte Arbeit für Sie, einschließlich der Erstellung des Container-Images, das das Modell und seine Abhängigkeiten enthält, und der Erstellung des Inferenzservers, der das Modell ausführt.

Voraussetzungen

Bevor Sie beginnen, vergewissern Sie sich, dass Sie Folgendes haben:

  • Ein Snowflake-Konto in einer beliebigen kommerziellen Region von AWS. Gov-Regionen werden nicht unterstützt. Wenden Sie sich an Ihren Kundenbetreuer, wenn sich Ihr Konto in Azure befindet.

  • Version 1.6.4 oder höher des snowflake-ml-python Python-Pakets.

  • Ein Modell, das Sie auf Snowpark Container Services ausführen möchten.

  • Vertrautheit mit dem Snowflake Model Registry.

  • Vertrautheit mit dem Snowpark Container Services. Insbesondere sollten Sie Computepools, Image-Repositorys und die damit verbundenen Berechtigungen verstehen.

Einen Computepool erstellen

Snowpark Container Services (SPCS) führt Container-Images in Computepools aus. Wenn Sie noch keinen geeigneten Computepool haben, erstellen Sie einen solchen wie folgt:

CREATE COMPUTE POOL IF NOT EXISTS mypool
    MIN_NODES = 2
    MAX_NODES = 4
    INSTANCE_FAMILY = 'CPU_X64_M'
    AUTO_RESUME = TRUE;
Copy

Eine Auflistung der gültigen Instanzfamilien finden Sie in der Familiennamen-Tabelle.

Stellen Sie sicher, dass die Rolle, die das Modell ausführt, Eigentümer des Computepools ist oder die Berechtigung USAGE oder OPERATE für den Pool besitzt.

Image-Repository erstellen

Snowflake Model Serving erstellt ein Container-Image, das das Modell und seine Abhängigkeiten enthält. Um dieses Image zu speichern, benötigen Sie ein Image-Repository. Wenn Sie noch keines haben, erstellen Sie es wie folgt:

CREATE IMAGE REPOSITORY IF NOT EXISTS my_inference_images
Copy

Wenn Sie ein Image-Repository verwenden, dessen Eigentümer Sie nicht sind, stellen Sie sicher, dass die Rolle, die das Container-Image erstellt, über die Berechtigungen SERVICE READ, SERVICE WRITE, READ und WRITE für das Repository verfügt. Gewähren Sie diese Berechtigungen wie folgt:

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;
Copy

Erstellen Sie eine Integration für den externen Zugriff

Der Container-Erstellungsprozess benötigt Zugriff auf verschiedene Websites, um Abhängigkeiten von conda-forge, PyPI oder anderen Repositorys oder Websites herunterzuladen. Diese müssen von der Rolle ACCOUNTADMIN als Integration für den externen Zugriff (EAIs) eingerichtet werden.

Bemerkung

Integrationen für den externen Zugriff sind nur dann erforderlich, wenn Abhängigkeiten von einem externen Repository, wie conda-forge oder PyPI, heruntergeladen werden müssen. Snowflake beabsichtigt, diese Anforderung in einem zukünftigen Release zu entfernen.

Integrationen für den externen Zugriff sind Objekte auf Kontoebene und können nicht gemeinsam genutzt werden.

Erstellen Sie zunächst die erforderlichen Regeln für das Netzwerk. Der Zugriff auf conda-forge ist immer erforderlich. Wenn Sie keinen Zugriff auf andere Paket-Repositorys benötigen, erstellen Sie diese Regel.

CREATE OR REPLACE NETWORK RULE conda_forge_rule
    MODE = 'EGRESS'
    TYPE = 'HOST_PORT'
    VALUE_LIST = ('conda.anaconda.org:443')
Copy

Bemerkung

Sie können den snowflake conda-Kanal nicht mit Snowpark Container Services verwenden. Alle Pakete von conda werden von conda-forge installiert, wenn Sie ein SPCS-Container-Image erstellen.

Wenn Sie Pakete von PyPI installieren müssen, erstellen Sie auch die folgende Regel. Alle vier der aufgelisteten Hosts sind erforderlich, damit pip funktioniert.

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');
Copy

Wenn Sie Zugriff auf viele andere Websites benötigen, können Sie eine Regel erstellen, die einen breiten Zugriff auf das Internet erlaubt. Solange diese Regel nur für die Rolle gilt, mit der Container-Images erstellt werden, besteht kaum ein Sicherheitsrisiko.

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

Erstellen Sie die Integration für den externen Zugriff mithilfe einer oder mehrerer Ihrer Regeln. Im folgenden Beispiel verwenden wir die beiden zuvor definierten conda_forge_rule und pypi_rule und erlauben nur den Zugriff auf conda-forge und PyPI.

CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION model_service_build_access
    ALLOWED_NETWORK_RULES = (conda_forge_rule, pypi_rule)
    ENABLED = true;
Copy

Gewähren Sie schließlich der Rolle, die die Container-Images erstellt, USAGE auf EAI.

GRANT USAGE ON INTEGRATION model_service_build_access TO ROLE model_users;
Copy

Einschränkungen

Während diese Funktion in der Vorschau angezeigt wird, gelten die folgenden Beschränkungen. Snowflake beabsichtigt, diese Beschränkungen vor der allgemeinen Verfügbarkeit zu beheben.

  • Nur der Eigentümer eines Modells kann es bei Snowpark Container Services einsetzen

  • Die Größe des Compute-Clusters wird nicht automatisch skaliert. Sie können die Anzahl der Instanzen zur Laufzeit mit ALTER SERVICE myservice MIN_INSTANCES = n manuell ändern. In einigen Fällen führt dies dazu, dass bestehende Knoten ausfallen.

  • Die Skalierung von Services und Computepools verläuft langsamer als erwartet. Dies sollte vor der allgemeinen Verfügbarkeit verbessert werden.

  • Das automatische Aussetzen eines Container-Dienstes wird nicht unterstützt. Wenn Sie eine sporadische Nutzung erwarten, sollten Sie den Dienst nach jeder Nutzung manuell aussetzen.

  • Die create_service Python-Methode erlaubt nicht die Angabe mehrerer externer Integrationen (EAIs). Wenn ein Modell sowohl conda als auch pip benötigt, erstellen Sie eine einzige EAI, die beides zulässt. (Beachten Sie, dass Sie eine EAI mit mehreren Regeln für das Netzwerk erstellen können)

  • Die Bilderstellung schlägt fehl, wenn sie mehr als eine Stunde dauert.

  • Tabellenfunktionen werden nicht unterstützt. Modelle ohne reguläre Funktion können derzeit nicht in Snowpark Container Services eingesetzt werden.

Ein Modell für SPCS bereitstellen

Entweder protokolliert eine neue Version des Modells (über reg.log_model) oder erhält einen Verweis auf eine bestehende Version des Modells (reg.get_model(...).version()). In beiden Fällen erhalten Sie einen Verweis auf ein ModelVersion-Objekt.

Modell-Abhängigkeiten und Eignung

Die Abhängigkeiten eines Modells bestimmen, ob es in einem Warehouse, in einem SPCS-Dienst oder in beiden laufen kann. Sie können bei Bedarf absichtlich Abhängigkeiten angeben, um ein Modell für die Ausführung in einer dieser Umgebungen ungeeignet zu machen.

Der Snowflake conda-Kanal ist nur in Warehouses verfügbar und ist die einzige Quelle für Abhängigkeiten von Warehouses. Standardmäßig beziehen die conda-Abhängigkeiten für SPCS-Modelle ihre Abhängigkeiten aus conda-forge.

Wenn Sie eine Modellversion protokollieren, werden die Abhängigkeiten des Modells mit dem Snowflake conda-Kanal abgeglichen. Wenn alle Abhängigkeiten des Modells dort verfügbar sind, kann das Modell in einem Warehouse ausgeführt werden. Er kann auch in einem SPCS-Dienst laufen, wenn alle seine Abhängigkeiten in der conda-forge verfügbar sind. Dies wird jedoch erst geprüft, wenn Sie einen Dienst erstellen.

Modelle, die mit PyPI Abhängigkeiten protokolliert wurden, müssen auf SPCS ausgeführt werden. Die Angabe von mindestens einer PyPI-Abhängigkeit ist eine Möglichkeit, ein Modell von der Ausführung in einem Warehouse auszuschließen. Wenn Ihr Modell nur Abhängigkeiten von conda hat, geben Sie mindestens eine mit einem expliziten Kanal an (auch conda-forge), wie im folgenden Beispiel gezeigt.

reg.log_model(
    model_name="my_model",
    version_name="v1",
    model=model,
    conda_dependencies=["conda-forge::scikit-learn"])
Copy

Für SPCS-bereitgestellte Modelle werden zuerst die conda-Abhängigkeiten, falls vorhanden, installiert, dann werden alle PyPI-Abhängigkeiten in der conda-Umgebung mit pip installiert.

Dienst erstellen

Um einen SPCS-Dienst zu erstellen und das Modell darin einzusetzen, rufen Sie die create_service-Methode der Modellversion auf, wie im folgenden Beispiel gezeigt.

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

Nachfolgend sind die erforderlichen Arguments an create_service zu sehen:

  • service_name: Der Name des zu erstellenden Services. Dieser Name muss innerhalb des Kontos eindeutig sein.

  • service_compute_pool: Der Name des Computepools, der für die Ausführung des Modells verwendet wird. Der Computepool muss bereits existieren.

  • image_repo: Der Name des Image-Repositorys, das zum Speichern des Container-Images verwendet werden soll. Das Projektarchiv muss bereits existieren und der Benutzer muss über die Berechtigung SERVICE WRITE (oder OWNERSHIP) verfügen.

  • build_external_access_integration: Der Name der Integration für den externen Zugriff, die beim Herunterladen von Abhängigkeiten verwendet werden soll. Diese EA sollte immer den Zugriff auf conda-forge erlauben und auch PyPI-Hosts enthalten, wenn irgendwelche Abhängigkeiten mit pip installiert sind.

  • ingress_enabled: Wenn True, wird der Service über einen HTTP-Endpunkt zugänglich gemacht. Um den Endpunkt zu erstellen, muss der Benutzer über die Berechtigung BIND SERVICE ENDPOINT verfügen.

  • gpu_requests: Eine Zeichenfolge, die die Anzahl der GPUs angibt. Bei einem Modell, das entweder auf CPU oder GPU ausgeführt werden kann, bestimmt dieses Argument, ob das Modell auf CPU oder auf GPUs ausgeführt wird. Wenn es sich bei dem Modell um einen bekannten Typ handelt, der nur auf CPU ausgeführt werden kann (z. B. scikit-learn-Modelle), schlägt die Image-Erstellung fehl, wenn GPUs angefragt wird.

Dieses Beispiel zeigt nur die erforderlichen und am häufigsten verwendeten Argumente. Eine vollständige Auflistung der Argumente finden Sie in der Referenz ModelVersion API.

Standard Konfiguration des Dienstes

Ein CPU-gestütztes Modell verwendet standardmäßig die doppelte Anzahl von CPUs, plus eins, Worker-Prozessen. GPU-gestützte Modelle verwenden einen Worker-Prozess. Sie können dies mit dem num_workers-Argument überschreiben.

Einige Modelle sind nicht Thread-sicher. Daher lädt der Dienst für jeden Worker-Prozess eine eigene Kopie des Modells. Dies kann bei großen Modellen zu einer Erschöpfung der Ressourcen führen.

Standardmäßig optimiert der Inferenzserver für die Ausführung einer einzigen Inferenz zur gleichen Zeit und versucht, alle CPU und den Speicher jedes Knotens voll auszunutzen.

Verhaltensweise bei der Erstellung von Container-Images

Standardmäßig erstellt Snowflake Model Serving das Container-Image unter Verwendung desselben Computepools, der für die Ausführung des Modells verwendet wird. Dieser Inferenz-Computepool ist für diese Aufgabe wahrscheinlich überfordert (zum Beispiel werden GPUs nicht für die Erstellung von Container-Images verwendet). In den meisten Fällen wird dies keine nennenswerten Auswirkungen auf die Kosten haben, aber wenn es ein Problem darstellt, können Sie einen weniger leistungsfähigen Pool für die Erstellung von Images wählen, indem Sie das Argument image_build_compute_pool angeben.

create_service ist eine idempotente Funktion. Ein mehrfacher Aufruf löst nicht jedes Mal die Image-Erstellung aus. Container-Images können jedoch auf der Grundlage von Updates im Inferenzdienst neu erstellt werden, einschließlich Korrekturen für Sicherheitslücken in abhängigen Paketen. Wenn dies geschieht, löst create_service automatisch eine Neuerstellung des Images aus. Daher dürfen Sie die Integration des externen Zugangs nicht nach dem ersten Aufruf von create_service deaktivieren.

Verwendung eines Modells, eingesetzt für SPCS

Sie können die Methoden eines Modells über SQL, Python oder einen HTTP-Endpunkt aufrufen.

SQL

Snowflake Model Serving erstellt Funktionen für Dienste, wenn ein Modell auf SPCS bereitgestellt wird. Diese Funktionen dienen als Brücke von SQL zu dem Modell, das im SPCS-Computepool läuft. Für jede Methode des Modells wird eine Dienstfunktion erstellt, die wie model_name_method_name benannt ist. Wenn das Modell beispielsweise zwei Methoden mit den Namen PREDICT und EXPLAIN hat und für einen Dienst mit dem Namen MY_SERVICE bereitgestellt wird, lauten die resultierenden Funktionen des Dienste MY_SERVICE_PREDICT und MY_SERVICE_EXPLAIN.

Bemerkung

Die Dienstefunktionen sind im Service enthalten. Aus diesem Grund haben sie nur einen einzigen Punkt für die Zugriffssteuerung, den Service. Sie können keine unterschiedlichen Zugriffssteuerungsrechte für verschiedene Funktionen in einem einzigen Dienst haben.

Der Aufruf der Dienstfunktionen eines Modells in SQL erfolgt über Code wie den folgenden:

SELECT MY_SERVICE_PREDICT(...) FROM ...;
Copy

Python

Rufen Sie die Methoden eines Service mit der Methode run eines Objekts der Modellversion auf, einschließlich des Arguments service_name zur Angabe des Serfvices, in dem die Methode ausgeführt wird. Beispiel:

service_prediction = mv.run(
    test_df,
    function_name="predict",
    service_name="my_service")
Copy

Wenn Sie das Argument service_name nicht angeben, läuft das Modell in einem Warehouse.

HTTP-Endpunkt

Nachdem Sie einen Service mit aktiviertem Ingress bereitgestellt haben, ist ein neuer HTTP-Endpunkt für den Dienst verfügbar. Sie können den Endpunkt mit dem Befehl ShOW ENDPOINTS IN SERVICE finden.

SHOW ENDPOINTS IN SERVICE my_service;
Copy

Beachten Sie die Spalte ingress_url, die wie random_str-account-id.snowflakecomputing.app aussehen sollte.

Wenn Sie mehr über die Verwendung dieses Endpunkts erfahren möchten, lesen Sie das Tutorial SPCS Einen Snowpark Container Services-Dienst erstellen und das Thema Verwenden eines Service von außerhalb von Snowflake im Entwicklerhandbuch. Weitere Informationen über das erforderliche Format der Daten finden Sie unter Eingabe- und Ausgabedatenformate von Remotediensten.

Unter Einsatz eines Hugging Face Satzumwandlers für GPU-gestützte Inferenz finden Sie ein Beispiel für die Verwendung eines Modelldienst-HTTP-Endpunkts.

Verwalten von Diensten

Snowpark Container-Dienste bieten eine SQL-Weboberfläche für die Verwaltung von Diensten. Sie können die Befehle DESCRIBE SERVICE und ALTER SERVICE für SPCS-Dienste verwenden, die von Snowflake Model Serving erstellt wurden, genauso wie für die Verwaltung aller anderen SPCS-Dienste. Sie können beispielsweise Folgendes tun:

  • Ändern Sie MIN_INSTANCES und andere Eigenschaften eines Dienstes

  • Einen Dienst verwerfen (löschen)

  • Einen Dienst für ein anderes Konto freigeben

  • Änderung der Eigentümerschaft eines Dienstes (der neue Eigentümer muss Zugriff auf das Modell haben)

Bemerkung

Wenn der Eigentümer eines Dienstes aus irgendeinem Grund den Zugriff auf das zugrunde liegende Modell verliert, funktioniert der Dienst nach einem Neustart nicht mehr. Er läuft weiter, sobald er neu gestartet wird.

Um die Reproduzierbarkeit und Fehlersuchbarkeit zu gewährleisten, dürfen Sie die Spezifikation eines bestehenden Inferenzdienstes nicht ändern. Sie können jedoch die Spezifikation kopieren, sie anpassen und die angepasste Spezifikation verwenden, um Ihren eigenen Dienst zum Hosten des Modells zu erstellen. Diese Methode schützt jedoch nicht davor, dass das zugrunde liegende Modell gelöscht wird. Im Allgemeinen ist es am besten, Snowflake Model Serving die Erstellung von Diensten zu gestatten.

Aussetzen von Diensten

Wenn Sie ein Modell nicht mehr verwenden oder wenn es nicht mehr genutzt wird, ist es sinnvoll, den Dienst auszusetzen, um Kosten zu sparen. Sie können dies mit dem Befehl ALTER SERVICE tun.

ALTER SERVICE my_service SUSPEND;
Copy

Der Dienst startet automatisch neu, wenn er eine Anfrage erhält, vorbehaltlich der Zeitpläne und Startverzögerungen. Die Verzögerung bei der Zeitplanung hängt von der Verfügbarkeit des Computepools ab, und die Verzögerung beim Start hängt von der Größe des Modells ab.

Löschen von Modellen

Sie können Modelle und Modellversionen wie gewohnt über die SQL-Weboberfläche oder die Python-API verwalten, mit der Einschränkung, dass ein Modell oder eine Modellversion, das/die von einem Dienst verwendet wird (unabhängig davon, ob es/sie läuft oder ausgesetzt ist), nicht gelöscht werden kann. Um ein Modell oder eine Version zu löschen, müssen Sie zuerst den Dienst löschen.

Beispiele

Diese Beispiele gehen davon aus, dass Sie bereits einen Computepool, ein Image-Repository und eine Integration für den externen Zugriff erstellt und die erforderlichen Berechtigungen erteilt haben. Weitere Informationen dazu finden Sie unter Voraussetzungen.

Einsatz eines XGBoost-Modells für CPU-gestützte Inferenz

THe der folgende Code veranschaulicht die Schlüsselschritte bei der Bereitstellung eines XGBoost Modells für die Inferenz in SPCS und der anschließenden Verwendung des bereitgestellten Modells für die Inferenz. Ein Notizbuch für dieses Beispiel ist verfügbar unter.

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

Einsatz eines Hugging Face Satzumwandlers für GPU-gestützte Inferenz

Dieser Code trainiert und setzt einen Hugging Face Satzumwandler ein, einschließlich eines HTTP-Endpunkts.

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

Da bei diesem Modell der Ingress aktiviert ist, können Sie den HTTP-Endpunkt wie folgt aufrufen.

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

Einsatz eines PyTorch-Modells für GPU-gestützte Inferenz

Unter finden Sie in diesem Quickstart ein Beispiel für das Training und den Einsatz eines PyTorch Deep Learning-Empfehlungsmodells (DLRM) auf SPCS für GPU-Inferenz.

Best Practices

Gemeinsame Nutzung des Image-Repositorys

Es ist üblich, dass mehrere Benutzer oder Rollen dasselbe Modell verwenden. Durch die Verwendung eines einzigen Image-Repositorys kann das Image einmal erstellt und von allen Benutzern wiederverwendet werden, was Zeit und Kosten spart. Alle Rollen, die das Repository verwenden, benötigen die Berechtigungen SERVICE READ, SERVICE WRITE, READ und WRITE für das Repository. Da das Image möglicherweise neu erstellt werden muss, um Abhängigkeiten zu aktualisieren, sollten Sie die Schreibrechte behalten und sie nicht widerrufen, nachdem das Image ursprünglich erstellt wurde.

Skalierung des Inferencedienstes

Die automatische Skalierung von Snowpark Container-Dienstets ist sehr konservativ und skaliert nicht schnell genug für die meisten ML-Workloads. Aus diesem Grund empfiehlt Snowflake, sowohl MIN_INSTANCES als auch MAX_INSTANCES auf denselben Wert einzustellen und diese Werte so zu wählen, dass Sie die Leistung erhalten, die Sie für Ihre typischen Workloads benötigen. Verwenden Sie SQL wie folgt:

ALTER SERVICE myservice
    SET MIN_INSTANCES = <new_num>
        MAX_INSTANCES = <new_num>;
Copy

Aus demselben Grund akzeptiert die Methode create_service bei der anfänglichen Erstellung des Dienstes mit Python API nur max_instances und verwendet denselben Wert für min_instances.

Auswahl des Knotentyps und der Anzahl der Instanzen

Verwenden Sie den kleinsten GPU-Knoten, bei dem das Modell in den Speicher passt. Skalieren Sie, indem Sie die Anzahl der Instanzen erhöhen, im Gegensatz zur Erhöhung von num_workers in einem größeren GPU-Knoten. Wenn das Modell z. B. in den Instanztyp GPU_NV_S passt, verwenden Sie gpu_requests=1 und skalieren Sie nach oben, indem Sie max_instances erhöhen, anstatt eine Kombination aus gpu_requests und num_workers in einer größeren GPU-Instanz zu verwenden.

Wahl der Warehouse-Größe

Je größer das Warehouse ist, desto mehr parallele Anfragen werden an die Inferenzserver gesendet. Die Inferenz ist eine teure Operation, verwenden Sie daher nach Möglichkeit ein kleineres Warehouse. Die Verwendung einer Warehouse-Größe, die größer als mittel ist, beschleunigt die Leistung der Abfrage nicht und verursacht zusätzliche Kosten.

Separates Schema für die Bereitstellung von Modellen

Wenn Sie einen Service erstellen, werden mehrere Objekte auf Schema-Ebene erstellt (der Service selbst und eine Dienstfunktion pro Modellfunktion). Um Unordnung zu vermeiden, verwenden Sie separate Schemas für die Speicherung von Modellen (Snowflake Model Registry) und deren Bereitstellung (Snowflake Model Serving).

Problembehandlung

Überwachung der SPCS-Bereitstellungen

Sie können die Bereitstellung überwachen, indem Sie die Dienste, die gestartet werden, mit der folgenden SQL-Abfrage überprüfen.

SHOW SERVICES IN COMPUTE POOL my_compute_pool;
Copy

Zwei Jobs werden gestartet:

  • MODEL_BUILD_xxxxx: Die letzten Zeichen des Namens werden randomisiert, um Namenskonflikte zu vermeiden. Dieser Job erstellt das Image und endet, nachdem das Image erstellt wurde. Wenn bereits ein Image existiert, wird der Job übersprungen.

    Die Protokolle sind nützlich, um Konflikte in Paketabhängigkeiten oder Probleme bei der Integration von externem Zugriff zu beheben, die den Zugriff auf Paket-Repositories verhindern, neben anderen möglichen Problemen. Um die Protokolle dieses Jobs zu sehen, führen Sie die folgende SQL aus. Achten Sie darauf, dass Sie die gleichen letzten Zeichen verwenden:

    CALL SYSTEM$GET_SERVICE_LOGS('MODEL_BUILD_xxxxx', 0, 'model-build');
    
    Copy
  • MYSERVICE: Der Name des Dienstes, wie er im Aufruf von create_service angegeben ist. Dieser Job wird gestartet, wenn der MODEL_BUILD-Job erfolgreich ist oder übersprungen wird. Um die Protokolle dieses Jobs zu sehen, führen Sie die folgende SQL aus:

    CALL SYSTEM$GET_SERVICE_LOGS('MYSERVICE', 0, 'model-inference');
    
    Copy

Paketkonflikte

Zwei Systeme bestimmen, welche Pakete im Service Container installiert werden: das Modell selbst und der Inferenzserver. Um Konflikte mit den Abhängigkeiten Ihres Modells zu minimieren, benötigt der Inferenzserver nur die folgenden Pakete:

  • gunicorn<24.0.0

  • starlette<1.0.0

  • uvicorn-standard<1.0.0

Vergewissern Sie sich, dass Ihre Modellabhängigkeiten, zusammen mit den oben genannten, von pip oder conda aufgelöst werden können.

Wenn ein Modell sowohl conda_dependencies als auch pip_requirements eingestellt hat, werden diese über conda wie folgt installiert:

Kanäle:

  • conda-forge

  • nodefaults

Abhängigkeiten:

  • all_conda_packages

  • pip :
    • all_pip_packages

Snowflake verwendet standardmäßig conda-forge für Anaconda Pakete, da der Snowflake conda-Kanal in Warehouses verfügbar ist und der defaults-Kanal von den Benutzern verlangt, dass sie die Anaconda-Nutzungsbedingungen akzeptieren. Um Pakete aus dem Standardkanal anzugeben, fügen Sie den Namen des Pakets hinzu: defaults::pkg_name.

Dienst außerhalb des Speichers

Einige Modelle sind nicht thread-sicher, daher lädt Snowflake für jeden Worker-Prozess eine Kopie des Modells in den Speicher. Dies kann bei großen Modellen mit einer größeren Anzahl von Workern dazu führen, dass der Speicher überlastet wird. Versuchen Sie, num_workers zu reduzieren.

Unbefriedigende Leistung bei Abfragen

Normalerweise wird die Inferenz durch die Anzahl der Instanzen im Inferenzdienst behindert. Versuchen Sie, bei der Bereitstellung des Modells einen höheren Wert für max_instances anzugeben.

Sie können die Dienstspezifikation nicht ändern

Die Dienstspezifikationen für die Modellerstellung und die Inferenz können nicht über ALTER SERVICE geändert werden. Sie können nur Attribute wie TAG, MIN_INSTANCES und so weiter ändern.

Da das Image jedoch im Image Repository veröffentlicht ist, können Sie die Spezifikation kopieren, sie ändern und daraus einen neuen Dienst erstellen, den Sie manuell starten können.