Name
global.ActiveLearningIntegrator
Description
Interface for Active learning solution
Script
var ActiveLearningIntegrator = Class.create();
(function() {
var tables = {
CS_TOPIC: 'sys_cs_topic_language',
NLU_MODEL: 'sys_nlu_model',
VA_CHAT_LOGS: "open_nlu_predict_intent_feedback",
ML_LABEL_CANDIDATE: "ml_label_candidate",
ML_LABELED_DATA: "ml_labeled_data",
SYS_PROPERTIES: "sys_properties",
ML_SOLUTION: "ml_solution"
};
var defaults = {
IS_ENABLED: "false",
MAX_MODELS: 20,
MAX_VA_CHAT_LOGS_RECORDS: 3000
};
var sysProperties = {
IS_ENABLED: "glide.mlpredictor.option.nlu.activeLearning.isEnabled",
MAX_MODELS_LIMIT: "glide.mlpredictor.option.nlu.activeLearning.max_models_limit",
MIN_VA_CHAT_LOGS_RECORDS: "glide.mlpredictor.option.nlu.activeLearning.va_chat_logs.min_row_limit",
MAX_VA_CHAT_LOGS_RECORDS: "glide.mlpredictor.option.nlu.activeLearning.va_chat_logs.max_row_limit",
VA_CHAT_LOGS_FILTERING_ON: "glide.mlpredictor.option.nlu.activeLearning.va_chat_logs.filtering_on",
MAX_LABEL_DATA_RECORDS: "glide.mlpredictor.option.nlu.activeLearning.label_table.max_data_size",
MAX_LABEL_CANDIDATE_DATA_RECORDS: "glide.mlpredictor.option.nlu.activeLearning.label_candidate_table.max_data_size",
MAX_LABEL_CANDIDATE_DATA_RECORDS_IN_RESPONSE: "glide.mlpredictor.option.nlu.activeLearning.label_candidate_table.max_response_size"
};
ActiveLearningIntegrator.prototype = {
initialize: function() {
},
train: function() {
try {
var isActiveLearningEnabled = this._getSysProperty(sysProperties.IS_ENABLED) || defaults.IS_ENABLED;
if (isActiveLearningEnabled == "false") {
gs.debug('Active learning scheduled job is not enabled');
return null;
}
var models = this._getModels();
if (!String.prototype.format) {
String.prototype.format = function() {
var args = arguments;
return this.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined' ?
args[number] :
match;
});
};
}
var vaChatLogsQuery = "";
var vaChatLogsTimeQuery = "";
var vaChatLogsModelQuery = "model IN ".concat(models.toString());
var lastScheduledJobCreatedOn = this._getlastScheduledJobCreatedOn();
var nluProviderId = NLUMappingsUtil.getSNNLUProvider();
if (lastScheduledJobCreatedOn != null) {
vaChatLogsTimeQuery = "sys_created_on>={0}".format(lastScheduledJobCreatedOn);
vaChatLogsQuery = vaChatLogsTimeQuery.concat("^".concat(vaChatLogsModelQuery));
vaChatLogsQuery += "^OR".concat(vaChatLogsTimeQuery);
vaChatLogsQuery = vaChatLogsQuery.concat("^modelISEMPTY^nlu_provider.sys_id=".concat(nluProviderId));
} else {
vaChatLogsQuery = vaChatLogsModelQuery;
vaChatLogsQuery = vaChatLogsQuery.concat("^ORmodelISEMPTY^nlu_provider.sys_id=".concat(nluProviderId));
}
var vaChatLogsCount = this._getVaChatLogsCount(models, vaChatLogsQuery);
//validations
if (models.length == 0 || vaChatLogsCount < parseInt(this._getSysProperty(sysProperties.MIN_VA_CHAT_LOGS_RECORDS))) {
gs.debug('Active learning scheduled job is cancelled due to less data');
return null;
}
var modelIds = this._getModelUniqueIds(models);
var authoringModels = this._getAuthoringModels(modelIds);
var solutionInfo = {
"label": "active_learning",
"nluTrainingMode": "ActiveLearning"
};
//Defining datasets
var VAChatLogsData = new sn_ml.DatasetDefinition({
'tableName': tables.VA_CHAT_LOGS,
'fieldNames': ['utterance', 'prediction', 'confidence', 'model', 'sys_created_on'],
'encodedQuery': vaChatLogsQuery
});
var lableCandidateData = new sn_ml.DatasetDefinition({
'tableName': tables.ML_LABEL_CANDIDATE,
'fieldNames': ['frequency', 'text', 'suggested_label', 'sys_id', 'product', 'source', 'last_received_time', 'recommendation']
});
var utteranceLabelData = new sn_ml.DatasetDefinition({
'tableName': tables.ML_LABELED_DATA,
'fieldNames': ['frequency', 'label', 'label_reference', 'label_table', 'label_type', 'product', 'source', 'text', 'usage', 'recommendation']
});
var datasets = {
"va_chat_logs": VAChatLogsData,
"labelling_candidates_table": lableCandidateData,
"utterance_label_table": utteranceLabelData
};
//Defining pipeline input
var pipelineInput = {
"datasets": datasets,
"config": {
"authoring_models_list": authoringModels,
"max_label_data_records": parseInt(this._getSysProperty(sysProperties.MAX_LABEL_DATA_RECORDS)),
"max_label_candidate_data_records": parseInt(this._getSysProperty(sysProperties.MAX_LABEL_CANDIDATE_DATA_RECORDS)),
"max_label_candidate_data_records_in_response": parseInt(this._getSysProperty(sysProperties.MAX_LABEL_CANDIDATE_DATA_RECORDS_IN_RESPONSE)),
"va_chat_logs_rows_limit": parseInt(this._getSysProperty(sysProperties.MAX_VA_CHAT_LOGS_RECORDS)),
"filtering_on": (this._getSysProperty(sysProperties.VA_CHAT_LOGS_FILTERING_ON) == "true")
}
};
//Attaching all Active learning sys properties to config
pipelineInput["config"]["sys_properties"] = this._getAllActiveLearningSysProperties();
//Defining pipeline info
var pipelineInfo = {
"label": solutionInfo.label,
"description": "Active Learning solution",
"schedulingInfo": {
"useCase": "Active Learning Solution"
},
"tags": [
"Active learning"
],
"workflowConfiguration": {
"trainingFrequency": "run_once"
},
"trainingPipeline": {
"pipelineInput": pipelineInput,
"pipelineName": "active_learning_workflow",
"pipelineOutput": {
"models": {
"active_learning_report": "::dsl_active_learning.outputModel"
}
}
}
};
var solutionPipeline = new sn_ml.WorkflowSolution(pipelineInfo);
var solutionName = sn_ml.WorkflowSolutionStore.add(solutionPipeline);
var repName = solutionName + "_active_learning_report";
pipelineInfo.trainingPipeline.pipelineInput = pipelineInput;
pipelineInfo.trainingPipeline.pipelineOutput.models = {};
pipelineInfo.trainingPipeline.pipelineOutput.models[repName] = "::dsl_active_learning.outputModel";
solutionPipeline = new sn_ml.WorkflowSolution(pipelineInfo);
sn_ml.WorkflowSolutionStore.update(solutionName, solutionPipeline);
// Submit training job
var solutionVersion = solutionPipeline.submitTrainingJob();
gs.debug("props: " + JSON.stringify(solutionVersion.getProperties()));
return solutionName;
} catch (e) {
gs.warn('Error creating Active learning definition:' + e.message + '\n' + e);
}
},
_getAuthoringModels: function(modelIds) {
var authoringModels = [];
modelIds.forEach(function(modelId) {
nluModel = new NLUModel(modelId);
modelGr = nluModel.getGR();
trainJson = NLUStudioTrainer.getTrainJson(nluModel, new NLUParloIntegrator(modelGr));
authoringModels.push(trainJson);
});
return authoringModels;
},
_getVaChatLogsCount: function(models, query) {
if (models.length == 0) {
return 0;
}
var ga = new GlideAggregate(tables.VA_CHAT_LOGS);
ga.addAggregate('COUNT');
ga.addEncodedQuery(query);
ga.query();
var count = ga.next() && ga.getAggregate('COUNT');
return count;
},
_getModelUniqueIds: function(models) {
var modelIds = [];
models.forEach(function(model) {
var gr = new GlideRecord(tables.NLU_MODEL);
gr.addQuery('name', model);
gr.query();
while (gr.next()) {
modelIds.push(gr.getUniqueValue());
}
});
return modelIds;
},
_getModels: function() {
var nluProviderId = NLUMappingsUtil.getSNNLUProvider();
if (!nluProviderId) {
gs.debug('NLU Provider is NOT active');
return [];
}
var va_models = [];
var gr = new GlideRecord(tables.CS_TOPIC);
gr.addQuery('nlu_provider', nluProviderId);
gr.addQuery('language_code', 'en');
gr.orderByDesc('sys_updated_on');
gr.query();
while (gr.next()) {
var model = gr.getValue('nlu_model');
if (va_models.indexOf(model) === -1)
va_models.push(model);
}
var models = [];
gr = GlideRecord(tables.NLU_MODEL);
gr.addQuery('state', "Published");
gr.addQuery('language', 'en');
gr.addQuery('name', 'IN', va_models.join(','));
gr.orderByDesc('sys_updated_on');
gr.query();
while (gr.next()) {
var model = gr.getValue('name');
if (models.indexOf(model) === -1)
models.push(model);
}
var max_models = parseInt(this._getSysProperty(sysProperties.MAX_MODELS_LIMIT)) || defaults.MAX_MODELS;
if (models.length > max_models) {
models = models.slice(0, max_models);
}
return models;
},
_getSysProperty: function(key) {
var value = null;
var sys_gr = new GlideRecord(tables.SYS_PROPERTIES);
sys_gr.addQuery("name", key);
sys_gr.query();
while (sys_gr.next()) {
value = sys_gr.getValue("value");
}
return value;
},
_getAllActiveLearningSysProperties: function() {
var sys_gr = new GlideRecord(tables.SYS_PROPERTIES);
sys_gr.addEncodedQuery("nameSTARTSWITHglide.mlpredictor.option.nlu.activeLearning");
sys_gr.query();
var properties = {};
while (sys_gr.next()) {
properties[sys_gr.getValue("name")] = sys_gr.getValue("value");
}
return properties;
},
_getlastScheduledJobCreatedOn: function() {
var gr = new GlideRecord(tables.ML_SOLUTION);
var last_created_time = null;
gr.addQuery('progress', 100);
gr.addEncodedQuery("solution_nameLIKEactive_learning^stateINsolution_complete");
gr.orderByDesc('sys_created_on');
gr.setLimit(1);
gr.query();
while (gr.next()) {
last_created_time = gr.getValue("sys_created_on");
}
return last_created_time;
},
type: 'ActiveLearningIntegrator'
};
})();
Sys ID
941bc9f1eb5630103da4ee2c47522826