Created
July 31, 2017 01:45
-
-
Save afawcett/f8c91900e55615bcf4a6a1596a5408d0 to your computer and use it in GitHub Desktop.
Einstein Sentiment Wrappers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public with sharing class EinsteinSentimentAction { | |
public class Request { | |
@InvocableVariable | |
public String recordId; | |
@InvocableVariable | |
public String document; | |
@InvocableVariable | |
public String modelId; | |
} | |
public class Prediction { | |
@InvocableVariable | |
public double positive; | |
@InvocableVariable | |
public double negative; | |
@InvocableVariable | |
public double neutral; | |
} | |
@InvocableMethod(label='Classify the given text and optionally updates the given record with the results.') | |
public static List<EinsteinSentimentAction.Prediction> analyze(List<EinsteinSentimentAction.Request> requests) { | |
// TODO: Bulkify! | |
EinsteinSentimentAction.Request request = requests[0]; | |
// Switch to async? | |
if(!System.isQueueable() && request.recordId!=null) { // TODO: Maybe put this in the callers hands as a param? | |
System.enqueueJob(new AsyncCallback(requests)); | |
return null; | |
} | |
// Call Einstein API and update record (if provided) | |
Sentiment.Prediction prediction = | |
new Sentiment().getSentiment( | |
new VisionController().getAccessToken(), | |
request.document, | |
request.modelId); | |
// Update record? | |
if(request.recordId!=null) { | |
Id recordToUpdateId = (Id) request.recordId; | |
SObject recordToUpdate = recordToUpdateId.getSObjectType().newSObject(recordToUpdateId); | |
recordToUpdate.put('SentimentPositive__c', prediction.positive); | |
recordToUpdate.put('SentimentNegative__c', prediction.negative); | |
recordToUpdate.put('SentimentNeutral__c', prediction.neutral); | |
update recordToUpdate; | |
} | |
// Return prediction for Flow use cases | |
EinsteinSentimentAction.Prediction response = new EinsteinSentimentAction.Prediction(); | |
response.positive = prediction.positive; | |
response.negative = prediction.negative; | |
response.neutral = prediction.neutral; | |
return new List<EinsteinSentimentAction.Prediction> { response }; | |
} | |
// Class re-enters above method in an async context | |
public class AsyncCallback implements Queueable, Database.AllowsCallouts { | |
private List<EinsteinSentimentAction.Request> requests; | |
public AsyncCallback(List<EinsteinSentimentAction.Request> requests) { | |
this.requests = requests; | |
} | |
public void execute(QueueableContext context) { | |
EinsteinSentimentAction.analyze(requests); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Sentiment { | |
public Prediction getSentiment(String token, String document, String modelId) { | |
// Instantiate a new http object | |
Http h = new Http(); | |
// Instantiate a new HTTP request | |
HttpRequest req = new HttpRequest(); | |
// HTTP Header | |
req.setEndpoint('https://api.einstein.ai/v2/language/sentiment'); | |
req.setHeader('Authorization', 'Bearer ' + token); | |
req.setHeader('Cache-Control', 'no-cache'); | |
req.setHeader('Connection', 'keep-alive'); | |
req.setHeader('Content-Type', HttpFormBuilder.GetContentType()); | |
// HTTP Body | |
string form64 = ''; | |
form64 += HttpFormBuilder.WriteBoundary(); | |
form64 += HttpFormBuilder.WriteBodyParameter('modelId', EncodingUtil.urlEncode(modelId==null ? 'CommunitySentiment' : modelId, 'UTF-8')); | |
form64 += HttpFormBuilder.WriteBoundary(); | |
form64 += HttpFormBuilder.WriteBodyParameter('document', document); | |
form64 += HttpFormBuilder.WriteBoundary(HttpFormBuilder.EndingType.CrLf); | |
blob formBlob = EncodingUtil.base64Decode(form64); | |
string contentLength = string.valueOf(formBlob.size()); | |
req.setBodyAsBlob(formBlob); | |
// HTTP Header | |
req.setHeader('Content-Length', contentLength); | |
req.setMethod('POST'); | |
// Send the request and parse response | |
HttpResponse res = h.send(req); | |
if(res.getStatusCode() == 200) { | |
Response resp = (Response) JSON.deserializeStrict(res.getBody().replace('object', 'object_x'), Response.class); | |
Prediction prediction = new Prediction(); | |
for(Probability prob : resp.probabilities) { | |
if(prob.label.equals('positive')) { | |
prediction.positive = prob.probability; | |
} else if(prob.label.equals('negative')) { | |
prediction.negative = prob.probability; | |
} else if(prob.label.equals('neutral')) { | |
prediction.neutral = prob.probability; | |
} | |
} | |
return prediction; | |
} | |
// TODO: Error handling | |
return null; | |
} | |
public class Prediction { | |
public double positive; | |
public double negative; | |
public double neutral; | |
} | |
public class Response { | |
public List<Probability> probabilities; | |
public String object_x; | |
} | |
public class Probability { | |
public String label; | |
public Double probability; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment