Snowflake Tasks Recipe (Preview)
Register two Snowflake ML Jobs and two Tasks that train and score a Kumo Engine model with MLOps turned on. When you finish this page, a train task runs every Sunday at 02:00 UTC: it fits the model on your Snowflake tables, stores it under a Snowflake stage, records the fit in Snowflake Experiment Tracking, and publishes a new version of USERS_CHURN in the Snowflake Model Registry with the champion alias. A score task runs daily at 03:00 UTC: it loads the version that holds champion, scores your users with trainer.predict() as in Score in Batch, and appends the scores to the table USERS_CHURN_PREDICTIONS. By default every train run moves champion, so a new version is used without review; see Review Before Promoting.
This recipe is in preview. It uses ML Job definitions (MLJobDefinition), a preview Snowflake API, and the statement they generate to run a job from a Task is not documented by Snowflake; both can change without notice. Nothing in this recipe has been registered or run yet.
The jobs and tasks come from examples/mlops/snowflake in the Kumo Engine repository. Each job runs one of the job scripts in examples/mlops, fit_job.py or score_job.py, on a Snowpark Container Services compute pool, on an example graph of users, items, and orders. They run the same kumo.MLOps workflow as Turn On MLOps, with a stage as the artifact root and Snowflake as the tracker and registry. To use your own graph, edit build_graph, QUERY, and TEXT_COLUMNS in jobs.py as described in Adapt the Template. For text columns, pass the wheel with [snowflake,text] as the --requirement.
The examples use the database ML and the schema MODELS. The source tables, stages, tasks, model, experiment, and predictions table all live in one schema; replace ML.MODELS with yours throughout.
Before You Start
You need:
- Three tables in one schema:
USERSwith primary keyUSER_ID,ITEMSwith primary keyITEM_ID, andORDERSwith primary keyORDER_ID, time columnORDER_TIME, and the foreign keysUSER_IDandITEM_ID. The default query needs a few months of orders. - A warehouse, which the tasks and the jobs’ queries use.
- A GPU compute pool for the jobs, created with
CREATE COMPUTE POOL. - An external access integration with a network rule that allows PyPI, from which each job installs the Kumo Engine wheel’s dependencies.
- The
kumo-enginewheel, from PyPI or the Kumo Engine releases page. Turn On MLOps shows how to check that a build includes MLOps. - A local Python environment with that wheel installed with the
snowflakeextra, and aconnections.tomlentry for the role that will own the tasks.
The role that owns the tasks needs:
Create the Stages
Create a stage for the job payloads and a stage for the artifact root. The artifact root stage needs server-side encryption:
SHOW STAGES IN SCHEMA ML.MODELS lists both.
Add the Wheel to the Job Payload
Clone the Kumo Engine repository. Each job uploads the examples/mlops directory as its payload and installs its requirements inside it, so copy the kumo-engine wheel into a wheels directory there:
The job refers to the wheel by its path in the payload, ./wheels/<wheel>.whl. A stage path does not work there, because pip cannot read from a stage.
Register the Jobs and Tasks
Run register_jobs.py with your connection, compute pool, stages, location, and warehouse. Replace the placeholders; <eai> is your external access integration:
The command registers the ML Job definitions KUMO_TRAIN and KUMO_SCORE, creates the tasks ML.MODELS.KUMO_TRAIN_TASK and ML.MODELS.KUMO_SCORE_TASK, and prints each task’s state:
--model-name (default USERS_CHURN, also used as the experiment name), --table-prefix (default empty, a prefix of the table names such as DEMO_), and --on-error (default raise) are passed to both jobs, and --predictions-table (default USERS_CHURN_PREDICTIONS) to the score job. A task is suspended after three failures in a row.
Run the Tasks Once
New tasks are suspended. Run the train task once, then the score task, and check each before you turn on the schedules:
Check the task’s runs:
STATE shows whether the task ran, but a failed job might not fail its task, so also check the job and its outputs. List the recent jobs with their name and status, using the same connection, then print a job’s log. Replace <job name> with a name from the list:
A finished job’s status is DONE, and the train job’s log ends with model: models/<model id>. A successful train run also leaves:
- A new version of
ML.MODELS.USERS_CHURNthat holdschampion, listed bySHOW VERSIONS IN MODEL ML.MODELS.USERS_CHURN. - A fit run in the experiment
USERS_CHURN, in Snowsight under AI & ML, then Experiments. - The snapshot, training table, and model under
@ML.MODELS.KUMO/kumo, listed byLIST @ML.MODELS.KUMO/kumo.
Then run the score task:
A successful score run appends one row per user to ML.MODELS.USERS_CHURN_PREDICTIONS, with the prediction run’s id in PREDICTION_ID and the model id in BUNDLE_ID, and stores the prediction run under the artifact root.
Turn On the Schedules
Resume both tasks:
SHOW TASKS IN SCHEMA ML.MODELS shows both tasks as started. The train task runs Sundays at 02:00 UTC and the score task daily at 03:00 UTC.
Running register_jobs.py again replaces both jobs and tasks, and resumes each task that was started.
Review Before Promoting
Every train run moves champion to its new version, so the next score run uses it. To review each version first, make the train job move candidate instead: in register_jobs.py, change job_args=(flags if kind == 'train' else ... to job_args=([*flags, '--alias', 'candidate'] if kind == 'train' else ..., then run register_jobs.py again. Move champion yourself as described in Promote a Version.