Skip to Content
DocsUser GuidesVirtual Variables

Introduction

The Virtual Variable functionality allows you to make use of variables derived from values in the customer lookup configured in the deployment without having to hard code the derivation of those variables into the pre scoring logic. This can be used to test new segmentation approaches and model features without first having to add those features to the production customer feature store.

The configuration and usage of the Virtual Variables requires the following steps:

  1. Configure your Virtual Variables in the Deployment settings.
  2. Use your Virtual Variables in any deployment type (Dynamic Interaction contextual variables, model features, or plugin params). From 0.9.6.1, Virtual Variables are not limited to Dynamic Interaction.

Below we give more details on implementing each of these steps and how the Virtual Variables are used in the pre and post scoring logic.

🔥
Note

Prior to version 0.9.6.1 Virtual Variables are only supported for Dynamic Interaction configurations and cannot be configured in the ecosystem.properties file.

Configuring Virtual Variables

The first step in using Virtual Variables is to configure them in the deployment settings. To do this using the Workbench follow these steps:

  1. Enable Parameters from Data Source in the Deployment settings and configure a customer feature store in the accordion which appears.
  2. Select the Create Virtual Variables checkbox and click the Add Variable button.
  3. Configure the rules for creating your variable. This can either be done by bucketing a field in the customer feature store or by concatenating a number of fields in the customer feature store.
  4. Update the Deployment to save your changes. There should now be a virtual_variables object saved in the JSON settings of the Deployment.
"virtual_variables": [ { "name": "segment_one", "default": "gt-15", "type": "discretize", "original_variable": "customer_feature_one", "fields": [], "buckets": [ { "from": 0, "label": "lt-15", "to": 15 } ] }, { "name": "segment_two", "default": "gt-500", "type": "discretize", "original_variable": "customer_feature_two", "fields": [], "buckets": [ { "from": 0, "label": "lt-50", "to": 50 }, { "from": 50, "label": "50-250", "to": 250 }, { "from": 250, "label": "250-500", "to": 500 } ] } ]

Defining a virtual variable does not train by itself. The runtime derives the name into featuresObj after customer lookup (discretize: default once, first inclusive from/to match wins; concatenate: space-join, skip nulls). Training uses those labels only when you select the name as Contextual Variable One/Two and/or a Dynamic Recommender training field, and Generate Options applies the same rules so seeded options match score-time labels.

To use a virtual variable in Dynamic Engagement (Workbench2):

  1. Link the Dynamic Interaction to the Deployment (same prediction case / uuid).
  2. On the Variables tab, Contextual Variable One/Two dropdowns include feature-store keys plus virtual names from that linked deployment.
  3. Selecting a virtual name sets contextual_variable_*_lookup to that name, *_from_data_source to true, and prefills values from bucket labels plus default.
  4. Extra features for Naive Bayes and other factorised approaches belong in training fields, not a concatenated contextual slot. Do not list the same virtual name as both a contextual slot and a training field (double partition).

Score time still reads virtual_variables from predictor.param.lookup (Push from the deployment). A copy on the dynamic_engagement document is for inspectability; it is not a second engine.

The following truncated example shows how to set the virtual_variables object in the python package:

from prediction.apis import online_learning_management as ol from prediction.apis import deployment_management as dm from prediction.apis import ecosystem_generation_engine as ge #Configure virtual_variables virtual_variables = [] virt_var = dm.define_deployment_virtual_variable( name="segment_one" ,original_variable="customer_feature_one" ,default="gt-15" ,variable_type="discretize" ,buckets=[{"from": 0,"label": "lt-15","to": 15}] ) virtual_variables.append(virt_var) virt_var = dm.define_deployment_virtual_variable( name="segment_two" ,original_variable="customer_feature_two" ,default="gt-500" ,variable_type="discretize" ,buckets=[ {"from": 0,"label": "lt-50","to": 50}, {"from": 50,"label": "50-250","to": 250}, {"from": 250,"label": "250-500","to": 500} ] ) virtual_variables.append(virt_var) #Configure the Dynamic Interactions to use the Virtual Variable configuration online_learning_uuid = ol.create_online_learning( auth, name=deployment_id, description=dynamic_interaction_description, feature_store_collection=ol_feature_store_collection, feature_store_database=ol_feature_store_database, options_store_database=options_collection, options_store_collection=options_db, randomisation_success_reward = 0.5, randomisation_fail_reward = 0.05, randomisation_processing_count = 200, randomisation_processing_window = 604800000, contextual_variables_offer_key="offer" contextual_variables_contextual_variable_one_name="segment_one", contextual_variables_contextual_variable_one_from_data_source = True, contextual_variables_contextual_variable_one_lookup = "segment_one", contextual_variables_contextual_variable_two_name="segment_two", contextual_variables_contextual_variable_two_from_data_source = True, contextual_variables_contextual_variable_two_lookup = "segment_two", virtual_variables=virtual_variables, ) #Configure the deployment to use the Dynamic Interaction configuration new_knowledge = dm.define_deployment_multi_armed_bandit(epsilon=0, dynamic_interaction_uuid=online_learning_uuid) #Configure the lookup to the customer feature store parameter_access = dm.define_deployment_parameter_access( auth, lookup_key="customer_number", lookup_type="int", database="feature_store_database", table_collection="customer_feature_store", datasource="mongodb", virtual_variables=virtual_variables ) #Create a deployment using the configured virtual variables deployment_step = dm.create_deployment( auth, project_id=project_id, deployment_id=deployment_id, version=version, plugin_post_score_class="PlatformDynamicEngagement.java", plugin_pre_score_class="PreScoreDynamic.java", scoring_engine_path_dev=runtime_path, parameter_access=parameter_access, multi_armed_bandit=new_knowledge, setup_offer_matrix=offer_matrix, ) #Push the deployment and print the resulting properties file push_result = ge.process_push(auth,deployment_step) if "ErrorMessage" in push_result: print(push_result["ErrorMessage"]) else: print(push_result["properties"])

When you push your Deplyoment configuration to the runtime the properties file that is created will

predictor.param.lookup={predictor:'dynamic-recommender',mojo:1,database:'mongodb',db:'telecommunications',table:'feature_store',url:'',lookup:{"value":123,"key":"customer"},virtual_variables:[{"default":"gt-15","buckets":[{"from":0,"label":"lt-15","to":15}],"name":"segment_one","type":"discretize","original_variable":"customer_feature_one","fields":[]},{"default":"gt-500","buckets":[{"from":0,"label":"lt-50","to":50},{"from":50,"label":"50-250","to":250},{"from":250,"label":"250-500","to":500}],"name":"segment_two","type":"discretize","original_variable":"customer_feature_two","fields":[]}],result:{parm1:'field1', parm2:'field2'}}

Virtual Variables and pre and post scoring logic

Pre scoring logic

When virtual_variables are present on predictor.param.lookup, StageParamsDB derives them into featuresObj after customer lookup and before the pre-score plugin runs. PreScoreDynamic does not call getVirtualVariables. Post-score can fill contextual slots from featuresObj using contextual_variable_*_name (and *_lookup when set).

To use Virtual Variables for the contextual variables in a Dynamic Interaction configuration, the getDynamicSettings and getPrepopulateContextualVariables methods still need to be called in the pre scoring logic. The template is PreScoreDynamic below. getDynamicSettings adds the Dynamic Interaction configuration from ecosystem_meta.dynamic_engagement to params as dynamicCorporaPreScore. getPrepopulateContextualVariables copies derived values into params.in_params as contextual_variable_one / contextual_variable_two when *_lookup is set.

package com.ecosystem.plugin.customer; import com.datastax.oss.driver.api.core.CqlSession; import com.ecosystem.data.mongodb.MongoDBWorkerRead; import com.ecosystem.utils.GlobalSettings; import com.mongodb.client.MongoClient; import org.json.JSONObject; import java.io.IOException; /** * Add key/value to properties predictor.param.lookup to allow for contextual variable lookup: */ public class PreScoreDynamic extends PreScoreSuper { public PreScoreDynamic() throws Exception { } /** * Pre-pre predict */ public void getPrePredict() { } /** * getPostPredict * @param params * @param session * @return */ public static JSONObject getPrePredict(MongoClient mongoClient, JSONObject params, CqlSession session) throws IOException { if (lookupDatabase == null) return params; try { /* Dynamic Engagement settings. Virtual variables are already on featuresObj from lookup. */ params = getDynamicSettings(mongoClient, params); /* Populate contextual variables by default based on settings. */ params = getPrepopulateContextualVariables(params); } catch (Exception e) { LOGGER.error("PreScoreDynamic:E001:UUID: " + params.get("uuid") + " Dynamic parameters failed: " + params.toString()); e.printStackTrace(); } return params; } }
🔥
Note

Prior to version 0.9.4.3 getPrePredict is not passed the Mongo Connection (mongoClient). In this case you will need to open a close a Mongo connection in the pre scoring logic, as shown in the code below. Note that this will increase the load on the database. This legacy example also calls getVirtualVariables; current PreScoreDynamic does not — lookup derivation happens in StageParamsDB.

package com.ecosystem.plugin.customer; import com.datastax.oss.driver.api.core.CqlSession; import com.ecosystem.data.mongodb.ConnectionFactory; import com.mongodb.client.MongoClient; import org.json.JSONObject; import java.io.IOException; public class PreScoreDynamic extends PreScoreSuper { public ConnectionFactory settingsConnection; public MongoClient mongoClient; public PreScoreDynamic() throws Exception { } /** * Pre-pre predict */ public void getPrePredict() { } /** * getPostPredict * @param params * @param session * @return */ public JSONObject getPrePredict(JSONObject params, CqlSession session) throws IOException { if (lookupDatabase == null) return params; try { settingsConnection = new ConnectionFactory(); mongoClient = settingsConnection.getMongoClient(); /* Get dynamic properties and add virtual variables to the feature store. */ params = getDynamicSettings(mongoClient, params); mongoClient.close(); params = getVirtualVariables(params); /* Populate contextual variables by default based on settings. */ params = getPrepopulateContextualVariables(params); } catch (Exception e) { LOGGER.error("PreScoreDynamic:E001:UUID: " + params.get("uuid") + " Dynamic parameters failed: " + params.toString()); e.printStackTrace(); } return params; } }

Post scoring logic

No additional configuration is required in the post scoring logic to use the Virtual Variables. The values of the variables can be accessed from featuresObj like any other feature in the customer feature store and the contextual variable values should be populated as usual if they are required in the configuration.

Virtual Variable across multiple customer feature stores

When configuring multiple customer lookups you can configure Virtual Variables for each data source. These variables can be processed and used as described above.

Last updated on