Bundles de code

Tout collaborateur peut regrouper des procédures Python, des UDFs ou des UDTFs personnalisées avec des modèles de collaboration. Les modèles font à leur tour référence au code regroupé pour effectuer des actions complexes sur les données dans le cadre de la collaboration. L’utilisation courante inclut le machine learning ou la manipulation de données personnalisée dans une requête. Votre code importé peut importer et utiliser des paquets à partir d’un bundle de packages Python approuvés et l’APISnowpark.

Le code personnalisé ne peut être appelé que via des modèles, et pas directement.

Note

Python est le seul langage de codage pris en charge pour les bundles de code.

Les sections suivantes vous montrent comment charger et utiliser des bundles de code.

Mise en œuvre de bundles de code personnalisés

Voici comment charger et utiliser un bundle de code :

Le demandeur de code :

  1. Crée et enregistre le code en appelant REGISTER_CODE_SPEC.

    Le code peut être en ligne dans la spécification, ou lié à une zone de préparation.

  2. Crée un modèle qui fait référence à la spécification du bundle de code par son ID dans le tableau code_specs du modèle. Ajoutez ce champ en tant que pair des champs du modèle et de paramètres, comme indiqué dans cet exemple :

     parameters:
       - name: <parameter_name>
         description: <parameter_description>
         required: <true_or_false>
         default: <default_value>
         type: <data_type>
    
     code_specs:             # Optional: List of code bundles used by this template
     - <code_spec_id>        # One or more code spec IDs.
    
     template: |
       <template_content>
    
  3. Enregistre le modèle, puis lie le modèle à la collaboration.

L’exécuteur d’analyses :

  • Exécute le modèle de la manière standard en appelant RUN.

Important

Snowflake effectue des contrôles de sécurité sur tous les bundles chargés avant de les déployer dans une salle blanche. Si un contrôle de sécurité échoue, le modèle et son code regroupé ne seront pas déployés et disponibles pour l’utilisation.

Pour confirmer qu’un modèle avec un bundle de code est déployé et prêt à l’emploi, procédez comme suit :

  1. Recherchez le nom de l’application de salles blanches dans laquelle vous essayez de déployer le bundle de code :

    SHOW APPLICATIONS LIKE 'SFDCR_<collaboration name>';
    
  2. Vérifiez la valeur upgrade_state dans la réponse DESCRIBE APPLICATION. Lorsque l’état de mise à niveau est COMPLETE, les contrôles de sécurité ont réussi et le nouveau modèle et le nouveau bundle sont disponibles pour l’utilisation. Transmettez le nom de l’application renvoyé par la commande à l’étape précédente en utilisant SQL comme dans l’exemple suivant : code SQL :

    DESCRIBE APPLICATION <application name>
    

Créer et enregistrer la spécification du bundle de code

La première étape du chargement d’un code personnalisé consiste à créer et à enregistrer la spécification du bundle de code.

Les fonctions personnalisées sont définies dans une spécification de bundle de code YAML. Chaque bundle de code expose une ou plusieurs fonctions qui peuvent être appelées par un modèle. La spécification du bundle de code peut soit inclure le code dans la spécification en ligne, soit renvoyer vers un code qui réside sur une zone de préparation Snowflake.

Un collaborateur enregistre une spécification en appelant``REGISTRY.REGISTER_CODE_SPEC``, qui renvoie l’ID du bundle.

Une fois que le modèle qui référence le bundle de code est lié à la collaboration, ce bundle de code est visible par toute personne de la collaboration qui peut accéder à un modèle qui lie le bundle de code. Appelez VIEW_CODE_SPECS pour répertorier les bundles de code accessibles dans une collaboration.

Toute personne pouvant voir un bundle de code dans une collaboration peut le voir et l’utiliser dans ses propres modèles au sein de cette collaboration. Tout code en ligne peut être vu par n’importe quel membre de la collaboration, mais le code d’artefact en zone de préparation ne peut pas être vu par les collaborateurs. Les collaborateurs doivent s’assurer que le content_hash des artefacts référencés correspond à la vérification de l’intégrité du code.

La spécification du bundle de code suivant qui expose une seule UDF Python appelée normalize_value, qui appelle la fonction normalize définie dans cette spécification :

CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.REGISTRY.REGISTER_CODE_SPEC(
  $$
  api_version: 2.0.0
  spec_type: code_spec
  name: custom_udf
  version: v1
  functions:
    - name: normalize_value
      type: UDF
      language: PYTHON
      handler: normalize
      arguments:
        - name: value
          type: FLOAT
      returns: FLOAT
      code_body: |
        def normalize(value):
            return value / 100.0
  $$
);

Créer et enregistrer le modèle appelant

Une fois la spécification de code enregistrée, le collaborateur enregistre un modèle qui utilise ce bundle de code. Pour utiliser un bundle de code, ajoutez l’ID de la spécification du bundle dans le champ code_specs du modèle. L’ajout de ce modèle à la collaboration entraînera également la disponibilité du code regroupé dans la collaboration.

Un modèle appelle une fonction personnalisée à l’aide de la syntaxe cleanroom.spec_name$function_name. Notez les marques littérales de portée de nom . et $.

Note

Utilisez le nom de la spécification, et non l’ID de la spécification, pour référencer une fonction dans votre modèle. Vous pouvez ainsi mettre rapidement à jour la version de votre bundle de code sans avoir à modifier toutes les références qui y sont mentionnées dans votre modèle.

Dans l’exemple suivant, un modèle utilise la fonction normalize_value du bundle de code custom_udf :

CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.REGISTRY.REGISTER_TEMPLATE(
  $$
  api_version: 2.0.0
  spec_type: template
  name: normalization_template
  version: v1
  type: sql_analysis
  code_specs:
    - custom_udf_v1  -- Imports the code bundle.
  template: |
    SELECT cleanroom.custom_udf$normalize_value(100)  -- Calls the UDF.
      AS normalized
        FROM {{ source_tables[0] }}
  $$
);

Ajouter un modèle à une collaboration

Ajoutez le modèle qui appelle votre fonction à la collaboration de manière standard. Pour plus d’informations, voir Modèles.

Snowflake valide et charge vers la collaboration lorsque le modèle appelant est ajouté à une collaboration. L’exemple suivant montre une requête pour ajouter un modèle à une collaboration existante :

CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.COLLABORATION.ADD_TEMPLATE_REQUEST(
  'my_collaboration',
  'normalization_template_v1',
  ['consumer']
);

Note

L’installation d’un modèle avec un bundle de code déclenche un contrôle de sécurité Snowflake et émet un nouveau correctif de la salle blanche sous-jacente. Le modèle ne sera pas disponible ni utilisable tant que le processus ne sera pas terminé et que le correctif n’aura pas été installé.

Pour vérifier la progression de l’installation du correctif :

  1. Recherchez le nom de l’application de la salle blanche. En règle générale, il s’agira de SFDCR_<clean room name>, mais vous pouvez effectuer une recherche pour le vérifier :

    -- Find the exact name of the clean room application.
    SHOW APPLICATIONS LIKE 'SFDCR_%';
    
  2. Vérifiez l’état de l’installation du correctif. Attendez que upgrade_state soit COMPLETE dans la requête suivante :

    DESCRIBE APPLICATION SFDCR_<application name>;
    

Versionnage de votre code

Chaque spécification de code enregistrée doit posséder un nom et une version uniques dans tous les registres de votre compte. Un modèle charge un nom et une version spécifiques d’une spécification de code. Si vous souhaitez créer ou consommer une nouvelle version de votre code, vous devez soumettre une nouvelle version du modèle qui fait référence à la nouvelle version du code dans le champ code_specs. Vous n’avez pas besoin de modifier le corps du modèle. Par exemple :

Étape 1 : consommez la version 1 du bundle de code :

CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.REGISTRY.REGISTER_TEMPLATE(
  $$
  api_version: 2.0.0
  spec_type: template
  name: normalization_template
  version: v1
  type: sql_analysis
  code_specs:
    - custom_udf_v1  -- Bundle ID includes the version number.
  template: |
    SELECT cleanroom.custom_udf$normalize_value(100)  -- Calls the UDF.
      AS normalized
        FROM {{ source_tables[0] }}
  $$
);

Étape 2 : mettez à jour et enregistrez la nouvelle version de votre bundle de code, puis mettez à jour votre modèle pour utiliser la nouvelle version :

CALL SAMOOHA_BY_SNOWFLAKE_LOCAL_DB.REGISTRY.REGISTER_TEMPLATE(
  $$
  api_version: 2.0.0
  spec_type: template
  name: normalization_template
  version: v2        -- Update the template version.
  type: sql_analysis
  code_specs:
    - custom_udf_v2  -- Use the new code bundle.
  template: |
    SELECT cleanroom.custom_udf$normalize_value(100)  -- No change needed here.
      AS normalized
        FROM {{ source_tables[0] }}
  $$
);

Notez que les noms de fonctions n’incluent pas la version, de sorte que vous n’avez pas besoin de modifier le code d’appel dans le corps du modèle lorsque vous chargez une nouvelle version d’une fonction.

Exemples de spécifications

UDF en ligne avec corps de code

Une UDF simple avec du code Python en ligne :

api_version: 2.0.0
spec_type: code_spec
name: string_utils
version: v1
description: String utility functions

functions:
  - name: clean_string
    type: UDF
    language: PYTHON
    runtime_version: "3.10"
    handler: clean
    arguments:
      - name: input_str
        type: STRING
    returns: STRING
    description: Removes leading/trailing whitespace and converts to lowercase
    code_body: |
      def clean(input_str):
          if input_str is None:
              return None
          return input_str.strip().lower()

  - name: extract_domain
    type: UDF
    language: PYTHON
    runtime_version: "3.10"
    handler: extract
    arguments:
      - name: email
        type: STRING
    returns: STRING
    description: Extracts domain from email address
    code_body: |
      def extract(email):
          if email is None or '@' not in email:
              return None
          return email.split('@')[1]

UDTF (Fonction de table définie par l’utilisateur)

Cet exemple de YAML définit une UDTF qui renvoie plusieurs lignes :

api_version: 2.0.0
spec_type: code_spec
name: tokenizer
version: v1
description: Text tokenization UDTF

functions:
  - name: tokenize_text
    type: UDTF
    language: PYTHON
    runtime_version: "3.10"
    handler: Tokenizer
    arguments:
      - name: text
        type: STRING
      - name: delimiter
        type: STRING
    returns: TABLE(token STRING, position INTEGER)
    description: Splits text into tokens and returns each with its position
    code_body: |
      class Tokenizer:
          def process(self, text, delimiter):
              if text is None:
                  return
              tokens = text.split(delimiter if delimiter else ' ')
              for i, token in enumerate(tokens):
                  yield (token.strip(), i)

Artefact en zone de préparation avec paquet de roue

Assurez-vous de consulter les exigences de la documentation stage_path pour la liaison vers un code en zone de préparation dans votre spécification de code.

Cet exemple de YAML utilise un paquet de roue Python en zone de préparation :

api_version: 2.0.0
spec_type: code_spec
name: ml_scoring
version: v2
description: ML scoring functions using custom library

artifacts:
  - alias: ml_lib
    stage_path: "@MY_DB.PUBLIC.CODE_STAGE/libs/ml_scoring_lib-1.0.0-py3-none-any.whl"
    description: Custom ML scoring library
    content_hash: "a1b2c3d4e5f6..."

functions:
  - name: predict_score
    type: UDF
    language: PYTHON
    runtime_version: "3.10"
    handler: ml_scoring_lib.predictor.predict
    arguments:
      - name: features
        type: ARRAY
    returns: FLOAT
    packages:
      - numpy
      - scikit-learn
    imports:
      - ml_lib
    description: Predicts score using trained ML model

Procédure stockée

Cet exemple de YAML définit une procédure stockée pour le traitement des données :

api_version: 2.0.0
spec_type: code_spec
name: data_processor
version: v1
description: Data processing procedures

procedures:
  - name: aggregate_metrics
    language: PYTHON
    runtime_version: "3.10"
    handler: process
    arguments:
      - name: table_name
        type: STRING
      - name: group_column
        type: STRING
    returns: STRING
    packages:
      - snowflake-snowpark-python
    description: Aggregates metrics by specified column
    code_body: |
      def process(session, table_name, group_column):
          df = session.table(table_name)
          result = df.group_by(group_column).count()
          result.write.mode("overwrite").save_as_table("aggregated_results")
          return f"Aggregated {df.count()} rows into aggregated_results"

Plusieurs fichiers Python comme artefacts en zone de préparation

Assurez-vous de consulter les exigences de la documentation stage_path pour la liaison vers un code en zone de préparation dans votre spécification de code.

Cet exemple de YAML utilise plusieurs fichiers sources Python en zone de préparation :

api_version: 2.0.0
spec_type: code_spec
name: analytics_suite
version: v3
description: Analytics suite with multiple modules

artifacts:
  - alias: utils
    stage_path: "@MY_DB.PUBLIC.CODE_STAGE/analytics/utils.py"
    description: Utility functions
  - alias: transformers
    stage_path: "@MY_DB.PUBLIC.CODE_STAGE/analytics/transformers.py"
    description: Data transformation functions
  - alias: validators
    stage_path: "@MY_DB.PUBLIC.CODE_STAGE/analytics/validators.py"
    description: Validation functions

functions:
  - name: transform_and_validate
    type: UDF
    language: PYTHON
    runtime_version: "3.10"
    handler: transformers.transform_validate
    arguments:
      - name: data
        type: OBJECT
    returns: OBJECT
    imports:
      - utils
      - transformers
      - validators
    description: Transforms and validates input data