Name

global.NLULookupTrainer

Description

Methods for training static and table lookups

Script

var NLULookupTrainer = Class.create();
(function() {

  var tables = NLUConstants.tables;
  var vocabTypes = NLUConstants.VOCAB_TYPES;

  NLULookupTrainer.maxTrainsRunning = function() {
      var ongoing = 0;
      var gr = new GlideRecord('sys_nlu_vocabulary');
      gr.addEncodedQuery('type=lookup^solution_nameISNOTEMPTY');
      gr.query();
      while (gr.next()) {
          var lookupStatus = new NLULookup(gr.getUniqueValue()).getStatus();
          var latestSolution = lookupStatus.latestSolution;
          if (latestSolution && latestSolution.state === 'training') {
              ongoing++;
              if (ongoing >= NLUConstants.MAXIMUM_SYNC) return true;
          }
      }
      return false;
  };

  NLULookupTrainer.prototype = {
      initialize: function(lookupId, lookupGR) {
          this.lookupId = lookupId;
          this.lookupGR = lookupGR;
          if (lookupGR) this.lookupId = lookupGR.getUniqueValue();
      },

      getLookupGR: function() {
          if (!this.lookupGR) this.lookupGR = new NLULookup(this.lookupId).getGR();
          if (!this.lookupGR)
              throw new Error(gs.getMessage('Lookup Id does not exist'));
          return this.lookupGR;
      },

      trainLookup: function(options) {
          if (NLULookupTrainer.maxTrainsRunning()) {
              return {
                  status: 'failure',
                  message: gs.getMessage('Maximum number of syncs are already in progress, please try after sometime')
              };
          }
          var result = {};
          try {
              this.getLookupGR();
              this._vaidateLookupType();
              this._checkMaxRecords();
              var nluLookupIntegrator = new NLULookupIntegrator(this.lookupGR);
              var trainJson = this._getLookupTrainJson(nluLookupIntegrator);
              var trainOptions = this._getLookupTrainOptions();
              result = nluLookupIntegrator.train(trainJson, trainOptions, options);

          } catch (e) {
              result.status = 'failure';
              result.message = e.message;
          }
          return result;
      },

      cancelLookupTraining: function() {
          var result = {};
          try {
              this.getLookupGR();
              this._vaidateLookupType();
              result = new NLULookupIntegrator(this.lookupGR).cancelTraining();
          } catch (e) {
              result.status = 'failure';
              result.message = e.message;
          }
          return result;
      },

      _vaidateLookupType: function() {
          var lookupType = this.lookupGR.getValue('type');
          if (!(lookupType === vocabTypes.lookup || lookupType === vocabTypes.static_lookup)) {
              gs.debug("Operation supported only for Lookup Type vocabulary");
              throw new Error(gs.getMessage("Operation supported only for Lookup Type vocabulary"));
          }
      },

      _checkMaxRecords: function() {
          if (this.lookupGR && this.lookupGR.getValue('type') === vocabTypes.lookup) {
              var tableName = this.lookupGR.getValue('table');
              if (tableName) {
                  var query = this.lookupGR.getValue('filter_condition');
                  var ga = new GlideAggregate(tableName);
                  if (query) ga.addEncodedQuery(query);
                  ga.addAggregate('COUNT');
                  ga.query();
                  var count = ga.next() && ga.getAggregate('COUNT');
                  var maxLookupRecordCount = gs.getProperty('glide.platform_ml.api.max_nlu_lookupsource_records', 100000);
                  if (count > parseInt(maxLookupRecordCount)) {
                      throw new Error(gs.getMessage("Tables with more than {0} records can't be synced. Please use the filters to define a subset of your table.", maxLookupRecordCount));
                  }
              }
          }
      },

      _getLookupTrainOptions: function() {
          var trainOptions = {};
          var vocabularyJson = JSON.parse(this.lookupGR.getValue('vocabulary_json'));
          if (vocabularyJson && vocabularyJson.options) {
              if (!gs.nil(vocabularyJson.options.sync_frequency))
                  trainOptions.trainingFrequency = vocabularyJson.options.sync_frequency;
          }
          return trainOptions;
      },

      _addTableLookupProperties: function(trainJson, vocabularyJson) {
          var sources = trainJson.sources[0];
          var encodedQuery = this.lookupGR.getValue('filter_condition');
          if (vocabularyJson && vocabularyJson.fields && vocabularyJson.options) {

              sources.encodedQuery = gs.nil(encodedQuery) ? '' : encodedQuery;
              sources.tableName = this.lookupGR.getValue('table');
              var fieldNames = [];
              sources.matcherTarget = {
                  'composition': {
                      fieldNames: [],
                      strategy: vocabularyJson.options.lookup_fields_appear_together ? "ONE_TO_ONE_LTR" : "APPEND_AS_LIST",
                      'case-insensitive': vocabularyJson.options.case_sensitive ? false : true
                  }
              };
              vocabularyJson.fields.forEach(function(field) {
                  var fieldObject = {
                      name: field.name,
                      attributes: {
                          'multi-value': field.multiple_values
                      }
                  };
                  fieldNames.push(fieldObject);
                  if (field.enable_lookup)
                      sources.matcherTarget.composition.fieldNames.push(field.name);
              });

              sources.fieldNames = fieldNames;
          }
      },

      _addStaticLookupProperties: function(trainJson, vocabularyJson) {
          var sources = trainJson.sources[0];
          if (vocabularyJson && vocabularyJson.values && vocabularyJson.options) {

              sources.tableName = this.lookupGR.getValue('name');
              sources.matcherTarget = {
                  composition: {
                      fieldNames: ['item_name', 'keywords'],
                      strategy: "APPEND_AS_LIST",
                      'case-insensitive': vocabularyJson.options.case_sensitive ? false : true
                  }
              };
              var itemNames = [];
              var keywords = [];
              vocabularyJson.values.forEach(function(value) {
                  itemNames.push(value.actual);
                  keywords.push(gs.nil(value.synonyms) ? null : value.synonyms);
              });

              sources.fieldNames = [{
                      name: 'item_name',
                      values: itemNames
                  },
                  {
                      name: 'keywords',
                      values: keywords,
                      attributes: {
                          'multi-value': true
                      }
                  }
              ];

          }
      },

      _getLookupTrainJson: function(nluLookupIntegrator) {
          var handleName = this.lookupGR.getValue('name');
          var lookupType = this.lookupGR.getValue('type');
          var relatedTerms = this.lookupGR.getValue('related_terms');
          var relatedTermsList = gs.nil(relatedTerms) ? [] : relatedTerms.split(',');
          var vocabularyJson = JSON.parse(this.lookupGR.getValue('vocabulary_json'));
          if (vocabularyJson && vocabularyJson.options) {
              var matcherTemplateValue;
              if (vocabularyJson.options.hasOwnProperty('matcherTemplate') && !gs.nil(vocabularyJson.options.matcherTemplate))
                  matcherTemplateValue = vocabularyJson.options.matcherTemplate;
              else
                  matcherTemplateValue = vocabularyJson.options.enable_fuzzy_matching ? 'DEFAULT_VA' : 'EXACT_MATCH';
              var trainJson = {
                  name: handleName,
                  schemaVersion: "LS-1",
                  language: vocabularyJson.options.language,
                  relatedTerms: relatedTermsList,
                  version: nluLookupIntegrator.getModelVersion(vocabularyJson.options.language),
                  sources: [{
                      name: handleName,
                      type: lookupType === vocabTypes.lookup ? 'glide-table' : 'json-table',
                      relatedTerms: relatedTermsList,
                      matcherTemplate: matcherTemplateValue
                  }]
              };
              if (lookupType === vocabTypes.lookup)
                  this._addTableLookupProperties(trainJson, vocabularyJson);
              else
                  this._addStaticLookupProperties(trainJson, vocabularyJson);

              return trainJson;
          } else {
              throw new Error(gs.getMessage('Invalid vocabulary JSON'));
          }

      },
      type: 'NLULookupTrainer'
  };

})();

Sys ID

2637ad73730310103bb6a4fa54f6a70f

Offical Documentation

Official Docs: