Name

sn_nlu_workbench.NLUConflictExecution

Description

Utilities for NLU Conflict Report - Execution

Script

var NLUConflictExecution = Class.create();

(function() {
  var tables = NLUWorkbenchConstants.tables;
  var sysProps = NLUWorkbenchConstants.sysProps;
  var FIELDS = {
      DEFINITION: 'conflict_definition',
      SOLUTION: 'solution',
      MODELS_DATA: 'models_data',
      STATUS: 'status'
  };
  var processedMap = [];
  var REVIEWED_QUERY =
      'ignored=false^utterance_1.utteranceSAMEASoriginal_utterance_1^utterance_2.utteranceSAMEASoriginal_utterance_2';

  NLUConflictExecution.getLatestExecution = function(modelId) {
      var modelSnapshot = [];
      var gr = new GlideRecord(tables.NLU_CONFLICT_EXECUTION);
      gr.addQuery('conflict_definition.models', modelId);
      gr.addQuery('status', 'success');
      gr.orderByDesc('sys_created_on');
      gr.setLimit(1);
      gr.query();
      while (gr.next()) {
          var models = gr.conflict_definition.models.toString();
          if (models === modelId && NLUConflictExecution.isLatestExecution(modelId, gr))
              return gr;
      }
  };

  NLUConflictExecution.isLatestExecution = function(modelId, executionGr) {
      var modelStatus = global.NLUStudioService.getModelStatus(modelId);
      var lastTrainedTimestamp = !gs.nil(modelStatus) && !gs.nil(modelStatus.lastTrainedOn) ?
          new GlideDateTime(modelStatus.lastTrainedOn).getValue() : null;
      return executionGr.getValue('sys_created_on') >= lastTrainedTimestamp;
  };

  NLUConflictExecution.getConflictsCount = function(modelId, type) {
      var executionGr = NLUConflictExecution.getLatestExecution(modelId);
      if (!executionGr) throw new Error(gs.getMessage('NLU Conflict execution: No record exists for model {0)}', modelId));
      var executionId = executionGr.getUniqueValue();
      var intentsWithConflicts = [];
      var ga = new GlideAggregate(tables.NLU_CONFLICT_RESULT);
      ga.addAggregate('COUNT');
      ga.groupBy('intent_1');
      ga.groupBy('intent_2');
      var encodedQuery = 'conflict_execution=' + executionId + '^ignored=false^utterance_1.utteranceSAMEASoriginal_utterance_1^utterance_2.utteranceSAMEASoriginal_utterance_2';
      if (type) encodedQuery = encodedQuery + '^tag=' + type;
      ga.addEncodedQuery(encodedQuery);
      ga.query();
      while (ga.next()) {
          var intent1 = ga.getValue('intent_1').toString();
          var intent2 = ga.getValue('intent_2').toString();
          if (intentsWithConflicts.indexOf(intent1) === -1) intentsWithConflicts.push(intent1);
          if (intentsWithConflicts.indexOf(intent2) === -1) intentsWithConflicts.push(intent2);

      }
      return intentsWithConflicts.length;

  };

  NLUConflictExecution.getConflictsCountForIntent = function(intentId, type) {
      var intentGr = global.NLUIntent.getGRById(intentId);
      var modelId = intentGr.getValue('model');
      var executionGr = NLUConflictExecution.getLatestExecution(modelId);
      if (!executionGr) throw new Error(gs.getMessage('NLU Conflict execution: No record exists'));
      var executionId = executionGr.getUniqueValue();
      var count = 0;
      var ga = new GlideAggregate(tables.NLU_CONFLICT_RESULT);
      ga.addAggregate('COUNT');
      var encodedQuery = 'conflict_execution=' + executionId + '^ignored=false^utterance_1.utteranceSAMEASoriginal_utterance_1^utterance_2.utteranceSAMEASoriginal_utterance_2';
      if (type) encodedQuery = encodedQuery + '^tag=' + type;
      encodedQuery = encodedQuery + '^intent_1=' + intentId + '^ORintent_2=' + intentId;
      ga.addEncodedQuery(encodedQuery);
      ga.query();

      if (ga.next())
          count = ga.getAggregate('COUNT');
      return {
          count: count,
          executionId: executionId
      };
  };

  NLUConflictExecution.addRecord = function(defintionId, modelSnapshot) {
      var record = new GlideRecord(tables.NLU_CONFLICT_EXECUTION);
      record.initialize();
      record.setValue(FIELDS.DEFINITION, defintionId);
      record.setValue(FIELDS.MODELS_DATA, JSON.stringify(modelSnapshot));
      record.setValue(FIELDS.STATUS, 'inprogress');
      return record.insert();
  };

  NLUConflictExecution._getInputJson = function(modelName, intentName) {
      return {
          intents: [{
              intentName: intentName,
              modelName: modelName
          }],
          mode: 'FAST'
      };
  };

  NLUConflictExecution._getOptions = function() {
      var currDate = (new Date()).toJSON();
      var currDateString = currDate.split('T')[0];
      return {
          clientRequestTime: currDateString,
          warnThreshold: "0.7",
          highThreshold: gs.getProperty(sysProps.CONFLICT_THRESHOLD_MODERATE, "0.85"),
          criticalThreshold: gs.getProperty(sysProps.CONFLICT_THRESHOLD_CRITICAL, "0.9")
      };
  };

  NLUConflictExecution._getIntent = function(eachResp) {
      var intentGr = new GlideRecord(global.NLUConstants.tables.SYS_NLU_INTENT);
      var joinGr = intentGr.addJoinQuery(global.NLUConstants.tables.SYS_NLU_MODEL, 'model', 'sys_id');

      intentGr.addQuery('name', eachResp.intentName);
      joinGr.addCondition('name', eachResp.modelName);

      intentGr.query();

      if (intentGr.next()) {
          return intentGr.getUniqueValue();
      }
      return null;
  };

  NLUConflictExecution._alreadyProcessed = function(srcIntent, tgtIntent) {
      for (var i = 0; i < processedMap.length; i++) {
          var eachPair = processedMap[i];
          if (Object.keys(eachPair).indexOf(tgtIntent) !== -1) {
              if (eachPair[tgtIntent] === srcIntent) return true;
          }
          if (Object.keys(eachPair).indexOf(srcIntent) !== -1) {
              if (eachPair[srcIntent] === tgtIntent) return true;
          }
      }
      return false;
  };

  NLUConflictExecution.prototype = {

      initialize: function(executionId) {
          this.executionId = executionId;
      },

      getGR: function() {
          if (!gs.nil(this.gr)) return this.gr;
          this.gr = new GlideRecord(tables.NLU_CONFLICT_EXECUTION);
          return this.gr.get(this.executionId) && this.gr;
      },

      execute: function() {
          var allResponses = [];
          var conflictsCount = 0;
          var gr = this.getGR();

          try {

              var solutionInfo = this._getSolutionInfo();
              if (gs.nil(solutionInfo)) throw new Error(gs.getMessage('Unable to get model solution details'));

              solutionInfo.forEach(function(eachSolution) {
                  var modelIntents = NLUMLSolutionUtil.getIntents(
                      eachSolution.solutionVersion, eachSolution.modelId);

                  var modelName = modelIntents.model;
                  var intents = modelIntents.intents;

                  // filter out intents with no utterances
                  intents = intents.filter(function(intent) {
                      var intentId = NLUConflictExecution._getIntent({
                          intentName: intent,
                          modelName: modelName
                      });
                      if (intentId) {
                          var uttrCount = new GlideAggregate(global.NLUConstants.tables.SYS_NLU_UTTERANCE);
                          uttrCount.addQuery('intent', intentId);
                          uttrCount.addAggregate('COUNT');
                          uttrCount.query();
                          if (uttrCount.next()) {
                              if (uttrCount.getAggregate('COUNT') > 0) {
                                  return true;
                              }
                          }
                      }
                      return false;
                  });

                  for (var i = 0; i < intents.length; i++) {
                      var inputJson = NLUConflictExecution._getInputJson(modelName, intents[i]);
                      if (gs.nil(inputJson)) throw new Error(gs.getMessage('Unable to get modelname, intentname details'));

                      var result = sn_ml.MLServiceUtil.detectConflicts(
                          JSON.stringify(solutionInfo), JSON.stringify(inputJson), NLUConflictExecution._getOptions());
                      if (!gs.nil(result)) result = JSON.parse(result);
                      if (gs.nil(result) || result.status !== 'success') {
                          gs.debug('NLU Conflict execution: ' + this.executionId + ' response: ' + JSON.stringify(result));
                          throw new Error(gs.getMessage('Failed to detect conflicts'));
                      }
                      allResponses.push(result.response);
                  }
              });

              gr.setValue(FIELDS.STATUS, 'processing_results');
              gr.update();

              var resultsProcessor = new NLUConflictResultProcessor(this.executionId);

              allResponses.forEach(function(eachResp) {
                  var sourceIntent = NLUConflictExecution._getIntent(eachResp);
                  if (!gs.nil(sourceIntent)) {
                      var conflicts = eachResp.conflicts;
                      conflicts && conflicts.forEach(function(eachConflict) {
                          var targetIntent = NLUConflictExecution._getIntent(eachConflict);
                          if (!gs.nil(targetIntent)) {
                              if (!NLUConflictExecution._alreadyProcessed(sourceIntent, targetIntent)) {
                                  var conflictingUtterances = eachConflict.conflictingUtterances;
                                  conflictingUtterances && conflictingUtterances.forEach(function(eachUtterance) {
                                      if (!gs.nil(resultsProcessor.add(eachUtterance, sourceIntent, targetIntent)))
                                          conflictsCount++;
                                  });

                                  var newPair = {};
                                  newPair[sourceIntent] = targetIntent;
                                  processedMap.push(newPair);
                              }
                          }
                      });
                  }
              });

              gr.setValue(FIELDS.STATUS, 'success');
              gr.update();
          } catch (e) {
              gr.setValue(FIELDS.STATUS, 'failed');
              gr.update();
              this._errorResult(e.message);
          }
      },

      getConflictPairs: function(intentPair, filters, scope) {
          if (!this.executionId)
              throw new Exception(gs.getMessage('Execution ID is empty'));
          var intent1, intent2;
          if (Array.isArray(intentPair) && intentPair.length > 0) {
              intent1 = intentPair[0];
              if (intentPair.length > 1)
                  intent2 = intentPair[1];
          }
          var baseQuery = 'conflict_execution.sys_id=' + this.executionId;
          baseQuery += (filters && filters.showModerate) ? '^tagINcritical,high' : '^tagINcritical';
          if (filters && filters.hideReviewed)
              baseQuery += '^' + REVIEWED_QUERY;
          var query = baseQuery;
          if (intent1 && intent2) {
              var intentQuery1 = 'intent_1.sys_id=' + intent1 + '^intent_2.sys_id=' + intent2;
              var intentQuery2 = 'intent_1.sys_id=' + intent2 + '^intent_2.sys_id=' + intent1;
              query += '^' + intentQuery1 + '^NQ' + baseQuery + '^' + intentQuery2;
          } else if (intent1) {
              query += '^intent_1.sys_id=' + intent1 + '^NQ' + baseQuery + '^' + 'intent_2.sys_id=' + intent1;
          }
          return NLUConflictResult.getResults(query, scope);
      },

      _getSolutionInfo: function() {
          var modelSnapshot = JSON.parse(this.getGR().getValue(FIELDS.MODELS_DATA));
          if (!Array.isArray(modelSnapshot))
              throw new Error(gs.getMessage('Model list is empty'));

          var solutionInfo = [];
          modelSnapshot.forEach(function(eachModel) {
              solutionInfo.push({
                  solutionName: eachModel.name,
                  modelId: eachModel.id,
                  solutionVersion: eachModel.trained_version
              });
          });
          return solutionInfo;
      },

      _errorResult: function(message) {
          gs.error('NLU Conflict Analysis Execution: ' + this.executionId + ' > Error: ' + message);
          return {
              status: 'failure',
              message: message
          };
      },

      type: 'NLUConflictExecution'
  };
})();

Sys ID

b092f3170760201028ef0a701ad3000b

Offical Documentation

Official Docs: