Docs
Runtime & Deployment
Plugins: Post-Predict
Post-Score Basic

Post-Score Basic Plugin

The Post Score Basic plugin is used to format the output of the predictor before it is returned to the client. This plugin is responsible for converting the predictor’s output into a format that can be easily consumed by the client. The Post Score Basic plugin is a default post-predict plugin that is available in the ecosystem.Ai platform.

How does it work?

The Post Score Basic plugin takes the output of the predictor and formats it into a JSON object. The JSON object contains the predictor’s output along with any additional metadata that is required by the client. The Post Score Basic plugin is a simple plugin that is designed to be used in conjunction with other post-predict plugins to customize the output of the predictor.

Java Code

This Java code belongs to a custom plugin extending the abilities of a runtime engine for ‘post-scoring’ tasks in a predictive modelling environment. The package path suggests that it could be a part of an ecosystem or AI subsystem.

The class PostScoreBasic extends a PostScoreSuper class, which likely provides basic functionality for all subclasses and this subclass extends or customizes that behavior. The structure and comments of this class suggest that it provides additional logic after a predictive model has made its predictions (i.e., “post-scoring”).

The getPostPredict() method accepts a JSONObject with prediction results, parameters for the scoring operation, a session object for a Cassandra database, and an array of preloaded models. The method then processes the results and prediction parameters, including extracting features, evaluating offer eligibility and constructing an array of modified offer scores.

It does some checking and manipulation of the input data, (e.g. a whitelist for offers, a preload corpora), different scoring of offers based on different model types (clustering, anomaly detection, regression, etc.) and inserts additional information into a JSONObject.

After processing, the results are sorted based on score and the top scores are retrieved. There is also a time tracking operation which logs the time taken to execute the method.

The code is designed to handle various types of predictive models and use their predictions in a post-processing stage to create ranked lists of offers to return as a final result.

Apart from the processing method, an empty constructor and an empty getPostPredict method (presumably meant to be overwritten) has been declared. A Logger object has been initialized for logging purposes.

The following is an example of the Post Score Basic plugin implemented in Java:

package com.ecosystem.plugin.customer;
 
import com.datastax.oss.driver.api.core.CqlSession;
import com.ecosystem.utils.DataTypeConversions;
import com.ecosystem.utils.JSONArraySort;
import hex.genmodel.easy.EasyPredictModelWrapper;
import com.ecosystem.utils.log.LogManager;
import com.ecosystem.utils.log.Logger;
import org.json.JSONArray;
import org.json.JSONObject;
 
import java.util.ArrayList;
 
import static com.ecosystem.EcosystemResponse.obtainBudget;
 
/**
 * This the ecosystem/Ai generic post-score template.
 * Customer plugin for specialized logic to be added to the runtime engine.
 * This class is loaded through the plugin loader system.
 */
public class PostScoreBasic extends PostScoreSuper {
	private static final Logger LOGGER = LogManager.getLogger(PostScoreBasic.class.getName());
 
	public PostScoreBasic() {
	}
 
	/**
	 * Pre-post predict logic
	 */
	public void getPostPredict () {
	}
 
	/**
	 * getPostPredict
	 *
	 * @param predictModelMojoResult Result from scoring
	 * @param params                 Params carried from input
	 * @param session                Session variable for Cassandra
	 * @param models 				 Preloaded H2O Models
	 * @return JSONObject result to further post-scoring logic
	 */
	public static JSONObject getPostPredict(JSONObject predictModelMojoResult, JSONObject params, CqlSession session, EasyPredictModelWrapper[] models) {
		double startTimePost = System.nanoTime();
		try {
			/* Setup JSON objects for specific prediction case */
			JSONObject featuresObj = predictModelMojoResult.getJSONObject("featuresObj");
			JSONObject domainsProbabilityObj = new JSONObject();
			if (predictModelMojoResult.has("domainsProbabilityObj"))
				domainsProbabilityObj = predictModelMojoResult.getJSONObject("domainsProbabilityObj");
 
			/* If whitelist settings then only allow offers on list */
			boolean whitelist = false;
			ArrayList<String> offerWhiteList = new ArrayList<>();
			if (params.has("whitelist")) {
				if (!params.getJSONObject("whitelist").isEmpty()) {
					offerWhiteList = (ArrayList<String>) params.getJSONObject("whitelist").get("whitelist");
					params.put("resultcount", offerWhiteList.size());
					whitelist = DataTypeConversions.getBooleanFromString(params.getJSONObject("whitelist").get("logicin"));
				}
			}
 
			if (params.has("preloadCorpora")) {
				if (params.getJSONObject("preloadCorpora").has("network")) {
					JSONObject a = params.getJSONObject("preloadCorpora");
					JSONObject preloadCorpora = a.getJSONObject("network");
				}
			}
 
			JSONArray finalOffers = new JSONArray();
			int resultcount = (int) params.get("resultcount");
			/* For each offer in offer matrix determine eligibility */
			/* get selector field from properties: predictor.selector.setup */
			// String s = new JSONObject(settings.getSelectorSetup()).getJSONObject("lookup").getString("fields");
 
			/** This loop can be used to add number of offers/options to return result */
			JSONObject finalOffersObject = new JSONObject();
			int offerIndex = 0;
			for (int i = 0; i < resultcount; i++) {
 
				/** Model type based approaches */
				String type = "";
				boolean explainability = false;
				// LOGGER.info("predictModelMojoResult: " + predictModelMojoResult.toString());
				if (predictModelMojoResult.get("type").getClass().getName().toLowerCase().contains("array")) {
					type = predictModelMojoResult
							.getJSONArray("type")
							.get(0)
							.toString().toLowerCase().trim();
					if (predictModelMojoResult.has("shapley_contributions"))
						explainability = true;
				} else {
					type = ((String) predictModelMojoResult.get("type")).toLowerCase().trim();
				}
 
				/** Offer name, defaults to type (replace with offer matrix etc) */
				if (featuresObj.has("offer_name_final"))
					finalOffersObject.put("offer_name", featuresObj.get("offer_name_final"));
				else
					finalOffersObject.put("offer_name", type);
 
				if (featuresObj.has("offer"))
					finalOffersObject.put("offer", featuresObj.get("offer"));
				else
					finalOffersObject.put("offer", type);
 
				if (featuresObj.has("offer_id"))
					finalOffersObject.put("offer", featuresObj.get("offer_id"));
				else
					finalOffersObject.put("offer_id", type);
 
				if (featuresObj.has("price"))
					finalOffersObject.put("price", featuresObj.get("price"));
				else
					finalOffersObject.put("price", 1.0);
 
				if (featuresObj.has("cost"))
					finalOffersObject.put("cost", featuresObj.get("cost"));
				else
					finalOffersObject.put("cost", 1.0);
 
				/** Score based on model type */
				if (type.contains("clustering")) {
					finalOffersObject.put("cluster", predictModelMojoResult.getJSONArray("cluster").get(0));
					finalOffersObject.put("score", DataTypeConversions.getDouble(domainsProbabilityObj, "score"));
					finalOffersObject.put("modified_offer_score", DataTypeConversions.getDouble(domainsProbabilityObj, "score"));
				} else if (type.contains("anomalydetection")) {
					double[] score = (double[]) domainsProbabilityObj.get("score");
					finalOffersObject.put("score", score[0]);
					finalOffersObject.put("modified_offer_score", score[0]);
				} else if (type.contains("regression")) {
					Object score = predictModelMojoResult.getJSONArray("value").get(0);
					finalOffersObject.put("score", score);
					finalOffersObject.put("modified_offer_score", score);
				} else if (type.contains("multinomial")) {
					Object probability = predictModelMojoResult.getJSONArray("probability").get(0);
					Object label = null;
					try {
						label = predictModelMojoResult.getJSONArray("label").get(0);
					} catch (Exception e) {
						LOGGER.error("PostScoreBasic:getPostPredict:E001: Error relates to scoring your model. The model wasn't loaded or is not accessible.");
						e.printStackTrace();
					}
					Object response = predictModelMojoResult.getJSONArray("response").get(0);
					finalOffersObject.put("score", probability);
					finalOffersObject.put("modified_offer_score", probability);
					finalOffersObject.put("offer", label);
					finalOffersObject.put("offer_name", response);
				} else if (type.contains("coxph")) {
					Object score = predictModelMojoResult.getJSONArray("value").get(0);
					finalOffersObject.put("score", score);
					finalOffersObject.put("modified_offer_score", score);
				} else if (type.contains("wordembedding")) {
					float[] score = (float[]) predictModelMojoResult.getJSONArray("_text_word2vec").get(0);
					finalOffersObject.put("score", Double.valueOf(String.valueOf(score[0])));
					finalOffersObject.put("embedding", score);
					finalOffersObject.put("modified_offer_score", 0.0);
				} else if (type.contains("deeplearning")) {
					/** From TensorFlow or PyTorch */
					Object score = domainsProbabilityObj.getDouble("1");
					finalOffersObject.put("score", score);
					finalOffersObject.put("modified_offer_score", score);
					Object response = predictModelMojoResult.getJSONArray("response").get(0);
					finalOffersObject.put("offer_name", response);
				} else if (type.contains("empty score")) {
					/** This is typically used for data lookup only, obtain values from feature store! */
					if (featuresObj.has("offer_name"))
						finalOffersObject.put("offer_name", featuresObj.get("offer_name"));
 
					if (featuresObj.has("offer"))
						finalOffersObject.put("offer", featuresObj.get("offer"));
 
					if (featuresObj.has("score"))
						finalOffersObject.put("score", Double.valueOf(String.valueOf(featuresObj.get("score"))));
					else
						finalOffersObject.put("score", 1.0);
 
					if (featuresObj.has("modified_offer_score"))
						finalOffersObject.put("modified_offer_score", Double.valueOf(String.valueOf(featuresObj.get("modified_offer_score"))));
					else
						finalOffersObject.put("modified_offer_score", 1.0);
 
					if (featuresObj.has("cost"))
						finalOffersObject.put("cost", Double.valueOf(String.valueOf(featuresObj.get("cost"))));
					else
						finalOffersObject.put("cost", 0.0);
 
				} else {
					finalOffersObject.put("score", 1.0);
					finalOffersObject.put("modified_offer_score", 1.0);
				}
 
				finalOffersObject.put("offer_details", domainsProbabilityObj);
				if (explainability) {
					finalOffersObject.put("shapley_contributions", predictModelMojoResult.get("shapley_contributions"));
					finalOffersObject.put("shapley_contributions_names", predictModelMojoResult.get("shapley_contributions_names"));
				}
 
				/** Default value, could be replaced by offer matrix or feature store */
				double offer_value = 1.0;
				finalOffersObject.put("offer_value", offer_value);
				finalOffersObject.put("uuid", params.get("uuid"));
 
				/** Add other structures to the final result */
				finalOffersObject.put("offer_matrix", featuresObj);
 
				/** Budget processing option, if it's set in the properties */
				if (settings.getPredictorOfferBudget() != null) {
					JSONObject budgetItem = obtainBudget(featuresObj, params.getJSONObject("featuresObj"), offer_value);
					double budgetSpendLimit = budgetItem.getDouble("spend_limit");
					finalOffersObject.put("spend_limit", budgetSpendLimit);
				}
 
				/** Prepare offer array before final sorting */
				finalOffers.put(offerIndex, finalOffersObject);
				offerIndex = offerIndex + 1;
			}
 
			/** Sort final offer list based on score */
			JSONArray sortJsonArray = JSONArraySort.sortArray(finalOffers, "score", "double", "d");
			predictModelMojoResult.put("final_result", sortJsonArray);
 
		} catch (Exception e) {
			LOGGER.error(e);
		}
 
		/** Get top scores and test for explore/exploit randomization */
		predictModelMojoResult = getTopScores(params, predictModelMojoResult);
 
		double endTimePost = System.nanoTime();
		LOGGER.info("getPostPredict:I001: execution time in ms: ".concat( String.valueOf((endTimePost - startTimePost) / 1000000) ));
		return predictModelMojoResult;
	}
 
}
 

Python

Coming Soon

C#

Coming Soon