From e3e4777e748d517f6b205fffed25c2f2cdd29a1b Mon Sep 17 00:00:00 2001 From: jpage Date: Thu, 14 Sep 2023 21:41:01 -0600 Subject: [PATCH 1/4] Merge pull request #6 from Adobe-Marketing-Cloud/updateForBeta Update for Beta --- notebooks/SyntheticData.ipynb | 4805 +++++++++++++++++++++++++++++++++ 1 file changed, 4805 insertions(+) create mode 100644 notebooks/SyntheticData.ipynb diff --git a/notebooks/SyntheticData.ipynb b/notebooks/SyntheticData.ipynb new file mode 100644 index 0000000..49efa18 --- /dev/null +++ b/notebooks/SyntheticData.ipynb @@ -0,0 +1,4805 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Scope of Notebook\n", + "\n", + "The goal of this notebook is to showcase how you can generate a synthetic dataset through building a schema and fieldgroups and then use the Data Distiller to do exploratory data analysis." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![EndToEndDesign](../media/CMLE-Notebooks-Week1-Workflow.jpeg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "8d84084d-c613-4cf0-abdc-b432fbace941", + "showTitle": false, + "title": "" + } + }, + "source": [ + "# Setup\n", + "\n", + "This notebook requires some configuration data to properly authenticate to your Adobe Experience Platform instance. You should be able to find all the values required above by following the Setup section of the **README**.\n", + "\n", + "The next cell will be looking for your configuration file under your **ADOBE_HOME** path to fetch the values used throughout this notebook. See more details in the Setup section of the **README** to understand how to create your configuration file." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "b44bbb8f-5ac7-4dc5-993a-c99674aa0da5", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "import os\n", + "from configparser import ConfigParser\n", + "\n", + "if \"ADOBE_HOME\" not in os.environ:\n", + " raise Exception(\"ADOBE_HOME environment variable needs to be set.\")\n", + "\n", + "config = ConfigParser()\n", + "config_path = os.path.join(os.environ[\"ADOBE_HOME\"], \"conf\", \"config.ini\")\n", + "\n", + "if not os.path.exists(config_path):\n", + " raise Exception(f\"Looking for configuration under {config_path} but config not found, please verify path\")\n", + "\n", + "config.read(config_path)\n", + " \n", + "ims_org_id = config.get(\"Platform\", \"ims_org_id\")\n", + "environment = config.get(\"Platform\", \"environment\")\n", + "sandbox_name = config.get(\"Platform\", \"sandbox_name\")\n", + "client_id = config.get(\"Authentication\", \"client_id\")\n", + "client_secret = config.get(\"Authentication\", \"client_secret\")\n", + "private_key_path = config.get(\"Authentication\", \"private_key_path\")\n", + "tech_account_id = config.get(\"Authentication\", \"tech_acct_id\")\n", + "dataset_id = config.get(\"Platform\", \"dataset_id\")\n", + " \n", + "if not os.path.exists(private_key_path):\n", + " raise Exception(f\"Looking for private key file under {private_key_path} but key not found, please verify path\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To ensure uniqueness of resources created as part of this notebook, we are using your local username to include in each of the resource titles to avoid conflicts." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import re\n", + "\n", + "username = os.getlogin()\n", + "unique_id = s = re.sub(\"[^0-9a-zA-Z]+\", \"_\", username)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before we run anything, make sure to install the following required libraries for this notebook. They are all publicly available libraries and the latest version should work fine." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "061c1404-2bd7-4997-b379-1a33fdcbb809", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: mmh3 in /usr/local/lib/python3.10/site-packages (3.0.0)\n", + "\u001b[33mWARNING: You are using pip version 22.0.2; however, version 23.0.1 is available.\n", + "You should consider upgrading via the '/usr/local/opt/python@3.10/bin/python3.10 -m pip install --upgrade pip' command.\u001b[0m\u001b[33m\n", + "\u001b[0mRequirement already satisfied: rstr in /usr/local/lib/python3.10/site-packages (3.2.0)\n", + "\u001b[33mWARNING: You are using pip version 22.0.2; however, version 23.0.1 is available.\n", + "You should consider upgrading via the '/usr/local/opt/python@3.10/bin/python3.10 -m pip install --upgrade pip' command.\u001b[0m\u001b[33m\n", + "\u001b[0mRequirement already satisfied: aepp in /usr/local/lib/python3.10/site-packages (0.2.7)\n", + "Requirement already satisfied: PyJWT[crypto] in /usr/local/lib/python3.10/site-packages (from aepp) (1.7.1)\n", + "Requirement already satisfied: pathlib2 in /usr/local/lib/python3.10/site-packages (from aepp) (2.3.7.post1)\n", + "Requirement already satisfied: pandas in /Users/cmenguy/Library/Python/3.10/lib/python/site-packages (from aepp) (1.4.3)\n", + "Requirement already satisfied: pathlib in /usr/local/lib/python3.10/site-packages (from aepp) (1.0.1)\n", + "Requirement already satisfied: requests in /usr/local/lib/python3.10/site-packages (from aepp) (2.27.1)\n", + "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/site-packages (from pandas->aepp) (2021.3)\n", + "Requirement already satisfied: numpy>=1.21.0 in /Users/cmenguy/Library/Python/3.10/lib/python/site-packages (from pandas->aepp) (1.23.1)\n", + "Requirement already satisfied: python-dateutil>=2.8.1 in /usr/local/lib/python3.10/site-packages (from pandas->aepp) (2.8.2)\n", + "Requirement already satisfied: six in /usr/local/lib/python3.10/site-packages (from pathlib2->aepp) (1.16.0)\n", + "Requirement already satisfied: cryptography>=1.4 in /usr/local/lib/python3.10/site-packages (from PyJWT[crypto]->aepp) (36.0.1)\n", + "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /usr/local/lib/python3.10/site-packages (from requests->aepp) (1.26.8)\n", + "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/site-packages (from requests->aepp) (3.3)\n", + "Requirement already satisfied: charset-normalizer~=2.0.0 in /usr/local/lib/python3.10/site-packages (from requests->aepp) (2.0.12)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/site-packages (from requests->aepp) (2021.10.8)\n", + "Requirement already satisfied: cffi>=1.12 in /usr/local/lib/python3.10/site-packages (from cryptography>=1.4->PyJWT[crypto]->aepp) (1.15.0)\n", + "Requirement already satisfied: pycparser in /usr/local/lib/python3.10/site-packages (from cffi>=1.12->cryptography>=1.4->PyJWT[crypto]->aepp) (2.21)\n", + "\u001b[33mWARNING: You are using pip version 22.0.2; however, version 23.0.1 is available.\n", + "You should consider upgrading via the '/usr/local/opt/python@3.10/bin/python3.10 -m pip install --upgrade pip' command.\u001b[0m\u001b[33m\n", + "\u001b[0mRequirement already satisfied: pygresql in /usr/local/lib/python3.10/site-packages (5.2.4)\n", + "\u001b[33mWARNING: You are using pip version 22.0.2; however, version 23.0.1 is available.\n", + "You should consider upgrading via the '/usr/local/opt/python@3.10/bin/python3.10 -m pip install --upgrade pip' command.\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + } + ], + "source": [ + "!pip install mmh3\n", + "!pip install rstr\n", + "!pip install aepp\n", + "!pip install pygresql" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Some utility functions that will be used throughout this notebook:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def get_ui_link(tenant_id, resource_type, resource_id):\n", + " if environment == \"prod\":\n", + " prefix = f\"https://experience.adobe.com\"\n", + " else:\n", + " prefix = f\"https://experience-{environment}.adobe.com\"\n", + " return f\"{prefix}/#/@{tenant_id}/sname:{sandbox_name}/platform/{resource_type}/{resource_id}\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "cb0424d8-a4d5-4282-ac39-f8222747e68e", + "showTitle": false, + "title": "" + } + }, + "source": [ + "In order to generate synthetic data we'll need to first create a schema and a dataset using the [aepp Python library](https://github.com/pitchmuc/aepp), this library is a rest API interface around the workflow in the AEP UI. Please see the following reference [guide](https://developer.adobe.com/experience-platform-apis/) for the underlying APIS. For the AEP UI workflow please click [here](https://experienceleague.adobe.com/docs/experience-platform/xdm/tutorials/create-schema-ui.html?lang=en)." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "50967b2c-967e-4edd-84c6-b885fcbb627a", + "showTitle": false, + "title": "" + } + }, + "source": [ + "We will now need to configure the aepp library and setup authentication credentials. For this please setup the following pieces of information. For information about how you can get these, please refer to the `Setup` section of the **Readme**:\n", + "- Client ID\n", + "- Client secret\n", + "- Private key\n", + "- Technical account ID" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "5a93f362-5a98-4736-8192-ab9e924af5e2", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "import aepp\n", + "aepp.configure(\n", + " org_id=ims_org_id,\n", + " tech_id=tech_account_id, \n", + " secret=client_secret,\n", + " path_to_key=private_key_path,\n", + " client_id=client_id,\n", + " environment=environment,\n", + " sandbox=sandbox_name\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 1. Generating Synthetic Data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1.1 Setting up schemas" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "74af2b4f-6e1d-4b3a-a67f-a5ccc480ab00", + "showTitle": false, + "title": "" + } + }, + "source": [ + "We will now create the schema to support our synthetic data. We need a few fields which will be included in the synthetic data:\n", + "\n", + "Direct Marketing information\n", + "Web details\n", + "Identity information\n", + "These are already provided in your AEP instance as default field groups, so we'll be leveraging that for creation below. The image below identifies the workflow in the AEP UI to create the schema" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "e0e00bce-88a1-4819-8352-ca6fc7b3882a", + "showTitle": false, + "title": "" + } + }, + "source": [ + "We will now create a schema to support the synthetic data to be generated. \n", + "The following are the fields to be included in the synthetic data:\n", + "- Direct Marketing Information\n", + "- Web Details\n", + "- Identity information\n", + "The above fields are already provided in the AEP instance as default field groups , we'll be using that information to create the schema details below. We first print out the tenantId, this represents our ims org name." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "d75837ff-0ebb-474c-9b00-32234e03649a", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'cloudmlecosystem'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from aepp import schema\n", + "schema_conn = schema.Schema()\n", + "schema_conn.sandbox\n", + "tenant_id = schema_conn.getTenantId()\n", + "tenant_id" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "5502cd58-6473-496d-91ac-6336d1f7f092", + "showTitle": false, + "title": "" + } + }, + "source": [ + "### 1.1.1 Creating the Experience Event field group\n", + "\n", + "Our goal is to create schemas for the Profile and Experience Events and fieldgroups in these schemas, a fieldgroup allows us to define and query segments around the profile and experience events, conceptually a fieldgroup allows us to gather together a set of fields to represent data in our segments" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "e68576ba-1e7c-4565-adc7-4331049dbc8b", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "fieldgroup_res = schema_conn.createFieldGroup({\n", + " \t\"type\": \"object\",\n", + "\t\"title\": f\"[CMLE] [Week1] Exp Event related to user propensity subscription (created by {username})\",\n", + "\t\"description\": \"This mixin is used to define a propensity score that can be assigned to a given profile and associated experience events.\",\n", + "\t\"allOf\": [{\n", + "\t\t\"$ref\": \"#/definitions/customFields\"\n", + "\t}],\n", + "\t\"meta:containerId\": \"tenant\",\n", + "\t\"meta:resourceType\": \"mixins\",\n", + "\t\"meta:xdmType\": \"object\",\n", + "\t\"definitions\": {\n", + " \"customFields\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " f\"_{tenant_id}\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"userid\": {\n", + " \"title\": \"User ID\",\n", + " \"description\": \"This refers to the user having a propensity towards an outcome.\",\n", + " \"type\": \"string\"\n", + " }\n", + " }\n", + " }\n", + " }\n", + " }\n", + "\t},\n", + "\t\"meta:intendedToExtend\": [\"https://ns.adobe.com/xdm/context/experienceevent\"]\n", + "})\n", + "\n", + "fieldgroup_res\n", + "fieldgroup_id = fieldgroup_res['$id']\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "3ef3cfe8-e716-4f98-b0cb-5f14dd670193", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://experience-stage.adobe.com/#/@cloudmlecosystem/sname:bugbash-pod-a/platform/schema/mixin/browse/https%3A%2F%2Fns.adobe.com%2Fcloudmlecosystem%2Fmixins%2Fc402d85d6dc7058e588fbffc1d0d02d7fe667726bed6c080\n" + ] + } + ], + "source": [ + "import urllib.parse\n", + "fieldgroup_link = get_ui_link(tenant_id, \"schema/mixin/browse\", urllib.parse.quote(fieldgroup_id, safe=\"a\"))\n", + "print(fieldgroup_link)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![AEP-FieldGroup](../media/CMLE-Notebooks-Week1-FieldGroup.jpeg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "b8eee48a-674b-498b-a4af-5d58d791df8f", + "showTitle": false, + "title": "" + } + }, + "source": [ + "## 1.1.2 Creating the Profile field group" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "31cf1897-e3b2-40b4-8737-7199738b5fa7", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'$id': 'https://ns.adobe.com/cloudmlecosystem/mixins/70d2e7dbd03a4ba05eacc0c5c0e8b8f6328de076f7002969',\n", + " 'meta:altId': '_cloudmlecosystem.mixins.70d2e7dbd03a4ba05eacc0c5c0e8b8f6328de076f7002969',\n", + " 'meta:resourceType': 'mixins',\n", + " 'version': '1.0',\n", + " 'title': '[CMLE] [Week1] Profile Fieldgroup associated with user propensity subscription (created by saikatkanjilal)',\n", + " 'type': 'object',\n", + " 'description': 'This mixin is used to define a propensity score that can be assigned to a given profile and associated experience events.',\n", + " 'definitions': {'customFields': {'type': 'object',\n", + " 'properties': {'_cloudmlecosystem': {'type': 'object',\n", + " 'properties': {'userid': {'title': 'User ID',\n", + " 'description': 'This refers to the user having a propensity towards an outcome.',\n", + " 'type': 'string',\n", + " 'meta:xdmType': 'string'}},\n", + " 'meta:xdmType': 'object'}},\n", + " 'meta:xdmType': 'object'}},\n", + " 'allOf': [{'$ref': '#/definitions/customFields',\n", + " 'type': 'object',\n", + " 'meta:xdmType': 'object'}],\n", + " 'refs': [],\n", + " 'imsOrg': '3ADF23C463D98F640A494032@AdobeOrg',\n", + " 'meta:extensible': True,\n", + " 'meta:abstract': True,\n", + " 'meta:intendedToExtend': ['https://ns.adobe.com/xdm/context/profile'],\n", + " 'meta:xdmType': 'object',\n", + " 'meta:registryMetadata': {'repo:createdDate': 1679451481023,\n", + " 'repo:lastModifiedDate': 1679451481023,\n", + " 'xdm:createdClientId': '35e6e4d205274c4ca1418805ac41153b',\n", + " 'xdm:lastModifiedClientId': '35e6e4d205274c4ca1418805ac41153b',\n", + " 'xdm:createdUserId': 'D94C245363DBF9770A494005@techacct.adobe.com',\n", + " 'xdm:lastModifiedUserId': 'D94C245363DBF9770A494005@techacct.adobe.com',\n", + " 'eTag': 'ae9ba30dbd0811eb2684fc6eb224a63a55dbb3e6bfe7bdf501828de6e4fd584d',\n", + " 'meta:globalLibVersion': '1.40.2'},\n", + " 'meta:containerId': '2e62b46d-b7f6-4b0c-a2b4-6db7f65b0cf5',\n", + " 'meta:sandboxId': '2e62b46d-b7f6-4b0c-a2b4-6db7f65b0cf5',\n", + " 'meta:sandboxType': 'development',\n", + " 'meta:tenantNamespace': '_cloudmlecosystem'}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fieldgroup_res_profile = schema_conn.createFieldGroup({\n", + " \t\"type\": \"object\",\n", + "\t\"title\": f\"[CMLE] [Week1] Profile Fieldgroup associated with user propensity subscription (created by {username})\",\n", + "\t\"description\": \"This mixin is used to define a propensity score that can be assigned to a given profile and associated experience events.\",\n", + "\t\"allOf\": [{\n", + "\t\t\"$ref\": \"#/definitions/customFields\"\n", + "\t}],\n", + "\t\"meta:containerId\": \"tenant\",\n", + "\t\"meta:resourceType\": \"mixins\",\n", + "\t\"meta:xdmType\": \"object\",\n", + "\t\"definitions\": {\n", + " \"customFields\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " f\"_{tenant_id}\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"userid\": {\n", + " \"title\": \"User ID\",\n", + " \"description\": \"This refers to the user having a propensity towards an outcome.\",\n", + " \"type\": \"string\"\n", + " }\n", + " }\n", + " }\n", + " }\n", + " }\n", + "\t},\n", + "\t\"meta:intendedToExtend\": [\"https://ns.adobe.com/xdm/context/profile\"]\n", + "})\n", + "\n", + "fieldgroup_res_profile" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "9eea6a9e-273c-4e45-81de-5c158edbddd1", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "fieldgroup_id_profile=fieldgroup_res_profile[\"$id\"]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "ff751e32-819b-4cae-9005-a2145e262898", + "showTitle": false, + "title": "" + } + }, + "source": [ + "## 1.1.3 Creating the ExperienceEvent schema\n", + "\n", + "Now create the experience event schema and the descriptor, schema descriptors are tenant-level metadata, unique to your IMS Organization and all descriptor operations take place in the tenant container." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "9f263fc3-86d2-4366-96b8-6973ebc9e2d3", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "schema_res = schema_conn.createExperienceEventSchema(\n", + " name=f\"[CMLE] [Week1] Notebook with ecid added and Synthetic Event Schema (created by {username})\",\n", + " mixinIds=[\n", + " fieldgroup_id,\n", + " \"https://ns.adobe.com/xdm/context/experienceevent-directmarketing\",\n", + " \"https://ns.adobe.com/xdm/context/experienceevent-web\"\n", + " ],\n", + " description=\"Profile Schema generated by CMLE for synthetic events\",\n", + ")\n", + "schema_res\n", + "schema_experience_event_id = schema_res['$id']" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://experience-stage.adobe.com/#/@cloudmlecosystem/sname:bugbash-pod-a/platform/schema/mixin/browse/https%3A%2F%2Fns.adobe.com%2Fcloudmlecosystem%2Fschemas%2F70e2392745a94ad72a1270a52722c54596ec416028ae836f\n" + ] + } + ], + "source": [ + "import urllib.parse\n", + "schema_link = get_ui_link(tenant_id, \"schema/mixin/browse\", urllib.parse.quote(schema_experience_event_id, safe=\"a\"))\n", + "print(schema_link)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![AEP-Schema](../media/CMLE-Notebooks-Week1-Schema.jpeg)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "f91bea3e-28ff-4f3a-9495-d9ecc606ee42", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Schema ID: https://ns.adobe.com/cloudmlecosystem/schemas/70e2392745a94ad72a1270a52722c54596ec416028ae836f\n", + "Schema Alt ID: _cloudmlecosystem.schemas.70e2392745a94ad72a1270a52722c54596ec416028ae836f\n" + ] + } + ], + "source": [ + "schema_id = schema_res[\"$id\"]\n", + "schema_alt_id = schema_res[\"meta:altId\"]\n", + "\n", + "print(f\"Schema ID: {schema_id}\")\n", + "print(f\"Schema Alt ID: {schema_alt_id}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1.1.4 Creating the Experience Event identity descriptor" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "8a394873-4165-4cf2-b5ca-1cc6691e22a6", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'@id': 'a9e850e8afe98d52e40deb34b2d6437713e770ea9603eb0a',\n", + " '@type': 'xdm:descriptorIdentity',\n", + " 'xdm:sourceSchema': 'https://ns.adobe.com/cloudmlecosystem/schemas/70e2392745a94ad72a1270a52722c54596ec416028ae836f',\n", + " 'xdm:sourceVersion': 1,\n", + " 'xdm:sourceProperty': '/_cloudmlecosystem/userid',\n", + " 'imsOrg': '3ADF23C463D98F640A494032@AdobeOrg',\n", + " 'version': '1',\n", + " 'xdm:namespace': 'ECID',\n", + " 'xdm:property': 'xdm:id',\n", + " 'xdm:isPrimary': True,\n", + " 'meta:containerId': '2e62b46d-b7f6-4b0c-a2b4-6db7f65b0cf5',\n", + " 'meta:sandboxId': '2e62b46d-b7f6-4b0c-a2b4-6db7f65b0cf5',\n", + " 'meta:sandboxType': 'development'}" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "identity_type = \"ECID\"\n", + "descriptor_res = schema_conn.createDescriptor(\n", + " descriptorObj = {\n", + " \"@type\": \"xdm:descriptorIdentity\",\n", + " \"xdm:sourceSchema\": schema_id,\n", + " \"xdm:sourceVersion\": 1,\n", + " \"xdm:sourceProperty\": f\"/_{tenant_id}/userid\",\n", + " \"xdm:namespace\": identity_type,\n", + " \"xdm:property\": \"xdm:id\",\n", + " \"xdm:isPrimary\": True\n", + " }\n", + ")\n", + "descriptor_res" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1.1.5 Creating the Profile Schema" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "bdcc22de-9baf-4892-ad8f-e260a46b46b6", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'$id': 'https://ns.adobe.com/cloudmlecosystem/schemas/2e3b704e0b7a435587ba4348d09c3e543ef65b178ba78e23',\n", + " 'meta:altId': '_cloudmlecosystem.schemas.2e3b704e0b7a435587ba4348d09c3e543ef65b178ba78e23',\n", + " 'meta:resourceType': 'schemas',\n", + " 'version': '1.0',\n", + " 'title': '[CMLE] [Week1] Notebook with ecid added and Profile Schema (created by saikatkanjilal)',\n", + " 'type': 'object',\n", + " 'description': 'Profile Schema generated by CMLEs',\n", + " 'allOf': [{'$ref': 'https://ns.adobe.com/xdm/context/profile',\n", + " 'type': 'object',\n", + " 'meta:xdmType': 'object'},\n", + " {'$ref': 'https://ns.adobe.com/cloudmlecosystem/mixins/70d2e7dbd03a4ba05eacc0c5c0e8b8f6328de076f7002969',\n", + " 'type': 'object',\n", + " 'meta:xdmType': 'object'}],\n", + " 'refs': ['https://ns.adobe.com/cloudmlecosystem/mixins/70d2e7dbd03a4ba05eacc0c5c0e8b8f6328de076f7002969',\n", + " 'https://ns.adobe.com/xdm/context/profile'],\n", + " 'imsOrg': '3ADF23C463D98F640A494032@AdobeOrg',\n", + " 'additionalInfo': {'numberOfIdentities': 0,\n", + " 'numberOfRelationShips': 0,\n", + " 'classTitle': 'XDM Individual Profile',\n", + " 'behavior': 'Record',\n", + " 'hasRelationShip': False,\n", + " 'profileEnabled': False},\n", + " 'meta:extensible': False,\n", + " 'meta:abstract': False,\n", + " 'meta:extends': ['https://ns.adobe.com/xdm/common/auditable',\n", + " 'https://ns.adobe.com/xdm/data/record',\n", + " 'https://ns.adobe.com/cloudmlecosystem/mixins/70d2e7dbd03a4ba05eacc0c5c0e8b8f6328de076f7002969',\n", + " 'https://ns.adobe.com/xdm/context/profile'],\n", + " 'meta:xdmType': 'object',\n", + " 'meta:registryMetadata': {'repo:createdDate': 1679451665137,\n", + " 'repo:lastModifiedDate': 1679451665137,\n", + " 'xdm:createdClientId': '35e6e4d205274c4ca1418805ac41153b',\n", + " 'xdm:lastModifiedClientId': '35e6e4d205274c4ca1418805ac41153b',\n", + " 'xdm:createdUserId': 'D94C245363DBF9770A494005@techacct.adobe.com',\n", + " 'xdm:lastModifiedUserId': 'D94C245363DBF9770A494005@techacct.adobe.com',\n", + " 'eTag': '62c61e622660122fe3d118659e3b707b0736dbe173b7edd770bf6c3dae459ae0',\n", + " 'meta:globalLibVersion': '1.40.2'},\n", + " 'meta:class': 'https://ns.adobe.com/xdm/context/profile',\n", + " 'meta:containerId': '2e62b46d-b7f6-4b0c-a2b4-6db7f65b0cf5',\n", + " 'meta:sandboxId': '2e62b46d-b7f6-4b0c-a2b4-6db7f65b0cf5',\n", + " 'meta:sandboxType': 'development',\n", + " 'meta:tenantNamespace': '_cloudmlecosystem'}" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "schema_res_profile = schema_conn.createProfileSchema(\n", + " name=f\"[CMLE] [Week1] Notebook with ecid added and Profile Schema (created by {username})\",\n", + " mixinIds=[\n", + " fieldgroup_id_profile\n", + " ],\n", + " description=\"Profile Schema generated by CMLEs\",\n", + ")\n", + "schema_res_profile" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "a0e6a7e6-9c4b-40d4-9975-b676059dc93d", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'_cloudmlecosystem.schemas.2e3b704e0b7a435587ba4348d09c3e543ef65b178ba78e23'" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "schema_profile_id=schema_res_profile[\"$id\"]\n", + "schema_alt_profile_id = schema_res_profile[\"meta:altId\"]\n", + "schema_alt_profile_id" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "346dbe9e-44bf-4d6d-bd04-ccca4b2c3f7c", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'@id': 'a9e850e8afe98d52e40deb34b2d6437713e770ea9603eb0a',\n", + " '@type': 'xdm:descriptorIdentity',\n", + " 'xdm:sourceSchema': 'https://ns.adobe.com/cloudmlecosystem/schemas/70e2392745a94ad72a1270a52722c54596ec416028ae836f',\n", + " 'xdm:sourceVersion': 1,\n", + " 'xdm:sourceProperty': '/_cloudmlecosystem/userid',\n", + " 'imsOrg': '3ADF23C463D98F640A494032@AdobeOrg',\n", + " 'version': '1',\n", + " 'xdm:namespace': 'ECID',\n", + " 'xdm:property': 'xdm:id',\n", + " 'xdm:isPrimary': True,\n", + " 'meta:containerId': '2e62b46d-b7f6-4b0c-a2b4-6db7f65b0cf5',\n", + " 'meta:sandboxId': '2e62b46d-b7f6-4b0c-a2b4-6db7f65b0cf5',\n", + " 'meta:sandboxType': 'development'}" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "identity_type = \"ECID\"\n", + "descriptor_profile_res = schema_conn.createDescriptor(\n", + " descriptorObj = {\n", + " \"@type\": \"xdm:descriptorIdentity\",\n", + " \"xdm:sourceSchema\": schema_id,\n", + " \"xdm:sourceVersion\": 1,\n", + " \"xdm:sourceProperty\": f\"/_{tenant_id}/userid\",\n", + " \"xdm:namespace\": identity_type,\n", + " \"xdm:property\": \"xdm:id\",\n", + " \"xdm:isPrimary\": True\n", + " }\n", + ")\n", + "descriptor_res" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "b2816c41-158a-4da6-a809-8c35391a6165", + "showTitle": false, + "title": "" + } + }, + "source": [ + "### 1.1.6 Enabling Schemas for Unified Profile" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "4c92185a-1cad-45c2-9805-efbb073b2dff", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'$id': 'https://ns.adobe.com/cloudmlecosystem/schemas/70e2392745a94ad72a1270a52722c54596ec416028ae836f',\n", + " 'meta:altId': '_cloudmlecosystem.schemas.70e2392745a94ad72a1270a52722c54596ec416028ae836f',\n", + " 'meta:resourceType': 'schemas',\n", + " 'version': '1.1',\n", + " 'title': '[CMLE] [Week1] Notebook with ecid added and Synthetic Event Schema (created by saikatkanjilal)',\n", + " 'type': 'object',\n", + " 'description': 'Profile Schema generated by CMLE for synthetic events',\n", + " 'allOf': [{'$ref': 'https://ns.adobe.com/xdm/context/experienceevent',\n", + " 'type': 'object',\n", + " 'meta:xdmType': 'object'},\n", + " {'$ref': 'https://ns.adobe.com/cloudmlecosystem/mixins/c402d85d6dc7058e588fbffc1d0d02d7fe667726bed6c080',\n", + " 'type': 'object',\n", + " 'meta:xdmType': 'object'},\n", + " {'$ref': 'https://ns.adobe.com/xdm/context/experienceevent-directmarketing',\n", + " 'type': 'object',\n", + " 'meta:xdmType': 'object'},\n", + " {'$ref': 'https://ns.adobe.com/xdm/context/experienceevent-web',\n", + " 'type': 'object',\n", + " 'meta:xdmType': 'object'}],\n", + " 'refs': ['https://ns.adobe.com/cloudmlecosystem/mixins/c402d85d6dc7058e588fbffc1d0d02d7fe667726bed6c080',\n", + " 'https://ns.adobe.com/xdm/context/experienceevent-directmarketing',\n", + " 'https://ns.adobe.com/xdm/context/experienceevent-web',\n", + " 'https://ns.adobe.com/xdm/context/experienceevent'],\n", + " 'required': ['@id', 'xdm:timestamp'],\n", + " 'imsOrg': '3ADF23C463D98F640A494032@AdobeOrg',\n", + " 'additionalInfo': {'numberOfIdentities': 1,\n", + " 'numberOfRelationShips': 0,\n", + " 'classTitle': 'XDM ExperienceEvent',\n", + " 'hasPrimaryIdentity': 'true',\n", + " 'primaryIdentityNamespace': 'ECID',\n", + " 'hasRelationShip': False,\n", + " 'profileEnabled': True},\n", + " 'meta:extensible': False,\n", + " 'meta:abstract': False,\n", + " 'meta:extends': ['https://ns.adobe.com/xdm/data/time-series',\n", + " 'https://ns.adobe.com/cloudmlecosystem/mixins/c402d85d6dc7058e588fbffc1d0d02d7fe667726bed6c080',\n", + " 'https://ns.adobe.com/xdm/context/experienceevent-directmarketing',\n", + " 'https://ns.adobe.com/xdm/context/identitymap',\n", + " 'https://ns.adobe.com/xdm/context/experienceevent-web',\n", + " 'https://ns.adobe.com/xdm/context/experienceevent'],\n", + " 'meta:xdmType': 'object',\n", + " 'meta:registryMetadata': {'repo:createdDate': 1679451499853,\n", + " 'repo:lastModifiedDate': 1679451687725,\n", + " 'xdm:createdClientId': '35e6e4d205274c4ca1418805ac41153b',\n", + " 'xdm:lastModifiedClientId': '35e6e4d205274c4ca1418805ac41153b',\n", + " 'xdm:createdUserId': 'D94C245363DBF9770A494005@techacct.adobe.com',\n", + " 'xdm:lastModifiedUserId': 'D94C245363DBF9770A494005@techacct.adobe.com',\n", + " 'eTag': '283d09105605250dd390ce9851569f82fa38bc6fd1945c6be042d9ca7628c89b',\n", + " 'meta:globalLibVersion': '1.40.2'},\n", + " 'meta:class': 'https://ns.adobe.com/xdm/context/experienceevent',\n", + " 'meta:containerId': '2e62b46d-b7f6-4b0c-a2b4-6db7f65b0cf5',\n", + " 'meta:sandboxId': '2e62b46d-b7f6-4b0c-a2b4-6db7f65b0cf5',\n", + " 'meta:sandboxType': 'development',\n", + " 'meta:tenantNamespace': '_cloudmlecosystem',\n", + " 'meta:immutableTags': ['union'],\n", + " 'meta:descriptorStatus': {'result': []}}" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "enable_res = schema_conn.enableSchemaForRealTime(schema_alt_id)\n", + "enable_res" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "ac0de747-b14b-4af3-8ff6-503ddb50d014", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'$id': 'https://ns.adobe.com/cloudmlecosystem/schemas/2e3b704e0b7a435587ba4348d09c3e543ef65b178ba78e23',\n", + " 'meta:altId': '_cloudmlecosystem.schemas.2e3b704e0b7a435587ba4348d09c3e543ef65b178ba78e23',\n", + " 'meta:resourceType': 'schemas',\n", + " 'version': '1.1',\n", + " 'title': '[CMLE] [Week1] Notebook with ecid added and Profile Schema (created by saikatkanjilal)',\n", + " 'type': 'object',\n", + " 'description': 'Profile Schema generated by CMLEs',\n", + " 'allOf': [{'$ref': 'https://ns.adobe.com/xdm/context/profile',\n", + " 'type': 'object',\n", + " 'meta:xdmType': 'object'},\n", + " {'$ref': 'https://ns.adobe.com/cloudmlecosystem/mixins/70d2e7dbd03a4ba05eacc0c5c0e8b8f6328de076f7002969',\n", + " 'type': 'object',\n", + " 'meta:xdmType': 'object'}],\n", + " 'refs': ['https://ns.adobe.com/cloudmlecosystem/mixins/70d2e7dbd03a4ba05eacc0c5c0e8b8f6328de076f7002969',\n", + " 'https://ns.adobe.com/xdm/context/profile'],\n", + " 'imsOrg': '3ADF23C463D98F640A494032@AdobeOrg',\n", + " 'additionalInfo': {'numberOfIdentities': 0,\n", + " 'numberOfRelationShips': 0,\n", + " 'classTitle': 'XDM Individual Profile',\n", + " 'behavior': 'Record',\n", + " 'hasRelationShip': False,\n", + " 'profileEnabled': True},\n", + " 'meta:extensible': False,\n", + " 'meta:abstract': False,\n", + " 'meta:extends': ['https://ns.adobe.com/xdm/common/auditable',\n", + " 'https://ns.adobe.com/xdm/data/record',\n", + " 'https://ns.adobe.com/cloudmlecosystem/mixins/70d2e7dbd03a4ba05eacc0c5c0e8b8f6328de076f7002969',\n", + " 'https://ns.adobe.com/xdm/context/profile'],\n", + " 'meta:xdmType': 'object',\n", + " 'meta:registryMetadata': {'repo:createdDate': 1679451665137,\n", + " 'repo:lastModifiedDate': 1679451719126,\n", + " 'xdm:createdClientId': '35e6e4d205274c4ca1418805ac41153b',\n", + " 'xdm:lastModifiedClientId': '35e6e4d205274c4ca1418805ac41153b',\n", + " 'xdm:createdUserId': 'D94C245363DBF9770A494005@techacct.adobe.com',\n", + " 'xdm:lastModifiedUserId': 'D94C245363DBF9770A494005@techacct.adobe.com',\n", + " 'eTag': '3ba44da736605b3ea13c89894391806ae8f891e7baa5a884f84baf4130a7f767',\n", + " 'meta:globalLibVersion': '1.40.2'},\n", + " 'meta:class': 'https://ns.adobe.com/xdm/context/profile',\n", + " 'meta:containerId': '2e62b46d-b7f6-4b0c-a2b4-6db7f65b0cf5',\n", + " 'meta:sandboxId': '2e62b46d-b7f6-4b0c-a2b4-6db7f65b0cf5',\n", + " 'meta:sandboxType': 'development',\n", + " 'meta:tenantNamespace': '_cloudmlecosystem',\n", + " 'meta:immutableTags': ['union'],\n", + " 'meta:descriptorStatus': {'result': []}}" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "enable_res_profile = schema_conn.enableSchemaForRealTime(schema_alt_profile_id)\n", + "enable_res_profile" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1.2 Setting up datasets" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "d897ec73-ad3b-49e5-a248-3f89c52f8833", + "showTitle": false, + "title": "" + } + }, + "source": [ + "### 1.2.1 Creating the Experience Event dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "b74983f8-bd4b-4ce4-8d53-669058a9a7d2", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "from aepp import catalog\n", + "cat_conn = catalog.Catalog()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "47d208d1-405a-4373-ae50-916554074b9a", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['@/dataSets/641a666b4081f11b98e54efd']" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dataset_res = cat_conn.createDataSets(\n", + " name=f\"[CMLE] [Week1] Notebook with ecid used Dataset (created by {username})\",\n", + " schemaId=schema_experience_event_id,\n", + ")\n", + "dataset_res" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "f70a32fd-7768-417e-b72b-7d6fc1652d58", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'641a666b4081f11b98e54efd'" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dataset_id = dataset_res[0].split(\"/\")[-1]\n", + "dataset_id" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://experience-stage.adobe.com/#/@cloudmlecosystem/sname:bugbash-pod-a/platform/dataset/browse/641a666b4081f11b98e54efd\n" + ] + } + ], + "source": [ + "dataset_link = get_ui_link(tenant_id, \"dataset/browse\", dataset_id)\n", + "print(dataset_link)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![AEPDataset](../media/CMLE-Notebooks-Week1-DataSet.jpeg)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "3de60a11-9d14-4e59-a036-3c8722b544a9", + "showTitle": false, + "title": "" + } + }, + "source": [ + "### 1.2.2 Enabling the dataset for Unified Profile\n" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "2e459a96-f160-48a2-a6da-f6e01980bd69", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['@/dataSets/641a666b4081f11b98e54efd']" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cat_conn.enableDatasetProfile(dataset_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Note: After you do this step please go in the UI and click on the link above, if the profile toggle is not enabled please manually toggle the profile on\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "0d78d4a8-9f88-42ef-a270-1a822cf65cb4", + "showTitle": false, + "title": "" + } + }, + "source": [ + "The dataset ID printed above is where we will be uploading all the synthetic data, and what we will use as the basis for querying the data and building our ML model down the line. Here is the [link](https://experience-stage.adobe.com/#/@cloudmlecosystem/sname:prod/platform/dataset/browse?hideSystemDatasets=true&limit=50&page=1&sortDescending=1&sortField=created) to the UI where the dataset is located" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "2dc850c8-56e2-40c1-8ec3-d1f6a815b70c", + "showTitle": false, + "title": "" + } + }, + "source": [ + "# 2. Statistical Simulation\n", + "\n", + "The first step is to create a detailed simulation that will allow a reasonable propensity model to be built. \n", + "\n", + "Our goal in this task will be to create a propensity model for \"subscription\" events.\n", + "\n", + "A subscription event will be defined as an event where a `web.formFilledOut` event is recorded, with a specific \n", + "These will be events where a customer subscribes to the desired plan.\n", + "\n", + "In order to incorporate our custom experience events we replace the identityMap with the tenantId\n", + "\n", + "## 2.1 EventTypes and their contribution to propensity\n", + "\n", + "We will allow for several types of experience events to be received for each user.\n", + "For each user, we will create a \"generative\" model of subscription as follows:\n", + "\n", + "1. We sample randomly from a poisson distribution for the number of advertising impressions, webPageViews, emailsSent. **These events can happen at random times over a 10 week interval.**\n", + "2. For each of these \"base\" exposure events, we then have a corresponding conversion:\n", + " - If an advertising impression occurs, we then allow for an advertising click to happen, with a certain probability. \n", + " - If a web Page view occurs, then linkClicks, productViews, purchases, propositionDisplays, Interacts and Dismisses can all occur.\n", + " - For an Email Sent, opens and clicks can then also occur. \n", + " \n", + "3. After all these base events have been generated, we then have a timeseries of events for each user. Each of the timeseries events affects the user's propensity to subscribe. After each event the user then has a certain probability of subscribing. The subscription is then evaluated with a Bernoulli draw - if the user subscribes, no further subscription evaluations are made. If the subscription does not happen, the subscription possibility will continue to be evaluated. \n", + "\n", + "4. Extra - if more than 10 advertising impressions, or 5 emails are sent, the user churns, and no more events for that user are generated." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "c28d360b-7fcd-4924-8613-a66909414030", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "import random, string\n", + "import uuid\n", + "from datetime import datetime, timedelta\n", + "import mmh3\n", + "import rstr\n", + "from random import randrange" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "b3469cd8-a2f8-48cc-b15d-9f28e51b44d9", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "#define some events and dependencies between the events\n", + "advertising_events = {\n", + " \n", + " #eventType : (weeklyAverageOccurrence, propensityDelta, [(field_to_replace, value)], timeInHoursFromDependent)\n", + " \"advertising.clicks\": (0.01, 0.002, [(\"advertising/clicks/value\", 1.0)], 0.5) , \n", + " \"advertising.impressions\": (0.1, 0.001, [(\"advertising/impressions/value\", 1.0)], 0),\n", + "\n", + " \"web.webpagedetails.pageViews\": (0.1, 0.005, [(\"web/webPageDetails/pageViews/value\", 1.0)], 0.1),\n", + " \"web.webinteraction.linkClicks\": (0.05, 0.005, [(\"web/webInteraction/linkClicks/value\", 1.0)], 0.1),\n", + " \n", + " \n", + " \"commerce.productViews\": (0.05, 0.005, [(\"commerce/productViews/value\", 1.0)], 0.2),\n", + " \"commerce.purchases\": (0.01, 0.1, [(\"commerce/purchases/value\", 1.0)], 1),\n", + " \n", + " \n", + " \"decisioning.propositionDisplay\": (0.05, 0.005, [(\"_experience/decisioning/propositionEventType/display\", 1)], 0.1),\n", + " \"decisioning.propositionInteract\": (0.01, 0.1, [(\"_experience/decisioning/propositionEventType/interact\", 1)], 0.05),\n", + " \"decisioning.propositionDismiss\": (0.01, -0.2, [(\"_experience/decisioning/propositionEventType/dismiss\", 1)], 0.05),\n", + "\n", + " \n", + " \"directMarketing.emailOpened\": (0.2, 0.02, [(\"directMarketing/opens/value\", 1.0)], 24),\n", + " \"directMarketing.emailClicked\": (0.05, 0.1, [(\"directMarketing/clicks/value\", 1.0)], 0.5),\n", + " \"directMarketing.emailSent\": (0.5, 0.005, [(\"directMarketing/sends/value\", 1.0)], 0),\n", + " \n", + " \"web.formFilledOut\": (0.0, 0.0, [(\"web/webPageDetails/name\", \"subscriptionForm\")], 0),\n", + "\n", + "}\n", + "\n", + "event_dependencies = {\n", + " \"advertising.impressions\": [\"advertising.clicks\"],\n", + " \"directMarketing.emailSent\": [\"directMarketing.emailOpened\"],\n", + " \"directMarketing.emailOpened\": [\"directMarketing.emailClicked\"],\n", + " \"directMarketing.emailClicked\": [\"web.webpagedetails.pageViews\"],\n", + " \"web.webpagedetails.pageViews\": [\"web.webinteraction.linkClicks\", \"commerce.productViews\", \"decisioning.propositionDisplay\"],\n", + " \"commerce.productViews\": [\"commerce.purchases\"],\n", + " \"decisioning.propositionDisplay\": [\"decisioning.propositionInteract\", \"decisioning.propositionDismiss\"]\n", + " \n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "54ca49f9-f5f4-4270-b8db-cc948674c386", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "# we define some utility functions to be used later\n", + "\n", + "import numpy as np\n", + "from datetime import datetime\n", + "import math\n", + "\n", + "\n", + "def random_date(start, end):\n", + " \"\"\"\n", + " This function will return a random datetime between two datetime \n", + " objects.\n", + " \"\"\"\n", + " delta = end - start\n", + " int_delta = (delta.days * 24 * 60 * 60) + delta.seconds\n", + " random_second = randrange(int_delta)\n", + " return start + timedelta(seconds=random_second)\n", + "\n", + "def create_data_for_n_users(n_users, first_user):\n", + " \n", + " N_USERS = n_users\n", + " FIRST_USER = first_user\n", + " \n", + " N_WEEKS = 10\n", + " GLOBAL_START_DATE = datetime.now() - timedelta(weeks=12)\n", + " GLOBAL_END_DATE = GLOBAL_START_DATE + timedelta(weeks=N_WEEKS)\n", + "\n", + " events = []\n", + "\n", + " for user in range(N_USERS):\n", + " user_id = FIRST_USER + user\n", + " user_events = []\n", + " base_events = {}\n", + " for event_type in [\"advertising.impressions\", \"web.webpagedetails.pageViews\", \"directMarketing.emailSent\"]:\n", + " n_events = np.random.poisson(advertising_events[event_type][0] * N_WEEKS)\n", + " times = []\n", + " for _ in range(n_events):\n", + " #times.append(random_date(GLOBAL_START_DATE, GLOBAL_END_DATE)\n", + " times.append(random_date(GLOBAL_START_DATE, GLOBAL_END_DATE).isoformat())\n", + "\n", + " base_events[event_type] = times\n", + "\n", + " for event_type, dependent_event_types in event_dependencies.items():\n", + "\n", + " if event_type in base_events:\n", + " #for each originating event\n", + " for event_time in base_events[event_type]:\n", + " #Look for possible later on events\n", + " for dependent_event in dependent_event_types:\n", + " n_events = np.random.poisson(advertising_events[dependent_event][0] * N_WEEKS)\n", + " times = []\n", + " for _ in range(n_events):\n", + " #times.append(event_time + timedelta(hours = np.random.exponential(advertising_events[dependent_event][3])))\n", + " new_time = datetime.fromisoformat(event_time) + timedelta(hours = np.random.exponential(advertising_events[dependent_event][3]))\n", + " times.append(new_time.isoformat())\n", + " base_events[dependent_event] = times\n", + "\n", + "\n", + " for event_type, times in base_events.items():\n", + " for time in times:\n", + " user_events.append({\"userId\": user_id, \"eventType\": event_type, \"timestamp\": time})\n", + "\n", + " user_events = sorted(user_events, key = lambda x: (x[\"userId\"], x[\"timestamp\"]))\n", + "\n", + "\n", + " cumulative_probability = 0.001\n", + " subscribed = False\n", + " for event in user_events:\n", + " cumulative_probability = min(1.0, max(cumulative_probability + advertising_events[event[\"eventType\"]][1], 0))\n", + " event[\"subscriptionPropensity\"] = cumulative_probability\n", + " if subscribed == False and \"directMarketing\" not in event[\"eventType\"] and \"advertising\" not in event[\"eventType\"]:\n", + " subscribed = np.random.binomial(1, cumulative_probability) > 0\n", + " if subscribed:\n", + " subscriptiontime = (datetime.fromisoformat(event[\"timestamp\"]) + timedelta(seconds = 60)).isoformat()\n", + " #subscriptiontime = event[\"timestamp\"] + timedelta(seconds = 60)\n", + " user_events.append({\"userId\": user_id, \"eventType\": \"web.formFilledOut\", \"timestamp\": subscriptiontime})\n", + " event[\"subscribed\"] = subscribed\n", + " user_events = sorted(user_events, key = lambda x: (x[\"userId\"], x[\"timestamp\"]))\n", + "\n", + " events = events + user_events\n", + " return events" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "8a919ab4-6dbd-4a64-b84d-b81e77426d93", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "#utility functions continued\n", + "def normalize_ecid(ecid_part):\n", + " ecid_part_str = str(abs(ecid_part))\n", + " if len(ecid_part_str) != 19:\n", + " ecid_part_str = \"\".join([str(x) for x in range(\n", + " 0, 19 - len(ecid_part_str))]) + ecid_part_str\n", + " return ecid_part_str\n", + "\n", + "\n", + "def get_ecid(email):\n", + " \"\"\"\n", + " The ECID must be two valid 19 digit longs concatenated together\n", + " \"\"\"\n", + " ecidpart1, ecidpart2 = mmh3.hash64(email)\n", + " ecid1, ecid2 = (normalize_ecid(ecidpart1), normalize_ecid(ecidpart2))\n", + " return ecid1 + ecid2" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "9c9a618f-a393-4e90-9b3e-88bc16ae7d3c", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "# define the different types of events\n", + "def create_email_event(user_id, event_type, timestamp):\n", + " \"\"\"\n", + " Combines previous methods to create various type of email events\n", + " \"\"\"\n", + " \n", + " if event_type == \"directMarketing.emailSent\":\n", + " directMarketing = {\"emailDelivered\": {\"value\": 1.0}, \n", + " \"sends\": {\"value\": 1.0}, \n", + " \"emailVisitorID\": user_id,\n", + " \"hashedEmail\": ''.join(random.choices(string.ascii_letters + string.digits, k=10)),\n", + " \"messageID\": str(uuid.uuid4()),\n", + " }\n", + " elif event_type == \"directMarketing.emailOpened\":\n", + " directMarketing = {\"offerOpens\": {\"value\": 1.0}, \n", + " \"opens\": {\"value\": 1.0}, \n", + " \"emailVisitorID\": user_id,\n", + " \"messageID\": str(uuid.uuid4()),\n", + " }\n", + " elif event_type == \"directMarketing.emailClicked\":\n", + " directMarketing = {\"clicks\": {\"value\": 1.0}, \n", + " \"offerOpens\": {\"value\": 1.0}, \n", + " \"emailVisitorID\": user_id,\n", + " \"messageID\": str(uuid.uuid4()),\n", + " }\n", + " return {\n", + " \"directMarketing\": directMarketing,\n", + " \"web\": None,\n", + " \"_id\": str(uuid.uuid4()),\n", + " \"eventMergeId\": None,\n", + " \"eventType\": event_type,\n", + " f\"_{tenant_id}\": {\"userid\":get_ecid(user_id)},\n", + " \"producedBy\": \"databricks-synthetic\",\n", + " \"timestamp\": timestamp\n", + " }\n", + " \n", + "def create_web_event(user_id, event_type, timestamp):\n", + " \"\"\"\n", + " Combines previous methods to creat various type of web events\n", + " \"\"\"\n", + " url = f\"http://www.{''.join(random.choices(string.ascii_letters + string.digits, k=5))}.com\"\n", + " ref_url = f\"http://www.{''.join(random.choices(string.ascii_letters + string.digits, k=5))}.com\"\n", + " name = ''.join(random.choices(string.ascii_letters + string.digits, k=5))\n", + " isHomePage = random.choice([True, False])\n", + " server = ''.join(random.choices(string.ascii_letters + string.digits, k=10))\n", + " site_section = ''.join(random.choices(string.ascii_letters, k=2))\n", + " view_name = ''.join(random.choices(string.ascii_letters, k=3))\n", + " region = ''.join(random.choices(string.ascii_letters + string.digits, k=5))\n", + " interaction_type = random.choice([\"download\", \"exit\", \"other\"])\n", + " web_referrer = random.choice([\"internal\", \"external\", \"search_engine\", \"email\", \"social\", \"unknown\", \"usenet\", \"typed_bookmarked\"])\n", + " base_web = {\"webInteraction\": {\"linkClicks\": {\"value\": 0.0}, \n", + " \"URL\": url, \n", + " \"name\": name,\n", + " \"region\": region,\n", + " \"type\": interaction_type},\n", + " \"webPageDetails\": {\"pageViews\": {\"value\": 1.0},\n", + " \"URL\": url,\n", + " \"isErrorPage\": False,\n", + " #\"isHomepage\": isHomePage,\n", + " \"name\": name,\n", + " \"server\": server,\n", + " \"siteSection\": site_section,\n", + " \"viewName\": view_name\n", + " },\n", + " \"webReferrer\": {\n", + " \"URL\": ref_url,\n", + " \"type\": web_referrer\n", + " }\n", + " }\n", + " if event_type in [\"advertising.clicks\", \"commerce.purchases\", \"web.webinteraction.linkClicks\", \"web.formFilledOut\", \n", + " \"decisioning.propositionInteract\", \"decisioning.propositionDismiss\"]:\n", + " base_web[\"webInteraction\"][\"linkClicks\"][\"value\"] = 1.0\n", + "\n", + " return {\n", + " \"directMarketing\": None,\n", + " \"web\": base_web,\n", + " \"_id\": str(uuid.uuid4()),\n", + " \"eventMergeId\": None,\n", + " \"eventType\": event_type,\n", + " f\"_{tenant_id}\": {\"userid\":get_ecid(user_id)},\n", + " \"producedBy\": \"databricks-synthetic\",\n", + " \"timestamp\": timestamp\n", + " }\n", + " \n", + " \n", + " \n", + "def create_xdm_event(user_id, event_type, timestamp):\n", + " \"\"\"\n", + " The final 'event factory' method that converts an event into an XDM event\n", + " \"\"\"\n", + " if \"directMarketing\" in event_type:\n", + " return create_email_event(user_id, event_type, timestamp)\n", + " else: \n", + " return create_web_event(user_id, event_type, timestamp)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "0656f8a3-3e11-41da-8bdc-1125fa1c722a", + "showTitle": false, + "title": "" + } + }, + "source": [ + "## 2.2 Batch ingestion " + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "4b94c34c-c3fc-44ee-8b31-e7e207b4ec78", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "num_batches = 10\n", + "batch_size = 10000" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "2a371094-1106-4550-881d-4df12b8c3ce5", + "showTitle": false, + "title": "" + } + }, + "source": [ + "Now we're going to use the ingestion APIs using the same `aepp` library. Ingesting a batch of data is a multi-step process:\n", + "1. Create an empty batch to initialize the connection\n", + "2. Upload some data using the same batch ID we just created\n", + "3. Mark the batch as completed successfully\n", + "\n", + "For more details about batch ingestion you can find API details [here](https://experienceleague.adobe.com/docs/experience-platform/ingestion/batch/overview.html?lang=en)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "6fe7d22a-0f2f-4ad3-9d46-04b21391589d", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "from aepp import ingestion\n", + "\n", + "ingest_conn = ingestion.DataIngestion()" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": { + "byteLimit": 2048000, + "rowLimit": 10000 + }, + "inputWidgets": {}, + "nuid": "6660aa28-0ca3-487c-aea1-9f54539ce43e", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Processing batch 1/10 with ID 01GW3JKCNFMB1TSMY21VGPV98K\n", + "Processing batch 2/10 with ID 01GW3JNJKT7X432G6P5RJ77G7M\n", + "Processing batch 3/10 with ID 01GW3JQX5WERH4SS7VPD44DVW8\n", + "Processing batch 4/10 with ID 01GW3JSZA1VYKAK7TQTP55P0PH\n", + "Processing batch 5/10 with ID 01GW3JW4D8NM4FZWSFT3G3HCND\n", + "Processing batch 6/10 with ID 01GW3JYGE3HKZBNJ9YKYANCA38\n", + "Processing batch 7/10 with ID 01GW3K0PDMDTG0T46DW27TZYJV\n", + "Processing batch 8/10 with ID 01GW3K2ZMCP7NPDQ56C9M28B6Q\n", + "Processing batch 9/10 with ID 01GW3K5ECDAHRSXW37CS424RMY\n", + "Processing batch 10/10 with ID 01GW3K7RDTQ0GMZNNJ0G6PKMYH\n" + ] + } + ], + "source": [ + "batch_ids = []\n", + "for batch_index in range(num_batches):\n", + " first_user_id_for_batch = batch_index * batch_size\n", + " batch_events = create_data_for_n_users(batch_size, first_user_id_for_batch)\n", + " batch_data = [create_xdm_event(f\"synthetic-user-{x['userId']}@adobe.com\", x[\"eventType\"], x[\"timestamp\"]) for x in batch_events]\n", + " \n", + " # Initialize batch creation\n", + " batch_res = ingest_conn.createBatch(\n", + " datasetId = dataset_id\n", + " )\n", + " #print(str(batch_res))\n", + " batch_id = batch_res[\"id\"]\n", + " print(f\"Processing batch {batch_index + 1}/{num_batches} with ID {batch_id}\")\n", + " \n", + " # Upload XDM data\n", + " file_path = f\"batch-synthetic-{batch_id}\"\n", + " ingest_conn.uploadSmallFile(\n", + " batchId = batch_id,\n", + " datasetId = dataset_id,\n", + " filePath = batch_id,\n", + " data = batch_data\n", + " )\n", + " \n", + " # Complete the batch\n", + " ingest_conn.uploadSmallFileFinish(\n", + " batchId = batch_id\n", + " )\n", + " \n", + " # Store the batch ID to check status\n", + " batch_ids.append(batch_id)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "308a979b-ef82-4aa6-ac24-3860bd3ff619", + "showTitle": false, + "title": "" + } + }, + "source": [ + "**Note**: Batches are ingested asynchronously in AEP. It may take some time for all the data generated here to be available in your dataset depending on how your AEP organization has been provisioned. You can check ingestion status for all your batches in [the dataset page of your AEP UI](https://experience.adobe.com/#/@TENANT/sname:SANDBOX/platform/dataset/browse/DATASETID)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "cdb87863-e017-43f2-98ef-3dfbee7147f7", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Remaining batches being ingested: 1\n", + "All batches have been ingested\n" + ] + } + ], + "source": [ + "from aepp import catalog\n", + "\n", + "import time\n", + "\n", + "cat_conn = catalog.Catalog()\n", + "\n", + "all_ingested = False\n", + "while not all_ingested:\n", + " incomplete_batches = cat_conn.getBatches(\n", + " limit=min(100, num_batches),\n", + " n_results=num_batches,\n", + " output=\"dataframe\",\n", + " dataSet=dataset_id,\n", + " status=\"staging\"\n", + " )\n", + " \n", + " num_incomplete_batches = len(incomplete_batches)\n", + " if num_incomplete_batches == 0:\n", + " print(\"All batches have been ingested\")\n", + " all_ingested = True\n", + " else:\n", + " print(f\"Remaining batches being ingested: {num_incomplete_batches}\")\n", + " time.sleep(30)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "33ed6b1f-e0fa-4453-86ed-e06d39e63afc", + "showTitle": false, + "title": "" + } + }, + "source": [ + "# 3. Data Exploration for Propensity Models\n", + "\n", + "In this notebook, we connect to the query service using the aepp library, and examine the data that we have uploaded. \n", + "\n", + "We do the following steps:\n", + "\n", + "- Connect to query service using the aepp configuration parameters\n", + "- Discover the schema of data, and explore a few rows\n", + "- Compute basic statistics\n", + "- Examine correlations among features, to inform feature creation" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "069804cb-e9dc-4201-a266-7676c4c63627", + "showTitle": false, + "title": "" + } + }, + "source": [ + "## 3.1 Interactive Session with Data Distiller" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Every dataset ID in the Adobe Experience Platform is tied to a table name in Query Service world. We can easily get the table name by doing a lookup on the dataset ID and extracting the table name from the tags:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'cmle_week1_new_notebook_with_ecid_used_dataset_created_by_saikat'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from aepp import catalog\n", + "\n", + "cat_conn = catalog.Catalog()\n", + "\n", + "dataset_info = cat_conn.getDataSet(dataset_id)\n", + "table_name = dataset_info[dataset_id][\"tags\"][\"adobe/pqs/table\"][0]\n", + "table_name" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you set the connection to the query service object you'll setup a connection to the actual table you need to connect to, this will be faster and use up less resources from the query service API" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "c0b34fab-a2b1-4b2c-8ce0-623e0bda8084", + "showTitle": false, + "title": "" + } + }, + "outputs": [], + "source": [ + "from aepp import queryservice\n", + "\n", + "qs_conn = queryservice.QueryService().connection()\n", + "qs_conn[\"dbname\"] = f\"{sandbox_name}:{table_name}\"\n", + "qs_cursor = queryservice.InteractiveQuery(qs_conn)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "70c34366-7c3f-42f2-9adf-993d3bcecff7", + "showTitle": false, + "title": "" + } + }, + "source": [ + "## 3.2 Querying the dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can use the interactive session created just before to issue any kinds of queries to Query Service. As an example here we simply select all the fields in our synthetic data table." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "eee551bc-bcf7-40af-abc3-0c6a152d072a", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
_aamds_iddirectMarketingeventMergeIdeventTypeproducedBytimestampweb
0(65243412659796291646255339364107433273)e5134037-8569-4aad-bbef-279bb831808f(NULL,\"(1.0)\",synthetic-user-5429@adobe.com,MD...NonedirectMarketing.emailSentdatabricks-synthetic2023-01-21 00:01:41.534None
1(49844234781406159997650770259889908940)e1793fdc-4ac7-49c6-9aa3-e0867aa0ec55NoneNonecommerce.productViewsdatabricks-synthetic2023-01-21 00:02:15.916(\"(http://www.SxTqn.com,\"(0.0)\",t91jg,n7Gcl,ex...
2(12020984676794453631540776783207087622)78ee3b46-c3fd-4058-8041-f7fe15180268(NULL,\"(1.0)\",synthetic-user-7954@adobe.com,re...NonedirectMarketing.emailSentdatabricks-synthetic2023-01-21 00:02:34.534None
3(21690903347635878125817940858837590243)d46358de-d9bf-4bc7-861a-cc3275203fde(NULL,\"(1.0)\",synthetic-user-3552@adobe.com,5N...NonedirectMarketing.emailSentdatabricks-synthetic2023-01-21 00:02:36.534None
4(53459861322107555163196673979056455929)5af2c15c-ec23-4a41-ac3d-1dab9fe9a057(NULL,\"(1.0)\",synthetic-user-5914@adobe.com,YB...NonedirectMarketing.emailSentdatabricks-synthetic2023-01-21 00:05:18.534None
\n", + "
" + ], + "text/plain": [ + " _aamds \\\n", + "0 (65243412659796291646255339364107433273) \n", + "1 (49844234781406159997650770259889908940) \n", + "2 (12020984676794453631540776783207087622) \n", + "3 (21690903347635878125817940858837590243) \n", + "4 (53459861322107555163196673979056455929) \n", + "\n", + " _id \\\n", + "0 e5134037-8569-4aad-bbef-279bb831808f \n", + "1 e1793fdc-4ac7-49c6-9aa3-e0867aa0ec55 \n", + "2 78ee3b46-c3fd-4058-8041-f7fe15180268 \n", + "3 d46358de-d9bf-4bc7-861a-cc3275203fde \n", + "4 5af2c15c-ec23-4a41-ac3d-1dab9fe9a057 \n", + "\n", + " directMarketing eventMergeId \\\n", + "0 (NULL,\"(1.0)\",synthetic-user-5429@adobe.com,MD... None \n", + "1 None None \n", + "2 (NULL,\"(1.0)\",synthetic-user-7954@adobe.com,re... None \n", + "3 (NULL,\"(1.0)\",synthetic-user-3552@adobe.com,5N... None \n", + "4 (NULL,\"(1.0)\",synthetic-user-5914@adobe.com,YB... None \n", + "\n", + " eventType producedBy timestamp \\\n", + "0 directMarketing.emailSent databricks-synthetic 2023-01-21 00:01:41.534 \n", + "1 commerce.productViews databricks-synthetic 2023-01-21 00:02:15.916 \n", + "2 directMarketing.emailSent databricks-synthetic 2023-01-21 00:02:34.534 \n", + "3 directMarketing.emailSent databricks-synthetic 2023-01-21 00:02:36.534 \n", + "4 directMarketing.emailSent databricks-synthetic 2023-01-21 00:05:18.534 \n", + "\n", + " web \n", + "0 None \n", + "1 (\"(http://www.SxTqn.com,\"(0.0)\",t91jg,n7Gcl,ex... \n", + "2 None \n", + "3 None \n", + "4 None " + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sample_experience_event_query = f'''SELECT * FROM {table_name} LIMIT 5'''\n", + "qs_cursor.query(sample_experience_event_query)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "a356d2d3-6931-4f7e-8286-ce74cf870f4f", + "showTitle": false, + "title": "" + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## 3.3 Querying Complex Fields\n", + "\n", + "Let's sample some of the fields in our dataset - we have different types, some are timestamps, some are just primitives like strings, and then some are complex nested XDM structures. Let's see what we get when we query it as-is: " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "62c856f3-b608-42e5-96b5-a1d10dfddd3c", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
directMarketing_ideventTypetimestamp
0(NULL,\"(1.0)\",synthetic-user-72328@adobe.com,h...fbf988a7-deb1-4dfa-b6a6-0f22a1e479e8directMarketing.emailSent2023-01-21 00:01:18.909
1(NULL,NULL,synthetic-user-74797@adobe.com,NULL...04bf1142-325b-4faf-b028-dcecb0b38f1bdirectMarketing.emailOpened2023-01-21 00:01:30.281
2(NULL,\"(1.0)\",synthetic-user-78676@adobe.com,z...5127f038-ad0b-40b6-9689-d5e17c5b6589directMarketing.emailSent2023-01-21 00:01:34.909
3None2dd27960-2ee6-4926-a1ff-940a19be7b42advertising.impressions2023-01-21 00:02:35.909
4(NULL,NULL,synthetic-user-72648@adobe.com,NULL...c4439186-05dd-4b21-9867-424af166c1e6directMarketing.emailOpened2023-01-21 00:03:13.375
\n", + "
" + ], + "text/plain": [ + " directMarketing \\\n", + "0 (NULL,\"(1.0)\",synthetic-user-72328@adobe.com,h... \n", + "1 (NULL,NULL,synthetic-user-74797@adobe.com,NULL... \n", + "2 (NULL,\"(1.0)\",synthetic-user-78676@adobe.com,z... \n", + "3 None \n", + "4 (NULL,NULL,synthetic-user-72648@adobe.com,NULL... \n", + "\n", + " _id eventType \\\n", + "0 fbf988a7-deb1-4dfa-b6a6-0f22a1e479e8 directMarketing.emailSent \n", + "1 04bf1142-325b-4faf-b028-dcecb0b38f1b directMarketing.emailOpened \n", + "2 5127f038-ad0b-40b6-9689-d5e17c5b6589 directMarketing.emailSent \n", + "3 2dd27960-2ee6-4926-a1ff-940a19be7b42 advertising.impressions \n", + "4 c4439186-05dd-4b21-9867-424af166c1e6 directMarketing.emailOpened \n", + "\n", + " timestamp \n", + "0 2023-01-21 00:01:18.909 \n", + "1 2023-01-21 00:01:30.281 \n", + "2 2023-01-21 00:01:34.909 \n", + "3 2023-01-21 00:02:35.909 \n", + "4 2023-01-21 00:03:13.375 " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "schema_query= f'''SELECT directMarketing, _id, eventType, timestamp FROM {table_name} LIMIT 5'''\n", + "df = qs_cursor.query(schema_query, output=\"dataframe\")\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we can see when looking at the complex nested field, it's pretty hard to make sense of what this data is and the underlying structure:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'(NULL,\"(1.0)\",synthetic-user-72328@adobe.com,h0etCqXVFg,db076fce-9c9a-4bab-ae63-25eb91e12de1,NULL,NULL,\"(1.0)\")'" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[\"directMarketing\"].iloc[0]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's run the same query again but with a twist: we can set the `auto_to_json` flag to be true - this configuration ensures that complex structures are automatically converted into a json form so that the field names can be queried." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
_ideventTypetimestampdirectMarketing
0fbf988a7-deb1-4dfa-b6a6-0f22a1e479e8directMarketing.emailSent2023-01-21 00:01:18.909{\"emailDelivered\":{\"value\":1.0},\"emailVisitorI...
104bf1142-325b-4faf-b028-dcecb0b38f1bdirectMarketing.emailOpened2023-01-21 00:01:30.281{\"emailVisitorID\":\"synthetic-user-74797@adobe....
25127f038-ad0b-40b6-9689-d5e17c5b6589directMarketing.emailSent2023-01-21 00:01:34.909{\"emailDelivered\":{\"value\":1.0},\"emailVisitorI...
32dd27960-2ee6-4926-a1ff-940a19be7b42advertising.impressions2023-01-21 00:02:35.909None
4c4439186-05dd-4b21-9867-424af166c1e6directMarketing.emailOpened2023-01-21 00:03:13.375{\"emailVisitorID\":\"synthetic-user-72648@adobe....
\n", + "
" + ], + "text/plain": [ + " _id eventType \\\n", + "0 fbf988a7-deb1-4dfa-b6a6-0f22a1e479e8 directMarketing.emailSent \n", + "1 04bf1142-325b-4faf-b028-dcecb0b38f1b directMarketing.emailOpened \n", + "2 5127f038-ad0b-40b6-9689-d5e17c5b6589 directMarketing.emailSent \n", + "3 2dd27960-2ee6-4926-a1ff-940a19be7b42 advertising.impressions \n", + "4 c4439186-05dd-4b21-9867-424af166c1e6 directMarketing.emailOpened \n", + "\n", + " timestamp directMarketing \n", + "0 2023-01-21 00:01:18.909 {\"emailDelivered\":{\"value\":1.0},\"emailVisitorI... \n", + "1 2023-01-21 00:01:30.281 {\"emailVisitorID\":\"synthetic-user-74797@adobe.... \n", + "2 2023-01-21 00:01:34.909 {\"emailDelivered\":{\"value\":1.0},\"emailVisitorI... \n", + "3 2023-01-21 00:02:35.909 None \n", + "4 2023-01-21 00:03:13.375 {\"emailVisitorID\":\"synthetic-user-72648@adobe.... " + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "schema_query= f\"\"\"\n", + "SET auto_to_json=true; \n", + "\n", + "SELECT directMarketing, _id, eventType, timestamp \n", + "FROM {table_name} \n", + "LIMIT 5\"\"\"\n", + "df = qs_cursor.query(schema_query, output=\"dataframe\")\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we can see, the data is now much easier to digest, and we can see clearly the underlying structure along with the different field names." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'{\"emailDelivered\":{\"value\":1.0},\"emailVisitorID\":\"synthetic-user-72328@adobe.com\",\"hashedEmail\":\"h0etCqXVFg\",\"messageID\":\"db076fce-9c9a-4bab-ae63-25eb91e12de1\",\"sends\":{\"value\":1.0}}'" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df[\"directMarketing\"].iloc[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'emailDelivered': {'value': 1.0},\n", + " 'emailVisitorID': 'synthetic-user-72328@adobe.com',\n", + " 'hashedEmail': 'h0etCqXVFg',\n", + " 'messageID': 'db076fce-9c9a-4bab-ae63-25eb91e12de1',\n", + " 'sends': {'value': 1.0}}" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import json\n", + "\n", + "json.loads(df[\"directMarketing\"].iloc[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "9ef944d7-9ac6-4946-ad9c-37f8d930b9bf", + "showTitle": false, + "title": "" + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "## 3.4 Manually get some basic statistics\n", + "\n", + "Let's look at the number of rows, number of profiles in our synthetic dataset as an example of basic computations that can be done with Query Service:" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "6a9a9bc1-808f-4c8c-a446-545de9f46bc3", + "showTitle": false, + "title": "" + }, + "gather": { + "logged": 1667866562768 + }, + "jupyter": { + "outputs_hidden": false, + "source_hidden": false + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
totalRowsdistinctUsers
010643371064337
\n", + "
" + ], + "text/plain": [ + " totalRows distinctUsers\n", + "0 1064337 1064337" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "basic_statistics_query = f\"\"\"\n", + "SELECT\n", + " COUNT(_id) as \"totalRows\", \n", + " COUNT(DISTINCT _id) as \"distinctUsers\" \n", + "FROM {table_name}\"\"\"\n", + "df = qs_cursor.query(basic_statistics_query, output=\"dataframe\")\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "c8254ae0-3017-4390-b79a-4d68b9e62c0f", + "showTitle": false, + "title": "" + } + }, + "source": [ + "## 3.5 Create a sampled version of the table\n", + "\n", + "If our dataset is too big, or we simply don't need to get exact numbers for our queries, we can use the [sampling functionality](https://experienceleague.adobe.com/docs/experience-platform/query/sql/dataset-samples.html?lang=en) available in Query Service. This happens in multiple steps:\n", + "- First we have to **analyze** the table to create an actual sample with a specific sampling ratio.\n", + "- Then we can query the actual sample created which will automatically extrapolate the numbers to the full dataset.\n", + "\n", + "As an example below, this is how we start by analyzing the table and creating a 5% sample:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "# A sampling rate of 10 is 100% in Query Service, so for 5% we have to use 0.5\n", + "sampling_rate = 0.5" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "analyze_table_query=f\"\"\"\n", + "SET aqp=true; \n", + "\n", + "ANALYZE TABLE {table_name} TABLESAMPLE SAMPLERATE {sampling_rate}\"\"\"\n", + "qs_cursor.query(analyze_table_query, output=\"raw\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we want to see all the different samples available for our table, we can use the `sample_meta` function which will have an entry for each sample pointing to that sample's dataset ID and table name as well as the recorded sampling ratio." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "f744d60d-303c-461a-bbca-fc6abc6619c0", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
sample_table_namesample_dataset_idparent_dataset_idsample_typesampling_ratefilter_condition_on_source_datasetsample_num_rowscreated
0cmle_week1_new_notebook_with_ecid_used_dataset...643426f164d2b81c05d79e6d642c452bb871e21c0669cba8uniform0.5541210/04/2023 03:10:41
\n", + "
" + ], + "text/plain": [ + " sample_table_name \\\n", + "0 cmle_week1_new_notebook_with_ecid_used_dataset... \n", + "\n", + " sample_dataset_id parent_dataset_id sample_type \\\n", + "0 643426f164d2b81c05d79e6d 642c452bb871e21c0669cba8 uniform \n", + "\n", + " sampling_rate filter_condition_on_source_dataset sample_num_rows \\\n", + "0 0.5 5412 \n", + "\n", + " created \n", + "0 10/04/2023 03:10:41 " + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sampled_version_of_table_query = f'''SELECT sample_meta('{table_name}')'''\n", + "\n", + "df_samples = qs_cursor.query(sampled_version_of_table_query, output=\"dataframe\")\n", + "df_samples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So now let's compare what happens when we run the same query on both the original table, and our 5% sample. We're using a very simple query to just do a `COUNT` to compare both the accuracy of the result, and also how much faster it is." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.29 ms, sys: 1.12 ms, total: 2.41 ms\n", + "Wall time: 4.48 s\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
count(1)
01066272
\n", + "
" + ], + "text/plain": [ + " count(1)\n", + "0 1066272" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%time\n", + "count_query=f'''SELECT count(*) from {table_name}'''\n", + "df = qs_cursor.query(count_query, output=\"dataframe\")\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To query the sample we get the sampling table name from the metadata above, and then query it directly and multiply the results by the sampling ratio to get an estimate." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'cmle_week1_new_notebook_with_ecid_used_dataset_cre_sample_0_5'" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sample_table_name = df_samples[df_samples[\"sampling_rate\"] == sampling_rate][\"sample_table_name\"].iloc[0]\n", + "sample_table_name" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Approximate count: 1079600.0 using 5.0% sample\n", + "CPU times: user 1.65 ms, sys: 1.23 ms, total: 2.87 ms\n", + "Wall time: 3.08 s\n" + ] + } + ], + "source": [ + "%%time\n", + "count_query=f'''SELECT count(*) as cnt from {sample_table_name}'''\n", + "df = qs_cursor.query(count_query, output=\"dataframe\")\n", + "approx_count = df[\"cnt\"].iloc[0] / (sampling_rate / 100)\n", + "print(f\"Approximate count: {approx_count} using {sampling_rate *10}% sample\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Note:\n", + " \n", + "You can also query the latest sample from that dataset by using `SELECT * from {table_name} WITHAPPROXIMATE` however it is not advised to do aggregation queries or joins with that since this is only a uniform random sample.\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can see that the results are pretty accurate <1% error, and also the runtime is reduced by at least 20%, so using samples are a good choice for featurization data if we have a ML model that is not necessarily data-hungry." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "272c9e84-9321-469e-9c9d-032fe45f4357", + "showTitle": false, + "title": "" + } + }, + "source": [ + "# 4. Analyzing the data\n", + "\n", + "Let's now analyze the data by creating a few visualizations using some commonly requested questions. \n", + "\n", + "## 4.1 Email Funnel Analysis\n", + "\n", + "Let's look at the funnel of how many users actually fill out the webForm. A funnel analysis is a method of understanding the steps required to reach an outcome on a website and how many users get through each of those steps." + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "6627674c-a074-49f0-80cd-327e58be1f30", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
eventTypedistinctUsersdistinctEvents
0directMarketing.emailSent500970500970
1directMarketing.emailOpened198474198474
2advertising.impressions100246100246
3web.webpagedetails.pageViews9938999389
4directMarketing.emailClicked4243142431
5decisioning.propositionDisplay3163931639
6commerce.productViews3154531545
7web.webinteraction.linkClicks3150131501
8web.formFilledOut1484114841
9advertising.clicks63766376
10decisioning.propositionDismiss25542554
11decisioning.propositionInteract25402540
12commerce.purchases25382538
\n", + "
" + ], + "text/plain": [ + " eventType distinctUsers distinctEvents\n", + "0 directMarketing.emailSent 500970 500970\n", + "1 directMarketing.emailOpened 198474 198474\n", + "2 advertising.impressions 100246 100246\n", + "3 web.webpagedetails.pageViews 99389 99389\n", + "4 directMarketing.emailClicked 42431 42431\n", + "5 decisioning.propositionDisplay 31639 31639\n", + "6 commerce.productViews 31545 31545\n", + "7 web.webinteraction.linkClicks 31501 31501\n", + "8 web.formFilledOut 14841 14841\n", + "9 advertising.clicks 6376 6376\n", + "10 decisioning.propositionDismiss 2554 2554\n", + "11 decisioning.propositionInteract 2540 2540\n", + "12 commerce.purchases 2538 2538" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "simple_funnel_analysis_query = f'''SELECT eventType, COUNT(DISTINCT _id) as \"distinctUsers\",COUNT(_id) as \"distinctEvents\" FROM {table_name} GROUP BY eventType ORDER BY distinctUsers DESC'''\n", + "funnel_df = qs_cursor.query(simple_funnel_analysis_query, output=\"dataframe\")\n", + "funnel_df" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "747b6df6-a2a1-48e0-9027-0284bbe839e0", + "showTitle": false, + "title": "" + }, + "nteract": { + "transient": { + "deleting": false + } + } + }, + "source": [ + "Here, we launch a query to get number of users in each phase" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "20853d7e-9b9f-4472-b96b-cbc74d22a7ce", + "showTitle": false, + "title": "" + }, + "gather": { + "logged": 1667870707273 + } + }, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hovertemplate": "distinctUsers=%{x}
eventType=%{y}", + "legendgroup": "", + "marker": { + "color": "#636efa" + }, + "name": "", + "orientation": "h", + "showlegend": false, + "type": "funnel", + "x": [ + 500970, + 198474, + 42431, + 14841 + ], + "xaxis": "x", + "y": [ + "directMarketing.emailSent", + "directMarketing.emailOpened", + "directMarketing.emailClicked", + "web.formFilledOut" + ], + "yaxis": "y" + } + ], + "layout": { + "legend": { + "tracegroupgap": 0 + }, + "margin": { + "t": 60 + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "xaxis": { + "anchor": "y", + "domain": [ + 0, + 1 + ], + "title": { + "text": "distinctUsers" + } + }, + "yaxis": { + "anchor": "x", + "domain": [ + 0, + 1 + ], + "title": { + "text": "eventType" + } + } + } + }, + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import plotly.express as px\n", + "\n", + "email_funnel_events = [\"directMarketing.emailSent\", \"directMarketing.emailOpened\", \"directMarketing.emailClicked\", \"web.formFilledOut\"]\n", + "email_funnel_df = funnel_df[funnel_df[\"eventType\"].isin(email_funnel_events)]\n", + "\n", + "fig = px.funnel(email_funnel_df, y='eventType', x='distinctUsers')\n", + "fig.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "ef5f0c97-62c6-4489-ba62-0e031e574f37", + "showTitle": false, + "title": "" + } + }, + "source": [ + "## 4.2 Event correlation\n", + "Now, we analyze the correlation between various types of events. \n", + "\n", + "We'll look for which events predict the `web.formFilledOut` outcome. \n", + "\n", + "To do this, we must execute a more complex join query." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "09da403f-4aac-4723-9611-b0ba64a83f62", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
eventType_FirsteventType_LaterdistinctUsers
0directMarketing.emailSentdirectMarketing.emailSent99319
1directMarketing.emailOpeneddirectMarketing.emailOpened85822
2directMarketing.emailSentdirectMarketing.emailOpened85822
3advertising.impressionsadvertising.impressions63322
4directMarketing.emailOpeneddirectMarketing.emailSent63169
............
164commerce.purchasesweb.webinteraction.linkClicks46
165commerce.purchasesdecisioning.propositionDisplay32
166commerce.purchasesdirectMarketing.emailClicked25
167commerce.purchasesdecisioning.propositionDismiss10
168commerce.purchasesdecisioning.propositionInteract9
\n", + "

169 rows × 3 columns

\n", + "
" + ], + "text/plain": [ + " eventType_First eventType_Later \\\n", + "0 directMarketing.emailSent directMarketing.emailSent \n", + "1 directMarketing.emailOpened directMarketing.emailOpened \n", + "2 directMarketing.emailSent directMarketing.emailOpened \n", + "3 advertising.impressions advertising.impressions \n", + "4 directMarketing.emailOpened directMarketing.emailSent \n", + ".. ... ... \n", + "164 commerce.purchases web.webinteraction.linkClicks \n", + "165 commerce.purchases decisioning.propositionDisplay \n", + "166 commerce.purchases directMarketing.emailClicked \n", + "167 commerce.purchases decisioning.propositionDismiss \n", + "168 commerce.purchases decisioning.propositionInteract \n", + "\n", + " distinctUsers \n", + "0 99319 \n", + "1 85822 \n", + "2 85822 \n", + "3 63322 \n", + "4 63169 \n", + ".. ... \n", + "164 46 \n", + "165 32 \n", + "166 25 \n", + "167 10 \n", + "168 9 \n", + "\n", + "[169 rows x 3 columns]" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "event_correlation_query=f'''SELECT eventType_First, eventType_Later, COUNT(DISTINCT userId) as \"distinctUsers\"\n", + "FROM \n", + " (\n", + " SELECT a.eventType as eventType_First, \n", + " b.eventType as eventType_Later, \n", + " a._{tenant_id}.userid as userID \n", + " FROM {table_name} a\n", + " JOIN {table_name} b\n", + " ON a._{tenant_id}.userid = b._{tenant_id}.userid\n", + " WHERE a.timestamp <= b.timestamp\n", + " )\n", + "GROUP BY eventType_First, eventType_Later\n", + "ORDER BY distinctUsers DESC'''\n", + "event_correlation_df = qs_cursor.query(event_correlation_query, output=\"dataframe\")\n", + "event_correlation_df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we join the results of this correlation to obtain a coocurrence matrix which we can then display to get a visual feel of which events are likely to be occurring together." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "3dc30699-dc62-4657-a86b-6cd9be4ac16e", + "showTitle": false, + "title": "" + }, + "gather": { + "logged": 1667866377834 + } + }, + "outputs": [], + "source": [ + "coocc_matrix = event_correlation_df\n", + "individual_counts = funnel_df\n", + "cocc_with_individual = coocc_matrix.merge(individual_counts, left_on=\"eventType_First\", right_on=\"eventType\")\n", + "cocc_with_individual[\"probability\"] = cocc_with_individual[\"distinctUsers_x\"]/ cocc_with_individual[\"distinctUsers_y\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "7206de06-a841-4774-b889-35a410a3b702", + "showTitle": false, + "title": "" + }, + "gather": { + "logged": 1667866380317 + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/var/folders/4_/y52rp_4d21sdgtx662w561dm0000gq/T/ipykernel_15483/402706120.py:3: FutureWarning:\n", + "\n", + "In a future version of pandas all arguments of DataFrame.pivot will be keyword-only.\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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QhQtmTkv5uzs7DAwMCAoKCjbMQcHB6Kjo3n8+LGyLzQ0VElfeZ8sLS0pV64c165do1q1ampb5cqVc61XsmRJbG1tczw/gPr163P79m10dHSytVu6dOk8x3T69Gnlzy9fviQyMhIHBwcAypQpw99//6127aKiot56nnXq1OHWrVtcvnz5rWVzExoayrBhw/j000+Vh2Dv3bunVsbAwAAvLy+WLFlCcHAwp06dIiYmBicnJ9LT00lOTs52PaysrJT6NjY2fPnll+zatYtRo0axevXqXMejp6eHiYmJ2iYpLUIIIYqVzIzC2T4AMnNezOnr6/Ptt98yduxYdHV1cXV15e7du/z+++94e3szefJkevfujb+/P3fv3uXrr7+mV69eShrK+zRlyhSGDRuGqakpbdq0IS0tjTNnzpCSkpJtZvZ1/v7+fPnll5QtW1Z52DI0NJSvv/4aDw8PXFxc6NChA3PnzsXe3p4///yTffv20bFjR5ydnQkPD8fHx4egoCDKly+vtLt8+XLs7OxwcHDg+++/JyUlhX79+gHQuHFjDA0N+e677xg2bBhhYWFq+fO5adGiBc2bN6dz584sXLiQatWqcenSJVQqFW3atMnXdbKzs2Pjxo04Ozvz119/MWbMGLUZ+cDAQNLT05Uxbtq0CQMDAypVqoSFhQXe3t74+PgoD9XevXuXoKAg6tSpw2effcaIESNo27Yt9vb2pKSkcPz4ceWmRAghhPggfSApKYVBZs4/AH5+fowaNYpJkybh4OBAt27dSE5OxtDQkEOHDvHgwQMaNmzI559/jru7O8uWLdPIOAcMGMCaNWsICAigdu3atGjRgsDAwDxnzuFVmseiRYtYsWIFNWvWpF27dly5cgV4lRKyf/9+mjdvTt++fbG3t6d79+7cuHFDuQF58uQJcXFx2dJSZs+ezezZs6lbty4nTpxg7969ymx7qVKl2LRpE/v376d27dps3boVf3//fJ3nzp07adiwIT169MDR0ZGxY8eSnp6e7+u0du1aUlJSqF+/Pr169WLYsGGULVtWOW5mZsbq1atxdXWlTp06HD16lH//+9/KKjMBAQH4+PgwatQoqlevTocOHYiIiKBixYoApKenM3ToUBwcHGjTpg329vZqS1oKIYQQovhSZb6ZeCvEBy4hIYHKlStz7tw56tWrp+nhfJCMDG010u88i6Ya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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import seaborn as sns\n", + "\n", + "pivoted = cocc_with_individual.pivot(\"eventType_First\", \"eventType_Later\", \"probability\")\n", + "sns.heatmap(pivoted)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "f05daa1f-a4f0-477a-bd38-01879c308a2c", + "showTitle": false, + "title": "" + } + }, + "source": [ + "## 4.3 A more robust correlation calculation\n", + "\n", + "Let's use an in-built feature of the query service (the Spark functions) to get a better handle of correlations between various eventTypes. We'll usee the `corr` function - which computes pearson correlation coefficients between a given eventType, and the target eventType" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "a471826d-84dc-4261-b6eb-7f45a77649cd", + "showTitle": false, + "title": "" + } + }, + "source": [ + "#### Run on the full dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "822365c5-3140-4ad4-bc67-4ac8f51cf775", + "showTitle": false, + "title": "" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
webFormsFilled_totalUsersadvertisingClicks_totalUsersproductViews_totalUsersproductPurchases_totalUserspropositionDismisses_totaUserspropositionDisplays_totaUserspropositionInteracts_totalUsersemailClicks_totalUsersemailOpens_totalUserswebLinksClicks_totalUsers...webForms_advertisingClickswebForms_productViewswebForms_productPurchaseswebForms_propositionDismisseswebForms_propositionInteractswebForms_emailClickswebForms_emailOpenswebForms_emailSendswebForms_webLinkClickswebForms_webPageViews
014841637631545025543163925404243119847431501...-0.0065710.228957None0.0497560.1325180.2464980.0942070.0276880.21801None
\n", + "

1 rows × 22 columns

\n", + "
" + ], + "text/plain": [ + " webFormsFilled_totalUsers advertisingClicks_totalUsers \\\n", + "0 14841 6376 \n", + "\n", + " productViews_totalUsers productPurchases_totalUsers \\\n", + "0 31545 0 \n", + "\n", + " propositionDismisses_totaUsers propositionDisplays_totaUsers \\\n", + "0 2554 31639 \n", + "\n", + " propositionInteracts_totalUsers emailClicks_totalUsers \\\n", + "0 2540 42431 \n", + "\n", + " emailOpens_totalUsers webLinksClicks_totalUsers ... \\\n", + "0 198474 31501 ... \n", + "\n", + " webForms_advertisingClicks webForms_productViews \\\n", + "0 -0.006571 0.228957 \n", + "\n", + " webForms_productPurchases webForms_propositionDismisses \\\n", + "0 None 0.049756 \n", + "\n", + " webForms_propositionInteracts webForms_emailClicks webForms_emailOpens \\\n", + "0 0.132518 0.246498 0.094207 \n", + "\n", + " webForms_emailSends webForms_webLinkClicks webForms_webPageViews \n", + "0 0.027688 0.21801 None \n", + "\n", + "[1 rows x 22 columns]" + ] + }, + "execution_count": 52, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "large_correlation_query=f'''\n", + "SELECT SUM(webFormsFilled) as webFormsFilled_totalUsers,\n", + " SUM(advertisingClicks) as advertisingClicks_totalUsers,\n", + " SUM(productViews) as productViews_totalUsers,\n", + " SUM(productPurchases) as productPurchases_totalUsers,\n", + " SUM(propositionDismisses) as propositionDismisses_totaUsers,\n", + " SUM(propositionDisplays) as propositionDisplays_totaUsers,\n", + " SUM(propositionInteracts) as propositionInteracts_totalUsers,\n", + " SUM(emailClicks) as emailClicks_totalUsers,\n", + " SUM(emailOpens) as emailOpens_totalUsers,\n", + " SUM(webLinkClicks) as webLinksClicks_totalUsers,\n", + " SUM(webPageViews) as webPageViews_totalusers,\n", + " corr(webFormsFilled, emailOpens) as webForms_EmalOpens,\n", + " corr(webFormsFilled, advertisingClicks) as webForms_advertisingClicks,\n", + " corr(webFormsFilled, productViews) as webForms_productViews,\n", + " corr(webFormsFilled, productPurchases) as webForms_productPurchases,\n", + " corr(webFormsFilled, propositionDismisses) as webForms_propositionDismisses,\n", + " corr(webFormsFilled, propositionInteracts) as webForms_propositionInteracts,\n", + " corr(webFormsFilled, emailClicks) as webForms_emailClicks,\n", + " corr(webFormsFilled, emailOpens) as webForms_emailOpens,\n", + " corr(webFormsFilled, emailSends) as webForms_emailSends,\n", + " corr(webFormsFilled, webLinkClicks) as webForms_webLinkClicks,\n", + " corr(webFormsFilled, webPageViews) as webForms_webPageViews\n", + "FROM(\n", + " SELECT _{tenant_id}.userid as userID,\n", + " SUM(CASE WHEN eventType='web.formFilledOut' THEN 1 ELSE 0 END) as webFormsFilled,\n", + " SUM(CASE WHEN eventType='advertising.clicks' THEN 1 ELSE 0 END) as advertisingClicks,\n", + " SUM(CASE WHEN eventType='commerce.productViews' THEN 1 ELSE 0 END) as productViews,\n", + " SUM(CASE WHEN eventType='commerce.productPurchases' THEN 1 ELSE 0 END) as productPurchases,\n", + " SUM(CASE WHEN eventType='decisioning.propositionDismiss' THEN 1 ELSE 0 END) as propositionDismisses,\n", + " SUM(CASE WHEN eventType='decisioning.propositionDisplay' THEN 1 ELSE 0 END) as propositionDisplays,\n", + " SUM(CASE WHEN eventType='decisioning.propositionInteract' THEN 1 ELSE 0 END) as propositionInteracts,\n", + " SUM(CASE WHEN eventType='directMarketing.emailClicked' THEN 1 ELSE 0 END) as emailClicks,\n", + " SUM(CASE WHEN eventType='directMarketing.emailOpened' THEN 1 ELSE 0 END) as emailOpens,\n", + " SUM(CASE WHEN eventType='directMarketing.emailSent' THEN 1 ELSE 0 END) as emailSends,\n", + " SUM(CASE WHEN eventType='web.webinteraction.linkClicks' THEN 1 ELSE 0 END) as webLinkClicks,\n", + " SUM(CASE WHEN eventType='web.webinteraction.pageViews' THEN 1 ELSE 0 END) as webPageViews\n", + " FROM {table_name}\n", + " GROUP BY userId\n", + ")\n", + "'''\n", + "large_correlation_df = qs_cursor.query(large_correlation_query, output=\"dataframe\")\n", + "large_correlation_df" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "90daab0e-20f3-4557-a344-a604c79ba745", + "showTitle": false, + "title": "" + }, + "gather": { + "logged": 1667866445864 + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
variablevaluefeaturepearsonCorrelation
0webForms_EmalOpens0.094207EmalOpens0.094207
1webForms_advertisingClicks-0.006571advertisingClicks-0.006571
2webForms_productViews0.228957productViews0.228957
3webForms_productPurchases0.000000productPurchases0.000000
4webForms_propositionDismisses0.049756propositionDismisses0.049756
5webForms_propositionInteracts0.132518propositionInteracts0.132518
6webForms_emailClicks0.246498emailClicks0.246498
7webForms_emailOpens0.094207emailOpens0.094207
8webForms_emailSends0.027688emailSends0.027688
9webForms_webLinkClicks0.218010webLinkClicks0.218010
10webForms_webPageViews0.000000webPageViews0.000000
\n", + "
" + ], + "text/plain": [ + " variable value feature \\\n", + "0 webForms_EmalOpens 0.094207 EmalOpens \n", + "1 webForms_advertisingClicks -0.006571 advertisingClicks \n", + "2 webForms_productViews 0.228957 productViews \n", + "3 webForms_productPurchases 0.000000 productPurchases \n", + "4 webForms_propositionDismisses 0.049756 propositionDismisses \n", + "5 webForms_propositionInteracts 0.132518 propositionInteracts \n", + "6 webForms_emailClicks 0.246498 emailClicks \n", + "7 webForms_emailOpens 0.094207 emailOpens \n", + "8 webForms_emailSends 0.027688 emailSends \n", + "9 webForms_webLinkClicks 0.218010 webLinkClicks \n", + "10 webForms_webPageViews 0.000000 webPageViews \n", + "\n", + " pearsonCorrelation \n", + "0 0.094207 \n", + "1 -0.006571 \n", + "2 0.228957 \n", + "3 0.000000 \n", + "4 0.049756 \n", + "5 0.132518 \n", + "6 0.246498 \n", + "7 0.094207 \n", + "8 0.027688 \n", + "9 0.218010 \n", + "10 0.000000 " + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cols = large_correlation_df.columns\n", + "corrdf = large_correlation_df[[col for col in cols if (\"webForms_\" in col)]].melt()\n", + "corrdf[\"feature\"] = corrdf[\"variable\"].apply(lambda x: x.replace(\"webForms_\", \"\"))\n", + "corrdf[\"pearsonCorrelation\"] = corrdf[\"value\"]\n", + "\n", + "corrdf.fillna(0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "040f70cd-2df9-4b05-bd4f-64bafeb5b541", + "showTitle": false, + "title": "" + } + }, + "source": [ + "Let's visualize the results:" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "4cef1e7c-df03-4060-b4e4-2673194810ae", + "showTitle": false, + "title": "" + }, + "gather": { + "logged": 1667866449127 + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Pearson Correlation of Events with the outcome event')" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmYAAANXCAYAAACffZM2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAACbYklEQVR4nOzdd1xW9f//8ecFCDIEFFEwURwguHcqDlyppblRtNRyVe5R6qdUTFPLWdrSypXlzKzcC3OvxExxi1iRlgNSCwXO7w9/XF8vAQVHHPVxv93OTa9z3ud9Xudcgyfvc66DxTAMQwAAAMh2dtldAAAAAG4imAEAAJgEwQwAAMAkCGYAAAAmQTADAAAwCYIZAACASRDMAAAATIJgBgAAYBIEMwAAAJMgmAG4LxaLRREREQ+0z9DQUIWGhj7QPh+0c+fOqU2bNvLy8pLFYtHUqVOzu6THgr+/v7p06ZLptk2bNn3gNXTp0kVubm4PvF8gMwhm+E/Nnj1bFovFOuXMmVOBgYHq3bu3zp07l93lmcK///6rKVOm6Omnn5aHh4fNMTp27Fh2l/fAHD58WBEREYqJicnuUu7JgAEDtGbNGg0bNkzz5s1T48aNM2x762v+9umVV175D6tO37Vr1xQREaHIyMjsLiWNh/U6MfM+34+xY8fq22+/ze4ynngrV668519YHR5sKUDmvP322ypSpIj+/fdfbd26VR9//LFWrlypX375RS4uLtldXrb566+/1LhxY+3bt09NmzZVhw4d5ObmpqNHj2rBggWaMWOGrl+/nt1lPhCHDx/WqFGjFBoaKn9/f5tla9euzZ6ismDjxo1q3ry5Bg8enKn2DRs2VKdOndLMDwwMfNClZdm1a9c0atQoScr2kcqjR4/Kzu7/xgzu9Dq5H2ba5wdp7NixatOmjVq0aJHdpTzRVq5cqQ8//PCewhnBDNmiSZMmqly5siSpW7du8vLy0uTJk7V8+XKFh4f/JzVcvXpVrq6u/8m2MqtLly7av3+/lixZotatW9ssGz16tN58880Hsp2M9t0wDP37779ydnZ+INu5V46Ojtm6/cw4f/68PD09M90+MDBQL7zwwsMr6DHh5OSU3SUA2csA/kOzZs0yJBl79uyxmf/DDz8Ykox33nnHOm/evHlGxYoVjZw5cxq5c+c22rVrZ8TGxtqs9+OPPxpt2rQx/Pz8DEdHR6NgwYJG//79jWvXrtm069y5s+Hq6mqcOHHCaNKkieHm5mY0b97cMAzDOHbsmNGqVSsjf/78hpOTk/HUU08Z7dq1My5fvmxd/8aNG8bbb79tFC1a1HB0dDQKFy5sDBs2zPj3339ttlO4cGHjueeeM7Zs2WJUqVLFcHJyMooUKWLMmTPnrsdm586dhiSje/fumTqWhmEYGzZsMGrWrGm4uLgYHh4exvPPP28cPnzYps3IkSMNScahQ4eM8PBww9PT0yhfvrxNvatXrzYqVapkODk5GVOmTDEMwzAuXbpk9OvXzyhYsKDh6OhoFCtWzBg/fryRnJxs078kY+TIkdbHMTExxquvvmoEBgYaOXPmNPLkyWO0adPGOH36tLVN6uvg9mnTpk2GYRhGnTp1jDp16ths59y5c8bLL79s5MuXz3BycjLKli1rzJ4926bN6dOnDUnGhAkTjE8//dT6fFWuXNnYvXt3po7pyZMnjTZt2hi5c+c2nJ2djaefftr44Ycf7lr7nUgyevXqdcc2vXr1MlxdXY2rV6+mWda+fXsjf/78RlJSknXeypUrrc+9m5ub8eyzzxq//PKLzXqpr/tff/3VaN68ueHq6mrkzZvXGDRokLWv1GN2+5T6nMbFxRldunQxnnrqKcPR0dHw8fExnn/+eZvn83bLly83JBkHDhywzluyZIkhyWjZsqVN26CgICMsLMz6uHDhwkbnzp0Nw7j76+Re32932+fMHLdUycnJxpQpU4ySJUsaTk5ORr58+YwePXoYFy9evGMNqTLzHu7cubNRuHDhNOumvrdTpbdPqcfSMAzj119/NV5++WXD19fXcHR0NPz9/Y1XXnnFSExMtLa52+vfMAxj06ZNhiRj4cKFRkREhFGgQAHDzc3NaN26tXH58mXj33//Nfr162d4e3sbrq6uRpcuXdJ8VhpG5j7jM/Lrr78aL730kpEvXz7D0dHRKFmypPH5559bl//xxx+Gvb29ERERkWbdI0eOGJKMadOmWedl5vMus58vnTt3zvJnxK0YMYMpnDx5UpLk5eUlSXrnnXc0fPhwhYWFqVu3bvrzzz81bdo01a5dW/v377eOVCxevFjXrl3Tq6++Ki8vL+3evVvTpk3Tr7/+qsWLF9tsIykpSY0aNVLNmjU1ceJEubi46Pr162rUqJESExPVp08f+fj46LffftMPP/ygy5cvy8PDQ9LNUb05c+aoTZs2GjRokHbt2qVx48YpOjpay5Yts9nOiRMn1KZNG3Xt2lWdO3fWF198oS5duqhSpUoqVapUhsfgu+++kyS9+OKLmTpm69evV5MmTVS0aFFFRETon3/+0bRp0xQSEqKffvopzWmftm3bKiAgQGPHjpVhGNb5R48eVXh4uHr27Knu3burRIkSunbtmurUqaPffvtNPXv2VKFChbR9+3YNGzZMcXFxd7zQfc+ePdq+fbvat2+vggULKiYmRh9//LFCQ0N1+PBhubi4qHbt2urbt68++OAD/e9//1NwcLAkWf+93T///KPQ0FCdOHFCvXv3VpEiRbR48WJ16dJFly9fVr9+/Wzaf/XVV/r777/Vs2dPWSwWvffee2rVqpVOnTqlHDlyZFj7uXPnVKNGDV27dk19+/aVl5eX5syZo+eff15LlixRy5YtVbt2bc2bN08vvvhihqcn0/Pvv//qr7/+SjPf3d1djo6OateunT788EOtWLFCbdu2tS6/du2avv/+e3Xp0kX29vaSpHnz5qlz585q1KiR3n33XV27dk0ff/yxatasqf3799s898nJyWrUqJGefvppTZw4UevXr9ekSZNUrFgxvfrqq/L29tbHH3+sV199VS1btlSrVq0kSWXLlpUktW7dWocOHVKfPn3k7++v8+fPa926dYqNjc3w1GLNmjVlsVj0448/WvvZsmWL7OzstHXrVmu7P//8U0eOHFHv3r3T7Sczr5N7eb/dbZ8zc9xS9ezZU7Nnz9ZLL72kvn376vTp05o+fbr279+vbdu23fH1ltX38N3MmzdP3bp1U9WqVdWjRw9JUrFixSRJv//+u6pWrarLly+rR48eCgoK0m+//aYlS5bo2rVrcnR0zNTr/1bjxo2Ts7Ozhg4dqhMnTmjatGnKkSOH7OzsdOnSJUVERGjnzp2aPXu2ihQpohEjRljXzexnfHrOnTunatWqyWKxqHfv3vL29taqVavUtWtXJSQkqH///sqfP7/q1KmjRYsWaeTIkTbrL1y4UPb29tb3WVY/7+72+dKzZ0/9/vvvWrdunebNm5el51ASI2b4b6X+Brx+/Xrjzz//NM6ePWssWLDA8PLyMpydnY1ff/3ViImJMezt7W1GzwzDMA4ePGg4ODjYzL99ZMwwDGPcuHGGxWIxzpw5Y52X+hvM0KFDbdru37/fkGQsXrw4w5qjoqIMSUa3bt1s5g8ePNiQZGzcuNE6r3DhwoYk48cff7TOO3/+vOHk5GQMGjTojsemZcuWhiTj0qVLd2yXqnz58ka+fPmMCxcuWOcdOHDAsLOzMzp16mSdl/pbdXh4eJo+UutdvXq1zfzRo0cbrq6uxrFjx2zmDx061LC3t7f5rVa3jZil95zs2LHDkGTMnTvXOm/x4sU2ox+3un3EbOrUqYYk48svv7TOu379ulG9enXDzc3NSEhIMAzj/36j9fLyshmxSB3B+f7779Ns61b9+/c3JBlbtmyxzvv777+NIkWKGP7+/ja/PSsTo2C3ts1o+vrrrw3DMIyUlBTjqaeeMlq3bm2z7qJFi2xeU3///bfh6emZZmT1jz/+MDw8PGzmp77u3377bZu2FSpUMCpVqmR9/Oeff6Z5Hg3j5iiC/v8IQVaVKlXKZiSsYsWKRtu2bQ1JRnR0tGEYhvHNN9+kGVm7dcTMMO78Ormf91tG+2wYmT9uW7ZsMSQZ8+fPt2m3evXqdOffLrPv4cyOmBmGYbi6utocv1SdOnUy7Ozs0pytMIybrz3DyPzrP3XErHTp0sb169etbcPDww2LxWI0adLEpv/q1avb1J+Vz/j0dO3a1fD19TX++usvm/nt27c3PDw8rJ9Bn376qSHJOHjwoE27kiVLGvXq1bM+zuznXVY+X3r16pWlUbJb8a1MZIsGDRrI29tbfn5+at++vdzc3LRs2TI99dRT+uabb5SSkqKwsDD99ddf1snHx0cBAQHatGmTtZ9br4W6evWq/vrrL9WoUUOGYWj//v1ptnvrb7qSrCNia9as0bVr19KtdeXKlZKkgQMH2swfNGiQJGnFihU280uWLKlatWpZH3t7e6tEiRI6derUHY9JQkKCJClXrlx3bCdJcXFxioqKUpcuXZQnTx7r/LJly6phw4bWmm+V0bf/ihQpokaNGtnMW7x4sWrVqqXcuXPbPAcNGjRQcnKyfvzxxwxru/U5uXHjhi5cuKDixYvL09NTP/300133LT0rV66Uj4+PzfWHOXLkUN++fXXlyhVt3rzZpn27du2UO3du6+PU5+Nuz8HKlStVtWpV1axZ0zrPzc1NPXr0UExMjA4fPnxP9UtS8+bNtW7dujRT3bp1Jd385mbbtm21cuVKXblyxbrewoUL9dRTT1lrWrdunS5fvqzw8HCb58be3l5PP/20zfsj1e3Pfa1ate56LKSbz6Wjo6MiIyN16dKlLO1vrVq1tGXLFknS33//rQMHDqhHjx7Kmzevdf6WLVvk6emp0qVLZ6nvW93r+y0z7nbcFi9eLA8PDzVs2NDmuahUqZLc3NzSfS5S3ct7+F6lpKTo22+/VbNmzazX9t7KYrFIyvrrv1OnTjYjgk8//bQMw9DLL79s0+7pp5/W2bNnlZSUJElZ+oy/nWEYWrp0qZo1aybDMGzWb9SokeLj462fM61atZKDg4MWLlxoXf+XX37R4cOH1a5dO+u8rH7e3evnS2ZxKhPZ4sMPP1RgYKAcHByUP39+lShRwvpNrOPHj8swDAUEBKS77q0fBLGxsRoxYoS+++67ND844uPjbR47ODioYMGCNvOKFCmigQMHavLkyZo/f75q1aql559/Xi+88II1tJ05c0Z2dnYqXry4zbo+Pj7y9PTUmTNnbOYXKlQoTc25c+e+6w82d3d3STd/iN3tovLUbZYoUSLNsuDgYK1ZsybNBf5FihRJt6/05h8/flw///yzvL29013n/PnzGdb2zz//aNy4cZo1a5Z+++03m9Omtz8nmXXmzBkFBATYfFtP+r9TWnd7DlI/RO/2HJw5c0ZPP/10mvm3budeQ0TBggXVoEGDO7Zp166dpk6dqu+++04dOnTQlStXtHLlSuspE+nmcyNJ9erVS7eP1NdRqpw5c6Z5HjPzepRuXoj/7rvvatCgQcqfP7+qVaumpk2bqlOnTvLx8bnjurVq1dInn3yiEydO6OTJk7JYLKpevbo1sHXv3l1btmxRSEhImuc1K+71/XY3mTlux48fV3x8vPLly5duH3d6n9zLe/he/fnnn0pISLjrazerr//bj33qZ6afn1+a+SkpKYqPj5eXl1eWPuPT25fLly9rxowZmjFjRrptUo973rx5Vb9+fS1atEijR4+WdPMXHQcHB+vpaynrn3f3+vmSWQQzZIuqVaum+5ubdPO3O4vFolWrVlmvqblV6o0fk5OT1bBhQ128eFFDhgxRUFCQXF1d9dtvv6lLly5KSUmxWc/JySndHwCTJk1Sly5dtHz5cq1du1Z9+/bVuHHjtHPnTpsgl/qD8W7Sq1mSTUBJT1BQkCTp4MGDNiMAD0pG37RMb35KSooaNmyoN954I9117nSLhz59+mjWrFnq37+/qlevLg8PD1ksFrVv3z7Nc/Kw3OtzkN2qVasmf39/LVq0SB06dND333+vf/75x+a3+9RjOG/evHTDkYOD7cd6Rscis/r3769mzZrp22+/1Zo1azR8+HCNGzdOGzduVIUKFTJcL3XU5ccff9SpU6dUsWJFubq6qlatWvrggw905coV7d+/X++888591fewnuvMHLeUlBTly5dP8+fPT3d5Rj/osyqjz57k5OQH0v+9yugY3e05yexnfHpSX/8vvPCCOnfunG6bW68VbN++vV566SVFRUWpfPnyWrRokerXr6+8efPa9JmVz7uH/flCMIPpFCtWTIZhqEiRIncMAAcPHtSxY8c0Z84cmwuw161bl+VtlilTRmXKlNFbb72l7du3KyQkRJ988onGjBmjwoULKyUlRcePH7e56PjcuXO6fPmyChcunOXtpadZs2YaN26cvvzyy7sGs9RtHj16NM2yI0eOKG/evPf1m3axYsV05cqVu47wpGfJkiXq3LmzJk2aZJ3377//6vLlyzbtMht0pZv7+/PPPyslJcUmXB85csS6/EEoXLhwhsf0QW7nTsLCwvT+++8rISFBCxculL+/v6pVq2Zdnnoxd758+e7p+UnP3Z6LYsWKadCgQRo0aJCOHz+u8uXLa9KkSfryyy8zXKdQoUIqVKiQtmzZolOnTllf07Vr19bAgQO1ePFiJScnq3bt2vdV2716EP0WK1ZM69evV0hISJZvMZOV93Du3LnTvH+ktCPFUvr75e3tLXd3d/3yyy93rem/eP1n9jM+Pd7e3sqVK5eSk5Mz9fpv0aKFevbsaT2deezYMQ0bNixNPff6eZeR+3l9cY0ZTKdVq1ayt7fXqFGj0vwGYhiGLly4IOn/fmu5tY1hGHr//fczva2EhATrdQ+pypQpIzs7OyUmJkqSnn32WUlK882cyZMnS5Kee+65TG/vTqpXr67GjRvrs88+S/fO3devX7fezNTX11fly5fXnDlzbD6wf/nlF61du9Za870KCwvTjh07tGbNmjTLLl++nOaY3cre3j7N8zZt2rQ0v92n/tBJ7wfO7Z599ln98ccfNteKJCUladq0aXJzc1OdOnXu2kdmPPvss9q9e7d27NhhnXf16lXNmDFD/v7+Klmy5APZzp20a9dOiYmJmjNnjlavXq2wsDCb5Y0aNZK7u7vGjh2rGzdupFn/zz//zPI2U2/qfPtzce3aNf37778284oVK6ZcuXJZ3x93UqtWLW3cuFG7d++2BrPy5csrV65cGj9+vJydnVWpUqU79pGV10lWZLTPWREWFqbk5GTrabJbJSUl3bHvrLyHixUrpvj4eP3888/WeXFxcWm+ES7dPF63b9fOzk4tWrTQ999/r71796ZZJ/X9+l+9/jP7GZ8ee3t7tW7dWkuXLk03aN7++vf09FSjRo20aNEiLViwQI6Ojmluvns/n3cZuZ/XLSNmMJ1ixYppzJgxGjZsmGJiYtSiRQvlypVLp0+f1rJly9SjRw8NHjxYQUFBKlasmAYPHqzffvtN7u7uWrp0aZbO82/cuFG9e/dW27ZtFRgYqKSkJM2bN8/65pekcuXKqXPnzpoxY4YuX76sOnXqaPfu3ZozZ45atGhhvXj7QZg7d66eeeYZtWrVSs2aNVP9+vXl6uqq48ePa8GCBYqLi9PEiRMlSRMmTFCTJk1UvXp1de3a1fpVew8Pj/v+25Wvv/66vvvuOzVt2tR664GrV6/q4MGDWrJkiWJiYmxOBdyqadOmmjdvnjw8PFSyZEnt2LFD69evt94KJVX58uVlb2+vd999V/Hx8XJyclK9evXSvV6nR48e+vTTT9WlSxft27dP/v7+WrJkibZt26apU6dm6gsTmTF06FB9/fXXatKkifr27as8efJozpw5On36tJYuXXpf10IdO3Ys3RGm/Pnzq2HDhtbHFStWVPHixfXmm28qMTHR5jSmdPMaso8//lgvvviiKlasqPbt28vb21uxsbFasWKFQkJCNH369CzV5uzsrJIlS2rhwoUKDAxUnjx5VLp0aSUlJal+/foKCwtTyZIl5eDgoGXLluncuXNq3779XfutVauW5s+fL4vFYj21aW9vrxo1amjNmjUKDQ29682Es/I6eRD7nJVrCOvUqaOePXtq3LhxioqK0jPPPKMcOXLo+PHjWrx4sd5//321adMmw/Uz+x5u3769hgwZopYtW6pv377W26MEBgam+UJNpUqVtH79ek2ePFkFChRQkSJF9PTTT2vs2LFau3at6tSpox49eig4OFhxcXFavHixtm7dKk9Pz4f6+r9VZj/jMzJ+/Hht2rRJTz/9tLp3766SJUvq4sWL+umnn7R+/XpdvHjRpn27du30wgsv6KOPPlKjRo3S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RURE6NChQ3ruuee0ceNGlSxZUsuWLUu3HycnJ7m7u9tMAAA8Cp6oYHbhwgUdPXpUb731lurXr6/g4GBdunTJujw4OFg///yz/v33X+u89C5u79Chg3755Rft27dPS5YsUceOHa3LKlasqD/++EMODg4qXry4zZQ3b9471ufo6Kjk5OS77oefn59eeeUVffPNNxo0aJBmzpyZmd1Pw8PDQ/nz59eePXus85KTk/XTTz9ZH+fJk0eNGjXShx9+qKtXr6bpI7P3TCtbtqy2bNmSJnDdKm/evNq4caNOnDihsLCwNG0DAwM1YMAArV27Vq1atdKsWbMytW0AAB4VT1Qwy507t7y8vDRjxgydOHFCGzdu1MCBA63LO3ToIIvFou7du+vw4cNauXKlJk6cmKYff39/1ahRQ127dlVycrKef/5567IGDRqoevXqatGihdauXauYmBht375db7755l2/Rejv769du3YpJiZGf/31l1JSUtK06d+/v9asWaPTp0/rp59+0qZNmxQcHHzPx6RPnz4aN26cli9frqNHj6pfv366dOmSLBaLtc2HH36o5ORkVa1aVUuXLtXx48cVHR2tDz74IM2p3oz07t1bCQkJat++vfbu3avjx49r3rx5Onr0qE27fPnyaePGjTpy5IjCw8OVlJSkf/75R71791ZkZKTOnDmjbdu2ac+ePfe13wAAmNETFczs7Oy0YMEC7du3T6VLl9aAAQM0YcIE63I3Nzd9//33OnjwoCpUqKA333zTeruG23Xs2FEHDhxQy5YtbU7TWSwWrVy5UrVr19ZLL72kwMBAtW/fXmfOnFH+/PnvWN/gwYNlb2+vkiVLytvbW7GxsWnaJCcnq1evXgoODlbjxo0VGBiojz766B6PiDRkyBCFh4erU6dOql69utzc3NSoUSOb6+yKFi2qn376SXXr1tWgQYNUunRpNWzYUBs2bEhz65CMeHl5aePGjbpy5Yrq1KmjSpUqaebMmelec+bj46ONGzfq4MGD6tixo+zs7HThwgV16tRJgYGBCgsLU5MmTbjAHwDw2LEYD+rqbjwWUlJSFBwcrLCwMI0ePTq7y3kgEhIS5OHhofj4+Pu+3uzktOZ3bVOsz/L72gYA4OF4kD8PHpYn7nYZsHXmzBmtXbtWderUUWJioqZPn67Tp0+rQ4cO2V0aAABPnCfqVCbSsrOz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yEhVrlxZkZGRGjBggEaNGqUrV64oPj5eJ06cUJ06dTRu3Dh17NjReoF8QECAPvjgA9WpU0cff/yxcubMKUkKCQmxjrgFBgZq27ZtmjJliho2bHhPNd64cUOffPKJihUrJknq3bu33n777TTtli1bpk6dOumzzz5Tu3btrPOPHz+u0NDQe9p2qvXr12v37t2Kjo5WYGCgJKlo0aJp2h09elQNGzZUy5YtNXXqVFksFklSbGysKlSooMqVK0u6ORp3J+PGjdOoUaPuq2YAALIDI2b3qU6dOoqMjJRhGNqyZYtatWql4OBgbd26VZs3b1aBAgUUEBCgAwcOaPbs2XJzc7NOjRo1UkpKik6fPm3tr3r16jb9V69eXdHR0fdcn4uLizWUSZKvr6/Onz9v02bXrl1q27at5s2bZxPKJMkwjHvedqqoqCgVLFjQGsrS888//6hWrVpq1aqV3n//fWsok6RXX31VCxYsUPny5fXGG29o+/btd9zesGHDFB8fb53Onj173/sAAMB/gWB2n0JDQ7V161YdOHBAOXLkUFBQkEJDQxUZGanNmzerTp06kqQrV66oZ8+eioqKsk4HDhzQ8ePHbYLTg5YjRw6bxxaLJU3YKlasmIKCgvTFF1+k+ZZlYGCgjhw5cl81ODs737WNk5OTGjRooB9++EG//fabzbImTZrozJkzGjBggH7//XfVr18/w9OxqX25u7vbTAAAPAoIZvcp9TqzKVOmWENYajCLjIy0ngasWLGiDh8+rOLFi6eZHB0drf3t3LnTpv+dO3cqODj4oe5D3rx5tXHjRp04cUJhYWE24axDhw5av3699Tq6W924cSPNlxfSU7ZsWf366686duxYhm3s7Ow0b948VapUSXXr1tXvv/9us9zb21udO3fWl19+qalTp2rGjBlZ2EMAAB4NBLP7lDt3bpUtW1bz58+3hrDatWvrp59+0rFjx6xhbciQIdq+fbt69+6tqKgoHT9+XMuXL09z8f+2bdv03nvv6dixY/rwww+1ePFi9evXz6bNb7/9ZjPyFhUVpUuXLt3XfuTLl08bN27UkSNHFB4erqSkJElS//79FRISovr16+vDDz/UgQMHdOrUKS1atEjVqlXT8ePH79p3nTp1VLt2bbVu3Vrr1q3T6dOntWrVKq1evdqmnb29vebPn69y5cqpXr16+uOPPyRJI0aM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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "fig, ax = plt.subplots(figsize=(5,10))\n", + "sns.barplot(data=corrdf.fillna(0), y=\"feature\", x=\"pearsonCorrelation\")\n", + "ax.set_title(\"Pearson Correlation of Events with the outcome event\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "application/vnd.databricks.v1+cell": { + "cellMetadata": {}, + "inputWidgets": {}, + "nuid": "277dceed-66c7-4b34-9f57-90334de32a00", + "showTitle": false, + "title": "" + } + }, + "source": [ + "
\n", + " Conclusion\n", + "With this information, we now have a hypothesis on necessary features to use in our model.\n", + "We will use the number of these various event types, as well as the recency of each event type as features \n", + "for the model. The next step is to create these \"featurized\" datasets\n", + "
" + ] + } + ], + "metadata": { + "application/vnd.databricks.v1+notebook": { + "dashboards": [], + "language": "python", + "notebookMetadata": { + "pythonIndentUnit": 2 + }, + "notebookName": "Week1Notebook", + "notebookOrigID": 1016049760723614, + "widgets": { + "clientId": { + "currentValue": "35e6e4d205274c4ca1418805ac41153b", + "nuid": "1b95325b-a396-44b8-ba37-bfa820446cc3", + "widgetInfo": { + "defaultValue": "", + "label": "Client ID", + "name": "clientId", + "options": { + "validationRegex": null, + "widgetType": "text" + }, + "widgetType": "text" + } + }, + "clientSecret": { + "currentValue": "s8e-usTcdYC9Ye6CTzZ-aT_5XAdp04SYv-S-", + "nuid": "13cdebc3-d33a-419f-8b28-c1baa8c164cd", + "widgetInfo": { + "defaultValue": "", + "label": "Client Secret", + "name": "clientSecret", + "options": { + "validationRegex": null, + "widgetType": "text" + }, + "widgetType": "text" + } + }, + "datasetId": { + "currentValue": "63f95a0ada33491bd0915afd", + "nuid": "2a8d69b2-31d2-49c4-8dac-b58959f9eb7f", + "widgetInfo": { + "defaultValue": "", + "label": "Dataset ID", + "name": "datasetId", + "options": { + "validationRegex": null, + "widgetType": "text" + }, + "widgetType": "text" + } + }, + "imsOrgId": { + "currentValue": "3ADF23C463D98F640A494032@AdobeOrg", + "nuid": "9f1dfee3-a180-4d1a-9867-58884d1e9755", + "widgetInfo": { + "defaultValue": "", + "label": "IMS Org ID", + "name": "imsOrgId", + "options": { + "validationRegex": null, + "widgetType": "text" + }, + "widgetType": "text" + } + }, + "privateKeyPath": { + "currentValue": "/dbfs/FileStore/shared_uploads/cmenguy@adobe.com/keypairs/cloud-ml-ecosyste_stage/private.key", + "nuid": "6f7ae692-2556-4ab3-adf2-0d05cd238a72", + "widgetInfo": { + "defaultValue": "", + "label": "Private Key Path", + "name": "privateKeyPath", + "options": { + "validationRegex": null, + "widgetType": "text" + }, + "widgetType": "text" + } + }, + "sandboxName": { + "currentValue": "prod", + "nuid": "f34f687d-3b15-4fef-83af-e098ee403e0a", + "widgetInfo": { + "defaultValue": "", + "label": "Sandbox name", + "name": "sandboxName", + "options": { + "validationRegex": null, + "widgetType": "text" + }, + "widgetType": "text" + } + }, + "techAccountId": { + "currentValue": "D94C245363DBF9770A494005@techacct.adobe.com", + "nuid": "035ea90b-3fa3-4b3b-ad80-6b90ec67de79", + "widgetInfo": { + "defaultValue": "", + "label": "Technical Account ID", + "name": "techAccountId", + "options": { + "validationRegex": null, + "widgetType": "text" + }, + "widgetType": "text" + } + } + } + }, + "kernel_info": { + "name": "python3" + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.2" + }, + "nteract": { + "version": "nteract-front-end@1.0.0" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} From 43cffd2e4dbcd2a11c04006e73241e4f3c7a73c5 Mon Sep 17 00:00:00 2001 From: jpage Date: Fri, 22 Sep 2023 20:09:43 -0600 Subject: [PATCH 2/4] Updated README and added an image --- README.md | 287 +++++++++++++++++++++++------------------ img/CMLE Notebooks.png | Bin 0 -> 78008 bytes 2 files changed, 159 insertions(+), 128 deletions(-) create mode 100644 img/CMLE Notebooks.png diff --git a/README.md b/README.md index 22ccc59..cd6c760 100644 --- a/README.md +++ b/README.md @@ -1,189 +1,220 @@ -# Cloud ML Ecosystem (CMLE) +# Adobe Experience Platform - Cloud ML Ecosystem (CMLE) -This repository documents the various steps and pipelines needed to run Machine Learning (ML) models leveraging Adobe Experience Platform data. There are 2 parts to this repository: -- Notebooks to illustrate the end-to-end workflow on a variety of cloud ML platforms. -- Pipeline and library code that can be extended from to add your own ML model and data. +This repository provides sample notebooks that demonstrate an end-to-end workflow for using customer data from the Adobe Experience Platform (AEP) with cloud-based machine learning tools. The notebooks serve as a template to help data science teams take advantage of their organization's AEP data and services within their modeling workflow to develop custom models to support their organization's marketing and experience activities. -## Contents -The git repo currently contains five notebooks showcasing the full lifecycle of an ML application leveraging the Adobe Experience Platform. +README contents: +- [Intended use](#intended-use) +- [Overview of CMLE notebooks](#overview-of-cmle-notebooks) + - [Generate synthetic data](#generate-synthetic-data) + - [EDA and Featurization with Query Service](#eda-and-featurization-with-query-service) + - [Export training data](#export-training-data) + - [Train a propensity model](#train-a-propensity-model) + - [Score the propensity model](#score-the-propensity-model) + - [Ingest scores to AEP](#ingest-scores-to-aep) + - [Create and activate audiences from code](#create-and-activate-audiences-from-code) +- [Getting started with the CMLE notebooks](#getting-started-with-the-cmle-notebooks) +- [Troubleshooting](#troubleshooting) +- [Helpful resources](#helpful-resources) -Notebook Link | Environment | Summary | Scope -------------- |-------|---------| ----- -[Week1Notebook.ipynb](notebooks/assignments/Week1Notebook.ipynb) | Local | Data Exploration | Create synthetic data and perform exploratory data analysis. -[Week2Notebook.ipynb](notebooks/assignments/Week2Notebook.ipynb) | Local | Featurization | Generate a training set and export to cloud storage. -[Week3Notebook.ipynb](notebooks/assignments/Week3Notebook.ipynb) | Cloud Platform | Training | Plugging in features into a machine learning model. -[Week4Notebook.ipynb](notebooks/assignments/Week4Notebook.ipynb) | Cloud Platform | Scoring | Generating propensity scores for all profiles and importing back to the Experience Platform. -[Week5Notebook.ipynb](notebooks/assignments/Week5Notebook.ipynb) | Cloud Platform | Targeting | Target profiles based on propensity interval. +## Intended use -Before you can use any of the code in this repository, there is some setup required. -Please refer to the `Environment` part of the table above to determine the setup needed to run that notebook as described in the next section. +The sample notebooks in this repository provide a stylized example of training and scoring a propensity model to predict subscription conversions from AEP data. The first notebook will generate synthetic datasets in an AEP sandbox that will be used in subsequent notebooks to illustrate an end-to-end flow that includes: +- Exploring and featurizing data from AEP +- Making the prepared training data available in your machine learning environment (we use Databricks ML as an example, but you can modify the sample notebooks to use your own ML environment) +- Training and scoring the propensity model +- Enriching AEP profiles with the computed propensity scores, and using those scores to create and activate an audience -**Note**: If the `Environment` says `Cloud Platform` you can use your Cloud Platform of choice to run this notebook and refer to the appropriate section of the setup below. +The sample notebooks are intended to be used in one of two ways: +1. As a tutorial for using AEP data in ML workflows + - Ideally, use a dedicated AEP sandbox for completing the tutorial, to avoid mixing synthetic data with real customer data. You can reset or delete the sandbox after completing the tutorial to free it up for other use. + - Clone or download this repository to create a copy in your ML environment. + - Follow the instructions in [Getting started with the CMLE notebooks](#getting-started-with-the-cmle-notebooks) to get an AEP API credential with the required permissions and update the [config.ini](../conf/config.ini) file with the required values. + - Review and execute the cells in each notebook, in order to demonstrate and validate the workflow in your environment + - Modify the code in the notebooks as needed to adapt to your environment +2. As a template for AEP-related ML projects for your organization + - Fork the CMLE repository as a starting template for a new ML project + - Alternatively, simply reference the code in these notebooks as helpful examples to start a new project from scratch -## Configuration File +> **:warning: Warning** +> The workflow illustrated in these notebooks involves exporting datasets from AEP to a cloud storage destination, where it can be read and processed using external machine learnig tools. As such, there is some risk of sensitive personal data leaving the Experience Platform and being used inappropriately outside of the Platform. +> +> Experience Platform provides data governance tools for you to manage your data usage obligations and help minimize this risk. You are responsible ensuring that data in the Experience Platform is properly labeled before querying or exporting that data. This includes manually re-applying labels to derived datasets created from query output. Derived datasets from queries do not support the processing of sensitive personal data. You are responsible for understanding the limitations and obligations of your data and how you use that data in Experience Platform and the destination platform, which may have its own rules and obligations for incoming and outgoing data. Learn more about [data governance tools](https://experienceleague.adobe.com/docs/experience-platform/data-governance/home.html?lang=en) in Experience Platform. -There is a common [configuration file](./conf/config.ini) used by all the notebooks. -For the setup you can refer to the following section, but here are the different configuration options you should use: +## Overview of CMLE notebooks -Config Property | Section | Description | Value | Needed for -----------------|---------|------------------------------------------------------------|-------|------------ -ims_org_id | Platform | The organization ID | See section below on **Org-level Information** | Weeks 1 through 5 -sandbox_name | Platform | The ID of the sandbox to use | See section below on **Org-level Information** | Weeks 1 through 5 -dataset_id | Platform | The ID of the dataset containing the synthetic data | Dataset ID created as part of [Week1Notebook.ipynb](notebooks/assignments/Week1Notebook.ipynb) | Week 2 -featurized_dataset_id | Platform | The ID of the dataset containing the featurized data | Dataset ID created as part of [Week2Notebook.ipynb](notebooks/assignments/Week2Notebook.ipynb) | Weeks 3 & 4 -scoring_dataset_id | Platform | The ID of the dataset containing the scoring output | Dataset ID created as part of [Week4Notebook.ipynb](notebooks/assignments/Week4Notebook.ipynb) | Week 5 -environment | Platform | The type of environment this organization is running under | **prod** if running in production, **stage** otherwise | Weeks 1 through 5 -client_id | Authentication | The client ID used for API calls | See section below on **Authentication Information** | Weeks 1 through 5 -client_secret | Authentication | The client secret used for API calls | See section below on **Authentication Information** | Weeks 1 through 5 -private_key_path | Authentication | The path to the private key for your JWT token | See section below on **Authentication Information** | Weeks 1 through 5 -tech_acct_id | Authentication | The technical account ID used for API calls | See section below on **Authentication Information** | Weeks 1 through 5 -export_path | Cloud | The path in your Cloud Storage account where featurized data will be exported | Default to `cmle/egress` | Weeks 2, 3 & 4 -import_path | Cloud | The path in your Cloud Storage account where scoring results will be written | Default to `cmle/ingress` | Weeks 4 & 5 -data_format | Cloud | The format of the files for the featurized data | Default to `parquet` | Weeks 2, 3 & 4 -compression_type | Cloud | The type of compression for the featurized data | Default to `gzip` | Weeks 2, 3 & 4 -model_name | Cloud | The name of the model | Default to `cmle_propensity_model` | Weeks 3 & 4 +![CMLE workflow and notebooks]() -We assume familiarity with the [connectivity to Adobe Experience Platform APIs](https://experienceleague.adobe.com/docs/experience-platform/landing/platform-apis/api-guide.html?lang=en), but for brevity the key setup points are listed below. +The end-to-end workflow can be divided into 3 broad phases based on the services being used to implement the steps in the workflow. Initial exploration and preparation of AEP data relies on AEP services. Model training and scoring leverages tooling in the user's cloud-based ML environment (typically a ML platform such as Databricks ML, AWS Sagemaker, DataRobot, etc). Ingesting scores back into AEP and any code-based audience creation and activation based on those scores would again rely on AEP services. However, all of these phases can be executed in one or more notebooks from the user's ML environment without the user needing to switch contexts between AEP and their cloud-based ML tools. -### Org-level Information +We have divided the typical steps of this end-to-end flow into a set of modular notebooks which together demonstrate the steps involved in typical machine learning project involving AEP data. This makes it easier to use the notebooks as a reference for implementing specific activities, and to select and adapt code from the relevant notebooks to implement a real-world use case. In practice, a data scientist may prepare a single notebook the implements the end-to-end pipeline for their ML project. Alternatively, a data scientist may simply adapt the sample code for querying AEP data and making it available in their ML environment before continuing the project use UI-based features in their ML platform. -To connect programmatically to your Adobe Experience Platform instance, we need to know a couple pieces of information: -- The **IMS organization ID**: this represents your entire organization and is the same across all your sandboxes. -- The **sandbox name**: You may have multiple sandboxes for different environments or business units. The default one is `prod` +The sample notebooks included in this repository are briefly described below. Detailed documentation for each notebook is interspersed with the code in the notebooks themselves -You may already have this information, in which case you can skip to the next section. If you do not, you can log into your Adobe Experience Platform instance and press `CTRL + i` (even on Mac) to bring up the data debugger as shown below which contains your organization ID. -![UI Data Debugger](img/ui-data-debugger.png) +### [Generate synthetic data](../notebooks/SyntheticData.ipynb) -For the sandbox name, you can get it one of 2 ways: -- If you do not have admin access to your Adobe Experience Platform instance, a human-readable version of it can be found in the top-right corner. Be aware though it should be all lowercase and not contain any spaces so if you are unsure you can ask your instance admin to verify. -- If you have admin access, you can navigate to the `Sandboxes` panel to the left, click on `Browse` and note the **name** value of the instance you want to use. +This notebook provides code for generating datsets of synthetic profiles and experience events in your AEP that will be used to illustrate the CMLE workflow. -![UI Sandboxes](img/ui-sandboxes.png) +### EDA and Featurization with Query Service -### Authentication Information +This notebook includes examples of exploratory analysis on AEP datasets using interactive queries via AEP Query Service. These are followed with examples of featurization queries to create a training dataset for the example propensity model. -Authentication with the Adobe Experience Platform can be performed using JSON Web Tokens (JWT) and will allow you to interact with most Adobe Experience Platform APIs and handle automated processes such as: -- Creating schemas and/or datasets -- Ingesting data -- Querying data -- ... +### Export training data -The process to setup a JWT connection is described below, and you will need to capture a few fields that will be used throughout the notebooks and configurations in this repository. +This notebook illustrates exporting the training dataset to cloud storage that can be read by the user's ML tools. -The first step is to go to the [Adobe Developer Console](https://console.adobe.io/) which comes with any Adobe Experience Platform organization. Make sure you are logged into the organization you would like to use. You should be presented with a screen like below: +### Train a propensity model -![Console Home Screen](img/console-home.png) +This notebook illustrates training a propensity model. It assumes Databricks ML as the user's ML environment, but is written generically (i.e. without heavy use of Databricks-specific features/APIs) so that it can be adapted to other platforms. -Once on that page, there are 2 options: -- You already have an existing developer project setup. If so, just click on that project that should appear here. -- You haven't used the developer console yet or do not yet have a developer project setup. If so, just click on `Create new project` which will create it immediately and take you to its home page. +### Score the propensity model -Once on the project page, several options are presented to you as shown below. Click on `Add API`. +This notebook illustrates scoring the trained propensity model to produce a dataset of propensity scores for each AEP customer profile. -![Console Project Screen](img/console-project.png) +### Ingest scores to AEP -In this new API page, you will be shown the different types of APIs that are available. In our case, we want to create an `Experience Platform API`. Select that option and press `Next`. +This brief notebook illustrates ingesting the dataset of propensity scores to enrich the customer profiles in AEP. -![Console API Screen](img/console-api.png) +### Create and activate audiences from code -This next page allows you to configure access to your API. There's a couple options related to your choice of [SSH key pair](https://www.ssh.com/academy/ssh/public-key-authentication): -- If you do not have a key pair yet or would like to use a brand new one, you can select the first option to generate one on the fly. -- If you already have a key pair generated, you are able to upload it here and reuse it by selecting the second option. +This notebook illustrate how the user can create audiences from the scores and activate those audiences through AEP apps from their notebook code. -![Console API Configuration Screen](img/console-api-config.png) +## Getting started with the CMLE notebooks -For the purposes of this setup we recommend creating a new keypair with the first option. Clicking on `Next` will prompt you to download a `zip` file containing your public and private key, so make sure to accept and store it securely on your file system. +The CMLE notebooks make use of the [aepp](https://github.com/adobe/aepp/tree/main) package, which provides functions for making requests to [AEP APIs](https://developer.adobe.com/experience-platform-apis/). The following steps are required to set up access to AEP APIs through `aepp` (if you wish to code requests to AEP APIs yourself rather than use `aepp`, you will still need to complete these steps to get a credential with the necessary permissions and store it safely): -![Console API Keypair Download Screen](img/console-api-keypair.png) +### Step 1: Create an API credential in the [Adobe Developer Console](https://developer.adobe.com/console/home). -For example here we called our `zip` file `demo-config.zip`. Once download is complete, go into your terminal and extract the private key and certificate into a directory by using the following command: +API credentials may be created by anyone with Developer access to AEP in your organization. If you are a data scientist without Developer access, ask your manager or Adobe Admin to create a credential for you, or to grant you Developer access to create one yourself. -``` -$ unzip demo-config.zip -d demo-config -Archive: demo-config.zip - extracting: demo-config/certificate_pub.crt - extracting: demo-config/private.key -``` +We recommend creating an Oauth2 API credential specifically for Cloud ML workflows with appropriate permissions and labels (as described below in "Grant permissions to credentials for Cloud ML). -This file `private.key` is what you will need later on so make sure to remember where it is located. +See [Authenticate and access Experience Platform APIs](https://experienceleague.adobe.com/docs/experience-platform/landing/platform-apis/api-authentication.html) detailed instructions instructions on creating an API credential. -Make sure to note down the public key displayed on this screen as well, then click `Next`. This next page will ask you to select a product profile. It will depend what profiles are configured on your org - they are used to scope access to only what is necessary. You can work with your organization administrator to find out the right profile, and then select it as shown in the screen below. +### Step 2: Get the necessary attribute-based access control permissions for your credential. -![Console API Profile Screen](img/console-api-profile.png) +An API credential will not be able to access AEP APIs without explicit permissions granted by your organization's Adobe System Admin for specific AEP services and data. A System Admin can assign the API credential to a Role and manage permissions for Role in the [Permissions](https://experience.adobe.com/admin/permissions) UI in AEP. -Now your setup is complete, and you will be taken to the summary page for your API connection. You can verify that everything looks correct and scroll down to see a few fields: +You will need to provide your system admin with the name and technical account email of your API credential. System admins can find more details about managing permissions for API credentials [here](https://experienceleague.adobe.com/docs/experience-platform/landing/platform-apis/api-authentication.html#get-abac-permissions) and [here](https://experienceleague.adobe.com/docs/experience-platform/access-control/abac/permissions-ui/permissions.html?lang=en#manage-api-credentials-for-role). -![Console API Summary 1](img/console-api-summary-1.png) -![Console API Summary 2](img/console-api-summary-2.png) +The minimum permissions required to execute these notebooks include: +- Sandbox(es) that will be used for data science (usually prod) +- Data modeling: Manage Schemas +- Data management: Manage Datasets +- Data ingestion: View Sources +- Destinations: Manage and Activate Dataset Destinations +- Query Service: Manage Queries -The main fields you'll want to note down for further reference in this repository are: -- **Client ID**: This is used to identify yourself when you use programmatic API access. -- **Client secret**: Click on `Retrieve client secret` to see the value and **do not share it with anyone** -- **Technical account ID** +#### Label access -In addition to those, you'll want to save your private key. -Make sure to save it in a secure location on your disk as it will need to be pointed to in your configuration file. +By default, a Role (and API credentials assigned to that role) is blocked from accessing any labeled data. Given the organization's data governance policies, a System Admin may grant the Role access to certain labeled data that is deemed appropriate for data science usage. -## Setup +We recommend that any API credential used for CMLE workflows **NOT** have access to data labeled `C9` (No Data Science), `PSPD` (Permitted Sensitive Personal Data), or `RHD` (PHI/Regulated Health Data). AEP customers are responsible to manage label access and policies appropriately in order to comply with relevant regulations and organizational policies. -### 1. Local setup +### Step 3: Update the [config.ini](../conf/config.ini) file with credential and environment information -Make sure to set the environment variable `ADOBE_HOME` to the root of this repository. This can be accomplished with the following command for example: +Once you have an API credential with the required permissions, you'll need to add the credntial and environment values to the [config.ini](../conf/config.ini) file. -``` -$ export ADOBE_HOME=`pwd` +The [config.ini](../conf/config.ini) file should look like the following after copying the CMLE repository: + +```ini +[Platform] +ims_org_id= +sandbox_name= +environment=prod + +[Synthetic] +fieldgroup_id= +events_schema= +events_dataset= +profile_schema= +profile_dataset= + +[Authentication] +client_id= +client_secret= +scopes=openid, AdobeID, read_organizations, additional_info.projectedProductContext, session +tech_acct_id= + +[Cloud] +export_path=cmle/egress +import_path=cmle/ingress +data_format=parquet +compression_type=gzip +model_name=cmle_propensity_model ``` -For simplicity you can set it in your `.bashrc` or `.zshrc` (or the corresponding profile file if you use a different shell) to ensure it gets loaded automatically. +You will need to update the file with values for the following fields: +- `ims_org_id`: You can easily find the IMS Org ID by clicking `CTRL+i` anywhere in the AEP UI +- `sandbox_name`: Refer to [Sandboxes](https://experience.adobe.com/platform/sandbox/browse?limit=50&page=1&sortField=title) in the AEP UI to find the name (not the title) of the sandbox you will be using +- `client_id`: The Client ID for the API credential obtained in [Step 1](#step-1-create-an-api-credential-in-the-adobe-developer-console) +- `client_secret`: The Client Secret for the API credential obtained in [Step 1](#step-1-create-an-api-credential-in-the-adobe-developer-console) +- `tech_acct_id`: The Technical Account Email for the API credential obtained in [Step 1](#step-1-create-an-api-credential-in-the-adobe-developer-console) -After setting up the configuration file described above, you can start your Jupyter notebook server **at the root of this repository**. -It is important to start it at the root because the notebooks look for images on parent folders, so images will not render properly if you start the server too deep. +If you are an Adobe employee using the CMLE notebooks in an internal stage IMS Org, change the value for `environment` from "prod" to "stage". -### 2. Databricks setup +The `[Synthetic]` section stores ID references to the schema and dataset objects that are created in the `SyntheticData` notebook. These will be populated and referenced by the code in the notebooks, so you may leave them blank to start. -Here are the pre-requisites to run these notebooks on Databricks: -- Databricks Runtime Version should be of type **ML** and not Standard. -- Databricks Runtime Version should be above `12.1 ML` -- Your compute environment can be any number of nodes on any instance type. -- You will need to create a personal user token -- You will need to define $DBUSER to be your user on the databricks cluster -- To begin please setup a personal access token on your databricks cluster by following these instructions [Access_Token Setup](https://docs.databricks.com/dev-tools/auth.html) -The next few steps assume you have already installed and setup the [Databricks CLI](https://docs.databricks.com/dev-tools/cli/index.html) to point to your Databricks workspace. -- Copy the private key file you obtained following the configuration file setup to your Databrick workspace filesystem using: +The `[Cloud]` section is pre-populated for the example use case illustrated in the notebooks and can be left as is, or modified as needed if you are adapting the notebooks for your own project. -``` -$ databricks fs cp /path/to/private.key dbfs:/FileStore/shared_uploads/$DBUSER/cmle/keypairs/private.key -``` -- Update the [configuration file](./conf/config.ini) to point the field `private_key_path` to the destination path, for example `private_key_path=/dbfs/FileStore/shared_uploads/$DBUSER/cmle/keypairs/private.key` -- Copy the updated configuration file to your Databricks workspace filesystem using: +If you are using git with your copy of the CMLE directory, be sure to add the config.ini file to `.gitignore` to avoid accidentally publishing your credential information to a remote repository. -``` -$ databricks fs cp conf/config.ini dbfs:/FileStore/shared_uploads/$DBUSER/cmle/conf/config.ini -``` +### Step 4: Configure `aepp` to authenticate with AEP APIs -- Import the notebooks in your workspace. Please refer to the `Contents` section of this README to determine which notebooks should run on Databricks. -For example to import the week 3 notebook you can do: +To use the `aepp` package in your code you will need to read the [config.ini](../conf/config.ini) file using the standard `configparser` package and configure the connection to the AEP APIs. The following cell from the [Synthetic data generation](../notebooks/SyntheticData.ipynb) notebook provides an example: -``` -$ databricks workspace mkdirs /Users/$DBUSER/cmle -$ databricks workspace import notebooks/assignments/Week3Notebook.ipynb /Users/$DBUSER/cmle/Week3Notebook -l python -f jupyter -``` +```python +import os +from configparser import ConfigParser +import aepp + +os.environ["ADOBE_HOME"] = os.path.dirname(os.getcwd()) + +if "ADOBE_HOME" not in os.environ: + raise Exception("ADOBE_HOME environment variable needs to be set.") -- Create a compute environment following the pre-requisites mentioned above, and make sure to include in the `Environment variables` section the following: +config = ConfigParser() +config_file = "config.ini" +config_path = os.path.join(os.environ["ADOBE_HOME"], "conf", config_file) +if not os.path.exists(config_path): + raise Exception(f"Looking for configuration under {config_path} but config not found, please verify path") + +config.read(config_path) + +aepp.configure( + org_id=config.get("Platform", "ims_org_id"), + tech_id=config.get("Authentication", "tech_acct_id"), + secret=config.get("Authentication", "client_secret"), + scopes=config.get("Authentication", "scopes"), + client_id=config.get("Authentication", "client_id"), + environment=config.get("Platform", "environment"), + sandbox=config.get("Platform", "sandbox_name") +) ``` -ADOBE_HOME=/dbfs/FileStore/shared_uploads/$DBUSER/cmle + +If necessary, modify the `config_path` in your code with the actual location of your config.ini file. + +You can test the connection to AEP APIs by executing the following lines: + +```python +from aepp import schema +schema.Schema().getTenantId() ``` +If successful, your organization's AEP tenant ID will be displayed in the cell output. -![Environment Variables](img/databricks-env.png) +## Troubleshooting -- After the compute environment is started successfully, attach the imported notebook to it. You are now ready to execute it. +If the connection test above is unsuccessful, you will likely get `KeyError: 'tenantId'`. This usually means that the API credential you are using to connect to AEP does not have the required permissions (the "Data modeling: Manage Schemas" permission in this case). Try the following to resolve the error: -### 3. Azure ML setup +- Confirm with your Adobe System Admin that your API credential has been added to a Role that has the permissions specified above. +- Check your `config.ini` file and make sure that your environment and credential information is correct. -Not yet supported. +If your configuration is correct and you are able to successfully make calls to `aepp` methods, you may sometimes get an unsuccessful response from the AEP server. This may happen if you try to create an object in AEP that already exists, or get an object that does not exist, or attempt to send a malformed payload with a request. Most `aepp` methods make a request to an AEP API endpoint and return the response from the server. Print the response and review it to get error message from the API. This will usually give you enough information to understand the problem with the request and fix it. -### 4. SageMaker setup +## Helpful resources -Not yet supported. +- [aepp](https://github.com/adobe/aepp/tree/main) +- [Authenticate and access Experience Platform APIs](https://experienceleague.adobe.com/docs/experience-platform/landing/platform-apis/api-authentication.html) +- [Adobe Experience Platform APIs](https://developer.adobe.com/experience-platform-apis/) +- [Query Service Guide](https://experienceleague.adobe.com/docs/experience-platform/query/home.html?lang=en) \ No newline at end of file diff --git a/img/CMLE Notebooks.png b/img/CMLE Notebooks.png new file mode 100644 index 0000000000000000000000000000000000000000..f76a45a31c8869520dfec48b6e44f26e6a3bc223 GIT binary patch literal 78008 zcmeFa1zc5I+CMHJM^G9h1O!y1ySqW^03zLoJmjIJK?DgY0Rc%#k(LH2r6u%G(p{o7 z((vC$;f|yCo!`8l|DBmT?+ogRwbx#2?e%=0eijBRgJm!;U%Pza!Uas(JCb)VTtER` zxPau12E1P2rNvYM-jE#c%7|Ym>>*pea6t^!NlMen=Dr!!+Vlc7hs5_!)a}>ads~lqN ze83AU4>KnltM>Q)M&_orXJabbxkIh3ji}kBxtLjjp=cG2jG?wpc8(U*9OA%tSz9Ml zYv3Jd240m^ffr5S9~-Ly8^M2D3KRFonoNoe-mN@Gx_51I@JZckU@FP_s(_ zpRJ)*rofwwsj-zE;uZ-D2Rj>}MVgI`o0%2y2WV6^GBa|3{xAgM$xNM$%)dXCiUIc> zBUdFJIcH@J7d0Ct8=3o3-=D_C)WH#IXM6VWY|Pxuyx%W4xxq}ow;DNF8#y8xIi#pr z#ei`Ue>o&fpho5nM!+VrLeKWjRpFkciM@#l$2~K!m^9ygD{D=y?}OPI0W1DS24!IT znAmxbTVOrho$=QFdho?WpqI`4ee z;AjEh*Y$_Fex%CxeLUYy2Rl1pydQ}6CHuoh=tq~wS-^a6g04)9Q@BM8z9Dd`G z|3AY?7~GeYg2{=g+~G7;ws+^b&m}MY9X#x;E=JbQXPYZ^A7*XmfM60MTNB`wnw{Gk zcyMuu1MtZl@k!ai6lV0ThnSQy&_mM53E)};FdUuS&S?bf>^I0eI+?~<#hbI_hKDeoEWUH^i3cFwaliyzU>ebxwwnQwey{@d6H68$|$1p1r-`ERcup&EX| z`|pAbm=`hi4Vh9&v)Sb=}>kK zpnrdiooTQiFeYZ~1a&cTLI4X;$-jp#z*zaF866S$1C;Xb0MHc*Xbixz_$KI#V1R=A zub>0=;|~;c?B{~*-yefKzsR{?&|>aj=M4MaiqN6ww(tL>KiFB%Y$zkhxnc!C`iJTj z_H%vlqhjIsHVa_!|Dae9?12!!e;&PZX2$-&^S|u3qm`+XF~UFujBIf`XD4f@EuiJk z%~C`o!eaPA$+L5?O9NVuLmV*2O`rgQ&aa)@1b~ln-UQeL+~0nH?!PPAO^h5ZzWG9k zi4Z&k1&mk)BZ#TBvYjK;>AR}{v2$_)+^4^E5VMAwBYX%aJA@@@8SvY$bSRh86MB!VQp%L7~vdb=NPhqnwTIY$L|{1 zfGn~#`3;{4M)=!y^%>H*|0SR}vy0EA&<_}4Kle-j+z2@f1^g{(^(WL0d}mVs$Nm02 z?QrgV|9P|n-!B~bU+wUlZ~V{J4(H(i57iFm66y!$my$$8|GqoG(xygE&JIv_qi-ew zJL{R(q2g@%EhM07>fizeq9Z@M9{(_{@taBVd!d;w!ScV<8t4A-pGS(Zox28q ziO~ImgFm0z;5gsN|Cic0SLc7C4F}A)pDejwHvGR{#kZ*bKf$Z`4gUYBisRR~77(Df za{v-ttWJm^D%95eKh3H5BQf#6)DM3`arJiuLH_0X;anS>h4}uBLr!d5|J4qEo|qHc zIr#rmwZpGbr{6MbfL4Gx*uhL~fj}c7uXvX1K$tc^q-prVXB+=+AW|EDU9UxT9O#TP(= z;{T}1_-?WNzqQ04h>d@HEpaYLe+XFq5(W8}yA?l|4*VPY73_aUnD4)8;-94^enbC% zsG2|oK!1vX%G#Qn0@dGu^Kf1)8$)4alYhRs^bsWHUB522-p81eEb^Y{4P{}&?V<3jDU~l1U0h03lu#X z*_!{4b#FhE*_~H9e5-_XI6E_hsEYhvPxr0)TOH=N0@B~9zXPfvoB&`-e5=mX1WGEI zSOM1L5O=V1`d-Zew6Fms&gT`P8fV8h5apV`+8zG@eezp%+?h5xFVy-WGtYA#Zu?Q2 zoLf78B5iW+p#LS5rtIcq@vXT3yk3>o5pk;T+u0IhgcLcKAEvf0PzO6(8-Pr|pyw5`j{dD^1e>6%1ELM<|@b z<4**Izay&p=L=8#o*{Q`wEfBV``5VPFKqPR@WekYJaLZxKfvwyf%pGyYVFT?=7->< zgac4QiSReS7gQSkI}UsebAI;cWJ|YkzeL{zsSV+tu@P_uns^-GKPT2j7qGhDE%QxNw2;f~=(2 zz5Du~lTl;HT83Ke(ClxbqpOHh;)ug4r&et#RuMn8P2;EcVc1wy7w;h3^W12z-&&a% z$^Al}Ix(CuzT4B`mz-NzSToSKV=H7;44Zxvz|M9N14*J0hxNBNKldm)Xwe#wjL7@xc1E z_kTzJjWGWf`%I6!_qnupyW#Yhh5CkKBKH7Xo~2+u&Okq}ph8;XiKIGZ9h#@`Kakc$<=GxEcu^Rf-Cezmh?-%R4&Bu0bkh?EE zx16l^0?*cM^$0lk3hiDT(sda&9f9T~JJh7K=A^j4obXtyo2qHM?xDa?P<9vWrR%jb z0AX&&lV_wlVdmOj%81zR5m>v2wUXr6qq4QoEpHPaJB!qtlj>cwxpw?@RH@E=M^0dZ zgu`s(?P5c*_w(6_wl7hz1z8JM3n&0KYsW{r335Z$AY!Rq&Q3(0 zrzRbCUny|j>gKt0>p4yWpJTRd!|~TnX6{K($AXg9Yq375t`lxGo1F{{rzg9UKJwZh zXfK97tK!D5-yhoo*8Nia;&t~WDss>DrhO;17^@VouUcQqhxB82Ax8{_Rgl5m>+B{$ zPjzgo)4bZk$+?`C-oH)}yJOqnef+?CP}_=0tl5#On$)H&O88`NcFG;?Al2t2VTUYa zVEtuYA-sAqMaQl7LxxPAY7V%i#;a%7ZGS!vwZwUI#Ht8-_@z>5wD*NdMt`~0kfjY} z61L#FXnC*4?rOoL&uLxfqM%avoMNi5UV%wfW}axABtm&e6=2{c@LTW$GJIx zB!v!B%C=i{l^eo)Q~u9bjl@|$o5ty>*RIxBRVy~N>PVmwv%R1)d{;868-%pAGFXu4 z4XlAaQM+(U+J5R`7rM!8W;FQa(P)rZVUW5_D*B|Sdy!qUZ*&*7@E)b_r&dzCe!85b zC)n0aT=fnVUV|LYmd%v-;?+JBG;C8|d%Ys3_eh#EWuu>H=R799BaPwUqd)ul4Nbnl z+Urt%_vI|!+RFM)Vt{a_ukYJq3&~-qYZ{?4m3FZ=+3@E207%Fi-^?%Vp>NNkik`7- zPAgXHd1xnGH$($jUr4mG9JQ$|cnIB`>(I6?Y1#B+s#+M(Feq@6upD?9EB%-_imRl4 zZzgnSrKkaPJQd;qbe|Ure^yg0tb@_$G}j)bhQ*)W8}W8L$nPNoZlMmi;v?h=x!YV6 z*N%mD1MbDg#2;@)T?SV7)%xBI9BPn~;KswR z+{eeN9T~j5?RPazqNE-)0PvTYmMiYRE04M`q^m3T5iMDS>A2eJ^yF|Y&0yipJN{@T z?#|^jG5-fXRg|ngN9m+Iwz@XV3F|v7FyiBlHj1VrSS55YU#nbL6&J-b3jqA6VR$oH z=9@uhwCh!GS+Qpbm7i+jk2$l;GOuU_F?;~9R#4P%!cUC#6qymEGOaZ|{HDd?Q-AI! zU};mI`by1vEp6PsHWG^aPThV);m!R9ogtn|P{h{eJ~N3w{w`VZ_2xyG5}J3!b)i?) zig50+xWxxPI5)v<2{QLyQG=@UDR$Q<$rYb*=6R69 ziRsTsxr1TmPj?(Qa$|7jq&LS&s?NQq1iVjJ>+&yigD}X-0XN6 zV)%US7|=bL?j_Zb-c+NOffu zje>x|@dA!iv@G;{{xfY|xsL2cj9qQ$CD#(xok>5T66r?XTOPMA?S3Gt6{AO^0ufbS z)iCf<>u$KV#kp~*BL*jC=Pi~%{>X?UcKbrKl5pq1_2N`Ww zD^}F!>IP4EAKKt<%|5(fm@@6BO15u+HH=N?kgelzj?`s^lnb6ay~2l| zJ6#1*B?J>t)*L5T>dTXR@8?M46VKJ?kI|$G1@OK(Tx$?nu74*GIO!{UEZrC+cC3F& zU)mc;4BKqVjb=&0Su5=oc3(&^rx&?hi>t+-w0>hJR*#^8qlY(RbB?nHgGm3rQQCW% zU?i3S+9=pidSlv)JyP<-hASTx%KMXSGq$UvEnkJhC}@^fJ6w~*Z>vHwcDIyLIfPtP zPy^y82_|BN+%|Tg>C0U=6&h|%Z;JBvh#7L7^x`Qtqf~)J+A>=w8F=q! z5dt9UG{dPfp;_}5nF=9oJy_R=NWV$k*jXq)Jr5%Q6B8|PBS8T%RxxT^IIN|@%-gk>h9ra0f6%r z2zf^t07rw$Er1fN!TUHULG6GnBzL-0A8FD|L6qsMYO>2r4`TCO=au3gIEX5Ehg<78 z>CvplSUvY7wlWCRnz4@OyE>sKnA)rl`;-zwEa_7kseH=k)J!>PPA`Yyu;0Dz2@L5) zvU@27bs_%KuEZD|P%*m0N`)&e0sEin00DF#PU&{wc>O}cSDM3m+na{XX|_dn;L>-2 z#Kj->Xsnt2rTcI7qJJo;oX~dj0q;X+F9vLH_bFlP;vXrFR!4uX+ns2F>cIpOlQ35$K} zV`}OeH&!s%JK4H?KwS+k%8!w)kZ^bT)6B@LTn9N++;XKT*tCDgiGCiPf)Ypt1ShqJT9bC1h*wdkHsRKt{*4uUbE8+zFV( zX>fbEd!^T*Bnase2cRGIV%@e#7rbzVbPdO<*a$Z#ZYCz3USCXW(h8Ct_>{9S-+Yb1 zreL%l|bugRug1RhGv9k4b`$xk-fV>VMUewMniiU6%nc%QLGR0ot?!O-z$=ww z4(~cosEqAiZ%F&{;BnQKqCZ!7{vzuw&oh^(l`5k84O$#PDEJgFfO+@Lu{wf~=4Ps9 z!>>F`H!QWSuS(OK-0t4hd=kz(6O=}0^O4aD-dftiq2BH;9g9I=d?(tDx`_)FwO5ui zAk(8~eD`f2W*(k|=!DytD-Ial4WxJ4aX0j!P$HixMDBJ+0CC#GO&!0+DY-WsE6r_! z147ZJefG@ik%|Y~Lmfh-xj|x7D{(ArjZcCdJ~dDjHk=$Z?u1Sf7BWS$8*Ea83?Eow zZ34m*^puc*RU^+AiKJ(VZku!Ui+j>wBPh zb*{!knHVP{G(w-BdPp4LIl0jhBvyeSY@=5fc_Hjtul{s%B{5uNgB*Oss1A_#c&;`F zR?tFh;yyb#xfVv;KUrSHy`|e13-?oP-ama2j7MPu4*5uXj4wConasczlpSgky~~6@ z>A9t-e2MB)p_yM_M7((Z@8xqA`!wyCdo!|>If*-KFd zVV^Ep71dR|(m}(@Y>j&%1sb|}^r~-~bev4f=g2=9hTJZjhEL>4N)6g8JoL_`&8V{5 z3n+w*PB+6v=#3{Smg!A|IFg0M6?ivxVx1dYkc^wYbQ}1;cqK=Q#!|?h zf7A9R^L@MrgqSbBj=%P_Qm7eHsc5ErM#oswqoR>yvfHdZU&|-C*jwsH-HzUTId%D7 zb6VuiyEx)VDzy1`vg{99b88Ix*$g0!2mBhcF_ME9@^T!D9^S%JRmFhdc!^BY&k^n2 z6rJeJM-84A(r@=*u|(ZkTh_rpG8ZC(T%em0rA=lqU|!o>vbzyCsSrcFHyCBn@ZmlY zb>T^de(Oo5V=ntTNIpy%OWm#)msyh%|{FKE6#bGeY zGf3=J(&Fi^&nb=PSTZj}G&0%8p*PonlN8Ud4e zwWv%?E^jarvv!r)-h??7JNTtg;03H!D0)GZDzO?eAGdM$rE zDQK(59A?K1a17|_$rZQk^k&NMC~g>ED!mq_BPWfqsmG$5>j{Z`2Vj`8k0ssP$F4ce zyT~VY*c{(83BAywl?1%!)gb5j(Q7y6*$q%Y((Tx5Y%l0Sk?1&%>Fbk{YN`TERxpx`cSghR^mVk$iLMdYOMz2T6W$C9NpRr!)C0SsE? zmp|Rv+hE8SkQt;@0-!X9uB-Q&5ewqWfKBri3@e?^ z3Wu?WKA5X*>L*~MZO*Cg4-!*sA(p(FV-cb?*u|pTEZy7y=-E}_6T2IqD96QcDiivz8o5goIl3P#FC2JqPTsP!>OFgfVK>lM;#@);lcdNF5QxEl)7C z+yZ^*Gx+4YcX|5?%WGv4-OhNvut&W8l8=#`uOH1=S6LWEIpC>nlCcHhU0#%5GyZJc zxfp=sf3Kx0iPX3xNQ^Vkx62rZ(%{L}){t3%{tQ88Vj|hiRWtd^K-N? zKBeDQKXhb=C?8rWv)>HzCr%@a8m7@|$}yn{;2uVhe@^P&6Kh7LGlLAnAi-x3oq!uG)I1tQ23-g z)DAXuD0?HFroTsuHGEh9l~c1V20jfq-+@(`mJJX>^wf|G!u$CeNzIL)h)moM2a6Dz zv}gw`Fbar6o}dGo+C=Hto5B&9`_A7l+n^YTqdb_p)C$wpAV>Zt;bu%^5I#?`w(RU4fVRx1$edt!+AYxh`R?l`H&)fi2nWWu1m>J>Gj@g_C1t7j&TFqi#5?-?bh^fC^Og*xW<_B=@C(wQc(CMs}KV|ZZ(mX z+n_4BjnA3%Bh9=`p_AcP$`oY)fgrLPP3Jq-)E?6IBx)9l9@{pklX)VQhM3%Y_lomFfrJ`I~gmbU8#; z9^A`e=7cEcJS{EmkVL`aNS4d0)!F8JLwC?oNJW|Oz^LBg)5w-V!}`4#V#!#ZxWfMN zO9tAE#NHGq#Ki=W>HV%sGuL~P11mb{`wp@Vz$&r>&t#7XVmtI3@5S7k3154H5I=Px* z#)CHxihS6!@P|N`TXCatVm${rK3UG!s-^L!_aF48$Sd-jb;Wn)>ps4D&0maPI>s9& z&yAgLAn1D0`j89HQ{=NQH)Qg`^x|9uApqPx87p?lSyZ@C<&-$+)e;@YkRe@TKqm|P zRp*jx0xs6Es@tA}y6T^WI4lfl#J5Nq*L!2v049+&CnIJ`lgd* z>*vu@NX=YF!i)&4d?g}gM{(aJE|a8ebGEpZiA)aAGt!-P!Dm1VoRj?Eela11j6 z@~hdYYnNOiucffWO^#^?FP0 z>CAdH_e#RENH47szEa#66QfO+T69R3s4iP{?bzx#h!Uh6-Ic2D>J2N6G=CYhp#6Er z;qZaHYzi}n9^JHwaV{Ui4J51BsW2zdAdqmqyz*f56B8x(#w#gG?PI=cq6sU_NACDZ z#102Z!J_l-*j9Gu8MC=iUtE9BsM3{}RHF85UD+x=6V`dz*D?b|>26G2@}9jW*>m7| zQN9yMHE8W02Gx+v_2uXppWoda4BXB8A%D?}T7HPAn^Cow>eX@_6*40JY6@d|+dE{r z4kTC9%mmZr=)4aT#u_?tm`PuKPuPi)Ac78$iHiCIuTz6eGO1W$Kp=pj{Q1az48J5C z%4Eu`)=@w(NCM$Af`|IziBUbrs8B9`!6Sk|&Q}nFhb)aD2j%MYWCUWDm+49In|y5oF;^X&; zUbLZcTD%t}fH>Z5pVSSlI(c$TK2%o~Au=f5O8$i*wc%Li#rqP1P2RyF4;i-5naJ*E zPZ?Gd7E)F?RCIXf_$ogAl^)7` zR~82agl8%o9$U*Nt@P-q?^Z*>B=f*x$7-z7sQ6lJ_f7|xhP|6-)H_;8WH>3jYDMn3 zO@-r~9UZy_GWfB6C||hAuH0^tRBF!MM)py@%)d4Ad2uG0w19;@!wfQ|C~C$Ea5w27KxJQsY@L0 zQvNfT2GL@YS{h4YUP%vte&frtCyOCLrZ#5-z-Fcti8=IF69Uhq?9iO1oSMyFLeGu< z^AoqD#WScxAytl&{J;Z<2g?fb)xwaoSF=|5`N5)aSwqEs{}#~>EeyuJDgp|8(&)ch zzo?!}+FXzyD#g%_OwWQjf>Olg)JL5{n(A{i2;zC7c8+q8va`sGJR{4Ray%B=!71IWSlof^f8QRj6;cf3y z#kr3MHe*8F53SeRx83IsL%Drj6H1t20VBDhM($n73hi-3c)|7(3 z50$JVJ4r_8484l40Icg`rn51ciJxfKp&g;?;{sXxV5GOg^90MY5ypwW&L#jZpg2_< z($I`Bh`&V}P3DkyM1jCcJAi07<@#nl99(Dou>I>KaZ_0#h93r6^XpT>D{C|OC`V*# zwMCj+rH91GJEVR$!z07_>A5kOuTkn97+H^N$p9FR1o>UzdCEM@DIH{e8iuQ|(uvdV zi&#j>ITTla2E=Rw38d}>%EB0-{6H}a@PK15 z|FVtNlBTlbSvaW#WTl560InY=+Uv52vaL-vag#&4$A;P(fui;Rd8YIPnx|H4vkuo- zT8}R0r~QdcFzHOlXcnnlczg6^Z5d|cS>eg&_K-*; zMsu>J!W5)m;6)kr2`zB~rV|YT_7s#^E`bq0984pZ>ZSf|2qcNAgOw~r?qJMEU#`cU znA?L&rlI5{$jdnQ?J1yfyt5eAr{$M=aA>b1*1#pSK5`S}I!-OLE~?nud%y#*IS%h< z*5!C($lI9*yIJo_i%Fn%IIC^`(LB0aT9!nFI%*YXS7NRRl2xF=ev7^lw9G z`gko5>KMPBX%U0lDzyzJpJDZ5cHDNu@z0nXS{ws1N_4aW zj<0lwoWJ=&%Zp|BOIO)h^HzAWGr~B4;w-(_JvbrGmCuVe1h(}yWdW%K<&}$&37^s` zV=+a`2x3<2Ek{O+jn5DXN}7v>wcruX`qz&}g>TpG%Ybhdw;~WmgUs^z<`+wQkXyQW z90_vyV+6bvd$L`Eo047Su!S|Fw@T{~CI=O4={dZltu?UCZB16gn@qj3eD+M&;E;`otU$fpB8K1#`yzK+P38yM{ zW?An3nJj$kBh(=L+jkB>-&9Pv8|_$zSjL5mggOfDpXi_)Eyhj8+fLB=+Dvo+W>-=M zgAp)mNt744e$zRep{MbyfyWev-wYMb)`?CuN|7FyFd)xqt>HR|e<@#cV<)NKcL4%0qsE^HQLGGiDcXw5vQm=?L>0JvdN$c1u60 zn@CHNf!iwki*_Z};58Cn$Lv8e&O2+&l}X&a;?Gm74gI{6xa6(4?FywxInfSyVINs{ zQh8Ml%dB#u`Ca;Jm^vk!c;|4It7aiOMUIovh4eeT{?FIs8-y9cuF)!zGnaoRpkF@P zo#4tsnT&OBU4BjOx7&h}8D${bh7ArsT=JXd{R-3qndN;Pyj>K28|$g9f&Rz}UvBT} zKrQjU=^Zjco7-Quo|LtxtBoEVWo~~tzPpQ=smOxaaJY&DUC%Q*v^LpHg}*_)TWeYh zP1Z}KaeZQ@_yp_tmi6hL3p@!L+)%obHK>!^r&Pn_$tD#7Bf_`o7_0e$>lz zTkjY%#@T6yvP3bST8?SIfms0Hfb;$t-i zgQ^`JUlHrFxtH}&aLHX6)Rg#mCA%lJsHOf?-<7dCv-o37Y#H>X&|!W|mb`9ubyzah zPMzvA%@BJ~svb?9quC3?uL6|^%M}8-JfUKc1P)w(yVWPcRhpJ#cePzSpgKhs6PY5J zqfasQA_;rq!pY(V*nGS62Jei_SVH|v*@e7^eJH3w!v>9)6usFe^Z5PB)rSj_U%&X{L(Sb9 zW0wYURZ%Fu8kqMEe(FwKdDD|zUMeFR*prZMP6Y}`*d3h9csqRlcA zoE_TjSszTLO;@jbmS3tR9o$dmZQ${1S*O{Lj zb?fPBB~cbW!}SnrCQuiy)x}xsF*(aVAu_8)uFN%x%Zt1RqcCrQ2^wbukqw33L~=aB z1>}XP%GtWRE0;roB8=B=cbBxwtbCyTJaG9-vMZ^~n6G)7aYEsPJaT$N;HlF=Iy~T4 zU|M_j*$6>%4zHZZF2I{gJ!CzaNz4roi@r2eoId?>lK8In=4eHh7zWJd{@%28n=VYi zbC!rv_XSU!9(OTu+MRF%(^%0C3FWV@Kox*!f{4RL%fKrmi7z6+fBwQI8m0SnF?Ha6 zloYb5ch3VnZ#LFw|DHlNr$ocOuC3R(0;MhOgMNfmA{t#p-}xCb7cBBvKG?^b#pSPU$5 zm+wSUUE81ZImlL`I2N>eT6JCOwZXfmNVrXPp!uEB`8bWlKurJpp`|k6{YF6Cg-NFp z3p}*ZLIJNVs*>^dn_i|c{%Bv)f*f$NZuFLZmX^JHF|foKQp?6iA72 zBDZ^%Mp2sGn6q-)#^~frXDh`N9u{SIoYe>?P5u*Hl$et+5H{A#WkRcu#h2L{$Co0f z-=bJ+^H{$iZ3|cH17U8U3fO@`fzu_D)J zWt!N_eO7N9hZLF(vyL;fDkB52&|+=do2P*+#%SQJ*+(+srt$VOiw&!E&o}vxZZ1!U zWhpXa#aa-I&$~Y5FSzaH9=5$Y47YqF`_7uq%h8qC%6=v?^4>bRjrvE`PjwlbI~2>u zTX*qM?(`KSO?y#H+}i#i6D)13C#}8j`(As!g$aG=xpgqo!%vS+;I-xfAznoVZ+S1p z99M!d7cZ3TAFD0LnP(P+`;)B+(@Cbl}K*ZJ4(2Uwk$s1OP6=>M&~f8oQ4hV zET+wA`SH-#$yeh(#-8~1T-2^LPmQ}~mG%|}@2jogiySkHoDe4kQoOIPJBjC@QQlnB zcaS9?c<#Tzr2C=}xJGM6vAe2AV*RNWkB|DGZ=#Mt>EUEDx1tUfN&1lc4*V;iZLSC} zNY)Said;IzTpg{vi%U@tm(zY_KWmso+iC|+%ofp@%Pe}CCR(HFbeb5&P(+p_d|GSh zr+%_CB)S~XMRvS9i6pC8;I@@1yrZP}EYs@|)7-6ZiMb34Pr&#+wvnGOe(}rOoNPWxqG}@lOq#xVMXf-;fsCONz}`yqwfNdqVruFn*9COKwp>f zBe@sW7%9u_#on(bOqZ4drdK&&dR5kY4b&k3qK$*5r;WW4?MY-Mh$vivoUK!c8VZ z``BD`6J6M){>Vd^p`ci1rzFFgLxy0e*AAnAtnK73S1o)j0Upbg$rbUmqJiNvN@#o7 zc;5NkrxW44Hd+H?R2wi5%LYXLRGm*sv}z7Rx*BV_5gzvec+WnBDxP(+&g< zGMCfQjZPu1S~OfE5|>BAGjxCEw7vU0An?SCp)=X*?bMPr%F9{zLOxARX?KAhgrDs{ zP=bJ`!x#Y1@^A1o+%$pij%Pu&Ksi@^FBV=mA^uq7Y*k*Qtjs4wlh?KQj-_bQtXDnN zz&rO|(0G9-#5WX6E9`dBtB`BzCbd}zs#UVic+BY-`k zSD=vEyQT|$YXQ|(zEoXDQSoNedmR5(%xf1{Ibd->YzL0j1T46~k-%3==^8zpS0p+O1bD^PJ+wpH!%=AkHC zO7)0k?5es(I0=5z>t1~?XCXl&aZ$4qEhx2f9;KWuS;9d$Wd1>_XHp|c98JEcieT}Q zAfKDVl;zI!V-m4Qo}90COtsdc&)9KM#!3Od?*452UZIwfO5trVQ)xuM6dxhivDo zK-RmiPj?&*N8_)uRlU&tprE}d2~E^t$45an*BH?lnNDf;1UO{L4Lao&yf!GTZ#huy zu6{$;eJQl;`RF*+^tGM08Su$extqdqW=fdj-aQG--DE7|4TallRgo7ByDbK&okVIp zuI5U~RRGoM>DwvQu=~dAwd;*>*z%L4tPRH=8YFxUi%`? zL&^E0;k$2dSEEwM1p6hTGzV7m+20EHI6X+(Zry;hiKta6sd2hnlR`V+!xWYoK^?lC zCnu8bFARtc>ok>?pQae)UnWFhpInR zf@Z`RJEStCQJKM2NVvM5&Fj-z_$WjT>r;2-gEjGKns1Y_I$5O6o!X6*KQ(C9zM$Hud3V=s}^P>{wnrDL14KwvCJa+Q*$Hgw5?Np z*|Mn-+1p8qN45%8Xkv!-HB7faRlK+>>m6KpNJD##vomjl`5zi}8;kQ$(KKJ2%86L% zUTKrd3BwvUiBup2IH0)k^CpZpg2pul>rmI-(j1x`{f2U_Xf0-f7tHUN-k+~$)O-Q& z?eb9%wp`xzC-HA1A_AVq&-z3MdePRo#5lcKQ&UZ8g6WQEH%ioOY!7*O;%5OXmU*=H$ppp2N7$tT$>b7F*R9ZXh8$lVT8i0_sjFxC#_o z!^7IW_J@-Av=yt`8DGd8gCBbKF(BcgIJih07yq z<}RP^g%OMLQc_pp9T&g3?AIXVz1uTR)7K0LcI1ac*Ewl}v^1YPO;`C>m5qj`zAL)Zx^~gY&IO>U38t* zS(DGMkH$q2VG!Rwq-E1wtDKZ9KpsS;I`J!!WCAfWsPxC8Jwi`O*wL=Y$GZeuFE$dp zu;G(ebln8n2w`;|Q1j;n-6An!7ztfY^UuTww{L$mJw6^@lN*ZBPV!UD#y(O0RHCv| zEg9Uji!IMWaf5uv=7s0Y=)gObOhh#qQ%~Q}2@|3%isOZ`-QN%m-U~GL0bgV!ngJ>% z7^aU4tw~xLrz-r@GSl<s5*8R%*Yzc7hQ*+Bf+aZSX=Qi2Fva z_HwqoTV2A(3pk!+Od{sJ@n8q!P&^knP^xQsY(@8aS_?3Y+S*pAM}7L3L%uW&uh4fu zjyz#Dr_=+EuMh2}?P6XE#bB}BUlUr+C+_Q`7Q4)Ieay|%6>G@)ZIeF=(GwAMU6n=k zxuzW9M(-~ps3BxIRTm#m4A#|3cPEoJQ^B5r%_!goGpl|ghXxFV#248zII&YWXeg;t zd*Yva&_9T<*AT~bm3+`R@~+ki9of?-iH`%Vti_9({&hUeEqD;4andKQh42ddxUR6f z6YMlR>>6r_O>H3N&iv-Pl{mn*Pdylo)4i)l$_4L>rU@lRS&(^py+<0GR9LVb?cpIV z8(zFxLjqsv6Esl_v`FfukHJb9?Ah|KW^YaRb!lYZ-q^{>u5z2Iyg035rrLf zxsxzYf#tTj7F8d1p+Q+&%i~7aU|^a(BS_PcGRTCK-|1s9Wn_FjCPe&*7-gNZI6m5I z<|bNvs}QE(eqt3mk59f7vvh`faMOsDyz2zX=;2(oL6(qwK?;&zV! z$eu;)Lo@1HVQf}+A(~zQ47a+(>c!r3UnNp1F9+v%x~0qpao4019a*0`{DV?gZK;EU z!u5M2$rjjddhU=%tfn+1VN0PG%*MRfQ7P=)^p-Af_2C<>Z#W3Z9oCa+vnaQh++Z!N zcz0)Vg2-%{&%<&FB5BBU5&6`I{j;HI1DTXj0gQ{QuibA5<%UN1lBsl%KrV!9>b|^#g3cg+HJ1|ki-&xq z|JQf78L2capN>&BKjPbeN~)WE8ymAjthB;topq4Jb*9%*RGNm7E)rE_k2e9}K8SC? zLP^2fnoCt?A7tXVvRd#S$&?(&zgn``N`cp2GX20hdK)2ttPbrq7(qbtVECk~)JB89 z*|3uUI;5Aie06#ARk9e?m*UI$lj%~X?uw^(V|ZhX>90n!KT%+n!KBb1e&{=FRpWex zy^C^h3qSv%58o??QZv5*q!!#Jrob*?ureVPu6KYg`#hPj=l#fn_6}8f7INAa71^tv z3XKfvmyumnjw15b?OmJR(`E@URcMN0B&Eea86?Oe)*yXIIov1x7!4lFZv^N#8$X6j5G)TbU#P#sCmb@?bBo2o1Er51O9vH$PM<(R9_oAq7iB< z#GxsqDq!?AKS+f!VdbSi2(>EX2;UXf2*{%aKntYdFo<7RkFRztZ<=a)^QxI2k8$kl z;Ti*nf<0!TmL_+64*oi_4@7kA$UMJ7+cZRz2zET-@D5rUa=D8|At8PI^oRpyrBfjr zoyPD;HNQ}DY^{YTD?VgaF`kaeBabsHW(MOzMD#2YQQ$K3Mw9ESwLCaHQQozPUhzop zpn>PjXZF3Pvmk#vfmh9)&qp7ZQa(PV-Zqz6mQ?4X6|A0ESa=@`n%+LD_7aCoKh%6+ zV;3qMGChe8lHDzczH>E%;r&5Qz%mD^+P!}11Q~SKWu@wH3{imz{3rOxrnrSILg=W~ zvMcYCmkRpcIAww3@x|Vt(QKO_Juu<*>tZ!;SG)(ydMVgVgT3wuFZGbqnT(+&lwM~m zlzQYtl6`pV-G?>}^|jFLeCDj&(}GZnDGrDvZ!(P;(hwa@_a;T(8 zsC5hNo{R9OlO2;av1(hL>FYB-kJ3Z0B3}`&>Flh^J`(WpHspf&H4lfgCAzGdTub%H z$0etKP#CQjs)l?8P5p_9W9Nc*K+mO0+PgvGt?7O(0bjqgMjT>iW~*jM$0F5L;TzE* zrJAe+WLX4D5fxzYDg~krKfm3RNTg||Yv|4$KOmQgNRPW#J5^K`zumi>YXSDz^qOHYZc5$u}S6ytTJlG5jTPv#b5 zmY8=}p4S4j@(3tYCddU*8)AJBF1bB5NRTWuk0K&+i#{^I#PNY>6mv`sx}sIi6Zcp; z<2tRXv`?A~Ck)+5wB@VM(6AzA9?oCHK(8;XI8hZJ%DiXw?6Tt`#HA}DI39UbBKyXz zSZdmcNoD3Z!OFNYkE9($_VBneo$|$(hUz1{Eo;)Plf*^ZC;IBz%~OLqSuz<53%ofx zB8PGdukMOO6>DjTO*Nuq;VV7HjNzD!Dm>(@Sk1pFk;aLWMm!Q%sgC*oarG7qQGU_8 zDBUr1N_U5JcekW8sB|OU-QCh4BHcZNGzd5#t)z5!&w2UXd(Qoz`vDmCyVs7j))N~N z*=(*=w1aq})I#;ify$)oL%cxiD@=-Kvh?zvwmvhc0yt@0;k1F@f4(i}osM@8oY#+~ z(uW@g%^2A$dHHZKAWB~hP}$yApdSr#2p}k9!s?g8vSK1GjMDIJC(IyX>X%ZGEsRGC z95VM1{RiUmH73eq*dfecoW2FXWOYg9IO6rK9y|i(PlG}uzH3ArTnJ=aRg`LoMyLIi z(=g2r%sm&%1`AY3Id4^r9tdsifZpgJm%w330WH@)_WsHvJ)~ljP`(-#_IOV48@=u9 zyN5%%N|UB+fa>e4Dyeroe6vOx(()vd-~&y-ONP)OO&;x)mOF!E+!N=sUV%hus*e&Q zKPfViFnHSmqz}M*MSI(t-xm^}{vX5|=@s1E8tA%;?q_dPe106^lQvN zLe5O1xJk;E&WiUxb&)O};*;EI&?NlDBp^(*vK@+*+5MmzJp;q4QCrQ;V@05q7t zYBYpKN=Cn;t;Y446x`+?72eQek`phG|EH8!jOx2yP|0(^C6mt+XA3a@|3TRG!`7mf zkItfkMx2q7{I8sbkM0wyj>>7otNu+_i&idKC`1*d8rQG z0050hRqu+uA0~sgN99}jf8pT?@TU+uq&e6d8DlAKjLs< zq(4sS9}T`pVb~ZEMN0Z281ZMye__#DpdxH|79b>^{oJ@$0_pbQ3!?0j*{21fMK%%+ zjEt*^HYpwa%%3P^MEN?|s3By|>HNz~I#t!ZYugt4GI6}4q@2Lu@I(719+gF|Im)6& zTdpmjKoiUkLdSi+KUkZdMFjw`iOjz2xmVScvDT?R1)Ow1R-B0fr&Yz03Df*;>3WYJ zA!!;PI|sm=46kg22&^8Dn0^Jyq3_@D(b7$vQRZwBEN|TXUzsJxVxA8v4PzNtaAeoX z;_u|Qa`9Dk*5>h`eGrJ~%1IiUBl%CY=7P+nL zUZi~QKUCT;oQc{SX@-f!J0|AyziQk>-1i_IUT`ykFfkuoxi$#gKUa zkpwkv=;Wond6coOB*tDMLi`6~3q;#Hm;G4{`p{qQ1Sd;%X3>Y!5-Mv!W@4G4ejCf- zAZKn{ZNd5L`7~iKEGt#Rqz9VUIQQu-5B6O!6E(JeuAv5w2<}~-R$ru!e&-s@5NS}o zFOp$NROr(fW3gqAOL6$&^uMeqqBQ2{*(YnM(PoK92iq)@0s8={e#Vc~CSutpUKvI$ zsT2WkUFn_VK`D-{O8)W)Y1M6aP5!KE8g-WLI-c{|Kc@#TV_-rz0bP1~f_-@>?(Mq>FQ9o@AxxrmMO1 zANFW;8Xp(Jreu*B_I@eA_Bc3rIYjo|JO~SYzTegU5xKzwVwXQ1^d0+4r_GB;QPlBuxJesZx&?$>kr%V4DGcEMD0uQ-JSwfa&9US zykni83HF6Srkw}huaa!}VVehq&9$VcaKyC~e~aj4{rMcX#i+d;@Ja;ZS%NSi-3eWU zWs7ws3oW<2E_qBi2hd&jF#adWH(~U(X&gI~1J&(l z9Yr5Kh>YC?$3}Q&YTkRs!Pd&aBZbc+Y~QZYr#mpdczqd8(;CHrH%_7wxSF=@q80dZ zg{O$QFBNrge4oA18n!aK*kBP#WXT@gA-T7k?d3qY! zMGbS}?kfVYn4&1lGW0Vk{Oeh!K-EZ?xE%5)?}vHZtl5%0$3Ei%_u#0gN*-{s{=mk5 zo_(bc7wzEm1vvk}wCd96MK0HPN&G+Lr?cfi$j!tMik8Vr5c6hqNy0@8Zuj}H1+{J? zd`EMMe_~L#NOCynwI1oF@HRhyR|)kqiHCi;ZXXal{}XzLp-&UtFGm!?hY3peeR{g* zWY#G3VK^76m1q~)h|_QgGlRG2`1k#*_bq&7Lv%YaqWV6iH`URsSJmd}2u0c=e6r2X z*A=I#T&=O7NtdCEKgC#rRCMa2jT4buaPHe9l;twmm@)CEdJ$xV9Hv-A5}s_(B;C?l z72uKuyJU!SxBnxIk)*~0*5@}L1n=Ss-l$!{P~N|pwNSQ^xawD4@peSt{-Mf(u6O?S zZ>g)2&Q>UeyQ;TkLOccg#zKNiiJBgNMfbxvFIts7vhAY3yX|uG+}Vx{27rGw3knKd zPI9Fs7e2ft8I!y}{VRrX@d2w{RH)--8KF{94x^+j3dT0HBp*b6gd*1|j2)jZMAiG8 z**9_hqa~SSusk9G7oLr55T6P}2v_*W*W9rEa>{^WKlOwTNYU0hGR3*qH=?z)#)z1@ zra<3_P-F#S;TWHXLAHL=0j+%}M{dA}DTeh$swh)ZlG4h0Izj`UufzRRg|n$JPY?=c zJ&DreHV>YjbxaDexr;b?&{9lLHnz#7L+u%Jl9Df{(8ti-{&?cnitP__YG=g~lY3|q zkA6v5XYrU48hekMBt5P+m_+MR6T`ardF70gjoR8nSpmZ)iZykjEWC@z$;{IP$j>e# zs;**Sce;P_H#KhD*VdbSLfH<5;j~o$e&!V~70qcAl0&&Qd4?A-U5#?#l)m{R z5dYyULdUzBco3mo=f)u#mU-iT7vZ+-ThXX{P&E^R0V7^?{0eWXAt5p6mi(%5Jn=gP zp4X}LlHA9G|F{#Xdy!ub438LYi8lBVhWXqw6_YYuyhSi9d#2e5BjgID`y~kSd15$P z+hi$7iBDOc5+REUF1mD6{oDQOhs~IWX}p<3J6yUjAu~%!P*Wjh%vD9LU89*<|Fj~Y z)U%bKMv4w{E5zic;`?rP6n`XP4Lh#uucF$>CN17UV@`G$f)lpQG|~;-=}d3t#0He3 zYZ=q3$E2?ZC>AW-p}Ht{SF2&O@Zp>NWsN2q8@1Q%X^t?pD%tsQBD71%LsS38Y)u!r zT*UC7mHHraZG;P4QrkeTy|UL@ejj`lEcltDogWS0Db)+M$4fM;5cnTG6e0C*#_5}h z@{o2|noW!6jV{aZ(?N=a$0CW>3p`FbHVCZod{2AAGhoZ};}z2w86W6Sa)^wJU}Z5)J=!2whA#$wE5xhmh|DtDuvVLG$6 zUSDyn`q#ssat+o^dn=N6CW}Ez)DKs)sDkz6$*H_Rrbr6OOa;#|Vw{lvg*JVRu$5Qh zRz_k(zzyL!3O|ijGl!1KVklA`RIrp|pGalWF%BBzmK}t%N%X$3cpj4)`I?;b^-3N^ zQ8K`#xnk1H(&{DI*QSi}%eGiB`fJ!}8V4@7VecZNN?WMW56XkW)>pG_kZp5#8CBN~ z#4DT|i9(`)(Af+Fp}WLl!nW-DAy<@8n9EwYG(XH&JLlW!X9e;2+GiR6OTyKq@<*)e znj09I;Um8yV_6ZcimVC#jlV79WePH!FDmJz|R|t4oMszzmNkv)qgmP;8NE zySfcf5{ybSSoQ@7{<@98dv2Oi_J@?KWcQE$R#v>Gy35H(C6J{p2$qpf_th@xq}sK9 zmJ)^Fz}KGZfWMNa6<*9mOSz@LZhaq}Ok{2s3I6m&H(Uv1*G|{R5V@i3LY%Nwty+yi z7!Maps!yL)8~foQpP++thLKJm3k%7(*WdNJ%5hH#%D3OfLUagfC$HM3-66A{@iM^4 zI(5uwQr{pO?C_3Cy~im-zHAJRWMp|ROZ=s+w^^-@_)}ctd#A@bi2#W%Y-K)K>Wm_~ zCNJ9A3dTlgGTK!vYnkV~QrVeDfM)$fxzs=2iyIyNK2&Z@{D)X04&&e^2|^T<@m{>p z&ruka!baeV@7%DzUzo*eH1E#g`rJZT@udB}vv$$g`OAki9k*fkehMn}UM97tHY1z-1Q$o+v9$e@_9FTGB zpuGoNS@es!7D(nlKHBuBcvw+y!5|b914?VJ^g}Z4KAO;d5eA`Mll_C(Wj=1toMy6B zua_>WTM;(j%C|vMCkymlmdCY_ECo97zH8c5Tie=@d)D$Xy}sqyRRP2_U^dC;8M$ma zPL{%+s3*7g@&6?n1dO{v6I>sDciOG+zbmPvnzZ%haYi~ozuKowAja9b8A)Jp>UTt0 zz(aw%?RQHVe++JoN6soW3sf>uB96!pV%kT*-NH?;;-WY~ti0RFySTa;^_+5TO#-&R zr_DbA^!SnI2>xTN^{w&-FbqiwPYbhdoZvwHY^Jm2`b^3_`ex%n9^9zz zLv7PTS+W^=?@Au7#WS6Zzl5424SP}a{_McP0 zH+D$Z-G-$6a?4G1SCa)6BI*-Cq^vc+TkL|iUNYu8I2{VrjRaC63&>d>wQ@vNmY=lt zyMDzu%WvGgFUANGH8!evugi+YUUx4m{P^eKIVEJT<+<#yQX>;Y7?0cA9h&^q?jz78 z`WUre|GWHsYl_j^T3@xd90&_J6Z~m}CS`Ua(ZgDGk>O)w|20mqpbzHRS3j}`mvPzt z-anj)pltaeE0eJqwrGt041g~$HJb>eX!&(f1CP7Sp81#sp!XAHHFz>bnXkqC&kuzE z*X19%Ynne~}ca;z>H3J~ij&VE*hd5}Q9SJ7Bjqlovigf<|F~o-8 zggJzoPKokLVR3XaX$gz_1}R`@HaC#B`_PkBurj1MIX;`0Ssy>Snz)2CUryx|rtcP{ zQQ@f9cb>(65N58!9)v+3bH(ZXG8z5V!S%!sqDx6MBUO+E7@IKFFx6EeSf1T)Ksx_u zw{4`~2cx+Gc7ZBuG?@8pj`KRcr$v)#cL61HkF8h7qer}(b90WG^CG5vf#0=s4~PukhLy6PmdT3zM0U5ybSuCc#sHvdoNsw6Rnlu}|? zysTCXIdT=aV?C1=J7HcF3d6w!nGpfTK)jEA#F~7CsWfD`2GF2W))|$AKdvG0W_r_i$ID zPb4l%Pa8un3^4w3w>q{Z!N5k+`^M~gu<)u{A~8enn64N>}#;cjd2yB_Xp zvgVQgDO=6EjqB_fVzwoD($8+XZvE5GaX65MI+eAgO7RI^{^Z*0SdU)?=b>YkYBKt@ z8KnfhMx&>SoNwU zW0|NO{AD=zS+Q4MsA0PCMf%qYCA^xikHZWBgm%CMl(m#j#7zZ;p~s@HBd1#dj5FNQ zHYZ}tT<8|1dKK}hsE-%)-qSBX4E9Zvhnz~t8Gebw$=)zaDx*OPG;~*ljZie6lzglF zG9^ME>kkNv_Jp^s_hynuCDA~Nj7T?M3cnfYDq5Pq%6fem6Ci<rlDz*8jW&;ZKH4gR1D5PO`x2Hj$ zz2lXUBcld~62ojimX_Y2Gk{oyj|h1<_4#cwd_iH~aop>pF$ZY1m0?~LipC$`nGOc$q_7gNow+3g zb>_GzH>XIVjXChHcF7vj552w&S3H&{F;T5&nFQDiwuFC{f^ zMhXy7Sz|Ol`V^24gV7DKlB|E_f&+q^KgcC}vk9Q0@!m<8Al8X1C8g8_3I%ixmZPavAR zyTiJwzY}dtptbs0^&Eimb++_1XJ}~ei+gGvaja1P(9|{4@6ObY*myO-A(143iDt{X zu19)-E_Of=9UZFSoLua=Kt+1%H4^W453}ZMl#aD%eu@eh9DijyZPM!VX^{*-^>l(8via3g z>KD{VC(CdARP>#x8#ut-mle&rLHpI1KTcVLe6y6=;pFH^KQ-LbLLOzRS})kq27T&V z0Uyq*mwmlAM5R52>^rkxR(hsZ6g&N!R%?}3I==wI)e1*IXV?<@3Kg}wGf7zXReo-C z+gh4x&pvj;6u%kSK_=^(hThR`P;7~-C}5l&j`XgfGX4XlIYfuh;=E)(#U?XBnC5Z- zt_Z>1Zuq3UR(}Gr7bP2hy97PncR}2s4Fn=qw0f5}wp#i4(ikpzuJg#NkwEX^mvaE% zo{%!&i=UR9=suxfb-*^^ghr24woC`JK(wj{RO+2=>R%Lz(uh^XD!#Xb;yLn=w%DR{i0Np|T6YRP0v{ zu1`Cr#NI;pr&g<>r5bd<>Y?T3K8wKx{2z*yRZ*=GOH^uNwKFg~RSLcN=+G!W2_5$$ zYRn6BA=r_;?qi2fI)Q^Q0_oTDRXHr7OC_0(UBG6J<*2y)Q@g!oo$M&V1HJ z;qJ5CwBwO9H}2GVsI40e76ciOri#UN)LO{dO?=H#y40DwpD3M(&%#&60REV%?oF-Q zUBk4XK#Fpc!CpvS=L2oU^(k&D)*=h^ZpBvFIzganzpNC487 zI!q99$mtdXNOd791RGNRfxlq(A=qi0O%lU?;K~ANd`dqe<74$(UPFw}hNiy1x+F+S zM)7qMA<5a%=-(?`fBJF!YliNKDRs?&m~dW!%BFl>U@?FE3HSr=W~Q@&&&Gr7cnZal0yI5zIp3tBJpge4m zh4Kj==OJ4NqU;fk zm&8x8PN~JTcb#ND)Ui#i4DK2|;+Fv9$*RbK@1Qp-q0=uKDPm%gr2r~MMFvYrGKmS? zpjl3-nbo|xVgwv)Qv7*4MS2af3@Qa<4UE2aSBsWUy*9b-S>ueuF!r#Sq!P9whB@-_ z$=}+K6!EOK5!Fa%AE*$>aous#Kvc>_HVtK(mM(wvAo~TO`z!~k1U6kC@cQelYpKK3 zzI&Aantoolsvo5vHlIR_xr1xGaUo44h(zl#zz1d7Wk9F-hJ)=D_m%84%tkLYe%r9H zmr5c_>_%w+P|>bqXdy!pm5;W_e#?sSKri2icz*GxDy%%e0AuBTU)p4P60eN{4(t=x z+AF^t^q~^!6yw)5KGkdyuTIQM68B0ZUA~iBS|uNgMYt~#=3&;U{NDXp&Thd{Y~p@( z_bFkZ=>Go;j_Vs1IV+?wb;VSS{}~Dc(~xR%1j7Ofh7oDB2DxAxu#CYRlTD4VDO>ol0J=rV45ZZN5KAp69#_=q#0Th43uV4#pb?ia@P1e1wJU>EcR`2rg}AQEX+Q6mV8`tiETjgd zA8dermZG4!C-nRkhDchIO}4+B%d=8S2L~R^n0y;ahD(t2=UM1^$C_LP1~5r@iBwEJ zm}?WBK{|xxP<~-XgzZ!>PWp;?y*trPGC^wpPUA;x6}}#ZB@G01aeZJrX(FLeCqR*) zQj41NrCsoP&8Ad#`WJ>OM?#go)VNL~t=1wt%hmNy0gD!E6vY6L>bmHs92SR9F^CnN zOrB3|!~*_Y2A*}}g&*0>~2lKi<; zm#;Qt*T9cjjaT{jWLtAf8b1$eheOXUoPP&AKBvgAIj!g&Y~-(Zost};NhpomjBJ2!YpDI@`*?s0+xzFI?nXtv&JR#oBLndY7gBfWdg{k& z1_2%WfC5=FE$jiY+NTn|h3Ff4e~?v*+ftBKjsr$MF?TfVpzo^O>q(-R$p}zDtUIZ* z0t1K&0V@H}F!s}(Rj6j!KvWbaeUIbHOm48f#=A^I`Ay2Td%`GbZpOgSAZvn>Kp28z zcN|4rlGtxGeb-N67=!HQ;Z@p66p(CgiZu9887l4lgxMTDvON99jIEEZPO{$4-CWkcnph0lKBB*=)FM#ih zt);Ca#QTTfyVgg7pnKhzeMl2eR!O>!)5{x}1IC6T2OQjy)&l{qP5mG8%$;z{gGoH& z4|0K`{$pqbkd&N|D^TX!26{sM03V>B1Qm-&2e#Y4WGjkD7#aM2bpO%AUXeVQ6HQ8T za$4E)W~lbv?C(YrK}{o{f3jaFbcQS9+dI|srSoC`%@Q>pZj_J`;CrWX$m;M}@i7o$ zFZ}&x{*&Pa0CB4x$vayCWAF(s!<#R8_4Wdv9Sp49&(_bfcYR?_p=8OrIw-m=eor+YFQB)Xy}c3y4bKJArSh|w?xO5?4%aDv+pj7=PAcBX*j z80R6lJ2?W>9ROLCu|j_@P^vV2=EAhdT4moR1H7iqRTp8sCI_XE9( zA4PXCs&G6w`jVVaVkI(bd0If@?uh5rq~dOAs+X&^(E08Md&cuEKngwi<33PoWYu_~ zH8MO_(-z6NydO?SATHE*oQ^=Fg($Hc1(2t8TmK;hR^$(;1_KVs63^Zq7+?N6_jqpV zU_4y_*)sK1S^W*- zRjUU=#LFw85Hn!*B^Y!!Q7O}?6R)Zf65xzt4a5X~uzZj%Pn0geAkr0yTWt++WQmRK z3l95XkiJ;No8IzM6!-0Q(O2OTwRgLk+l(}YwDAsNXjQDGvxs(y}vsggLM>xK%)UQ?>OT-j~OZ&7q^+$Yu&#e!C z3j+ubC=GD@C(xMrgYKxCVak-*Pg6rRSy3k726{S>&;1R!GQW*x_wD96k#-W?N9Y*} zxG<)mImxv%-Ond1QrzI~F#%ikPyBcuae8W@6{@HJKY~n=JWlk|^!X+%gr1pYd45l{ z+FhoIg2v_7Fk~oiSnynXDd;&gpRRmoB%z8WFn>zSxA{*hd#hPF%)iPoQZA8jPG;SxsL2kj`Ac;S%Iz{dc#L4~G zUX+ZLo1}Ly6P$R;V#x8y!PaAng5Dn2aqWqd5p$H%F8aQkF$g)-gz)x?Yha6EDMrAe zr}dl6pl~o|EO^3OVKRjFga1x6@`9C55vO7ztyj zqdp=56)nzoLrbCv)m8by4ifKKr z5S_b7!tU6dItERTAT~X8L<%`#9*ePkqfGhv_`O*wqJtG`A0nEoRNpV|Eil4I^^#kS zD0mL}IigTwkSYa1HI9K%$zcZSirbwyFvGLyfE#zZwqCd@)5>k6WCtzCT@PVG`P~V2 zctYfERt-g>{gQoTX11yE{0Osiz)-yxmTp;b|wFFZu2R4gOS5r2#?#`|H(bI zS{+0@Lzzhy+e*`}EOqddjU^tne%#}g-Pz2c1YF1rHsin$V}q<1!jA#(Ar2}~Q&8z| z?r-SW5kHHKfgyTgY|bejNpgx6`uCZsHf+cN;!iF#f__hTGrq|&#F}jz4~KYGG~(gl zCW2@TJ-FS0K~DpIbs_o{it$ntU{GI`09X0?yHHhodw|_}P7QMZH{@31Pfl4hpY}>h zJ@ELq)gBX4xRaJ+x0j}od9xQ2Ibw8K5gUDiYI;QJ`>vsaFd3!VE`01*=C3?J1@L%r%&3{T5 z-ZSSBD!LtW<*-@^V7-I{zK$ zk_fsB>-X9u&g&K~9L;waM<*u(H+)>6p%Zz;qk*C$C;YB1Nl@2y3r-hEORM2|?)3iW zs^=*>0pbr#Q8rBn0%ipl-v*;tPQe8#_a#$dD1ba5>LTMublff{Ame}%VeNtdYY{f2nC zBtN8(hrDLnf2VjjyknH6wwMHE`iy68QoD|f%Gm}z;k4BRA#=KHR>J)|38fpf-pAVuhpE`Xa2-62sse1~B$$#!6g znvjD){i5ax`(lANzeTV-WQlj+)010p^R2n)!{5~9-I;Ue;;X_fn3-$^ew527k#wQK zaVbQ2fgI*jL7O=Eyw*K58cdPerlD8UuEd;$njrxj7Z=v?LABa@H_k)(r}$O zSA%P4tm;km))fw+yA=|$FK%c)?T!HpnjaeQxt>p-o+?Hup;@ciU6pcQ3p@AQ))pUv zGA@4mpQ?(=ThB*+i;gqJ7nd7IQ_-;l5)BdC!>u#{cEVxcB`(D@xj ziCE#2TlveW!A{#^Nz6ir58g}D*`ls~0#unsfFj~8q_IRaO@Ui-WBoA@9Q>Hz_1CtR z7$0cp`B0Nr;^$D=|1~C1SkN>eY8 zLU!eXH$CDI5 zc$9P)&p`16wf;Bg&?MhH#es~D0GW!;{DzV0N=9HN0^fIcgc3Z3*e@^EMZ*V0Ii?e_ z#=VZ0A**+hqqSaY;_VqbxISZJzqew@{(|;@pB>@m%l;K_-|ykrjrKRB%Hl%r3=(^R z-Y3yq7UVt6Q!>V?&Qh6Q4t|n|oz!1nsy^Mh|AQYU$}}|nr9M#+ig_VXcyC?#B+#^h zOG)(`wszE9+yW;ZPA6~t>@KT?U9Kw}>F5 z*^lUN-;MRosIN$pP<6+g|Heby>GdhH&5wo6^<_>gQ~-T|cWP3*ByJN`T;@Hu_(8pc zt3Tl`Nv~CKzuv<;1=?8llK?k?cIc#v*UPp3wrY}2OGwn}m|$s{Ch*uN`%Qcla@0FC zNf)a@q*%|hH>17qz`6ebD{eTec4eqzt=YC?@^qu0q8`R@dQ*Qa``P5{{n{xRZKJ1* z&4pXOoT*6B{;kgx&V32OP?42L3M%UGwBZzPzsv@NFfLkjrs;kSd@pC6*q;#wO#ahi z;-ZQ5kJ|gfY5&G|FL_HY3F4C37*NpPi<^~u;TVP7v&{RQxGFT)G-vIhH*I_fmKe6g z6L*BSq;zt;AYqy3Aj^{u6TzP@a(O7bOlZVYz-wKk~oyJQ%TmRM)@7Bjjdhqui`la1@ zAIqj6g?HuwP6SgW`=;y1fO%3818x^J*TXBBH!g77`labU9!M&pd-3OmwF{;D-~{tFKH zf-eh)v%$u}-tvyEy(9qe;dY3p2pAYbw)i(wM*q_LzRen2wHROxO?K%oUi#mj(2S7J zmaW?c>}xMunnrV*40He7lxAR<^$K(QC*nRzIxuj4_Twi|Ece^VUdKid#`=X3AY@f_ zeZ3PA!fr1ylwqo>M!wA)@9q-bcAwyQZ?tF{A|8LISoS_)he(yLT(J#Nmhg}%bjW|w z%hl3e+gNNGSUaoF3V3oK3-qi@5oJM>BY~W56Yqa+z07{yKB$qqF%l094R=t(75j&p zqEl$&+hp&Tl7y86E&TVbHGa1jWZ1KDF{2p^Yen)m`Ed6phHg!_$0MyU2`|SYcPHTC zpGFGFv?|5*DsP-aOZ2G2?1<72jQ~ACuYO01sT|9AqJ1jJC(IOEC?3>^X{6}+isn5h z3*^Jclm#%MPj=~V9mPYj5%ZruvIT!d))G6{W}pXSc7+Fm0Dp`t%*3nOS$EpQVq%j9!Tw@Ga#;|>?Q z&*E|6`=#I)O>ni<$Q^1eiVlM8F%eS(M*%MOnhakUn%{V$u{rZ zd9tVq21|A+mDX~iGXYIEv$t+^vFzAc%r%#bIl1z0+;m2v+UUT1F754j(n(H1XPp!o z{rqk>^p(S}0*pzwUR$T9-U?-pn?Lgt>EOM3)wW+E9Sf0u{SlLGHDn76{VvG#W+rb- zF0-R~|0g2`n zB>TkxIPG>UD3OtWkHt*`J0<6#JF;ey z*Sl|)&p8d<69rH)G}$z{&{9~CPCPG_rc-EFS>3KkT_sSuN~)_ML<+Iyj#0JVa@M^B zTTqI)^+1cKwPO4*T0J}=Ad&l7Ax>auF}27F(;-A7;LHiJs=PaOT5Fip@U+ue^Q+@< zn_}2U-#gHkyXmOgClQ6S!Y0W1lzDY)JY;_Dvxz3^^qT>C?C6BkaoclOcU?;?IuI3*ZJMXwRcVtqH z{b?|^hsn0M&^h*Ih#kVAekU2U6x4E=c_*JOZrX}jHptE>@LS~NBZS4o~pe%m>Dv23tqD@i;zk&Rm5 zU`T6Ysjefw4PK>F<-}i;0FB(g1c^5Tsff+uZ;ww(W9fTG-S#y@$NjvMat?Fw#rQer zcYus#an6VkckjY#u>Q}&_$hCj?;6CdP#8!$O+638LRCz>-cs^rpa_Lvc7_&=%pcC9 zn`ZF7Iz}|3)a?p=;tb={Ae?gz5Ldc+u!vN6G#(2~WpGT9$ZU?9w7BPn$wu0^gqeEm zn(N`vW%C#XZ)?X=eGt zDFU9GM!#TY)yy|p!qoPXn=Q_2Us14SK?$Fw{Q5yQKVHwbA*!WLeE7{8RA=UlRD5^@ zq3=WF{w}kg8!mhZ*40x^3D)2^T*(a5gnlm>8$m(f9Y|({;Hpk$EmYgFx@P;IF^pXY z-x>Y|lZPI+C9N?==6^?W+L0i+cWU_pj}=`7FKJ#L$`p%#oZ6>CE-GuQXSq+!LSQ3t zALKRZ{iz%!G3WO{}CCF#zq}XN+ zzRlVkS*Te^p{#bXlc7(7ER;o78QdV9G!?a!(Bq4&t#QfR`XfCUv~pr&ux^?{s0&ki z*rh;RuY^uTa^?xay( z>Pz(Tf4u~YZS!T+nr;6DaD5I4;3|v3lnT8W$dmVOmH$t+x4z<6x=b?nDUn(Q*dZ8u zFz!I<-?!i9cis*K-?l5pqO((_!=!3ucoS_DLadDGBIWlP?y*Sm(V@vz#6|e+3mKPP zhgy<`E;ZLo7{2IknJ~uN3 ze#2<)RKh2&DNO}va|VdH{mU9XUY55as+`h1JW4~##w8J+!pphLL{7&M&=f`yk zc!nDnS5tvCY1VG-Ns&LO#F#96i3-t(Glur=crmTN85oDY6w{y!Y%_HWt6R%qV++XI zK`3c>3+dhF<<+*V^1MjNS)G)XVqvr2tjo%SUp(Dc`{ivX@?sK+b$g*ln%0K*x99aQlz8%4x(o2qE@nXwDZms-93d(x*D@UnR?$~{8@YOaRz*c0fPRV@OP>CfxJWbESagJZ zKj16n@9y$EYrpU2h%{{d2I2N8C(BCKD?_t>JDCTnIvA#_`quwCwpu~zS-osMCiVu1-KFovS!1)?i^s<4+qd16)ryT`>;rlB+u{bumYt&i-|< zzjKSiDDZ_o*L=MTI#Hn#G7v)%E%jou`Aze(vx{@qM%Eff@J7)cuVAs1*@JmsJ)CYR zIDCr_uS7g;Mgg|#GXFsjgW{OJ(RK7G)a~Ax-O2wD=s8vWx8yOJu9=VwlyTzg$Fr1c zsbZ5AyoV`+1~>S^XElWsRQwJE8i5%#Qs2{p(3ANiPlyQIePl**GQg6ivij?@E2#d5 zzIuM}E3K-XskG@(UlLRy8wojUkCzzdv37$?slC+2g+!U+!nvG{@jm+$hel4KKV~)2 z@6<7H!qTYlf(ePqKRxXC4Apf(Fy-1_fed;)=tOX+mo!$OR|XhR?Ye0p2sk{$5yGntnI&1QcscI%-2yF8*7kl+g~pGJnS^Pu!j4Xu{>4$cK5bJLXT6 zfmqXAZW0aAt30>+%K=Y&(0KK*x~(qLe0m!m(@qd9&5U&VhNjU*X6fBPFADsMZ$ta) zH;pzhJ!C6UkUX}Ysob+Rft561zH6*$T~8CTTd<~J{W~&N(@YIF=g|SDZ5c;loLokh z;R!PLIn{C<{6ln8?);Sf?9sGN2rwg_j-2E~=?|*vsyViglsuH9;sTubqvuPB*Y%1I zRE6GEQ;oL)E3_NK*ygM3-q=q8fm3=oikKfLei8WamSdGT$EM%Q+m1T}&YW>Mbh%yd z!WvX*S5xs1ap&!zG;eRcl!I{}2`K&J_+UT;o)ET=!DzZMxVl)Cu-V;$(6Y^^#rz?2$weNwOP` z=U>~ZL3gJo@mqMdBV%f9%%Szdw7hOy-xY3Zs_@WuSw6-SkmO={+5URMmf0UP$zptX zffKXcL^~BGZl~Y$;JSY*f5w%bOeR82n_5N-Fl}|7-Xy^mz(@1cq}%J382#E27#B&1W6Zly#-8dN~KyF(D9QN%$y zrMsk5N~BBaZg@A>dq2;0UHALPcO2gz9vsfhxzD}#%DsMTueDj}Orq@>N?OdRX@@T-xwqdaOS6$h zXr-}yb9q+ZJ9PCY*JM36vddR}Kc#kF&jC9>fB17gIn?3%c}bE*i%8n-m2jF+Z^ZWq z2?D}f#_sbgeGDG3CFMBSpd{{8*Qb(*jd2a5PGU+6A3RCflUMu18mOKszg<7xO!=c`i9*UJv&gO)NPQTT5T`h_1 z>o=mVKd27BAPla7P$KMs{Kp0>*f+Cc}j<@LF|hRy3FPjHYYerf1Ref5sjV zZ*!H~v@5L3bdd&JU&8Cc=Vf)ct$*1zJIT>H*9#61)KCaB?E_NMn+j;yO z_!a2Aqa1#!(%D zttAiioF21=7ljpc>z8x)lBu*tjny_hpK_?>1lS)kn9I=2?8(*?ErK zahgsL4;1-zunAZRP3oY7lEXH{!95w+V z3&lfgLC;XxB;~mBZ!3S8u7}yHoQZv8gu&vJr@BwGT0_kxeXwg;tRzW{}aP4D%rs1jOw2_qkb_iE7 zMM|Hr^rniFUYuOyH!%m5J88gR@H#B@Tk-u=+`Ai~BBrNRY0S6n=a8J`gSu(AH13zh zqZEt01+*L#R79p^(kslHS6ExwjC#p+%olxGu5Ep#Mmg?YM}`*^%&=00bH zv2u5eFqxDQ2F~-7p|joLEpNl7sn2Gq&%*XPv7ZJpMW5yW9xX>T<*{hsP|Rm$1U~fX zdClC!5hKo8oBXzJN$Yl2?I(zqi5jFm^&2y1L+*tCB%~Vx=PX+Xbp0xjoVj zf0~4|wOOW%bwGg+?Vx zN8el#FNfSe&Jsm8-j3!tx2ucp7}^%^AAl>`amIKhS`p}*3HwS* z0SPol%lwQD&>(}4`kj~WG}bVQ$(Z;bhI=4HV9Nus*h^G1R07#`iL3ti9g`0M(41}jl)u_mHgpx4_V;rwB9pXT(MhAf>^nsT@iN9mf2k>s+)2K z3TDL~3YlDSIQpb7z)Du%)qETf!elx!O|&Z8vt-hv78hA<&1hX^#Fd zm!*@Da6o*UOl%$H<@DvpABRSvLDsw_p`gz6T<)uak4%y{UbqkOJiJuDY>b-Jx+yK( zTaP8(mZ@=2*G=ZICTcPaa>=esE@+U8p)Xh+wkjp zw<8U^KnsRA(+-T8`m;Z~j$6ywXAcrA`~=j55WLM_zv!&b(=+g#di5W|cf@Cz?gtOU zT@I3V%IENU5VBTlU-W2n)EdPfocZo{el>O>4^&B9xH^>=vum{E;7tlUKKiBqRlYv)Io!aj(1PMne+l7tLhHkFZ%_Qvq;|I#t&~p z6%OF)QLh9F=D(>WHA(o(Y727T+Kg)sy)xL!QlGd`mE_)z1kbxbQ_i3)!6jTH$v z7ikts*M~;Sxy7z@x z&Ub5LG&6oSwLIUo*r7?%?ZxAd*`sOTHyBX!=x$C7Kh0?)okywm-RL^nCfG!(k}C40(s&F{_-E{{?rvuf%G$y`&X^r@(`SVo|0hxN$5&#VSQ~x zy*(#iFan*z8Os+{tVBnC{eWC<;ZQf8ktt=uqmVQL{f7rkKKZ+)Cd4bqwt?!3PE=*+ z7DZkrwvQV?Iizck!i}Rni27V((Ps#E+V`>)-JfYZOCa?+l#~q)I}I%ly7=knsI{_o z`;B+X9#QYt%4JgwHBwOzS~(gAa~_Y|I`f@?nKJ0dt1Vh&tw^YEHhP&Py9kq<1tZ>5 z+cBH1_(t40{8}_^!=RI*j1pBnzPo78B<|6pyBxsE?_J)BNgT(QHz*Fb{?JCa6jMM! z7HBbObS*gKk{GL*yF+BAyE;h6C&>DSCDw|r6N;@KUJWr`aD0BsuZVP7-CusA0E)#J zBb8r=US-q5BJwFm>y2|#T&(czM=ZwVTkJEx>)3PSBwgl?72ou=(xLayk9^g4@~3`0 zLL$v6-JVK)>JtdXYoPg`zoM9YKH|6Y9dTVSMI7D+^FTNF!_*ixpgvvjs*$bJqIImF z+g1iyyUs_##Vcd5e!2JFoz!H#CVgG=Gms@qjRBY6(_#<)=(c@98}gg}^AH@Tu{@lH zOW&*Ug>wrQctG(R7h^C>aC(QPkvRwL#OhXNkyNfiS%d?={l8yta^XBHVQJ0&@z*X| zk<10qm~8v+5wKly3a-N9O|MXPHN`K%Zo<;cspFlMA_vF>o3klS`6>DT&|z3$OEzooU`8(0dc=`{ zmST?Y8fhT9@?fSQxe|IXc7&^dTsCyNeJ)ofLVAsTb zP*)&Aj+Bj=ell~XvxP9ZHR1Yf9Wk9E;bd0N`UMW+YPE$pSOs_}$lw9Fi&|+t2z1B< z7ctCh%1jJ$=^G8qxHLzPygJ!AIiF66QbKo;%Q9igS`9;Mja)Q!SFF?I5|=4x$kPpn z-|j;fgH8LP9#dXru1W=4ltNDJ%&v?b#-HmWTZ$8sA=+DOo8Dkc!${U9D?akMquu|% zuIF?O+E>F{H-&5hq_=-43{J8z%2y5ek{o<|SJGkM{+hd-KYKqa3zG33UVBXc?3_A; zw9m4|%7S_!NZ*g;4~t8G+TJ-HdxsdAM-l06L&_%fBfK`pBseAAGd9roSZ-9DMdM4I zeL=%w3b*^4za-6@q7EN*5Yu>m+I(WMXK}zU&8(7Ic1~GOZqx^9gLIg%ba!t8P8*LGJXv)h{47h0zvo=;IAnBjFKTgaYgC0hA)BGx`!7Zm zzIL1bspUR>e6!2?w%W)!d?#VsOrBF0lG0;B|LPbt4{X|{+k-!3tbWB7lx z^W01Te+*fgRlW4A&H4qUzt?W(V!FqykLO;014irgpY)u&-&MK8v%NIQ|E!m=6Wh83 zd$j>isjh@^GbU7PMpHm@I8{7sJI?R%I$7#<2;9M*3#a4MMsfj`S1EksJ_%s>FVbv# zKYWsI40QrTFT}xEA7tN?@43KOZ2pm2UA-HP630u>;8=b)7WLHZiUuQMN(cJ9%*O>% zSxhLGO+f-Nxi`7RU)ZTqE%k#N!+zl^;PtzP*9`icvOb*Kl}~9g_h(@m-``ubD6p0^ zkXm?+g#gib!X)q{tmpN*m1Oey@nL9$g!w6U-EKK9p}z~P_Dg7waAfkgfaA}*vwmjP zyYE#=_S8H+2({CKCHUnYkp*V?kTTKC?h(iilvJ4mIg|Ecelwl3dyML2?p&qQ zaCw63XEgpm18iK~xufA3fnGyRL__i1Yb@qQ3os3TdIMQr#n8O*lq6^hk+wG#*0e}O zUlYc+(%@qCo;XSi6mx<$kzfcBvYDz6a9St7o__vN>a41p=BYLiC^buYD^9Dxlv!a9 zM?XI#G9=et|3FNtKE*LiC$cHX)uJ7=u|U z;$V};#cM1Dtc6V0Y<hukj9C3WPOBf9(+j%-axxOks%Ku*|q!j?tv1nHN>!GbEGq)n;D}<^EEWEg_E-6oYQI)pq?WtdRaD zh_n_n9%JD&AB-4(METllEEBANg{g%wDU_ZXnr^8W2KBmY;5rs}!#Iq?j=b^cG}u8s z|KbqPJu?q(;AOd1S9JvSZ-andoaLILy}3UR5zIWzEqb76D>;_KPnjp7te8H1|NUqV z{C)<fW!CzOOyzXSdtakdUx+kUv_kW37&&#oA zP~r#s7lHIJw!sj5^~&I?|KCGM9>K(x;>>DkL29JmG9^~~H^3mHFwv*H@fB?f=n?Si zDr{?r4)Kk+kEK&#rRk{lZNDtps2oRSSAnLZl;_x$Bk$3MRlB@)B#bQNK&mR;z8}wH2Z4C z+Nf*8C%tO&P3J<&u3$_4B23P^o}akk14v88RKTzpqi>N|E;mfKa$=zpTiIYC;F1rr z@mXKaJig&>1c`xtmFNpb*ss%=o}*X3GK_bC3&=?4A5BT-ap%cj8|(5v8~bB7MIWjh z0P;Lkqlcz$vP~%cC6CFNz~gkswLOLpv7Zls*FpVtuwot=FAX?p`Z<#TWnKLT>i_3v z4tho3cuU}MSf>~J$v}hH0u9245r`9RS1KcLUzmz*FZJ(jt+iB&-vY>P)b&)rZLFeD zz~{yvV`@+qJDW8K$=6{QJ8}hG)|iz#$ZdmV)mPhz^ilj(5ALTM>+`;$+l11i&6`J+dg1^j=|MvNZW=#y1r=JvJ zl<)Gz46soLO=oW~pX81&R^)+dd?a-%Z&iUH3xi!zFe_=4C%Vf4r|-VU=kosVHHkXd z$KRG+q5LPOB+xk;cFvWy%V&C5CoEP}15S}9flC-XxjYPk|U+jsd6U;4dw%Ha11)mnZThv$ct+B?n+fndpyhNqOKg2x5pr`x z!uG#4M)I5Cb6;r~kYC6DVY6SmDcVq;rm|62Tkv{y2$Tv@KJ&U2HhG~KAKH!czoNUf z#Z(@>OgTY~#4=*PQD6l!&!{@*(jDbr{nA|mh43Y%Y-fRhJxy0%3ZapInk5OLFuh?OTeW~6!@%l%UzXe_YUx}HFt&Fk|cwO0}sg(T7!?p!H;KEqC@)oh0 zm9^OF6+11i_#{1jU()vB%~8q&V%JpK6Zj=*T(P1i`k&U~lfPR(2M)Ni?eatS2RzHW z9Sn3dskG#W88GiO$`OB+7bs*6tW}6KJ_h?|ZWp6ku66`4SdITNSjCFn#)?SM3#WMN z%#U3s8#F+PI~`3T)<4rgLwOy@JbM1NchleGo~-}d-hszImB3-M6QADnxXtQXdL04( z$ewvPC$Ik9p?9;2 zgDu{@@7h18v%I@u&wfHOTw{9fu4A>EeFFIg?)U!JKsjv>BCa3Z`7dex(e|Z2qBRK5 z*{8K;_CIsjM1Zc}8K%QPOrSSnGD?nEWW%-@1Z;I<{Z}$nmX}#kb=j&*i(U4fyFwzat1bc>oF-jEqzxfmy`@l%CGsd<`rCs0#j{KmOB@RExO3e7(Ovy!o!s6ze{+aJH^09&nZ)5XAqq zxrbxakqC4$is&3=|MSC}mo?gNI(_E{ZM zeERqBf4yu;v4t#fT4OTs?zblL|H%dT_cTJJFA-qa%faI4fqyLM=EXhHew;XUIl%A! z*EB$5as@E#**jyJwEvoW91XfQ)J4vU_{Jps^Si@HFw~)Vjj-T<&7DyM<2`&Sq>ui_ zMfm4;e<;CFf7~4GpZt5I5NQXnqdkPlk~fvt|M}f_elXPc?dhqWe~$$H|3#d_dW)U? zp?m#>nt3j6!@f>`K7L417x`7WbiAnm=E*^a{U^>}Zoa5QmWK_ao0_)|q)ZTXUbsw0+y9m8Ee2<=dc=swI^Y?g3 z7L-=B^kuef;~lI&5U`4uchZEDghRn1ghiHx&E&FKu!@S{!*Ue{Np~I!?T=o8p7iN< z<>7WUzh1ST9gLg$_GbBBao!#fkejrp_c@s_-|OS<|NLdk=#}wU%MzqAvLEdJz zsZrfL98#%w!Pk7@a(eLX;qt)kp#j=cOHijvWY(*~#JQ7PcFV{(d#v2|XPe0c92AUF z$S#VIN$AXd^ySswZa2e+h1-`0-<0S>Bs+l3Ey7us z`nXGysH`)}*jCNkg7EfESF`%@xltP0m*3OZkZp z60{#mR^>NcT^`TwjTt-knz(*teRua|#MFe>{#Q_c$0q^&tIrqy_2y}&$J0qL(9TW7UmWP~rMIk+)`AOM{4D1iYQ;Q*pJC!y4F`Q;yKzVCruOg(nz~J&(+y z{9;W@t1}O_ei@76&LIyUBu_L)Oy&SL|J~|NNJ_rZ za>26M9%!Ql+Ob|R6Yw`UiG7vd-fGw%-23G=tDs5ErCsNGGAO=%|0p_;=&o|T+csY) z-K*4w)0OlQL&=|Z6}>L~yzE~#$|HH|*K)0n`>6|gZ^&B8NHP{m%s?NE^Kx@a*XMNk z4P%bH9WAPp^3jWUp3)YK@~g9TrRyv3>ZKXa?PxA0rl>K*X6<6k9^fQwk|?>D?F2Qx z_&{PQ(YMTGqL9wHj$03tzC92x&VQKmj0e1NgnHsxUUaUoL-XaU)4hKFwslb#=UGx#P+d7s_M4H38=QDW$AI^X(vB0|2 zX5ETSIdGXN31^;Ld{b#{OU|tg#UHxQdQ{?LpRB7F4`^-b@MW`_;t_RKpISdUc4i2M zaS`%CbM!`44dVD-^-l+y%R%a?*Xza1i}Vs+@6(

Rwr&0>3@+E&rHX^=N%iJd?SVV}$)o3jjGfEb?Ko+QRUZY1A2pFK?v$I6ez=$6@ zX6{9w3nWv0Vj4{O&6;liTe)jcqW}7F{mXT>=Ig634VOnhmtTCHDMsFqxZ(Qh97tq| z{1%7FWqo)*A?w>aHVKTd+)1f}VYxJzWwONSQX=y_8R1(2<{(|+`3TVbtMkLX<7rnx ziw;PdRf-{ElbSMv^im;^LCodJQb1Qgj24FZuMF2gG3J_Cu;=`>^YHcGAF}9KA73B+ zbR3a{0^!UVKz7r{AJRtB%J zN80VLf4v-!o(grSTc&7j3s8GkH|c%+D{sO?g8Lvnj;FLhz02u`uD${Y*JGBx-f6`R z?r>trlJ#b|`{G&94@y%nlEzT+ghT0IE}}H^_7H{3+$_lE@h`Wmxv37W)@G0H5BjFw zLVJ$|OlQ6J)emkv*vp1P9^T#SVa9F^*)0agg%Jb1Xs$a_L=VSc2IayU0WjexmbOyT z^YP9xedrZvz|7G>6rAN6`0{F}ow(m~yOFY3sf~Fe&~vNKIv>?0KkI$`Xwv6=GtWEv zgZXyjam*1~^RCo7);bOOAkgFWz3)>l4W2ch5$Cn+Y$QIEqS{=Xw9b<3Yo-!>qHH;M ze>6?{Gm-7agk@~>5yy7f3TIDtzAef7ekqok)loJ6Xo+G~n^pO-+FoY3guBy=$FP91 z0l|KG@7D6d6Xfbu=JK^zI?%lJ&-ghv0bi4J`5^Jepv}md40Qg+1Fa<7jtg^W4&9N6 zsK5W~S0thj#FmqK^1>*?_vu=@Bymff%CCDV=cvNGKjp{=;nBGcAV=V7ZW5Xq{iw8R z3RRun%XR!{exSZP)OIG2rYP6J8NdYW<#**a$d_|6wyDQ*z1Zw$-0y|2l8hyEsQr@c zznjP4E^L4)>3NjoIwUEQxNYLOSv4XuFGBqm_4t0luzVX6|?O8vf{O?Py6n-P^eknwWNFrGB91&VY?6_pk8jB3PT zYN%ML7%WFQ=M86nuizK8d|Bcu#o@!TeU+(@YQaY&I_IaX=|7Q|fqQY!*G&Z}izZJZ z+iTu*BC<++p1gZoYLM@U?O^u$O62ah-|VZrkIj=P$h@Ik5Yr4|i2Kg1rXhFHL|tSH zq+P;{kr5SjJGPFgva*;HCwZZ{aveW8V-aN!X~MdPX?rOp%eDXDiebik(2`93i0zyK zTflw>e^=rta7gWPnngBhzLg_#hdN2+EUwE5_Xc|*Isikj`0m~ zvT3cZIs88yjqv^*GC#Z!bc;(o@xi;|7p|)3Vd&9PT5EwCh?)a%W35S%$O+Hiw~zCK zopATrm)E~0U6~?6;jzVpf7#(2diOd1u6WnE^R~wnJRoyh76XG(PhLI9TyEEm73Bz7 zvC~T>xGtSwnlW$J9>I7TRhq4bW%XP@kcgLvo`{^w6yW*|Bj*=%{gf)Q0=MBJQ=$Qm zq^-0iK&>gmS3C_=%myOV^%#B$*KH6!?ViVP*KW&=wQ}C=q>M$`z%cM-`2rFJ74+A1 zWdZ_e7Fw`GE`6^QeZ>l$>}92-484^=5G2sUOem=3J~<{Ko~tV?LEwoO2e$wm3tK(r z0RgKlBNpaLW}OOk);VvIG#0ZJnxSpQjBm;JtC!B)`EW*Q=4oaVHj?|%heMgi;F1L8 zd9tL~4;^iVURRCYMFW{pR!Eo`4~ zo_GN&!{Iz+mvonm8%u=ziAIX3Bh#Md8vE=#ZC6k0Tj`H;Jbu#}2r>*Z?s3t8V|0Gb zb^kg?wchUJ>E_QC+3UDola{bP_C6X_iN~()^h|+}dKf-^h-gw9%EOW<(Vc$tq~ZIc zQ0kO+YX57lp}90!uh6Ci`ygvhhF}I4`du2!AG?B5N9gC(8OU1iu64f_!Ym~*|Gf;l zt29LxjQ!Snr7fAqZMPpdWG%GNwhehNP&K%3(K4^Y(EZEvyE;&=-+de^0hA$j2Q? zeMl(P!uyr%IX7X_&|p#wHa_XI&@Q6DJmQPM{$yHE6LSS(<4*QZ+u%CB%5Qf`QTI`ZKSlxW zI*MjxnG0utP8OYljR-l0k@|^M%*G4CMw{Bu&V>Kj-MusluKV=5zLo+EVwJR72C=M? zep|;o(6Y1c?6M+k72+YEW_@Ak8NK~J+E~)zd9RXkS6+$|a=7WwReP;$GO3#c z=p-I>Fz|{TGm4PIe1JfadZ*oUK1839%z5Sa$>h1jrzI{NBNMbm|Bxu>YID|*d(TAG zj6bUCa9*i>Q2|-(JQc^^^Fmr9e3PuRA>|A^8S_GYZ$)N!JN8G(FwgLOI~c>2Qnx>e zG{R;_Iy`4@y>B4*2pKkzu-hS2pXRlO+C<3ARJ7X%YR%D!zlxHuHQEVWGVgldps@-I z45z-VBy70VL#z^k86j0p7y`{ZleszkXhks-{32%M(nFfX0~Qk5WBrX}bddnPZ-B%MBGRTC))vqbmk*CyOaGzd zdundJl-*{8p12Bo%0p{ZJ6Bdea!-QkdGviPXz3i2A9)^pn6fj}{Q}jrstGOSvP!0r zH#3X+{3E;xByPIrb-=iSl_0^;6>ViCV}svb3hh>qI!XUPGu}%O!4T_a?6~3ulO<%P z1tmO<$>dWd*M&4~cvPawneoz8f-aZBixA46L`O+<2~_3zvB5Bm5fr`yt+~%E1~+KZ+}ou;DF}bm=_f(l#tQobxveGJBU8%qHBh0HP#da2 zlx1TE&2S8_&g=~2k|wl#kf?@G2o2;+oQ7P)C?z7-sFK*b{o=Tf$lN;2pd4i6n)eVc zKWSBT$pcmOgfySVD9l82zX11daDajq(DSLZ%mV4(CaJZD7aer=-Gq_zjzRcNaq~}? zNF*sO3^!q+VJq7|^T?tIceTNN3XvCTAnGTE68exgY(SzMuBi~_Cf5b>YuNmELKUcFCk^b%I@z?LFT9?sYb}SnJsTnm zbf@5|^L?2~-~olO%d`e-pv+yCKmids0nwEjkl;S#^K$%2f)K5u+Mxf6#HlsLHuDok zTFViA{iYE4KQlW+2-&9-?bND?RpTIS|1L$<+&62o&n%rS_l!wUnw5CCGVw0$q~!vA zT2Rq`4G0IK~KpO8veY}H2gkfw2bZWGlM>o z&l>8GC6v^|%l~$D!|A6qjs|gU$isc{#o*b6vexWWC1hc6LS^vE_bYlL|9VZR6LEzH z9;aFRVl|5|dY8YOv|Mr?@7ay`-!T3sF1fpZ$ffN{SrkC@3vj!by z8FC)r+QfR9$)2MG9Ry)`@?`$gN$ZA+1|cw{dvoXRfR^80n6Yf582>ZGp?tq;OAs9m52iIC=vH~F{y-8}~x zWr^|7S-wY$+O;{KIL<6GV8O<22N2+3%kqgj!hC?WO|fV>4b=!CmA*hycs3Dcezu6K zwBFTwCM3F}5&L|!=z&%y;N>8BT`$-M6~8sbsqyoddTJcjkTz1wdDMqCQdLAIE)@OZ zo+|5vAO$MZoq31F54}z)DcH~rnGGVQSP;(;-yj?l9l;42V$xWDJAU}}ZW}Xh@@*V9HeKZW zeOWOycCrIhh1}2K2HL$Ofwj60DMUUgE8()g7|X>Ne~;g&UnoM&x#zL}k-Y6+s&@2i zq(Hqz;jko5rN3tyVH7LD`vUnMJQ^xD5%~*-bfbP_7l9njic_<$E4BqkqnBaFWijTv z-9n#&1pLGk2<4#y>H2u49M)mE_*6V#xXn%_;yZ7ha2btQ;>bAeqJdXnFHXkP+z^;T zDnastewSV)i#*Q>t@Kb^^iXNgDa*Obn4?;+r@M~r z1|q1^Av-Z$#mlOZ!AQJcTasDn(oWmB)m%6a1>~22 zXbl46GL&jhd>+ZS{F`|O5@a%S`141tRT8YRIon|1H>PEWssXg%knXA9UV@I&*8943RMo7Y@;c3^0(L1z`*%V@FU$5gXNsm$+! zdmLpO`&vg%Q*NV2pPD{^lLC?6s>LVNZ==QgJLB*5lowG!{vV?Ghs5IV=p`{rxETFl zCnWYALKw_(Dwqw!Iwkh?Hf|rpUc^_XukYeJg|NLV_KJ0Wjx8)Q_;x?lZgV^HIG z)uhB@YErY`cKA#W1iy8Wh54PiM>!5@^tsBK;SiacxPb41k`*P@!dQ0K52P$r%ms5+ zggEW^b$&8UjW}^g6n2Es{1C>dD);4l7ru(isz7KCX$&y+}DfTeIw%NX#_ z(6#mM93&ho7*ORX>Kxy`f!kB$K%gC+iQj52u$bump0ADbw`%QRYlqse9luN|2r z0!S?4BH0AfMJ8dd$BrH#CfW5jSU~oQqgI>gjQOqplC*1&*|JrDO)x?+s(st%o)yC} zc>Qm%1LW9HF8K;^`8jI%}C?`B(d}VHx6?1 zzf=pe$baHf{})=hk1Q4X2Lkn<*H}dO^J4thz~I@=ma%_9IDh>*j1#9C@?Y=@7@G{! z81ug-?FVY^>6WNI5#gU|yNzYU50-4aJ#9Ed2zIs_=VtB%{zcq4roNX|CQhx`hg7oMj6v#s4uF%pFo4epI82My{eGXm zRG1gTg_qOhecqQX6R7(C1+x@Iv;uI1J5MP#Wp}Z=Ut)iN8K5(<7w6l}E{8w#Kji)> zP@|l*`S32+`s{F>9TS(xj&3bwq`#lP*+lB{KpXTnyxsq-z{>QUsB>^TZ6G#y_jJhj zN?V7)xV>E}#_*y_DC(ooVOdcGdW%k=)O}LuG4M+>=-P~CSW$@tupT_bu?6hf$2jUW^TwR{`gAhLL*N19}vkWV%|AARP?hZe_ z%y==X;sOA(>KAVPXFdf-j)w1^`@b2wckShmWbnP%<=r_P+f^By0@#N3(^T`2v61q5se5ema8w%&#_=lC&ShgRpB|#(QQl1lAD$r&}}q zd@)Q`;c?!m)oKtdXEEe4n1;C9-1!S;!YPdFHUqdqcv8$);h!i&?TdT3M`hjg+?b#_ z_DrLvQXjf1Rw(=h2wV38*kNp=(YB;f?+8RR*Bpl=k26r!Q_poD;o9I1JiK?wQZXQ? z_WeV_o5%Hr%|!PuoD5xhS=F|f00=`VcD9z6=d01ymjeI; zv9}`RMK=-ax`hbtT$4nb_i67l-Ul|UALA}>%mort2$*@xao_++$<25*Wh2uxNgA!= za*dGB0FAl#0LBJc_l#Gdh{q%nm3}p09-0DwUg5}w9K60dZr%fw@BjAj-mitrPd|w4 znod_nOt=(pvE7dY&48p5;1Pv<5BJPf!JDwn#!5g_8cONnDo!OVp zP)@a=4NJ)yUENMlQo1Rz%(7cimOV!XKz-3cA7DB195?`QZJvJh(>{DZ*un_}s+6Ks ze*>f`PV#7inN%_J22=r|Txwrq-^;_iBYM#F_V-9$s2LNAZCMivC)O*D!y;NoRXhml zrM5+pl>bhc3YfnydH6kED^zQO8iIZtbn8J_1MMH1h1m+IJh?&^ce}Jqo`U&T5I_!sb#oXG5MR1+x*Mc?f z>b=+P?twK0)bqS5t9EMJo#3K(GOca#uGdPbmT2|C*)!f*N9RtooD#U|KAh|meCH9I ze2fYBLiFy8fAIB)rs}tw&JiUT5&bo@KE}g$qvt@$rVmP|w`xzExJ}*Xg9W>3T_FLR zH%N`)eHcP93Ql5pu96LE2E3yQjj6#TXt@DZ8N3fP58Qb8RdVG2AUVMKzoymk&EwZL zOH_uAjfWu7vc&PAo^gE)*6=^M02#SEbGeH&5R_fVP3T;26X27wJ?p9V)su)f0%NaD z(mrD-aoozphNF)`gV2chXV{^5E2SXT)}O5Zn2Hn5@u&l@K8SKHUWq=O$5sE)%Ve{W zHt|Xj-d4mo092+i?|?sjYxBPFIx4U^3&e*(GY5Vlqov&)6OjA72NYHxsT$A7$)l!Y zu*3aZU$*Hz_;>CIIG_wxL0(C=##zU)rh#tn1pu@W55I@dIKXwk2du3Fw2-@I+9eY7 zdAqjVAfBzA521N7ny;dH5AwmnjswRSR6VYwr}x@vg_!yhl2s5JEljesB08=b0Xl{) zlirBlrOKffbXj#nXKiRi7WqobVOwU2)pNB7nXt?LI--&}uP|``& zeB%gpkDcQNw75_9`TVQMth_asqUZ^l*H#a6Y*f@MfXVs1c$(!l)J=Odk?Y zJYxbK%6eY(QOgQK*^hE&x*q12-C{g}>`_Q$xRR+R`pzAH=4ssz;#e%OwCfS*p{m5& zY&@Qc2hsi+5WpX)mwh1P%*u|5fRf#h+tq2Bo84KitoFdELpL$Z1K13i(`S*QB8!$4 z#bK5M41X0Wg+h(o8)(Xik&h{Z*@VRddLSlDd5R199%pn<^a;Qfs@9}s-6sL8d~21# zJkyB<%Z%uDkVTLU1uS3BQW)2H?|_5{W-xh&HZJJ8bhvQr&JCm@%N$ul*6FuoM`SFl zT;uR-3Fy8^r*30RdH}?zu{^2BF_@#3Ukrv4%7 zvj>OsW7I8l#(EJm(ON}fW>ohgop_sX!j&&t+Br_>Ev*Q5E^c59WDH<9W4%W&e>{7v zfkQH&GP4X@lEyU+azypp-G@UK74R%R!zsPnndLv@*vr(O;}OoE!yBqU^S0Y|kU@-vrS~S<;Uq9dMzW_qUqCWI z-c>CQ?n;99fJdLl9I0zWi|k1@*Jj2?_bjACsgFRt6aD#D7{N z_l|i^RS>BzDCv-4eqv5%My7^{zO^bcCM*%`-M0@n6m7;6>nv?M^BZqT6c|M{9!<%L za-O5N#&~z9#lIMQU$uJt2{zlhri<6~j+Gte)0b-SC4-y8q=z2zHP{`0m0A>`ls#aU z9}s7?^3LrsQ$}o~Atny(G}WH7KiiTQM$ZFNk!P_EI-D7Q)GL z&eXGj^lL#2QBN}%S8H{AzNyLd_G{;R>A2wzaiTYOI?>SKt*PzQpGcM*pKdar(%JD5 ziKmwS^!3KEGb4gnL3pD=y)aU7^JfG7nK>9IzF8A-NRpYe9i;g@Gi_14g=H>?k~#Am zULeIK+|J8rVG(_1fJ-Yt?b1b^lQp+;gsTu-)$vwKK|2kKPsF4d*Nn4=`efuDB1HH4 zx(GL_%1SD^^j)E58TmXF zd>Ya=#7~23My#Z~O5jYvLS1kDJY3jZd|LA1n3kL@2IkHH>*X=8<`9RY8GJz5K3YX7 z4QgUNC*v5TY;ZKZ9MCG79D-A6D8r=8_Bg&}+&+jtl%>gd3Fm?R(Ns;nJxFkcqdi7j zj!7&baJPNO=xof+>Lfz!T-yT|9`6{8hV9@^^v2ZZR54F_>dcI8n0U|dSvoRK=W~Qi z3gf5|8Rkko>G_)~{411rl!{8ewSYCBEPHAWjPWFwu?P_wpx8t8*b~e6ji~Ru!WrFl z25+@wa~9w1h$}P8>{0V-AKnfV6dsJPL$<&PGGn%pD?o#KYVMLq^3PeBZD>&p>1U?v zhbYs$>AMF)`6(BR{iGS6Q0P~hv4WOe9ATs#b?s;KP-&^TsD)|&W7ld9Jr$268~c5F zYf@`=+a~IH7v9eOPet&SmOCb)=iZ2c>)v=B9cx=87VE=rPaRu zHYiLV%OBeuCldEkhEpcHM+-VULB+2cXLNYl^jh642ts8*JFP)ZewB#&?vDNb-K#0( zG|Onjh9y!S-jN%;Op3h)QjengVpnvb(^v{$-wg{5YvD>GXN#AvtR&}T+9Co2S}u@T z8}CqowEolT2YPHp^bAwd0`jNtH!Y|@Hk99Kw$nGq9&4#id`=(1+p4UxDMrePSlm`u z9NLf?nDr2?I1Pe9x50Y1-s3TupwuB3C8eOX~NI>>Ic9m><}z2Wn`M;p^KR%Y~O? z#gFCQxNqgcJ4^3%v%eh@%#L6%z14^uS0+SvZxQ`wV|$aFl7w?YW?m0ZoclPy-dD@d zV_mhX->tSNUIeeTepTlsuKu89qRk^zt7t~**lth@I?=yD_e%{vvNKoKZIIQu;n*PJ#EO zE3q4X9^R*DSF^pG1hFZ<_-+e-W1f#e9NQl_L0Nk^EZ2`9Q4TV%Q>^6hTMSMSN@9fg ztezESFIQ-_Ygy3d5^Y=`XOSIBL_k0(8kG@88Ev|HECIl!7<49FcX6{TgXW~+jIy>o zD_3b3(OU~`OdZX5&aJG5%1AVJ;p7Aw)%-RkP#aBxfgZc7_n0wABw@Jh6#~Z7bh0qg z6(|G1kWyib#^cqH6K#Qx0NGjZPU+wx*?DfWfJ3T>*aq|7(mVb(=4mqVa*#zvP6edX zxU{W{g5LA%0Nlq^M^yM!dZxt-I%|wd?usNQt_{&ALt?);!B?evk%E+Bhq;&%y z447EM)0{IIQyClfh;1jxQ99-bdDUq6To_{{J9g{;DeNntqT1TO$zf;)iJ^y1>6DNd zS}7?(q@)Fr6loYjq(MNW8w3HRyAeTY6r@{e5k>O9=k~qtx7Noxti?Kq+54Ow&wkGS z#c-+%byx>|B-!HAki0vn*hO<(#66kepOFbyh92b)r`IPH!tKqalE^I51fm&|wQiJ^ zr=VbV5?H~HuNy06cxEuerC(3sxknZc)asmq30^f~LJ_KQV7^Yc##2G>4xq_M(`-3^ zmVA=CKI}w3`+_ZI<$=do5Wx?o>t*p)@so@Y#zMX};8c}7SUTE? z=p*B}?Hld%Xh-sJ-w&2zKr}p@$n4k49(T4v+p)+@tATuL2_gy)WL2-KefrR))cyxT zm=!Wt;2t6ZlhOj1k!V0#T^56bbEpV}qc1e#wC=Q??g+z_bm zeU;_g(=t6NmiV@zjSnknwNSXjF>mnf`JT~BHmFIZA?AC_GE{{ux|3Egtk;4JUfwMQ zAnw>B5(4&+(!Q5d`X_`dhm_d$NZt?{mpk*iKLZl2azcciPfX-|aPOP&$wJv^7oy3- z$LWSz@@wNV*IJ;Ox7(VU+3dm?Xf0Q&B&W#0{w6S4%9^qy<%D z%=!tJcp<&QZ7os3gMLvky-jy=k#0w=2F$x!Re(z1hA+x*xObd$^#fyhw=oPL;|3XI zRiEe_x@b-XHB0+W!}>7_F_e`CucHA?N8!MX!0m?=h#&ss?3O)JsQ#|Z!1d1tL}OEU zPQ;y8oJ2RE00@Rh{t*-0F3VgaZOoJ8=cE8aTC*AC#O1cIbVD_5yul}v+FWSFUHqkN z{SN5&LO8`>{hL)B3aoG62rP4>f`@NSjB5u9#aeW7+$UY3qDXNY; z&S0t-r%xKlEyJ|;h?%BqL;3bf7hFx|x_h~0dq&*Xwc)N&BcciU z2xeGemJD{Z8kh20^4oSI?!(hj^lG^j(K`F2Q&{JUy6TQ}!w|nG8&BLi$U+johC57Q zWs{6XH0co~CdP?zQ*tPb<&vk1rVyj-NGQ~ch?Gqv_j=Y^HYXRH1d z5XJkfA?fs@IE4BMsI@OSfJMSyG}D*>N`<9<_;xCEsAUKPX zmFRO(a5KIX6asN?e;WQd56sgD4KUA|i` zdlf5ZXteSyPmwo7R+0ZSU95uHtqe}~Rn3^8dg$!KT}x7%BN2eU(nG(a+%0c!%#N1{ zw^?CyueEeYtG%wi>-VK&7mjpNS8g+*^Ja%ilE$tYjL|4MB9=!hWNuD*bU%w4Lo`_=dN+(4dDUB<=72_lQ~UO&81(_t?@)l zD-Ia%~e2;tcUd%{=yn z46DWzmhtb{s=m23yoo@hWdt_fN&l81>Scbr??p;4df}*PiVvU*gg*1;^b%Gp^aMt*U7kgT<3m!kK6Cj3j8UR+2J3n{j8$$Ipt=Hh-!2hwLs zEV(0Im%NIs*~joghE3>9F$y!Bq`XvT>ZIc>rg`VJiUNbt8e!9PL|#|g)-!_Y1;u*Z z((@M++KN|~!nVzc>2A`Ip2C!ajiSKUnZ9mREdWvrJD&l&J z@6Ls$`MV|V!u>N*ny!8hr#mLqH)0~xKT(C|F9(+^=RVWhZBcl&2qP^W&ekm$ zn)MBu^PXcSSue}1Fu0(BsK@q=V^+aD$$oe4OaEvAA{>f1dG?SG zdB>Hi)W{hLVrt-hsReu+3W9O*c?Pj>ZGzQv5!6b?W9pxNJ{2#q$|;ObdWXH`{q4I* zsW#LIDqNG<_uYp&9}f%FcX%jql_JPSx3#`ET6Xx2&lDcjgDHvdL`6uXViy*b**vf9 z&e|96O*_CgQTjPKgLcPB`3-d!yGnHxyV!pct&O^WY3SmTv}~p1ca^&zfox{}obw4M zL^3x(27D2%>K7b7I zKCP^Eflgp!85j|{Hj=Aq6o%+U;!u$X{U+`@0ZN++qII?=a=8MDh=>yc11mKIhfp(> zyO~-MM}H8HXyLj|SXbHA8UWc`9eN!zO2$Qs2B`F14)(CPY@t1jx6ZrKTH&%dfaH9& zb}<*lQ3Q7)L6HcA{6Mq?z`hc5uK$%QZK1_dQ_|kbKQqYP0;b3E=&GszLeNMtcinT# zsBCPwWlaT;75?w0cAK_d9SO71MKH%l$(wOQk_%Q6X_gHehn~I;yi=x>`K4U=@#J03 z?0}O}9j6yhWw|=l{2wj{&7CYWpCZeJd>GX0uSJ~2*4q58jvA>WTck4GWm!t`J$9DG zAD!LkwlQ|_zF$)@T{k)`l(k z=_CMOT6~ENfIsJX%`6Ul^rf{7S5} z);t<&Iq0LyA7QuRp*FU_Yy@B=UAy)%$?hb;HM9&(918o|7XaFkU=&I_54IWumh}OQ z)j!tky|+o@GLAd|qI9J^JAuYka)l*kiYM*vpTBew3h

<0l=R@1?cn=T1v-gBO7 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 Date: Fri, 22 Sep 2023 20:45:14 -0600 Subject: [PATCH 3/4] Fixed links to repo files, updated config.ini --- README.md | 14 +++++++------- conf/config.ini | 12 ++++++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index cd6c760..04d2d8d 100644 --- a/README.md +++ b/README.md @@ -28,14 +28,14 @@ The sample notebooks are intended to be used in one of two ways: 1. As a tutorial for using AEP data in ML workflows - Ideally, use a dedicated AEP sandbox for completing the tutorial, to avoid mixing synthetic data with real customer data. You can reset or delete the sandbox after completing the tutorial to free it up for other use. - Clone or download this repository to create a copy in your ML environment. - - Follow the instructions in [Getting started with the CMLE notebooks](#getting-started-with-the-cmle-notebooks) to get an AEP API credential with the required permissions and update the [config.ini](../conf/config.ini) file with the required values. + - Follow the instructions in [Getting started with the CMLE notebooks](#getting-started-with-the-cmle-notebooks) to get an AEP API credential with the required permissions and update the [config.ini]() file with the required values. - Review and execute the cells in each notebook, in order to demonstrate and validate the workflow in your environment - Modify the code in the notebooks as needed to adapt to your environment 2. As a template for AEP-related ML projects for your organization - Fork the CMLE repository as a starting template for a new ML project - Alternatively, simply reference the code in these notebooks as helpful examples to start a new project from scratch -> **:warning: Warning** +> [!WARNING] > The workflow illustrated in these notebooks involves exporting datasets from AEP to a cloud storage destination, where it can be read and processed using external machine learnig tools. As such, there is some risk of sensitive personal data leaving the Experience Platform and being used inappropriately outside of the Platform. > > Experience Platform provides data governance tools for you to manage your data usage obligations and help minimize this risk. You are responsible ensuring that data in the Experience Platform is properly labeled before querying or exporting that data. This includes manually re-applying labels to derived datasets created from query output. Derived datasets from queries do not support the processing of sensitive personal data. You are responsible for understanding the limitations and obligations of your data and how you use that data in Experience Platform and the destination platform, which may have its own rules and obligations for incoming and outgoing data. Learn more about [data governance tools](https://experienceleague.adobe.com/docs/experience-platform/data-governance/home.html?lang=en) in Experience Platform. @@ -51,7 +51,7 @@ We have divided the typical steps of this end-to-end flow into a set of modular The sample notebooks included in this repository are briefly described below. Detailed documentation for each notebook is interspersed with the code in the notebooks themselves -### [Generate synthetic data](../notebooks/SyntheticData.ipynb) +### [Generate synthetic data]() This notebook provides code for generating datsets of synthetic profiles and experience events in your AEP that will be used to illustrate the CMLE workflow. @@ -111,11 +111,11 @@ By default, a Role (and API credentials assigned to that role) is blocked from a We recommend that any API credential used for CMLE workflows **NOT** have access to data labeled `C9` (No Data Science), `PSPD` (Permitted Sensitive Personal Data), or `RHD` (PHI/Regulated Health Data). AEP customers are responsible to manage label access and policies appropriately in order to comply with relevant regulations and organizational policies. -### Step 3: Update the [config.ini](../conf/config.ini) file with credential and environment information +### Step 3: Update the [config.ini]() file with credential and environment information -Once you have an API credential with the required permissions, you'll need to add the credntial and environment values to the [config.ini](../conf/config.ini) file. +Once you have an API credential with the required permissions, you'll need to add the credntial and environment values to the [config.ini]() file. -The [config.ini](../conf/config.ini) file should look like the following after copying the CMLE repository: +The [config.ini]() file should look like the following after copying the CMLE repository: ```ini [Platform] @@ -161,7 +161,7 @@ If you are using git with your copy of the CMLE directory, be sure to add the co ### Step 4: Configure `aepp` to authenticate with AEP APIs -To use the `aepp` package in your code you will need to read the [config.ini](../conf/config.ini) file using the standard `configparser` package and configure the connection to the AEP APIs. The following cell from the [Synthetic data generation](../notebooks/SyntheticData.ipynb) notebook provides an example: +To use the `aepp` package in your code you will need to read the [config.ini]() file using the standard `configparser` package and configure the connection to the AEP APIs. The following cell from the [Synthetic data generation](../notebooks/SyntheticData.ipynb) notebook provides an example: ```python import os diff --git a/conf/config.ini b/conf/config.ini index bf4cccb..e9fddb8 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -1,15 +1,19 @@ [Platform] ims_org_id= sandbox_name= -dataset_id= -featurized_dataset_id= -scoring_dataset_id= environment=prod +[Synthetic] +fieldgroup_id= +events_schema= +events_dataset= +profile_schema= +profile_dataset= + [Authentication] client_id= client_secret= -private_key_path= +scopes=openid, AdobeID, read_organizations, additional_info.projectedProductContext, session tech_acct_id= [Cloud] From 41ff70bb0c6a45cee4cda21990d866c2bc2874e1 Mon Sep 17 00:00:00 2001 From: Jeremy Page <116579445+jkpage00@users.noreply.github.com> Date: Tue, 3 Oct 2023 02:29:26 -0600 Subject: [PATCH 4/4] Update README.md Name change --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 04d2d8d..f3a2408 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Adobe Experience Platform - Cloud ML Ecosystem (CMLE) +# Adobe Experience Platform - ML Data Pipelines -This repository provides sample notebooks that demonstrate an end-to-end workflow for using customer data from the Adobe Experience Platform (AEP) with cloud-based machine learning tools. The notebooks serve as a template to help data science teams take advantage of their organization's AEP data and services within their modeling workflow to develop custom models to support their organization's marketing and experience activities. +This repository provides sample notebooks that demonstrate an end-to-end pipeline for using customer data from the Adobe Experience Platform (AEP) with external machine learning tools. The notebooks serve as a template to help data science teams take advantage of their organization's AEP data and services within their modeling workflow to develop custom models to support their organization's marketing and experience activities. README contents: - [Intended use](#intended-use) @@ -217,4 +217,4 @@ If your configuration is correct and you are able to successfully make calls to - [aepp](https://github.com/adobe/aepp/tree/main) - [Authenticate and access Experience Platform APIs](https://experienceleague.adobe.com/docs/experience-platform/landing/platform-apis/api-authentication.html) - [Adobe Experience Platform APIs](https://developer.adobe.com/experience-platform-apis/) -- [Query Service Guide](https://experienceleague.adobe.com/docs/experience-platform/query/home.html?lang=en) \ No newline at end of file +- [Query Service Guide](https://experienceleague.adobe.com/docs/experience-platform/query/home.html?lang=en)