Class ModelEvaluator

Object
ModelEvaluator

public class ModelEvaluator extends Object
A ModelEvaluator exposes a previously prepared/trained/calculated model to non-PO modules (Groovy logics). The idea is that the internals / implementation details of the model are shielded, and that only the behaviour intended to be exposed is accessible to the outside world.

Specifically, the evaluate(Map) method executes the model's logic in the evaluation calculation context. Depending on the ModelType definition, this could be a dedicated evaluation logic, or elements embedded in the model's main logic. In addition to evaluation, there is also a number of helper methods, which simplify getting objects related to (and usually generated by) a model.

Example: The standard Segmentation's evaluation logic determines the segment for a given set of (segmentation attribute, value) pairs, and returns the PolicyRecord for that segment, valid on a given date. The record contains the guidance and key metrics for that segment that an external application can translate to, for example, a target price for a product quoted to a customer. The evaluation logic is seen as implementation detail to the model. But the standard way of calling it, by means of a ModelEvaluator is not, as it represents the contract between the model (or ModelType more generally) and users (clients) of the model.


 def eval = api.modelEvaluator(modelUniqueName)
 def levels = eval.params["Segmentation Levels"]
 def input = levels.collectEntries{ api.stringUserEntry(it) }
 def record = eval.evaluate(input)
 return record
 
  • Field Details

  • Constructor Details

    • ModelEvaluator

      public ModelEvaluator(DMModel model, FormulaEngineContext context)
  • Method Details

    • evaluate

      public Map<String,Object> evaluate(Map<String,Object> inputs)
      Executes a model's evaluation logic, taking a map of input parameters. The expected inputs, as well as the returned result, are entirely dependent on the model, more specifically the ModelType of the model.
      Parameters:
      inputs - Map of input param (name,value) pairs
      Returns:
      Map containing one or two entries. One entry that is always there has the key "results". Its value is the evaluation logic's calculation results as a map of (element name, result) pairs. If there was any error evaluating the logic, the result map will also contain an entry with the key "errors", and as value the error messages (in ValidationVisitor format).
    • getTree

      public ModelFormulaContext.TreeNode getTree(String treeName)
      Retrieves the root node of the tree with the given name, if it exists (i.e. was created by the model).
      Parameters:
      treeName - Name of the tree, as specified in e.g. ModelFormulaContext.addTree(String, Collection)
      Returns:
      The root node of the tree
    • evaluateTree

      public String evaluateTree(ModelFormulaContext.TreeNode tree, Map<String,Object> input)
      Determines the node in a model tree that complies to the given input, starting from a given TreeNode. Usually the starting TreeNode is the root node of the tree, but this is not mandatory. Each node in the tree defines a Filter. When the filters of the starting node's children do not exclude the given input, the evaluation is passed on to their descendants, where again the input is tested against those nodes' filter criteria. When the traversal reaches a dead-end, the output of the last successfully matched node is returned. The tree is expected to be constructed in such a way that the result is unambivalent, but this is the responsibility of the model.

      Example: In the below tree, the root node has 2 children, one with the filter Filter.equal("Region", "EMEA") and one with Filter.equal("Region", "APAC"). The former has itself 1 child with the filter Filter.equal("Channel", "Retail"), the latter has 2 with filters Filter.equal("Channel", "Retail") and Filter.equal("Channel", "Industry"). When given an input [Region:"APAC", Channel:"Retail"], the root node's first child is rejected but the second child's filter is passed (Region == "APAC"). The evaluation is then passed to that node's first child, where it also passes (Channel == "Retail"), and given that this is a leave node, its output is returned up the call stack. Note that in the Segmentation model, a node's output is the name of the segment represented by that tree node (e.g. 'S000004').

       Segments
            |
               + EMEA
               |    |
               |    + Retail
               |
               + APAC
                    |
                        + Retail
                        |
                        + Industry
       

      Parameters:
      tree - The node from which to start the evaluation
      input - Map of input param (name,value) pairs
      Returns:
      The value of the output field of the last matched FilterNode
    • findRecords

      public List<Map<String,Object>> findRecords(Filter filter, String... sortBy)
      Parameters:
      filter - The criteria the records needs toad here to
      sortBy - Optional sort fields
      Returns:
      A list of map representations of the records, empty if none matched the criteria.
    • getParams

      public Map<String,Object> getParams()
      Returns:
      A map of param (name, value) pairs
    • getTable

      public DatamartContext.Table getTable(String name)
      Parameters:
      name -
      Returns:
      The Table object with the given tableName if it exists, or null if not.
    • pmmlEvaluator

      public ModelEvaluator.PMMLEvaluator pmmlEvaluator(String attachmentName)
      Returns an instance of ModelEvaluator.PMMLEvaluator that can safely be stored in api.global so that future usage can reuse the already loaded PMML in memory.

      This is useful when manipulating huge PMML that take too long to load on each request when using ModelFormulaContextImpl.evaluatePMML(String, Map) (within the evaluation formula).

      If the PMML file changes in the model, then the ModelEvaluator.PMMLEvaluator will automatically reload it.

      Sample code:

      
         // if this is changed, we are sure we won't use an incorrect previously loaded in api.global
         pmmlName = "xgbregressor_pipeline.pmml.gz"
         if (api.global.pmmlModel == null || api.global.pmmlName != pmmlName) {
           api.global.pmmlModel = model.pmmlEvaluator(pmmlName)
           api.global.pmmlName = pmmlName
         }
         def pmmlModel = api.global.pmmlModel
         // note: this won't go through the Model's eval logic but directly to the PMML!!
         pmmlModel.evaluate(inputs)
         // you can call it as much as you want if you need to batch process requests
         pmmlModel.evaluate(inputs)
       
      Parameters:
      attachmentName - the name of the attachment (in the model) of type pmml or pmml.gz
      Returns:
      a ModelEvaluator.PMMLEvaluator that can be safely stored in api.global.
      Since:
      7.6.0 - Bijou