Name
sn_topic_recommend.RecommendationUtil
Description
Functionality for topic recommendations.
Script
var RecommendationUtil = Class.create();
RecommendationUtil.prototype = {
initialize: function() {
},
getTaxonomyIntentTopics: function() {
var gr = new GlideRecord('sn_topic_recommend_taxonomy_topic');
gr.addQuery('topic_sys_policy', 'read');
gr.query();
var models = {};
var intents;
var intent;
var languages;
var intentTopic;
while (gr.next()) {
intentTopic = {
intent: gr.getValue('taxonomy_taxonomy_intent'),
model: gr.getValue('taxonomy_taxonomy_model'),
nluIntentId: gr.getValue('intent_sys_id'),
nluIntentName: gr.getValue('intent_name'),
nluModelId: gr.getValue('model_sys_id'),
nluModelName: gr.getValue('model_name'),
language: gr.getValue('taxonomy_language'),
topicId: gr.getValue('topic_sys_id'),
topicName: gr.getValue('topic_name'),
topicDescription: gr.getValue('topic_description'),
csTopicId: gr.getValue('cstopic_sys_id'),
topicIsActive: gr.getValue('cstopic_active')
};
intents = models[intentTopic.model] || {};
intent = intents[intentTopic.intent] || {};
languages = intent.languages || {};
languages[intentTopic.language] = intentTopic;
intent.languages = languages;
intents[intentTopic.intent] = intent;
models[intentTopic.model] = intents;
}
return models;
},
createModel: function(name, language) {
var gr = new GlideRecord('sys_nlu_model');
gr.setValue('display_name', name);
gr.setValue('language', language);
return gr.insert();
},
getUserTaxonomyIntentTopics: function() {
var intentGr = new GlideRecord('sn_topic_recommend_taxonomy_topic');
intentGr.addQuery('taxonomy_type', 'SYSTEM');
intentGr.addQuery('topic_sys_policy', 'read');
intentGr.orderBy('topic_created_on');
intentGr.query();
var taxa = {};
var taxonomyName;
var taxonomy;
var taxonomyIntent;
var intent;
var languageCode;
var language;
while (intentGr.next()) {
taxonomyName = intentGr.getValue('taxonomy_taxonomy_model');
taxonomy = taxa[taxonomyName] || {};
taxonomyIntent = intentGr.getValue('taxonomy_taxonomy_intent');
intent = taxonomy[taxonomyIntent] || {};
languageCode = intentGr.getValue('taxonomy_language');
language = {
nluIntent: intentGr.getValue('language_nlu_intent'),
nluModel: intentGr.getValue('language_nlu_model'),
nluProvider: intentGr.getValue('language_nlu_provider')
};
intent[languageCode] = language;
taxonomy[taxonomyIntent] = intent;
taxa[taxonomyName] = taxonomy;
}
var topicGr = new GlideRecord('sys_cb_topic_language');
topicGr.addNullQuery('cb_topic_id.sys_policy');
topicGr.orderBy('sys_updated_date');
topicGr.query();
var topics = {};
var topicKey;
while (topicGr.next()) {
topicKey = topicGr.getValue('nlu_provider') + '|' + topicGr.getValue('nlu_model') + '|' + topicGr.getValue('nlu_intent');
topics[topicKey] = {
name: topicGr.cb_topic_id.name.toString(),
createdDate: topicGr.cb_topic_id.sys_created_on.toString(),
updatedDate: topicGr.cb_topic_id.sys_updated_on.toString(),
sourceTopicId: topicGr.cb_topic_id.source_topic_id.toString()
};
}
var topic;
for (taxonomyName in taxa) {
taxonomy = taxa[taxonomyName];
for (taxonomyIntent in taxonomy) {
intent = taxonomy[taxonomyIntent];
for (languageCode in intent) {
language = intent[languageCode];
topicKey = language.nluProvider + '|' + language.nluModel + '|' + language.nluIntent;
topic = topics[topicKey];
intent[languageCode] = topic;
}
}
}
return taxa;
},
getInstalledTopics: function() {
var topics = {};
var topic;
var installedTopics = {};
// Get all topics installed through Topic Recommendation - linking table
var installedGr = new GlideRecord('sn_topic_recommend_topic_linking');
installedGr.addQuery('type', 'added');
installedGr.query();
while (installedGr.next()) {
topic = {
id: installedGr.getValue('topic'),
taxonomy: installedGr.getValue('taxonomy'),
intent: installedGr.getValue('intent'),
installedDate: installedGr.topic.sys_created_on.toString(),
name: installedGr.topic.name.toString(),
csTopicId: null,
topicIsActive: false
};
topics[topic.taxonomy] = topics[topic.taxonomy] || {};
topics[topic.taxonomy][topic.intent] = topic;
installedTopics[topic.id] = {
taxonomy: topic.taxonomy,
intent: topic.intent
};
}
// Get all topics installed through Topic Recommendation - staging table
installedGr = new GlideRecord('sn_topic_recommend_topic_staging');
installedGr.addNotNullQuery('topic_clone.sys_id');
var statusCondition = installedGr.addQuery('status', 'complete');
statusCondition.addOrCondition('status', 'warning');
installedGr.orderByDesc('sys_updated_on');
installedGr.query();
while (installedGr.next()) {
topic = {
id: installedGr.getValue('topic_clone'),
taxonomy: installedGr.getValue('taxonomy'),
intent: installedGr.getValue('intent'),
installedDate: installedGr.topic_clone.sys_created_on.toString(),
name: installedGr.topic_clone.name.toString(),
csTopicId: null,
topicIsActive: false
};
topics[topic.taxonomy] = topics[topic.taxonomy] || {};
if (!topics[topic.taxonomy][topic.intent]) {
topics[topic.taxonomy][topic.intent] = topic;
installedTopics[topic.id] = {
taxonomy: topic.taxonomy,
intent: topic.intent
};
}
}
var installedTopicIds = Object.keys(installedTopics);
var associatedCSTopicGr = new GlideRecord('sys_cs_topic');
associatedCSTopicGr.addQuery('cb_topic_id', 'IN', installedTopicIds);
associatedCSTopicGr.addQuery('published', true);
associatedCSTopicGr.query();
while (associatedCSTopicGr.next()) {
var topicId = associatedCSTopicGr.getValue('cb_topic_id');
var csTopicId = associatedCSTopicGr.getValue('sys_id');
var isActive = associatedCSTopicGr.getValue('active') === '1';
var installedTopic = installedTopics[topicId];
topics[installedTopic.taxonomy][installedTopic.intent].csTopicId = csTopicId;
topics[installedTopic.taxonomy][installedTopic.intent].topicIsActive = isActive;
}
// Get all other topics installed through Intent cloning
installedGr = new GlideRecord('sn_topic_recommend_taxonomy_topic');
installedGr.addQuery('taxonomy_type', 'CUSTOM');
installedGr.addNullQuery('topic_sys_policy');
installedGr.orderBy('topic_created_on');
installedGr.query();
while (installedGr.next()) {
topic = {
id: installedGr.getValue('topic_sys_id'),
taxonomy: installedGr.getValue('taxonomy_taxonomy_model'),
intent: installedGr.getValue('taxonomy_taxonomy_intent'),
installedDate: installedGr.getValue('topic_sys_created_on'),
name: installedGr.getValue('topic_name'),
csTopicId: installedGr.getValue('cstopic_sys_id'),
topicIsActive: installedGr.getValue('cstopic_active')
};
topics[topic.taxonomy] = topics[topic.taxonomy] || {};
topics[topic.taxonomy][topic.intent] = topics[topic.taxonomy][topic.intent] || topic;
}
return topics;
},
getNluProvider: function() {
var nluProvider = null;
var nluProviderName = null;
var enabled = false;
var gr = new GlideRecord('sys_cs_general_settings');
gr.setLimit(1);
gr.query();
while (gr.next()) {
enabled = gr.getValue('nlu_enabled') == 1;
nluProvider = gr.getValue('nlu_driver');
nluProviderName = gr.getDisplayValue('nlu_driver');
}
return { id: nluProvider, name: nluProviderName, enabled: enabled };
},
isServiceNowNLUEnabled: function() {
var provider = this.getNluProvider();
return provider.enabled && provider.name === 'ServiceNow NLU';
},
getAvailableModels: function() {
var enabledLanguages = this.getEnabledLanguages();
var allModels = global.NLUStudioService.getAllModels('virtual_agent');
var gr = new GlideRecord('sys_nlu_model');
gr.addQuery('sys_policy', 'read');
gr.query();
var readOnlyIds = {};
while (gr.next()) {
readOnlyIds[gr.getUniqueValue()] = true;
}
var results = [];
var primaryModels = {};
var secondaryLanguageEnabled = {};
var secondaryLanguages = {};
var primaryModelId;
var index;
var model;
var existing;
for (index = 0; index < allModels.length; index++) {
model = allModels[index];
if (!readOnlyIds[model.id]) {
if (model.type === 'primary') {
primaryModels[model.id] = model;
} else if (model.type === 'secondary') {
if (enabledLanguages[model.language]) {
secondaryLanguageEnabled[model.primaryId] = true;
}
existing = secondaryLanguages[model.primaryId];
secondaryLanguages[model.primaryId] = existing ? existing.concat(model.language) : [model.language];
} else if (enabledLanguages[model.language]) {
results.push(model);
}
}
}
for (primaryModelId in primaryModels) {
model = primaryModels[primaryModelId];
model.secondaryLanguages = secondaryLanguages[primaryModelId] || [];
if (enabledLanguages[model.language] || secondaryLanguageEnabled[primaryModelId]) {
results.push(model);
}
}
return results;
},
getEnabledLanguages: function() {
var languages = this.getLanguages();
var enabledLanguages = {};
for (var i = 0; i < languages.length; i++) {
var language = languages[i];
if (language.nluEnabled == true){
enabledLanguages[language.id] = true;
}
}
return enabledLanguages;
},
getSupportedNluLanguages: function() {
try {
var mlServiceResult = sn_ml.MLServiceUtil.fetchGraphQL('query { NLU { supportedLanguages { name, language, intents { entities { isEnabled } } } } }');
var result = JSON.parse(mlServiceResult);
var supportedLanguages = [];
if (result.data && result.data.NLU) {
supportedLanguages = result.data.NLU.supportedLanguages;
}
return supportedLanguages;
} catch(ex) {
return [];
}
},
getLanguages: function() {
var nluLanguages = {};
var nluProvider = this.getNluProvider();
var languages = [];
var languageId;
var languageName;
var sessionLanguage = gs.getSession().getLanguage();
var languageTracker = {};
var gr = new GlideRecord('sys_cs_nlu_language');
if (nluProvider.enabled) {
gr.addQuery('enabled', true);
gr.addQuery('language.driver', nluProvider.id);
gr.query();
while (gr.next()) {
nluLanguages[gr.language.code] = true;
}
}
gr = new GlideRecord('sys_choice');
gr.addQuery('name', 'sys_user');
gr.addQuery('element', 'preferred_language');
gr.addNullQuery('inactive').addOrCondition('inactive', false);
gr.addQuery('language', sessionLanguage);
gr.addQuery('value', '!=', 'NULL_OVERRIDE');
gr.query();
while (gr.next()) {
languageId = gr.getValue('value');
languageLabel = gr.getValue('label');
languages.push({ id: languageId, name: languageLabel, nluEnabled: !!nluLanguages[languageId] });
languageTracker[languageId] = true;
}
gr.initialize();
gr.addQuery('name', 'sys_user');
gr.addQuery('element', 'preferred_language');
gr.addNullQuery('inactive').addOrCondition('inactive', false);
gr.addQuery('language', 'en');
gr.addQuery('value', '!=', 'NULL_OVERRIDE');
gr.query();
while (gr.next()) {
languageId = gr.getValue('value');
languageLabel = gr.getValue('label');
if (!languageTracker[languageId]) {
languages.push({ id: languageId, name: languageLabel, nluEnabled: !!nluLanguages[languageId] });
languageTracker[languageId] = true;
}
}
var supportedLanguages = this.getSupportedNluLanguages();
supportedLanguages.map(function(supportedLanguage) {
languageId = supportedLanguage.language;
languageLabel = supportedLanguage.name;
if (!languageTracker[languageId]) {
languages.push({ id: languageId, name: languageLabel, nluEnabled: !!nluLanguages[languageId] });
}
});
return languages;
},
getLinkableTopics: function() {
var gr = new GlideRecord('sys_cb_topic');
gr.addNullQuery('sys_policy');
gr.addQuery('type', 'STANDARD');
gr.orderBy('name');
gr.query();
var results = [];
while (gr.next()) {
results.push({
id: gr.getUniqueValue(),
name: gr.getValue('name')
});
}
return results;
},
getSecondaryLanguageModels: function(modelId, secondaryLanguages) {
var gr = new GlideRecord('sys_nlu_model');
gr.addQuery('primary_model', modelId);
gr.addQuery('language', 'IN', secondaryLanguages);
gr.query();
var results = [];
while (gr.next()) {
var secondaryLanguageModel = {};
secondaryLanguageModel.id = gr.getValue('sys_id');
secondaryLanguageModel.name = gr.getValue('name');
secondaryLanguageModel.display_name = gr.getValue('display_name');
secondaryLanguageModel.language = gr.getValue('language');
results.push(secondaryLanguageModel);
}
return results;
},
getLinkedTopics: function() {
var gr = new GlideRecord('sn_topic_recommend_topic_linking');
gr.addQuery('type', 'linked');
gr.query();
var topics = {};
var linkedTopic;
var topicLinks = {};
while (gr.next()) {
linkedTopic = {
linkedId: gr.getUniqueValue(),
linkedDate: gr.sys_created_on.toString(),
taxonomy: gr.getValue('taxonomy'),
intent: gr.getValue('intent'),
topicId: gr.getValue('topic'),
topicName: gr.topic.name.toString(),
csTopicId: null,
topicIsActive: false
};
topics[linkedTopic.taxonomy] = topics[linkedTopic.taxonomy] || {};
topics[linkedTopic.taxonomy][linkedTopic.intent] = linkedTopic;
var taxonomyIntent = {
taxonomy: linkedTopic.taxonomy,
intent: linkedTopic.intent
};
topicLinks[linkedTopic.topicId] = topicLinks[linkedTopic.topicId] ? topicLinks[linkedTopic.topicId].concat(taxonomyIntent): [taxonomyIntent];
}
var linkedTopicIds = Object.keys(topicLinks);
var associatedCSTopicGr = new GlideRecord('sys_cs_topic');
associatedCSTopicGr.addQuery('cb_topic_id', 'IN', linkedTopicIds);
associatedCSTopicGr.addQuery('published', true);
associatedCSTopicGr.query();
while (associatedCSTopicGr.next()) {
var topicId = associatedCSTopicGr.getValue('cb_topic_id');
var csTopicId = associatedCSTopicGr.getValue('sys_id');
var isActive = associatedCSTopicGr.getValue('active') === '1';
var links = topicLinks[topicId];
for (index = 0; index < links.length; index++) {
var link = links[index];
topics[link.taxonomy][link.intent].csTopicId = csTopicId;
topics[link.taxonomy][link.intent].topicIsActive = isActive;
}
}
return topics;
},
getIgnoredIntents: function () {
var gr = new GlideRecord('sn_topic_recommend_topic_linking');
gr.addQuery('type', 'ignored');
gr.query();
var ignoredIntent = {};
var ignoredIntents = {};
while(gr.next()) {
ignoredIntent = {
ignoredId: gr.getUniqueValue(),
ignoredDate: gr.sys_created_on.toString(),
taxonomy: gr.getValue('taxonomy'),
intent: gr.getValue('intent'),
};
ignoredIntents[ignoredIntent.taxonomy] = ignoredIntents[ignoredIntent.taxonomy] || {};
ignoredIntents[ignoredIntent.taxonomy][ignoredIntent.intent] = ignoredIntent;
}
return ignoredIntents;
},
trainModel: function (modelId, options){
var trainJson, output, modelGr;
var parloIntegrator;
var result = {};
try {
nluModel = new global.NLUModel(modelId);
modelGr = nluModel.getGR();
if (!modelGr) throw new Error(gs.getMessage('Model id does not exist'));
parloIntegrator = new global.NLUParloIntegrator(modelGr);
// Populate train json:
trainJson = global.NLUStudioTrainer.getTrainJson(nluModel, parloIntegrator);
// Invoke service:
output = parloIntegrator.train(trainJson, options);
result.status = output.status;
if (output.status === 'training') {
result.trainingVersion = output.response.solutionVersion;
// Update nlu_model_status table to indicate it is being currently trained
nluModel.updateStatus({
state: 'training'
});
result.status = 'success';
} else if (output.status == 'success') {
result.trainedVersion = output.response.solutionVersion;
// Update nlu_model_status table
nluModel.updateStatus({
state: 'trained',
trained_version: result.trainedVersion,
last_trained_on: (new GlideDateTime()),
dirty: false
});
} else if (output.status == 'failure') {
result.messages = output.response.messages;
result.errors = global.NLUHelper.getErrorsFromResponse(output.response);
}
} catch (e) {
result.status = 'failure';
result.message = e.message;
}
return result;
},
type: 'RecommendationUtil'
};
Sys ID
d16245f8b5c31010fa9b379cf1d65d8b