Does anyone have documentation on the Machine Learning (sn_ml) API?

chrisperry
Giga Sage

Does anyone have documentation on the Machine Learning (sn_ml) API?  I can't seem to be able to find it anywhere... not sure if ServiceNow hasn't published anything or what.

In the OOB script include that gets enabled w/ the Machine Learning plugins - MLPredictor, there is a line of code at line 12 for: 

var finder = new sn_ml.SolutionFinder();

I haven't been able to find any documentation from ServiceNow on this sn_ml (Machine Learning) API.

 

My ultimate goal is to build a UI macro button next to a field, which when clicked, makes a GlideAjax call to a client callable script include which references the Machine Learning API, to then return a message with the Machine's prediction on the value of the output field based on the solution definition.  Has anyone had any luck doing anything similar?

At the very least I would like to better understand the Machine Learning API and its methods so that I can tinker with it to try and achieve my goal from above.

 

Thanks,
Chris

 

If this answer is helpful please mark correct and helpful!

Regards,
Chris Perry
1 ACCEPTED SOLUTION

chrisperry
Giga Sage

In case anyone is curious, here is how I figured out how to accomplish the functionality I was looking for --

 

It allows for client side use of the Machine Learning API to display prediction of output field and confidence level, without actually saving the prediction to the field on the server like the OOB 'Default Task Based Prediction' business rule does:

 

1. Create UI macro which is referenced from Dictionary Entry of ML solution definition's output field using the Field decorations dictionary attribute (value = name of UI macro)

Here is the code in my UI macro - where the input fields on the solution definition are short description and description, and the output field is 'u_call_type':

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<g:evaluate var="jvar_guid" expression="gs.generateGUID(this);" />
<j:set var="jvar_n" value="mlPredict_${ref}"/>
<a id="${jvar_n}" onclick="mlPredict('${ref}')" title="${gs.getMessage('Display Machine Learning Recommendation')}" tabindex="0" class="icon ref-button icon-cog btn btn-default btn-ref"></a>
	<script>
		function mlPredict() {
			
			g_form.hideFieldMsg('u_call_type');
			var shortDescr = g_form.getValue("short_description");
			var descr = g_form.getValue("description");
			var inputParams = {short_description:[shortDescr],description:[descr]};
			var strInputParams = Object.toJSON(inputParams);
		
			if(shortDescr == '' || descr == '') {
				g_form.showFieldMsg('u_call_type', 'Short description and Description must be populated to get Machine Learning recommendation', 'error');
			} else {
			
				var ga = new GlideAjax("mlPredictMsg");
				ga.addParam("sysparm_name", "callMlPredict");
				ga.addParam("sysparm_strInputParams", strInputParams);
				ga.addParam("sysparm_solutionName", "ml_x_xei_request_interaction_type");
		
				//turn on logging
				ga.addParam("sysparm_debug", true);
				ga.getXML(displayPredictMsg);	
				}
		}
		
		
		function displayPredictMsg(response) {
			var result = response.responseXML.documentElement.getAttribute("answer");
		
			if(result == "error") {
				g_form.showFieldMsg("u_call_type", "There was an issue with retrieving the Machine's prediction.", "error");
			} else {
				if(confidence != "0") { 
					result = result.evalJSON();
					var predictedValue = result.predictedValue;
					var confidence = result.confidence;
		
					//g_form.addInfoMessage('predictedValue is: ' + predictedValue + ', confidence is: ' + confidence);
					var predictionMessage = '';
					var predictedDisplayValue = '';
			
					if(predictedValue == 'request_for_info') {
						predictedDisplayValue = 'Request for Information';
					}
					if(predictedValue == 'change_request') {
						predictedDisplayValue = 'Change Request';
					}
					if(predictedValue == 'hang_up') {
						predictedDisplayValue = 'Hang Up/Transfer/Wrong Number';
					}
					if(predictedValue == 'hr_case') {
						predictedDisplayValue = 'HR Case';
					}
					if(predictedValue == 'incident') {
						predictedDisplayValue = 'Incident';
					}
					if(predictedValue == 'reuest_for_training') {
						predictedDisplayValue = 'Request for Training';
					}
					if(predictedValue == 'rm_enhancement') {
						predictedDisplayValue = 'Enhancement';
					}
					if(predictedValue == 'sc_request') {
						predictedDisplayValue = 'Catalog Request';
					}
				
					predictionMessage += 'Machine Learning predicts ' + predictedDisplayValue + ', with confidence of ' + confidence + '%';
				
				
				
					g_form.showFieldMsg("u_call_type", predictionMessage, "info");
				} else {
					g_form.showFieldMsg("u_call_type", "Machine Learning is unable to predict.", "error");
				}
			}
		
		}
	</script>
</j:jelly>

 

2. As you can see in line 19 from the UI macro above, it references a client callable script include called 'mlPredictMsg'.  This script include is re-usable for any ML solution definition, as the input fields are defined manually from the UI macro, and the output is defined from the solution definition itself:

 

var mlPredictMsg = Class.create();
mlPredictMsg.prototype = Object.extendsObject(AbstractAjaxProcessor, {
	
	
	callMlPredict: function() {
		var debug = this.getParameter("sysparm_debug");
		var solutionName = this.getParameter("sysparm_solutionName");
		var strInputParams = this.getParameter("sysparm_strInputParams");
		var threshold = NaN;
		var finalPredictedValueObj = {};
		
		var inputParams = new JSON().decode(strInputParams);
		//gs.log('inputParams from script include is: ' + inputParams + ', and strInputParams is: ' + strInputParams);
		
		var solutionFinder = new sn_ml.SolutionFinder();
		var solution = solutionFinder.getSolution(solutionName);
		
		var inputs = {};
		for (var key in inputParams) {
			if(inputParams.hasOwnProperty(key)) {
				inputs[key] = inputParams[key].toString();
			}
		}
		
		var predictedOutcome = solution.predictText(inputs, threshold);
		var outcome = predictedOutcome.predictedValue();
		var confidence = predictedOutcome.confidence();
		var roundedConfidence = Math.round(confidence);
		
		var outcomeObj = {};
		
		if(!predictedOutcome.hasPrediction() || outcome == null) {
			outcomeObj.predictedValue = "Unable to predict.";
			outcomeObj.confidence = "0";
		} else {
			outcomeObj.predictedValue = outcome.toString();
			outcomeObj.confidence = roundedConfidence.toString();
			}
		
		var json = new JSON();
		var finalOutcomeObj = json.encode(outcomeObj);
		
		return finalOutcomeObj;
		
	}, 
	

    type: 'mlPredictMsg'
	
});

 

Hopefully this is helpful - I think the solution is pretty elegant and really highlights how cool the Machine Learning application from ServiceNow is by displaying predictions in real time on the client side.

If this answer is helpful please mark correct and helpful!

Regards,
Chris Perry

View solution in original post

5 REPLIES 5

chrisperry
Giga Sage

In case anyone is curious, here is how I figured out how to accomplish the functionality I was looking for --

 

It allows for client side use of the Machine Learning API to display prediction of output field and confidence level, without actually saving the prediction to the field on the server like the OOB 'Default Task Based Prediction' business rule does:

 

1. Create UI macro which is referenced from Dictionary Entry of ML solution definition's output field using the Field decorations dictionary attribute (value = name of UI macro)

Here is the code in my UI macro - where the input fields on the solution definition are short description and description, and the output field is 'u_call_type':

<?xml version="1.0" encoding="utf-8" ?>
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
<g:evaluate var="jvar_guid" expression="gs.generateGUID(this);" />
<j:set var="jvar_n" value="mlPredict_${ref}"/>
<a id="${jvar_n}" onclick="mlPredict('${ref}')" title="${gs.getMessage('Display Machine Learning Recommendation')}" tabindex="0" class="icon ref-button icon-cog btn btn-default btn-ref"></a>
	<script>
		function mlPredict() {
			
			g_form.hideFieldMsg('u_call_type');
			var shortDescr = g_form.getValue("short_description");
			var descr = g_form.getValue("description");
			var inputParams = {short_description:[shortDescr],description:[descr]};
			var strInputParams = Object.toJSON(inputParams);
		
			if(shortDescr == '' || descr == '') {
				g_form.showFieldMsg('u_call_type', 'Short description and Description must be populated to get Machine Learning recommendation', 'error');
			} else {
			
				var ga = new GlideAjax("mlPredictMsg");
				ga.addParam("sysparm_name", "callMlPredict");
				ga.addParam("sysparm_strInputParams", strInputParams);
				ga.addParam("sysparm_solutionName", "ml_x_xei_request_interaction_type");
		
				//turn on logging
				ga.addParam("sysparm_debug", true);
				ga.getXML(displayPredictMsg);	
				}
		}
		
		
		function displayPredictMsg(response) {
			var result = response.responseXML.documentElement.getAttribute("answer");
		
			if(result == "error") {
				g_form.showFieldMsg("u_call_type", "There was an issue with retrieving the Machine's prediction.", "error");
			} else {
				if(confidence != "0") { 
					result = result.evalJSON();
					var predictedValue = result.predictedValue;
					var confidence = result.confidence;
		
					//g_form.addInfoMessage('predictedValue is: ' + predictedValue + ', confidence is: ' + confidence);
					var predictionMessage = '';
					var predictedDisplayValue = '';
			
					if(predictedValue == 'request_for_info') {
						predictedDisplayValue = 'Request for Information';
					}
					if(predictedValue == 'change_request') {
						predictedDisplayValue = 'Change Request';
					}
					if(predictedValue == 'hang_up') {
						predictedDisplayValue = 'Hang Up/Transfer/Wrong Number';
					}
					if(predictedValue == 'hr_case') {
						predictedDisplayValue = 'HR Case';
					}
					if(predictedValue == 'incident') {
						predictedDisplayValue = 'Incident';
					}
					if(predictedValue == 'reuest_for_training') {
						predictedDisplayValue = 'Request for Training';
					}
					if(predictedValue == 'rm_enhancement') {
						predictedDisplayValue = 'Enhancement';
					}
					if(predictedValue == 'sc_request') {
						predictedDisplayValue = 'Catalog Request';
					}
				
					predictionMessage += 'Machine Learning predicts ' + predictedDisplayValue + ', with confidence of ' + confidence + '%';
				
				
				
					g_form.showFieldMsg("u_call_type", predictionMessage, "info");
				} else {
					g_form.showFieldMsg("u_call_type", "Machine Learning is unable to predict.", "error");
				}
			}
		
		}
	</script>
</j:jelly>

 

2. As you can see in line 19 from the UI macro above, it references a client callable script include called 'mlPredictMsg'.  This script include is re-usable for any ML solution definition, as the input fields are defined manually from the UI macro, and the output is defined from the solution definition itself:

 

var mlPredictMsg = Class.create();
mlPredictMsg.prototype = Object.extendsObject(AbstractAjaxProcessor, {
	
	
	callMlPredict: function() {
		var debug = this.getParameter("sysparm_debug");
		var solutionName = this.getParameter("sysparm_solutionName");
		var strInputParams = this.getParameter("sysparm_strInputParams");
		var threshold = NaN;
		var finalPredictedValueObj = {};
		
		var inputParams = new JSON().decode(strInputParams);
		//gs.log('inputParams from script include is: ' + inputParams + ', and strInputParams is: ' + strInputParams);
		
		var solutionFinder = new sn_ml.SolutionFinder();
		var solution = solutionFinder.getSolution(solutionName);
		
		var inputs = {};
		for (var key in inputParams) {
			if(inputParams.hasOwnProperty(key)) {
				inputs[key] = inputParams[key].toString();
			}
		}
		
		var predictedOutcome = solution.predictText(inputs, threshold);
		var outcome = predictedOutcome.predictedValue();
		var confidence = predictedOutcome.confidence();
		var roundedConfidence = Math.round(confidence);
		
		var outcomeObj = {};
		
		if(!predictedOutcome.hasPrediction() || outcome == null) {
			outcomeObj.predictedValue = "Unable to predict.";
			outcomeObj.confidence = "0";
		} else {
			outcomeObj.predictedValue = outcome.toString();
			outcomeObj.confidence = roundedConfidence.toString();
			}
		
		var json = new JSON();
		var finalOutcomeObj = json.encode(outcomeObj);
		
		return finalOutcomeObj;
		
	}, 
	

    type: 'mlPredictMsg'
	
});

 

Hopefully this is helpful - I think the solution is pretty elegant and really highlights how cool the Machine Learning application from ServiceNow is by displaying predictions in real time on the client side.

If this answer is helpful please mark correct and helpful!

Regards,
Chris Perry

Great article on implementing Agent Intelligence/Predictive Intelligence with a UI Marco.  Thanks so much for sharing and documenting! 

Saurabh Harshe
Kilo Explorer

Hello

I am also having the same issue with machine learning. It would be very helpful if anyone will share a solution. 

The latest Predictive Intelligence ML API documentation with examples is here, just click classification/similarity/clustering/regression to see the code snippet examples on how to use.

You can also scroll to the bottom of this article and use this ML API code and put it into a UI action with some tweaks.

Also if you are on San Diego, we have created those UI actions for you in Service Operations Workspace for classification, see below.

find_real_file.png