Snowpark Container Servicesのモデルサービス¶
注釈
This feature is available in AWS, Azure and Google Cloud commercial regions. It isn't available in government regions.
注釈
このトピックで説明するSnowpark Container Services(SPCS)でモデルを実行する機能は、 snowflake-ml-python バージョン1.8.0以降で利用可能です。
Snowflake Model Registry では、モデルをウェアハウス(デフォルト)か、Model Serving を通じて Snowpark Container Services(SPCS)のコンピューティングプールで実行することができます。ウェアハウスでモデルを実行すると、使用できるモデルのサイズと種類にいくつかの制限が課せられます(具体的には、Snowflake condaチャネルで利用可能なパッケージによって依存関係を満たすことができる小~中規模のサイズ CPU-限定モデル)。
Snowpark Container Services(SPCS)上でモデルを実行すると、これらの制限が緩和され、あるいは完全になくなります。Python Package Index(PyPI)やその他のソースのパッケージを含め、好きなパッケージを使うことができます。大規模なモデルは、 GPUs の分散クラスタ上で実行できます。DockerやKubernetesといったコンテナー技術について知る必要はありません。Snowflake Model Servingが細部まで世話をします。
主な概念¶
Snowflake Model Serving推論アーキテクチャの簡略化された高レベルの概要を以下に示します。
アーキテクチャの主な構成要素は以下の通りです。
推論サーバー:モデルを実行し、予測を提供するサーバー。推論サーバーは、ノードの能力をフルに活用するために、複数の推論プロセスを使用することができます。モデルへのリクエストは、アドミッション・コントロールによってディスパッチされます。アドミッション・コントロールは、メモリ不足の状態を避けるために受信リクエストキューを管理し、サーバーが過負荷になったときにクライアントを拒否します。今日、Snowflakeはシンプルで柔軟なPythonベースの推論サーバーを提供し、あらゆるタイプのモデルの推論を実行することができます。Snowflakeでは、特定のモデルタイプに最適化した推論サーバーを順次ご提供していく予定です。
モデル固有の Python 環境:依存関係をダウンロードしてモデルをロードするのに必要な時間を含む、モデルを開始する際の待ち時間を短縮するために、Snowflakeは特定のモデルの依存関係をカプセル化するコンテナーを構築します。
サービス関数:ウェアハウスで実行されているコードから推論サーバーと通信するために、Snowflake Model Serving はモデルと同じシグネチャを持つ関数をビルドしますが、その代わりに 外部関数プロトコル を介して推論サーバーを呼び出します。
イングレスエンドポイント:Snowflake外のアプリケーションがモデルを呼び出せるように、Snowflake Model Servingは、パブリックインターネットにアクセス可能なオプションの HTTP エンドポイント をプロビジョニングできます。
機能の仕組み¶
次の図は、Snowflake Model Serving がウェアハウス内または SPCS 上でどのようにモデルをデプロイして提供するかを示しています。
ご覧のように、 SPCS デプロイメントへのパスは、ウェアハウスデプロイメントへのパスよりも複雑ですが、Snowflake Model Serving は、モデルとその依存関係を保持するコンテナイメージの構築、モデルを実行する推論サーバーの作成など、すべての作業を代行します。
前提条件¶
始める前に、以下をご確認ください。
A Snowflake account in any commercial AWS, Azure or Google Cloud region. Government regions are not supported.
snowflake-ml-pythonPythonパッケージのバージョン1.6.4以降。Snowpark Container Servicesで実行したいモデル。
Snowflake Model Registry に精通していること。
Snowpark Container Services に精通していること。特に、 コンピューティングプール 、 イメージリポジトリ 、および関連する権限について理解しておく必要があります。
コンピューティングプールの作成¶
Snowpark Container Services (SPCS) は、コンピューティングプールでコンテナーイメージを実行します。適切なコンピューティングプールがまだない場合は、以下のようにして作成します。
CREATE COMPUTE POOL IF NOT EXISTS mypool
MIN_NODES = 2
MAX_NODES = 4
INSTANCE_FAMILY = 'CPU_X64_M'
AUTO_RESUME = TRUE;
有効なインスタンスファミリーの一覧は、 ファミリ名のテーブル をご参照ください。
モデルを実行するロールが、コンピューティングプールのオーナーであるか、あるいは、 USAGE 、あるいは、 OPERATE 、そのプールの権限を持っていることをご確認しださい。
必要な権限¶
Modeling Servingは、 Snowpark Container Services 上で実行されます。Modeling Servingを使うには、ユーザーは以下の権限が必要です。
サービスが実行される コンピューティングプール 上の USAGE または OWNERSHIP。
サービングしているモデルでイングレスエンドポイントが必要な場合、ユーザーは BIND SERVICE ENDPOINT 権限をアカウントで 持っている必要があります。
モデルのREAD権限を持つモデル所有者またはユーザーは、モデルを Serving にデプロイできます。別のロールが推論にアクセスできるようにするには、サービス所有者が:doc:`サービスロール</sql-reference/sql/grant-service-role>```INFERENCE_SERVICE_FUNCTION_USAGE``を付与してサービス関数を共有し、``ALL_ENDPOINTS_USAGE``を付与してイングレスエンドポイントを共有します。
制限事項¶
Snowpark Container Servicesでのモデルの提供には、以下の制限が適用されます。
モデルのREAD権限を持つモデル所有者またはロールのみが、Snowpark Container Servicesにデプロイすることができます。
コンピュートクラスタのサイズは自動スケールしません。
ALTER SERVICE myservice MIN_INSTANCES = nを使って、実行時にインスタンス数を手動で変更することができます。場合によっては、既存のノードが故障することもあります。サービスやコンピューティングプールのスケールアップが予想以上に遅いです。
イメージ作成に1時間以上かかると失敗します。
テーブル機能はサポートされていません。現在、テーブル関数のないモデルをSnowpark Container Servicesにデプロイすることはできません。
SPCS へのモデルの展開¶
が新しいモデルバージョン (reg.log_model を使用)をログに記録するか、 既存のモデルバージョンの参照情報を取得します (reg.get_model(...).version(...))。どちらの場合でも、 ModelVersion オブジェクトへの参照情報で終了します。
モデルの依存性と適格性¶
モデルの依存関係は、それがウェアハウスで実行できるか、 SPCS サービスで実行できるか、あるいはその両方で実行できるかを決定します。必要であれば、依存関係を意図的に指定して、モデルをこれらの環境のいずれかで実行できないようにすることができます。
Snowflake の conda チャネルはウェアハウスでのみ利用可能で、ウェアハウスの依存関係の唯一のソースです。デフォルトでは、 SPCS モデルの conda 依存関係は conda-forge から取得します。
モデルのバージョンをログに記録すると、モデルの conda 依存関係が Snowflake の conda チャンネルに対して検証されます。モデルのすべてのconda依存関係がそこで利用可能であれば、そのモデルはウェアハウスで実行する資格があるとみなされます。また、依存関係がすべてconda-forgeから利用可能であれば、 SPCS サービスで実行することもできます。ただし、これはサービスを作成するまで確認されません。
PyPI の依存関係でログに記録されたモデルは、 SPCS で実行する必要があります。少なくとも1つの PyPI 依存関係を指定することは、モデルをウェアハウスで実行する資格がないようにする1つの方法です。モデルにcondaの依存関係しかない場合は、次の例に示すように、少なくとも1つのチャネルを明示的に指定します(conda-forgeでも構いません)。
# reg is a snowflake.ml.registry.Registry object
reg.log_model(
model_name="my_model",
version_name="v1",
model=model,
conda_dependencies=["conda-forge::scikit-learn"])
SPCS-deployedモデルの場合、condaの依存関係があれば、まずインストールされ、次に PyPI の依存関係があれば、 pip を使ってconda環境にインストールされます。
サービスの作成¶
SPCS サービスを作成し、そこにモデルをデプロイするには、次の例に示すように、モデルバージョンの create_service メソッドを呼び出します。
# mv is a snowflake.ml.model.ModelVersion object
mv.create_service(service_name="myservice",
service_compute_pool="my_compute_pool",
ingress_enabled=True,
gpu_requests=None)
create_service に必要な引数を以下に示します。
service_name: 作成するサービス名。この名前はアカウント内で一意である必要があります。service_compute_pool: モデルの実行に使用するコンピュートプールの名前。コンピューティングプールはすでに存在している必要があります。ingress_enabled:True の場合、サービスは HTTP エンドポイント経由でアクセスできるようになります。エンドポイントを作成するには、 BIND SERVICE ENDPOINT の権限が必要です。gpu_requests: GPUs の数を指定する文字列。CPU または GPU のいずれかで実行できるモデルの場合、この引数は、モデルが CPU と GPUs のどちらで実行されるかを決定します。モデルが CPU (例えばscikit-learnモデル)でしか実行できない既知のタイプの場合、 GPUs を要求するとイメージビルドは失敗します。
新しいモデルをデプロイする場合、CPU駆動型モデルのサービスを作成するのに最大5分、GPU駆動型モデルを作成するのに10分かかります。コンピューティングプールがアイドル状態であるか、サイズ変更が必要な場合は、サービスの作成に時間がかかる可能性があります。
This example shows only the required and most commonly used arguments. See the ModelVersion API reference for a complete list of arguments.
デフォルトのサービス構成¶
Inference Serverは、ほとんどの大文字と小文字で動作する使いやすいデフォルトを使用しています。そのセットは以下です。
ワーカースレッド数: CPU-poweredモデルの場合、サーバーは CPUs の2倍+1個のワーカープロセスを使用します。GPU使用型はワーカープロセスを1つ使います。
create_serviceの呼び出しでは、num_workers引数を使用してオーバーライドできます。スレッドセーフティ:スレッドセーフでないモデルもあります。そのため、サービスはワーカープロセスごとにモデルの別個のコピーをロードします。その結果、大規模なモデルではリソースが枯渇する可能性があります。
ノード利用:デフォルトでは、1つの推論サーバーインスタンスは、実行するノードのすべての CPU とメモリをリクエストすることで、ノード全体をリクエストします。インスタンスごとのリソース割り当てをカスタマイズするには、
cpu_requests、memory_requests、gpu_requestsのような引数を使用します。エンドポイント:推論エンドポイントは
inferenceと名付けられ、ポート5000を使用します。これらはカスタマイズできません。Auto Suspend:推論サービスは、非アクティブな状態が30分経過すると、デフォルトで自動的に一時停止します。一時停止したサービスは、リクエストを受け取ると自動的に再開されます。
コンテナイメージのビルド動作¶
デフォルトでは、Snowflake Model Servingは、モデルの実行に使用されるのと同じコンピューティングプールを使用してコンテナーイメージを構築します。この推論コンピューティングプールは、このタスクにはオーバーパワーである可能性が高いです(例えば、 GPUs は、コンテナーイメージの構築には使用されません)。ほとんどの場合、これはコンピューティングコストに大きな影響を与えませんが、気になる場合は、 image_build_compute_pool 引数を指定することでイメージのビルドのためによりパワフルではないコンピューティングプールを選択できます。
create_service はべき等関数です。複数回呼び出しても、毎回イメージ構築のトリガーにはなりません。しかし、コンテナーイメージは、依存パッケージの脆弱性の修正を含む推論サービスの更新に基づいて再構築される可能性があります。この場合、 create_service 、自動的にイメージの再構築がトリガーされます。
注釈
Snowpark ML モデリングクラス を使用して開発されたモデルは、 GPU を持つ環境にはデプロイできません。回避策として、ネイティブモデルを抽出して、それをデプロイすることができます。例:
# Train a model using Snowpark ML from snowflake.ml.modeling.xgboost import XGBRegressor regressor = XGBRegressor(...) regressor.fit(training_df) # Extract the native model xgb_model = regressor.to_xgboost() # Test the model with pandas dataframe pandas_test_df = test_df.select(['FEATURE1', 'FEATURE2', ...]).to_pandas() xgb_model.predict(pandas_test_df) # Log the model in Snowflake Model Registry mv = reg.log_model(xgb_model, model_name="my_native_xgb_model", sample_input_data=pandas_test_df, comment = 'A native XGB model trained from Snowflake Modeling API', ) # Now we should be able to deploy to a GPU compute pool on SPCS mv.create_service( service_name="my_service_gpu", service_compute_pool="my_gpu_pool", image_repo="my_repo", max_instances=1, gpu_requests="1", )
ユーザーインターフェイス¶
展開されたモデルは、Model Registry Snowsight UI で管理できます。詳細については、 モデル推論サービス をご参照ください。
SPCS に配備されたモデルを使用する¶
モデルのメソッドを呼び出すには、 SQL 、Python、 HTTP のエンドポイントを使用します。
SQL¶
Snowflake Model Serving は、モデルを SPCS にデプロイする際にサービス関数を作成します。これらの関数は、 SQL から、 SPCS のコンピューティングプールで実行されているモデルへのブリッジとして機能します。モデルの各メソッドに対して1つのサービス関数が作成され、それらは service_name!method_name のように命名されます。例えば、モデルが PREDICT と EXPLAIN という2つのメソッドを持ち、 MY_SERVICE というサービスにデプロイされる場合、結果として生じるサービス関数は MY_SERVICE!PREDICT と MY_SERVICE!EXPLAIN となります。
注釈
サービス関数はサービス内に含まれます。そのため、アクセスコントロールはサービス側一点のみとなります。1つのサービスで、機能ごとに異なるアクセス制御権限を設定することはできません。
SQL のモデルのサービス関数を呼び出すには、以下のようなコードを使用します。
-- See signature of the inference function in SQL.
SHOW FUNCTIONS IN SERVICE MY_SERVICE;
-- Call the inference function in SQL following the same signature (from `arguments` column of the above query)
SELECT MY_SERVICE!PREDICT(feature1, feature2, ...) FROM input_data_table;
Python¶
モデルバージョンオブジェクトの run メソッドを使用して、サービスのメソッドを呼び出します。service_name 引数を指定して、メソッドが実行されるサービスを指定することを含みます。例:
# Get signature of the inference function in Python
# mv: snowflake.ml.model.ModelVersion
mv.show_functions()
# Call the function in Python
service_prediction = mv.run(
test_df,
function_name="predict",
service_name="my_service")
service_name 引数を含めない場合、モデルはウェアハウスで実行されます。
HTTP endpoints¶
Every service comes with its internal DNS name. Deploying a service with ingress_enabled also creates a public HTTP endpoint available outside of Snowflake. Either endpoint can be used to call a service.
Endpoint names¶
You can find the public HTTP endpoint of a service with ingress enabled using the SHOW ENDPOINTS command or the list_services() method of a model version object.
# mv: snowflake.ml.model.ModelVersion
mv.list_services()
The output of both contains an ingress_url column, which has an entry of the format unique-service-id-account-id.snowflakecomputing.app.
This is the publicly available HTTP endpoint for your service. The DNS name limitations apply.
In a URL, underscores (_) in the method name are replaced by dashes (-) in the URL. For example, the service name predict_probability is changed to predict-probability in the URL.
To get the internal DNS name on Snowflake, use the DESCRIBE SERVICE command. The dns_name column of output from this command contains a service's internal DNS name. To find your service's port, use the SHOW ENDPOINTS IN SERVICE command. The port or port_range column contains the port used by a service. You can make internal calls to your service through the URL https://dns_name:port/<method_name>.
Request body¶
All inference requests must use the POST HTTP method with a Content-Type: application/json header, and the message body follows the data format described in リモートサービスの入力および出力データ形式.
The first column of your input is an INTEGER number representing the row number in the batch, and the remaining columns must match your service's signature. The following request body is an example for a model with the signature predict(INTEGER, VARCHAR, TIMESTAMP):
{
"data": [
[0, 10, "Alex", "2014-01-01 16:00:00"],
[1, 20, "Steve", "2015-01-01 16:00:00"],
[2, 30, "Alice", "2016-01-01 16:00:00"],
[3, 40, "Adrian", "2017-01-01 16:00:00"]
]
}
Calling the service¶
Users can call a service using the public endpoint programmatically in the following ways:
With a Programmatic Access Token (PAT), authentication based on a token you generate on Snowflake. For information on setting up a PAT for use with Snowflake services, see 認証のためのプログラム アクセス トークンの使用. To use a PAT when calling a service, include the token in your
Authorizationrequest header:Authorization: Snowflake Token="<your_token>"
For example, with a PAT stored in the environment variable
SNOWFLAKE_SERVICE_PATand thepredict(INTEGER, VARCHAR, TIMESTAMP)function signature used in previous examples, you could make a request to the endpointrandom-id.myaccount.snowflakecomputing.app/predictwith the followingcurlcommand:curl \ -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Snowflake Token=\"$SNOWFLAKE_SERVICE_PAT\"" \ -d '{ "data": [ [0, 10, "Alex", "2014-01-01 16:00:00"], [1, 20, "Steve", "2015-01-01 16:00:00"], [2, 30, "Alice", "2016-01-01 16:00:00"], [3, 40, "Adrian", "2017-01-01 16:00:00"] ] }' \ random-id.myaccount.snowflakecomputing.app/predict/predict
With a JSON Web Token (JWT), generated after key-pair authentication. Your application authenticates requests to the public endpoint by generating a JWT from your key-pair, exchanging it with Snowflake for an OAuth token, and then that OAuth token is used to authenticate with the public endpoint directly.
For an example of using JWT to authenticate with a public endpoint, see Snowpark Container Services Tutorial -- Access the public endpoint programmatically.
For more information on key-pair authentication in Snowflake, see キーペア認証とキーペアローテーション.
注釈
There are no side effects when calling the service over HTTP. All authorization failures such as an incorrect token or lack of network route to the service result in a 404 error. The service may return 400 or 429 errors when the request body is invalid or the service is busy.
モデルサービス HTTP エンドポイントの使用例については GPU-powered推論のためのHugging Face文型変換器の展開 をご参照ください。
Latency considerations¶
You can use the following options to run inference while hosting a model in Snowpark Container Services. They have different trade-offs with regard to latency expectation and use cases.
HTTP endpoints
HTTP endpoints are best for online or real-time inference and offer the lowest latency of your options. Traffic doesn't go through a warehouse or global Snowflake services, and input data is directly sent to the server after authentication.
SQL
SQL commands are best for batch inference. Input data is sent to the server from a warehouse, which compiles and executes the query. Response data is then written to a cache in the warehouse before being returned to the server. Warehouse transfers, compilation, and execution incur latency. Execution latency is always lower when a cached result is used.
Snowpark Python APIs
Python APIs are backed by SQL commands executed on Snowflake and best-suited for the same purposes as direct SQL. However, latency is affected by the type of
DataFrameused as input. Snowpark DataFrames use data already available in Snowflake and can operate entirely in the same manner as direct SQL. Pandas DataFrames upload their in-memory data to a temporary Snowflake table, which incurs transfer latency.For the lowest latency when using Python APIs, prepare your pandas DataFrames as Snowpark DataFrames before hosting your model.
注釈
Performance evaluations you conduct locally using a pandas DataFrame won't match performance with the same pandas DataFrame that is running on Snowpark Container Services, due to the latency of temporary table creation. For an accurate performance evaluation of your model, use a Snowpark DataFrame as input.
サービスの管理¶
Snowpark Container Servicesは、サービス管理のために SQL インターフェイスを提供します。DESCRIBE SERVICE および ALTER SERVICE コマンドは、他の SPCS サービスの管理と同様に、Snowflake Model Serving で作成された SPCS サービスで使用できます。たとえば、次が可能です。
サービスの MIN_INSTANCES およびその他のプロパティを変更する
サービスのドロップ(削除)
他のアカウントとサービスを共有する
サービスの所有権を変更する(新しい所有者はモデルへのREADアクセス権が必要です)
注釈
サービスのオーナーが何らかの理由で基礎となるモデルへのアクセスを失った場合、サービスは再起動後に動作しなくなります。再起動するまでは動作し続けます。
再現性とデバッグ性を確保するため、既存の推論サービスの仕様を変更することはできません。しかし、仕様をコピーしてカスタマイズし、カスタマイズした仕様を使用して、モデルをホストする独自のサービスを作成することができます。しかしこの方法では、基礎となるモデルが削除されるのを防ぐことはできません。さらに、 系統 を追跡することはできません。Snowflake Modeling Servingがサービスを作成できるようにするのが最善です。
サービスを一時停止します。¶
サービスは最初、非アクティブ状態が30分経過すると一時停止するように構成されています。サービスは、スケジューリングと起動の遅延に従い、新しいリクエストを受け取ると再開します。スケジューリングの遅延はコンピューティングプールの可用性に依存し、起動の遅延はモデルのサイズに依存します。
サービスを手動で一時停止したり再開したりするには、 ALTERSERVICE コマンドを使用してください。
ALTER SERVICE my_service [ SUSPEND | RESUME ];
自動一時停止の動作を手動で設定するには、ALTERSERVICE コマンドをAUTO_SUSPEND_SECS パラメーターと一緒に使用します。
ALTER SERVICE my_service SET AUTO_SUSPEND_SECS = <timeout_in_seconds>;
自動一時停止をオフにするには、AUTO_SUSPEND_SECSを 0に設定します。自動一時停止を元に戻すには、300秒以上のタイムアウト時間を指定します。
詳細については、ALTERSERVICE をご参照ください。
モデルの削除¶
モデルやモデルのバージョンは、 SQL インターフェイスや Python API を使って通常通り管理することができますが、サービスによって(実行中であれ中断中であれ)使われているモデルやモデルのバージョンはドロップ(削除)することができません。モデルまたはモデルのバージョンを削除するには、まずサービスを削除します。
例¶
これらの例は、既にCompute Pool、イメージリポジトリを作成し、必要に応じて権限を付与していることを前提としています。詳細については 前提条件 をご参照ください。
CPU-powered推論のための XGBoost モデルの展開¶
次のコードは、SPCS で推論のためにXGBoostモデルをデプロイし、デプロイされたモデルを推論に使用する主な手順を示しています。この例のノートブック は使用可能です 。
from snowflake.ml.registry import registry
from snowflake.ml.utils.connection_params import SnowflakeLoginOptions
from snowflake.snowpark import Session
from 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=pandas_test_df,
comment="XGBoost model for forecasting customer demand"
)
# Deploy the model to SPCS
model_ref.create_service(
service_name="forecast_model_service",
service_compute_pool="my_cpu_pool",
ingress_enabled=True)
# See all services running a model
model_ref.list_services()
# Run on SPCS
model_ref.run(pandas_test_df, function_name="predict", service_name="forecast_model_service")
# Delete the service
model_ref.delete_service("forecast_model_service")
Since this model has ingress enabled, you can call its public HTTP endpoint. The following example uses a PAT stored in the environment variable PAT_TOKEN to authenticate with a public Snowflake endpoint:
import os
import json
import numpy as np
from pprint import pprint
import requests
def get_headers(pat_token):
headers = {'Authorization': f'Snowflake Token="{pat_token}"'}
return headers
headers = get_headers(os.getenv("PAT_TOKEN"))
# Put the endpoint url with method name `predict`
# The endpoint url can be found with `show endpoints in service <service_name>`.
URL = 'https://<random_str>-<organization>-<account>.snowflakecomputing.app/predict'
# Prepare data to be sent
data = {"data": np.column_stack([range(pandas_test_df.shape[0]), pandas_test_df.values]).tolist()}
# 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)
print(json.loads(results))
GPU-powered推論のためのHugging Face文型変換器の展開¶
次のコードは、 HTTP エンドポイントを含むHugging Face文型変換器をトレーニングおよび展開します。
この例では、 sentence-transformers パッケージ、 GPU コンピューティングプール、イメージリポジトリが必要です。
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
ingress_enabled=True,
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")
SQL では、次のようにサービス関数を呼び出すことができます:
SELECT my_minilm_service!encode('This is a test sentence.');
同様に、 HTTP エンドポイントを次のように呼び出すことができます。
import json
from pprint import pprint
import requests
# Put the endpoint url with method name `encode`
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))
GPU-powered推論のための PyTorch モデルの展開¶
` ディープラーニング推奨モデル(<https://quickstarts.snowflake.com/guide/getting-started-with-running-distributed-pytorch-models-on-snowflake/>)を `_ 推論のために PyTorch にトレーニングしてデプロイする例については、 DLRM次のクイックスタート SPCSGPU をご参照ください。
ベストプラクティス¶
- イメージリポジトリの作成
複数のユーザーやロールが同じモデルを使用することはよくあることです。単一のイメージリポジトリを使用することで、一度構築したイメージをすべてのユーザーが再利用でき、時間と費用を節約できます。レポを使用するすべてのロールには、レポの SERVICE READ 、 SERVICE WRITE 、 READ 、 WRITE の権限が必要です。依存関係を更新するためにイメージを再構築する必要があるかもしれないので、取り消すことをせず、書き込み権限を保持しておくべきです。
- 推論サービスの拡張
Snowpark Container Services の自動スケーリングは非常に保守的で、ほとんどの ML ワークロードに対して十分な速度でスケールアップまたはスケールダウンできません。このため、Snowflake では、 MIN_INSTANCES と MAX_INSTANCES の両方を同じ値に設定し、一般的なワークロードに必要なパフォーマンスが得られるようにこれらの値を選択することを推奨しています。次のように SQL を使用します。
ALTER SERVICE myservice SET MIN_INSTANCES = <new_num> MAX_INSTANCES = <new_num>;
同じ理由で、Pythonの API を使ってサービスを最初に作成する場合、
create_serviceメソッドはmax_instancesのみを受け入れ、min_instancesに同じ値を使用します。- ノードタイプとインスタンス数の選択
モデルがメモリに収まる最小の GPU ノードを使用します。より大きな GPU ノードで
num_workersを増やすのとは対照的に、インスタンス数を増やすことで拡張します。たとえば、モデルが GPU_NV_S (Azureでは GPU_NV_SM)インスタンスタイプに適合する場合、gpu_requests=1を使用し、より大きな GPU インスタンスでgpu_requestsとnum_workersの組み合わせを使用するのではなく、max_instancesを増やしてスケールアップします。- ウェアハウスのサイズの選択
ウェアハウスが大きければ大きいほど、推論サーバーに送られる並列リクエストは多くなります。推論にはコストがかかるので、可能な限り小さなウェアハウスをご使用ください。Mediumより大きなウェアハウスサイズを使用すると、クエリパフォーマンスは向上せず、追加コストが発生します。
トラブルシューティング¶
SPCS 展開の監視¶
次の SQL クエリを使用して起動中のサービスを検査することで、デプロイメントを監視できます。
SHOW SERVICES IN COMPUTE POOL my_compute_pool;
2つのジョブが開始されます。
MODEL_BUILD_xxxxx:名前の衝突を避けるため、名前の最後の文字はランダム化されます。このジョブはイメージを構築し、イメージが構築された後に終了します。イメージがすでに存在する場合は、ジョブはスキップされます。
ログは、パッケージの依存関係の衝突などの問題をデバッグするのに便利です。このジョブのログを見るには、最後の文字が同じになるようにしたうえで以下の SQL を起動します。
CALL SYSTEM$GET_SERVICE_LOGS('MODEL_BUILD_xxxxx', 0, 'model-build');MYSERVICE:
create_serviceへのコールで指定されたサービス名。このジョブは、 MODEL_BUILD のジョブが成功またはスキップされた場合に開始されます。このジョブのログを見るには、以下の SQL を起動します。CALL SYSTEM$GET_SERVICE_LOGS('MYSERVICE', 0, 'model-inference');ビルドジョブまたはサービスが削除されたために
SYSTEM$GET_SERVICE_LOG経由でログが利用可能でない場合、 イベントテーブル (有効な場合)をチェックしてログを見ることができます。SELECT RESOURCE_ATTRIBUTES, VALUE FROM <EVENT_TABLE_NAME> WHERE true AND timestamp > dateadd(day, -1, current_timestamp()) -- choose appropriate timestamp range AND RESOURCE_ATTRIBUTES:"snow.database.name" = '<db of the service>' AND RESOURCE_ATTRIBUTES:"snow.schema.name" = '<schema of the service>' AND RESOURCE_ATTRIBUTES:"snow.service.name" = '<Job or Service name>' AND RESOURCE_ATTRIBUTES:"snow.service.container.instance" = '0' -- choose all instances or one particular AND RESOURCE_ATTRIBUTES:"snow.service.container.name" != 'snowflake-ingress' --skip logs from internal sidecar ORDER BY timestamp ASC;
パッケージの競合¶
サービスコンテナーにインストールされるパッケージは、モデル本体と推論サーバーの2つのシステムによって決定されます。モデルの依存関係との競合を最小限にするために、推論サーバーは以下のパッケージのみを必要とします。
gunicorn<24.0.0
starlette<1.0.0
uvicorn-standard<1.0.0
モデルの依存関係が、上記と同様に、 pip または conda のどちらかによって解決可能であることを確認してください。
モデルに conda_dependencies と pip_requirements の両方が設定されている場合、これらはcondaを介して以下のようにインストールされます。
チャネル
conda-forge
nodefaults
依存関係
all_conda_packages
- pip:
all_pip_packages
Snowflakeはコンテナーイメージをビルドする際に conda-forge からAnacaondaパッケージを取得します。これは、Snowflakeのcondaチャンネルはウェアハウスでのみ利用可能であり、 defaults チャンネルではユーザーがAnacondaの利用規約に同意する必要があるためですが、自動ビルド中には利用できません。defaults のような別のチャンネルからパッケージを取得するには、 defaults::pkg_name のように、各パッケージにチャンネル名を指定します。
注釈
conda_dependencies と pip_requirements の両方を指定すると、2つの依存関係セットに互換性がない場合でもコンテナーイメージは正常にビルドされますが、結果のコンテナーイメージが期待どおりに動作しない可能性があります。Snowflakeでは、 conda_dependencies のみ、または pip_requirements のみを使用することを推奨しており、両方を使用することは推奨しません。
メモリ不足のサービス¶
一部のモデルはスレッドセーフではないため、Snowflakeはワーカープロセスごとにモデルの別個のコピーをメモリにロードします。これは、ワーカー数の多い大規模なモデルでは、メモリ不足を引き起こす可能性があります。num_workers の削減を試します。
不満足のクエリパフォーマンス¶
通常、推論は推論サービスのインスタンス数がボトルネックになります。モデルを展開する際に、 max_instances に高い値を渡してみてください。
サービス仕様を変更できない¶
モデル構築および推論サービスの仕様は、 ALTER SERVICE を使用して変更することはできません。変更できるのは、 TAG 、 MIN_INSTANCES などの属性のみです。しかし、イメージはイメージ・レポで公開されているので、スペックをコピーして修正し、そこから新しいサービスを作成して手動で起動することができます。
パッケージが見つかりません¶
イメージ構築フェーズ中にモデルの展開に失敗しました。model-build ログによると、リクエストされたパッケージが見つかりませんでした。(このステップでは、パッケージが conda_dependencies に記載されている場合、デフォルトで conda-forge を使用します。)
パッケージのインストールは以下のような理由で失敗することがあります。
パッケージ名またはバージョンが無効です。パッケージのスペルとバージョンを確認してください。
リクエストされたバージョンのパッケージは
conda-forgeに存在しません。バージョン指定を削除して、conda-forgeで利用可能な最新バージョンを取得するか、代わりにpip_requirementsを使用してみてください。こちら からすべての利用可能なパッケージを閲覧できます。特別なチャンネル(例:
pytorch)からのパッケージが必要な場合もあります。pytorch::torchのように、channel_name::のプレフィックスを依存関係に追加してください。
Huggingface Hubのバージョン不一致¶
Hugging Faceモデル推論サービスがエラーメッセージで失敗することがあります。
ImportError: huggingface-hub>=0.30.0,<1.0 is required for a normal functioning of this module, but found huggingface-hub==0.25.2
これは、 transformers パッケージが、 huggingface-hub への正しい依存関係を指定せず、代わりにコードでチェックするためです。この問題を解決するには、モデルを再度ログに記録し、今度は conda_dependencies または pip_requirements で huggingface-hub の必要なバージョンを明示的に指定します。
torchが CUDA を有効にしてコンパイルされていません¶
このエラーの典型的な原因は、 conda_dependencies と pip_requirements の両方を指定していることです。パッケージの競合 のセクションで述べたように、 conda はコンテナーイメージのビルドに使用するパッケージ管理です。Anacondaは conda_dependencies と pip_requirements のパッケージを一緒に解決せず、condaパッケージを優先します。これは、condaパッケージがpipパッケージと互換性がないという事態を引き起こしかねません。conda_dependencies ではなく pip_requirements で torch を指定している可能性があります。依存関係を conda_dependencies または pip_requirements に統合することを検討してください。それが不可能な場合は、 conda_dependencies で最も重要なパッケージを指定してください。
推論イメージにカスタムイメージリポジトリを使用する¶
Snowpark Container Servicesにモデルをデプロイすると、Snowflake Model Serving はモデルとその依存関係を保持するコンテナイメージを構築します。このイメージを保存するには、イメージリポジトリが必要です。Snowflakeはデフォルトのイメージリポジトリを提供します。これは、サービスの作成時にリポジトリを指定しない場合、自動的に使用されます。別のリポジトリを使用するには、create_service`メソッドの:code:`image_repo 引数に名前を渡します。
所有していないイメージリポジトリを使用する場合は、コンテナイメージを構築するロールがリポジトリ上で READ、WRITE、SERVICE READ、SERVICE WRITE の権限を持っていることを確認してください。これらの権限を以下のように付与します。
GRANT READ ON IMAGE REPOSITORY my_inference_images TO ROLE myrole;
GRANT WRITE ON IMAGE REPOSITORY my_inference_images TO ROLE myrole;
GRANT SERVICE READ ON IMAGE REPOSITORY my_inference_images TO ROLE myrole;
GRANT SERVICE WRITE ON IMAGE REPOSITORY my_inference_images TO ROLE myrole;
