クリーンルームでカスタム関数をアップロードして実行する¶
概要¶
カスタムPython UDFs および UDTFs をクリーンルームにアップロードし、テンプレートから実行して複雑なデータアクションを実行します。これらのアクションには、単一のステップまたは :doc:`複数のステップフロー </user-guide/cleanrooms/multistep-flows>`の一部として、クエリ内での機械学習やカスタマイズされたデータ操作が含まれます。Pythonは、カスタム UDFs でサポートされている唯一のコーディング言語です。
アップロードされたコードは、Pythonパッケージの承認済みバンドル および Snowpark API からパッケージをインポートして、使用できます。
クリーンルームのテンプレートは、そのテンプレートを追加したアカウントによってアップロードされたコードを呼び出すことができます。アップロードされたコードは表示したりダウンロードしたりできません。Snowflakeは、アップロードされたコードをインストールする前に、そのコードのセキュリティ問題をスキャンします。
ロールに応じて、クリーンルームにコードをアップロードするメカニズムは異なります。
プロバイダー
インラインコードアップロード:クリーンルームにデフォルトのコンピューティングリソースを使用してコードをアップロードし、Pythonパッケージの標準バンドル(Snowpark API を含む)のみを使用する必要がある場合は、インラインコードをアップロードする必要があります。
クリーンルーム内で実行されるSnowpark Container Services:追加のコンピューティングライブラリやカスタムライブラリを指定するなど、環境をより細かく制御する必要がある場合は、クリーンルーム内でコンテナを実行できます。
コンシューマー
テンプレートによるインラインアップロード:コンシューマーは、コードがバンドルされているテンプレートをアップロードして実行することができます。コードはテンプレートにバインドされており、クリーンルームプロバイダーの承認が必要です。
このトピックは、カスタムPython UDFs および UDTFs をプロバイダーまたはコンシューマーとしてアップロードし、実行する方法を示しています。
Tip
クリーンルームで独自のPython UDFs を開発する方法に関する背景情報については、以下のトピックをご参照ください。
SnowflakeでPython関数を記述する方法に関する一般的な背景情報については、Snowflakeでの UDFs の仕組み。
関数からテーブルを返す場合は、Snowflakeで UDTFs を記述する方法。
:doc:`カスタムテンプレートを作成し、クリーンルームにアップロードする方法。</user-guide/cleanrooms/demo-flows/custom-templates>`UDFs/UDTFs は、カスタムテンプレートから呼び出されます。
:doc:`クリーンルームでのSnowparkの使用 </user-guide/cleanrooms/demo-flows/snowpark>`(Snowparkから UDFs を呼び出したい場合)。
アップロードされたコードのエントリポイント¶
アップロードされたコードの各バンドルは、お互いを呼び出す複数の関数を定義できますが、バンドルは1つのハンドラー関数のみを公開します。このハンドラー関数は、クリーンルームを使用するユーザーが作成または実行するテンプレートから呼び出すことができます。コードが内部テーブルを作成する場合、マルチステップフローのデザイン で説明されているようにそれらのテーブルにアクセスできます。
たとえば、2つの数値パラメーターを受け取る simple_add という名前の関数をアップロードした場合、ここに示すようにテンプレートから呼び出すことができます。関数は常にスコープ cleanroom を使用して参照されます。たとえば、テンプレートはこのような simple_add を呼び出すことができます。
Tip
プロバイダーが上記のコードを実行したい場合、結果テーブルがバックグラウンドで生成されるため、集計またはカスタム関数を使用するすべての SELECT 列にエイリアスを作成する必要があります。
1つのパッケージで複数の関数をアップロードでき、1つのパッケージ内の関数は相互に呼び出しできますが、関数は他のパッケージ内の関数を呼び出すことはできません。(ハンドラー関数を呼び出すことはできますが。)たとえば、各パッケージにハンドラー関数と2つのヘルパー関数がある2つのパッケージをクリーンルームにアップロードするとします。
パッケージ1 |
パッケージ2 |
|---|---|
|
|
いずれかの当事者(プロバイダーまたはコンシューマー)がアップロードしたコードは、どちらの当事者が提出したテンプレートでも実行できます。
テンプレートは関数Aまたは関数Bを呼び出すことができますが、A1、A2、B1、またはB2は呼び出すことができません。
関数Aは関数Bを呼び出し、その逆も可能です。
関数AはB1またはB2を呼び出すことができず、関数BはA1またはA2を呼び出すことはできません。
A1はA2を呼び出し、その逆も可能です。A1とA2はBを呼び出すことができます。A1とA2はB1またはB2を呼び出すことはできません。
B1はB2を呼び出し、その逆も可能です。B1とB2はAを呼び出すことができます。B1とB2はA1またはA2を呼び出すことはできません。
カスタム関数の更新または削除¶
既存の関数またはアップロードしたテンプレートをアップロードしたり、上書きしたりすることはできますが、既存の関数またはテンプレートを削除することはできません。関数を「削除」する唯一の方法は、常に成功するまったく同じ名前と署名を持つダミー関数を作成することです。
以前にアップロードしたものと同じ署名を持つ関数をアップロードすると、既存の関数が上書きされます。ここでは署名とは、外部ハンドラーの大文字と小文字を区別しない関数名と、その引数すべてのデータ型を同じ順序で並べたものを意味します。引数名は署名の一部ではありません。他のアカウントがアップロードした関数を上書きすることはできません。
関数を更新するときに署名が一致する必要があるため、既存の関数の署名を変更することはできません。関数 foo(name VARIANT age INTEGER) をアップロードしてから、関数 foo(name VARIANT age FLOAT) をアップロードすると、引数の型が異なるため、最初の関数に加えて、2番目の関数がクリーンルームに追加されます。
プロバイダー送信コード¶
プロバイダー送信関数は、インラインコードとして、またはSnowflakeステージからアップロードできます。両方の手法はここで説明されています。
アップロードされたコードは、Pythonパッケージの承認済みセット からネイティブにパッケージをインポートして、使用できます。デフォルト以外のパッケージが必要な場合は、クリーンルームでのSnowpark Container Services を使用してコードをホストする必要があります。
自分のコードであっても、アップロードされたコードは表示できません。そのため、必ずクリーンルームにアップロードするものの正確なコピーを追加してください。
概要¶
プロバイダーがクリーンルームにコードを追加する方法の概要は次のとおりです。
プロバイダーは通常の方法でクリーンルームを作成し、構成します。
プロバイダーは
provider.load_python_into_cleanroomを呼び出してバンドルをアップロードします。そのプロシージャ内で直接 コードをインラインでアップロードする して、そのプロシージャにステージの場所を提供できます。各バンドルには複数の関数を含めることができますが、アップロードごとに公開されるハンドラー関数は1つだけです。複数の関数をテンプレートに公開するには、各ハンドラーを個別にアップロードするか、一括アップロード(後述)を実行します。
クリーンルームが外部に公開されている場合、コードがクリーンルームにインストールされる前にセキュリティチェックが実行されます。
provider.view_cleanroom_scan_statusを呼び出して、デフォルトバージョンをインクリメントする前に、セキュリティチェックに合格したことを確認します。アップロードが成功するたびに、 クリーンルームの新しいパッチバージョンが生成されます。その後、新しいパッチ番号を使用して
provider.set_default_release_directiveを呼び出し、デフォルトバージョンを増やす必要があります。コードのハンドラーを呼び出すカスタムテンプレートを作成し、アップロードします。テンプレートは、
cleanroomスコープを使用するハンドラー関数、つまりcleanroom.my_function(...)を呼び出す必要があります。コンシューマーは、他のテンプレートと同じ方法でテンプレートを実行します。
Tip
コンシューマーがカスタムコードでクリーンルームをインストールする際にマウントエラーが発生した場合、これはコードの構文エラーを示している可能性があります。
このフローを示すコード例は、プロバイダー記述コードの例セクション にあります。
バージョン管理に関する重要な注意事項¶
プロバイダーが関数をアップロードするたびに、クリーンルームのパッチ番号は増えます(パッチ番号99が上限)。そのため、クリーンルームにコードを追加する前に、コードを徹底的にテストし、デバッグを行い、開発中のバージョン更新を減らすようにしてください。
単一の一括アップロード で複数のパッケージを一度にアップロードすると、生成されるパッチの数を減らすことができます。ただし、一括アップロードでは、アップロードにセキュリティスキャン問題がある場合、問題の原因となったファイルがエラー応答で報告されないため、デバッグがより困難になる可能性があります。
パッチ番号を更新した場合、クリーンルーム UI を使用しているカスタマーは、変更を確認するためにページの更新が必要になる場合があります。API を使用しているカスタマーはすぐに変更を確認できるはずですが、利用可能なリソースによっては、遅延が発生する可能性があります。クリーンルームのバージョン管理の詳細。
プロバイダー記述のインライン関数のアップロード¶
provider.load_python_into_cleanroom の code パラメーターにコードをインラインでアップロードできます。単純な関数をインラインでアップロードする例を次に示します。
呼び出しテンプレートは cleanroom.simple_add を呼び出してこの関数を呼び出します。この プロバイダーの例 は、インラインコードをアップロードする方法を示しています。
ステージからのプロバイダー記述関数のアップロード¶
Pythonファイルをクリーンルームステージにアップロードし、 provider.load_python_into_cleanroom を呼び出すときにステージを参照することができます。ステージからコードをロードすると、ローカルシステムのエディターでコードを開発でき、インラインでロードするときのコピー/ペーストのエラーが回避され、ソースコードのバージョン管理も改善されます。1回のプロシージャ呼び出しで複数のファイルをアップロードできますが、アップロードごとに公開されるハンドラー関数は1つだけであることに注意してください。
load_python_into_cleanroom を呼び出すと、コードがクリーンルームからステージにロードされます。後からステージ上でコードを変更しても、クリーンルームに伝播しません。
UDF をステージにアップロードするには、以下を実行します。
.pyファイルを作成し、Snowsightステージにアップロードできる場所で利用できるようにします。
クリーンルームのステージ名を取得するには、
provider.get_stage_for_python_filesを呼び出します。指定されたステージを使用する必要があります。自分が作成した任意のステージは使用できません。.pyファイルをクリーンルームのステージにアップロードします。CLI、Snowsight、言語固有のドライバーなど、これを行うには複数の方法 があります。
ステージの場所、ハンドラー、外部名、引数、戻り型で``provider.load_python_into_cleanroom`` を呼び出します。クリーンルームのテンプレートが関数を呼び出せるようになりました。
次のコード例は、ステージからクリーンルームにコードをロードする方法を示しています。
プロバイダーの例 は、ステージからのコードのアップロードを示しています。
アップロードされたコードの構文エラーやスキャン失敗のトラブルシューティング¶
構文エラーにより失敗する関数をアップロードした場合や、セキュリティスキャンが失敗した場合は、公開されていないパッチが生成される可能性があります。したがって、アップロード前にコードを徹底的にテストし、構文エラーがないことを確認する必要があります。
次の SQL コマンドを実行すると、パッケージのリストとレビューステータスを確認でき、示された場所にクリーンルーム ID が表示されます。
SHOW VERSIONS IN APPLICATION PACKAGE samooha_cleanroom_cleanroom_id;
セキュリティスキャン¶
セキュリティスキャンは、プロバイダーがPythonをクリーンルームにアップロードするときなど、外部クリーンルームで新しいパッチバージョンを生成するアクションの後に実行されます。(このページで説明されているコンシューマーが送信するコードは、セキュリティスキャンをトリガーません。)内部クリーンルームはセキュリティスキャンを実行しませんが、内部クリーンルームを外部クリーンルームに変更すると、そのパッチのセキュリティスキャンがトリガーされます。パッチがスキャンされるまで、クリーンルームのパッチを外部で公開することはできません。
Snowflake Data Clean Roomsは:doc:Snowflake Native Appのセキュリティスキャンフレームワーク</developer-guide/native-apps/security-run-scan>`を使用します。:doc:`ネイティブアプリのセキュリティのベストプラクティス </developer-guide/native-apps/security-app-requirements> に従い、セキュリティスキャンエラーを回避します。
最後のセキュリティスキャンが完了する前に、追加のパッチ作成アクションを実行できます。ただし、provider.view_cleanroom_scan_status を待って、クリーンルームの最新バージョンを使用するための、デフォルトのリリースディレクティブを更新する前に成功を示す必要があります。
単一のパッチによる複数のPython関数のアップロード(一括アップロード)¶
複数のPythonパッケージをクリーンルームにアップロードしたい場合は、 prepare_python_for_cleanroom を複数回呼び出すことができます。その後 load_prepared_python_into_cleanroom を1回呼び出してクリーンルーム用の単一のパッチをスキャン、アップロード、生成します。次の例は、一括アップロードを使用した UDF および UDTF のアップロードを示しています。
プロバイダー記述コードの例¶
次の例は、プロバイダー記述の UDFs および UDTFs のクリーンルームへの追加を示しています。
以下の例をダウンロードし、Snowflakeアカウントにワークシートファイルとしてアップロードします。プロバイダーとコンシューマーには、それぞれクリーンルーム APIがインストールされた別々のアカウントが必要です。サンプルファイルに示されているように情報を置き換えます。 SQL ワークシートをSnowflakeアカウントにアップロードする手順をご確認ください 。
:download:`ステージからのファイルのロード </samples/clean-rooms/udf_from_stage.ipynb>`プロバイダーの例を実行した後にこのノートブックを実行し、ステージから UDF のロードを試みます。
単一のパッチで複数のPython関数をアップロードします。これは単一アカウントの内部テストクリーンルームです。同じアカウントをプロバイダーロールとコンシューマーロールの両方に使用することができます。
コンシューマー送信コード¶
コンシューマーがアップロードしたコードはバンドルされ、コンシューマーのテンプレートアップロードフロー を使用したカスタムテンプレートでアップロードされます。アップロードされたコードは、クリーンルームのどのテンプレートからでも呼び出すことができます。
コンシューマーとしてコードをアップロードするには、カスタムテンプレート構文 を理解する必要があります。
コンシューマーがアップロードするコードは、アップロードの権限をリクエストする際に、プロバイダーに表示される可能性があることに注意してください。コンシューマーコードは、プロバイダーまたはコンシューマーがテンプレートを調べるときにも表示されます。
カスタムコンシューマーコードをアップロードする手順の概要は次のとおりです。
プロバイダーは標準的な方法でクリーンルームを作成し、コンシューマーを招待します。
コンシューマーは標準的な方法でクリーンルームをインストールし、構成します。
コンシューマーは、
cleanroom名前空間の中で UDF または UDTF を呼び出すテンプレートを準備します。たとえば、コンシューマー定義のcalculate_tax関数を呼び出す場合、簡潔なテンプレートは次のスニペットのようになります。コンシューマーはPythonコードを準備します。後で余計なエスケープが必要にならないよう、コード内では一重引用符(
' ')ではなく二重引用符(" ")を使用することをお勧めします。コードは これらのサポートされているPythonライブラリ を参照できます。コンシューマーはPythonコードを
consumer.generate_python_request_templateに渡します。プロシージャは、カスタム JinjaSQL テンプレートのプレースホルダーと一緒にPythonコードをストアドプロシージャとして返します。$$を複数行の区切り文字として使用するテンプレートには、複数行の文字列がいくつかあります。コンシューマーは、
generate_python_request_templateからの出力のテンプレートホルダーを JinjaSQL テンプレートに置き換えます。結合されたテンプレートでは、一重引用符
\'をエスケープします。これは、複数行のプロシージャ文字列全体の最も外側の区切り文字として一重引用符が使用されるためです。以下は、コンシューマーPythonコードとカスタムテンプレートを含み、文字エスケープされたストアドプロシージャの例です。コンシューマーは、テンプレートを組み合わせた
consumer.create_template_requestを呼び出します。template_definition引数のストアドプロシージャに提供するコードに、二重ドル記号区切り文字($$...$$)の代わりに一重引用符(' ')を使用します。例:コンシューマーとプロバイダーは標準の コンシューマー定義のテンプレートフロー を使用して続行します。
プロバイダーはテンプレートリクエスト(
provider.list_pending_template_requests)を表示してから、approve_template_requestを呼び出してリクエストを承認します。リクエストで、プロバイダーはテンプレートとバンドルコードを確認できます。コンシューマーは、リクエストのステータスを確認します(
consumer.list_template_requests)。ステータスが APPROVED になったら、テンプレートを実行します(consumer.run_analysis)。
コンシューマーコードのアップロードが、セキュリティスキャンをトリガーしたり、クリーンルームのパッチ番号に影響を与えたりすることはありません。
コンシューマー記述コードの例¶
次の例は、プロバイダー記述の UDFs のクリーンルームへの追加を示しています。
以下の例をダウンロードし、Snowflakeアカウントにワークシートファイルとしてアップロードします。プロバイダーとコンシューマーには、それぞれクリーンルーム APIがインストールされた別々のアカウントが必要です。サンプルファイルに示されているように情報を置き換えます。 SQL ワークシートをSnowflakeアカウントにアップロードする手順をご確認ください 。