diff --git a/.github/workflows/sdk-featurestore_sample-test_featurestore_cli_samples.yml b/.github/workflows/sdk-featurestore_sample-test_featurestore_cli_samples.yml new file mode 100644 index 0000000000..a31b9cb64a --- /dev/null +++ b/.github/workflows/sdk-featurestore_sample-test_featurestore_cli_samples.yml @@ -0,0 +1,80 @@ +# This code is autogenerated. +# Code is generated by running custom script: python3 readme.py +# Any manual changes to this file may cause incorrect behavior. +# Any manual changes will be overwritten if the code is regenerated. + +name: sdk-featurestore_sample-test_featurestore_cli_samples +# This file is created by sdk/python/readme.py. +# Please do not edit directly. +on: + workflow_dispatch: + schedule: + - cron: "56 10/12 * * *" + pull_request: + branches: + - main + paths: + - sdk/python/featurestore_sample/** + - .github/workflows/sdk-featurestore_sample-test_featurestore_cli_samples.yml + - sdk/python/dev-requirements.txt + - infra/bootstrapping/** + - sdk/python/setup.sh +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: check out repo + uses: actions/checkout@v2 + - name: setup python + uses: actions/setup-python@v2 + with: + python-version: "3.8" + - name: pip install notebook reqs + run: pip install -r sdk/python/dev-requirements.txt + - name: azure login + uses: azure/login@v1 + with: + creds: ${{secrets.AZUREML_CREDENTIALS}} + - name: bootstrap resources + run: | + echo '${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}'; + bash bootstrap.sh + working-directory: infra/bootstrapping + continue-on-error: false + - name: setup SDK + run: | + source "${{ github.workspace }}/infra/bootstrapping/sdk_helpers.sh"; + source "${{ github.workspace }}/infra/bootstrapping/init_environment.sh"; + bash setup.sh + working-directory: sdk/python + continue-on-error: true + - name: setup-cli + run: | + source "${{ github.workspace }}/infra/bootstrapping/sdk_helpers.sh"; + source "${{ github.workspace }}/infra/bootstrapping/init_environment.sh"; + bash setup.sh + working-directory: cli + continue-on-error: true + - name: setup feature-store resources + run: | + bash -x setup-resources-cli.sh test_featurestore_cli_samples.ipynb + working-directory: sdk/python/featurestore_sample + continue-on-error: true + - name: run featurestore_sample/test_featurestore_cli_samples.ipynb + run: | + source "${{ github.workspace }}/infra/bootstrapping/sdk_helpers.sh"; + source "${{ github.workspace }}/infra/bootstrapping/init_environment.sh"; + bash "${{ github.workspace }}/infra/bootstrapping/sdk_helpers.sh" generate_workspace_config "../../.azureml/config.json"; + bash "${{ github.workspace }}/infra/bootstrapping/sdk_helpers.sh" replace_template_values "test_featurestore_cli_samples.ipynb"; + [ -f "../../.azureml/config" ] && cat "../../.azureml/config"; + papermill -k python test_featurestore_cli_samples.ipynb test_featurestore_cli_samples.output.ipynb + working-directory: sdk/python/featurestore_sample + - name: upload notebook's working folder as an artifact + if: ${{ always() }} + uses: actions/upload-artifact@v2 + with: + name: test_featurestore_cli_samples + path: sdk/python/featurestore_sample diff --git a/sdk/python/featurestore_sample/featurestore_cli_job.py b/sdk/python/featurestore_sample/featurestore_cli_job.py new file mode 100644 index 0000000000..598fe31fa1 --- /dev/null +++ b/sdk/python/featurestore_sample/featurestore_cli_job.py @@ -0,0 +1,33 @@ +from pyspark.sql import SparkSession + +spark = SparkSession.builder.appName("AccessData").getOrCreate() + +import os + +for path, subdirs, files in os.walk("./"): + for name in files: + print(os.path.join(path, name)) + +print("=======Test CLI Notebook 1============") +with open( + "notebooks/sdk_and_cli/1. Develop a feature set and register with managed feature store.py" +) as f: + exec(f.read()) + +print("=======Test CLI Notebook 2============") +with open( + "notebooks/sdk_and_cli/2. Enable materialization and backfill feature data.py" +) as f: + exec(f.read()) + +print("=======Test CLI Notebook 3============") +with open( + "notebooks/sdk_and_cli/3. Experiment and train models using features.py" +) as f: + exec(f.read()) + +print("=======Test CLI Notebook 4============") +with open( + "notebooks/sdk_and_cli/4. Enable recurrent materialization and run batch inference.py" +) as f: + exec(f.read()) diff --git a/sdk/python/featurestore_sample/notebooks/sdk_and_cli/1. Develop a feature set and register with managed feature store.ipynb b/sdk/python/featurestore_sample/notebooks/sdk_and_cli/1. Develop a feature set and register with managed feature store.ipynb index 43f3dd4b3e..fe745c5b4c 100644 --- a/sdk/python/featurestore_sample/notebooks/sdk_and_cli/1. Develop a feature set and register with managed feature store.ipynb +++ b/sdk/python/featurestore_sample/notebooks/sdk_and_cli/1. Develop a feature set and register with managed feature store.ipynb @@ -216,7 +216,7 @@ "\n", "# Please update your alias belpw (or any custom directory you uploaded the samples to).\n", "# You can find the name from the directory structure in the left nav\n", - "root_dir = \"./Users//featurestore_sample\"\n", + "root_dir = \"./Users//featurestore_sample\"\n", "\n", "if os.path.isdir(root_dir):\n", " print(\"The folder exists.\")\n", @@ -258,7 +258,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -282,7 +285,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -399,7 +405,7 @@ "# You can optionally replace them to create the resources in a different subsciprtion/resourceGroup, or use existing resources\n", "import os\n", "\n", - "featurestore_name = \"my-featurestore\"\n", + "featurestore_name = \"\"\n", "featurestore_location = \"eastus\"\n", "featurestore_subscription_id = os.environ[\"AZUREML_ARM_SUBSCRIPTION\"]\n", "featurestore_resource_group_name = os.environ[\"AZUREML_ARM_RESOURCEGROUP\"]" @@ -435,7 +441,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -726,7 +735,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -767,7 +779,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ diff --git a/sdk/python/featurestore_sample/notebooks/sdk_and_cli/2. Enable materialization and backfill feature data.ipynb b/sdk/python/featurestore_sample/notebooks/sdk_and_cli/2. Enable materialization and backfill feature data.ipynb index 90e8fea73e..11af53f320 100644 --- a/sdk/python/featurestore_sample/notebooks/sdk_and_cli/2. Enable materialization and backfill feature data.ipynb +++ b/sdk/python/featurestore_sample/notebooks/sdk_and_cli/2. Enable materialization and backfill feature data.ipynb @@ -158,7 +158,7 @@ "\n", "# please update the dir to ./Users/{your-alias} (or any custom directory you uploaded the samples to).\n", "# You can find the name from the directory structure inm the left nav\n", - "root_dir = \"./Users//featurestore_sample\"\n", + "root_dir = \"./Users//featurestore_sample\"\n", "\n", "if os.path.isdir(root_dir):\n", " print(\"The folder exists.\")\n", @@ -199,7 +199,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -223,7 +226,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -247,7 +253,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -334,7 +343,7 @@ "outputs": [], "source": [ "# use the same name from part #1 of the tutorial\n", - "featurestore_name = \"my-featurestore\"\n", + "featurestore_name = \"\"\n", "# use the same location from part #1 of the tutorial\n", "featurestore_location = \"eastus\"\n", "# use the subscription of the project workspace by default\n", @@ -461,10 +470,10 @@ "\n", "storage_subscription_id = os.environ[\"AZUREML_ARM_SUBSCRIPTION\"]\n", "storage_resource_group_name = os.environ[\"AZUREML_ARM_RESOURCEGROUP\"]\n", - "storage_account_name = \"fstorestorage\"\n", + "storage_account_name = \"\"\n", "# feature store location is used by default. You can change it.\n", "storage_location = featurestore_location\n", - "storage_file_system_name = \"offlinestore\"" + "storage_file_system_name = \"\"" ] }, { @@ -496,7 +505,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -520,7 +532,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -653,7 +668,7 @@ "# User assigned managed identity values. Optionally you may change the values.\n", "uai_subscription_id = os.environ[\"AZUREML_ARM_SUBSCRIPTION\"]\n", "uai_resource_group_name = os.environ[\"AZUREML_ARM_RESOURCEGROUP\"]\n", - "uai_name = \"fstoreuai\"\n", + "uai_name = \"\"\n", "# feature store location is used by default. You can change it.\n", "uai_location = featurestore_location" ] @@ -687,7 +702,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -724,7 +742,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -815,7 +836,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -835,7 +859,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -876,7 +903,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ diff --git a/sdk/python/featurestore_sample/notebooks/sdk_and_cli/3. Experiment and train models using features.ipynb b/sdk/python/featurestore_sample/notebooks/sdk_and_cli/3. Experiment and train models using features.ipynb index 2744aec11c..b1b7f5501c 100644 --- a/sdk/python/featurestore_sample/notebooks/sdk_and_cli/3. Experiment and train models using features.ipynb +++ b/sdk/python/featurestore_sample/notebooks/sdk_and_cli/3. Experiment and train models using features.ipynb @@ -166,7 +166,7 @@ "\n", "# please update the dir to ./Users/{your-alias} (or any custom directory you uploaded the samples to).\n", "# You can find the name from the directory structure inm the left nav\n", - "root_dir = \"./Users//featurestore_sample\"\n", + "root_dir = \"./Users//featurestore_sample\"\n", "\n", "if os.path.isdir(root_dir):\n", " print(\"The folder exists.\")\n", @@ -204,7 +204,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -224,7 +227,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -247,7 +253,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -331,7 +340,9 @@ }, "outputs": [], "source": [ - "featurestore_name = \"my-featurestore\" # use the same name from part #1 of the tutorial\n", + "featurestore_name = (\n", + " \"\" # use the same name from part #1 of the tutorial\n", + ")\n", "featurestore_subscription_id = os.environ[\"AZUREML_ARM_SUBSCRIPTION\"]\n", "featurestore_resource_group_name = os.environ[\"AZUREML_ARM_RESOURCEGROUP\"]" ] @@ -415,10 +426,17 @@ }, "outputs": [], "source": [ - "compute_cluster_name = \"cpu-cluster\"\n", - "type = \"amlcompute\"\n", - "size = \"STANDARD_F4S_V2\"\n", - "\n", + "compute_cluster_name = \"\"\n", + "type = \"\"\n", + "size = \"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "!az ml compute create --name $compute_cluster_name --type $type --size $size --idle-time-before-scale-down 360 --resource-group $project_ws_rg --workspace-name $project_ws_name" ] }, diff --git a/sdk/python/featurestore_sample/notebooks/sdk_and_cli/4. Enable recurrent materialization and run batch inference.ipynb b/sdk/python/featurestore_sample/notebooks/sdk_and_cli/4. Enable recurrent materialization and run batch inference.ipynb index 078de8a96f..a96c33f3da 100644 --- a/sdk/python/featurestore_sample/notebooks/sdk_and_cli/4. Enable recurrent materialization and run batch inference.ipynb +++ b/sdk/python/featurestore_sample/notebooks/sdk_and_cli/4. Enable recurrent materialization and run batch inference.ipynb @@ -171,7 +171,7 @@ "\n", "# please update the dir to ./Users/{your-alias} (or any custom directory you uploaded the samples to).\n", "# You can find the name from the directory structure inm the left nav\n", - "root_dir = \"./Users//featurestore_sample\"\n", + "root_dir = \"./Users//featurestore_sample\"\n", "\n", "if os.path.isdir(root_dir):\n", " print(\"The folder exists.\")\n", @@ -210,7 +210,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -230,7 +233,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -253,7 +259,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ @@ -349,7 +358,9 @@ }, "outputs": [], "source": [ - "featurestore_name = \"my-featurestore\" # use the same name from part #1 of the tutorial\n", + "featurestore_name = (\n", + " \"\" # use the same name from part #1 of the tutorial\n", + ")\n", "featurestore_subscription_id = os.environ[\"AZUREML_ARM_SUBSCRIPTION\"]\n", "featurestore_resource_group_name = os.environ[\"AZUREML_ARM_RESOURCEGROUP\"]" ] @@ -557,7 +568,10 @@ "transient": { "deleting": false } - } + }, + "tags": [ + "active-ipynb" + ] }, "outputs": [], "source": [ diff --git a/sdk/python/featurestore_sample/setup-resources-cli.sh b/sdk/python/featurestore_sample/setup-resources-cli.sh new file mode 100644 index 0000000000..de76217617 --- /dev/null +++ b/sdk/python/featurestore_sample/setup-resources-cli.sh @@ -0,0 +1,86 @@ +pip install --upgrade jupytext + +# +SUBSCRIPTION_ID=$(az account show --query id -o tsv) +LOCATION=$(az ml workspace show --query location -o tsv) +RESOURCE_GROUP=$(az group show --query name -o tsv) +AML_WORKSPACE_NAME=$(az configure -l --query "[?name=='workspace'].value" -o tsv) +OUTPUT_COMMAND="print" +FEATURE_STORAGE_ACCOUNT_NAME=${RESOURCE_GROUP}fs +USER_ID="36b5b70a-a2b2-45e6-a496-df3c2ffde085" +RAND_NUM=$RANDOM +UAI_NAME=fstoreuai${RAND_NUM} +REDIS_NAME=${RESOURCE_GROUP}rds +FEATURE_VERSION=$(((RANDOM%10)+1)) +FEATURESTORE_NAME="my-featurestore" +ACCOUNT_ENTITY_PATH="./featurestore/entities/account.yaml" +ACCOUNT_FEATURESET_PATH="./featurestore/featuresets/transactions/featureset_asset.yaml" +TRANSACTION_ASSET_MAT_YML="./featurestore/featuresets/transactions/featureset_asset_offline_enabled.yaml" +STORAGE_ACCOUNT_NAME="fstorestorage" +STORAGE_FILE_SYSTEM_NAME="offlinestore" +RAND_NUM=$RANDOM +UAI_NAME=fstoreuai${RAND_NUM} +FEATURE_STORE_ARM_ID="/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.MachineLearningServices/workspaces/${FEATURESTORE_NAME}" +GEN2_CONTAINER_ARM_ID="/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.Storage/storageAccounts/${STORAGE_ACCOUNT_NAME}/blobServices/default/containers/${STORAGE_FILE_SYSTEM_NAME}" +# + +az ml feature-store create --subscription $SUBSCRIPTION_ID --resource-group $RESOURCE_GROUP --location $LOCATION --name $FEATURESTORE_NAME +az ml feature-store-entity create --file $ACCOUNT_ENTITY_PATH --resource-group $RESOURCE_GROUP --workspace-name $FEATURESTORE_NAME +az ml feature-set create --file $ACCOUNT_FEATURESET_PATH --resource-group $RESOURCE_GROUP --workspace-name $FEATURESTORE_NAME +az storage account create --name $STORAGE_ACCOUNT_NAME --enable-hierarchical-namespace true --resource-group $RESOURCE_GROUP --location $LOCATION --subscription $SUBSCRIPTION_ID +az storage fs create --name $STORAGE_FILE_SYSTEM_NAME --account-name $STORAGE_ACCOUNT_NAME --subscription $SUBSCRIPTION_ID + +az identity create --subscription $SUBSCRIPTION_ID --resource-group $RESOURCE_GROUP --location $LOCATION --name $UAI_NAME +az identity show --resource-group $RESOURCE_GROUP --subscription $SUBSCRIPTION_ID --name $UAI_NAME +UAI_OID=$(az identity show --resource-group $RESOURCE_GROUP -n $UAI_NAME --query principalId -o tsv) +az role assignment create --role "AzureML Data Scientist" --assignee-object-id $UAI_OID --assignee-principal-type ServicePrincipal --scope $FEATURE_STORE_ARM_ID +az role assignment create --role "Storage Blob Data Contributor" --assignee-object-id $UAI_OID --assignee-principal-type ServicePrincipal --scope $GEN2_CONTAINER_ARM_ID + + +# az ml feature-set update --file $TRANSACTION_ASSET_MAT_YML --resource-group $RESOURCE_GROUP --workspace-name $FEATURESTORE_NAME + +COMPUTE_CLUSTER_NAME="cpu-cluster" +COMPUTE_TYPE="amlcompute" +COMPUTE_SIZE="STANDARD_F4S_V2" +az ml compute create --name $COMPUTE_CLUSTER_NAME --type $COMPUTE_TYPE --size $COMPUTE_SIZE --idle-time-before-scale-down 360 --resource-group $RESOURCE_GROUP --workspace-name $AML_WORKSPACE_NAME + +# +NOTEBOOK_1="notebooks/sdk_and_cli/1. Develop a feature set and register with managed feature store" +NOTEBOOK_2="notebooks/sdk_and_cli/2. Enable materialization and backfill feature data" +NOTEBOOK_3="notebooks/sdk_and_cli/3. Experiment and train models using features" +NOTEBOOK_4="notebooks/sdk_and_cli/4. Enable recurrent materialization and run batch inference" +jupytext --to py "${NOTEBOOK_1}.ipynb" +jupytext --to py "${NOTEBOOK_2}.ipynb" +jupytext --to py "${NOTEBOOK_3}.ipynb" +jupytext --to py "${NOTEBOOK_4}.ipynb" +# + +# +sed -i "s//$SUBSCRIPTION_ID/g; + s//$RESOURCE_GROUP/g; + s//$AML_WORKSPACE_NAME/g;" $1 + +# +sed -i "s/display/$OUTPUT_COMMAND/g;s/.\/Users\/\/featurestore_sample/.\//g; + s//$FEATURE_VERSION/g; + s//$FEATURESTORE_NAME/g;" "${NOTEBOOK_1}.py" + +sed -i "s/display/$OUTPUT_COMMAND/g;s/.\/Users\/\/featurestore_sample/.\//g; + s//$FEATURESTORE_NAME/g; + s//$FEATURE_STORAGE_ACCOUNT_NAME/g; + s//$USER_ID/g + s//$STORAGE_ACCOUNT_NAME/g + s//$STORAGE_FILE_SYSTEM_NAME/g + s//$FEATURE_VERSION/g;; + s//$UAI_NAME/g;" "${NOTEBOOK_2}.py" + +sed -i "s/display/$OUTPUT_COMMAND/g;s/.\/Users\/\/featurestore_sample/.\//g; + s//$FEATURESTORE_NAME/g; + s//$COMPUTE_CLUSTER_NAME/g; + s//$COMPUTE_TYPE/g; + s//$COMPUTE_SIZE/g; + s//$FEATURE_VERSION/g;" "${NOTEBOOK_3}.py" + +sed -i "s/display/$OUTPUT_COMMAND/g;s/.\/Users\/\/featurestore_sample/.\//g; + s//$FEATURESTORE_NAME/g; + s//$FEATURE_VERSION/g;" "${NOTEBOOK_4}.py" \ No newline at end of file diff --git a/sdk/python/featurestore_sample/test_featurestore_cli_samples.ipynb b/sdk/python/featurestore_sample/test_featurestore_cli_samples.ipynb new file mode 100644 index 0000000000..6e75ca58d0 --- /dev/null +++ b/sdk/python/featurestore_sample/test_featurestore_cli_samples.ipynb @@ -0,0 +1,88 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Use a serverless Spark compute" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You should have an attached Synapse Spark pool available in your workspace. Please see documentation page: [Attach and manage a Synapse Spark pool in Azure Machine Learning (preview)](https://learn.microsoft.com/azure/machine-learning/how-to-manage-synapse-spark-pool) for more details.\n", + "\n", + "**Note** - To ensure successful execution of Spark job, the identity being used for the Spark job should be assigned **Contributor** and **Storage Blob Data Contributor** roles on the Azure storage account used for data input and output." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azure.ai.ml import MLClient, spark, Input, Output\n", + "from azure.identity import DefaultAzureCredential\n", + "from azure.ai.ml.entities import Environment\n", + "\n", + "subscription_id = \"\"\n", + "resource_group = \"\"\n", + "workspace = \"\"\n", + "ml_client = MLClient(\n", + " DefaultAzureCredential(), subscription_id, resource_group, workspace\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "spark_job = spark(\n", + " display_name=\"featurestore_sample_test\",\n", + " code=\"./\",\n", + " entry={\"file\": \"featurestore_cli_job.py\"},\n", + " driver_cores=1,\n", + " driver_memory=\"1g\",\n", + " executor_cores=1,\n", + " executor_memory=\"1g\",\n", + " executor_instances=1,\n", + " resources={\n", + " \"instance_type\": \"Standard_E8S_V3\",\n", + " \"runtime_version\": \"3.2.0\",\n", + " },\n", + " environment=Environment(conda_file=\"project/env/conda.yml\"),\n", + ")\n", + "\n", + "returned_spark_job = ml_client.jobs.create_or_update(spark_job)\n", + "\n", + "print(f\"CLI job {returned_spark_job.id}\")\n", + "# Wait until the job completes\n", + "ml_client.jobs.stream(returned_spark_job.name)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.10 - SDK V2", + "language": "python", + "name": "python310-sdkv2" + }, + "language_info": { + "name": "python", + "version": "3.7.10" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "6aeff17a1aa7735c2f7cb3a6d691fe1b4d4c3b8d2d650f644ad0f24e1b8e3f3f" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/sdk/python/readme.py b/sdk/python/readme.py index ef3ad304dc..89a5f65d50 100644 --- a/sdk/python/readme.py +++ b/sdk/python/readme.py @@ -472,11 +472,21 @@ def get_spark_config_workflow(folder_name, file_name): def get_featurestore_config_workflow(folder_name, file_name): - workflow = f""" - name: setup feature-store resources + is_sdk_noteobook = "_sdk_" in file_name + is_cli_notebook = "_cli_" in file_name + workflow = f""" - name: setup feature-store resources""" + if is_sdk_noteobook: + workflow += f""" run: | bash -x setup-resources.sh {file_name}.ipynb working-directory: sdk/python/featurestore_sample continue-on-error: true\n""" + if is_cli_notebook: + workflow += f""" + run: | + bash -x setup-resources-cli.sh {file_name}.ipynb + working-directory: sdk/python/featurestore_sample + continue-on-error: true\n""" return workflow