Category: Salesforce Einstein

Salesforce Einstein Intent

Introduction

In this blog, I am going to explain how to use salesforce Einstein Intent.  Einstein Intent  Categorize unstructured text into user-defined labels to better understand what users are trying to accomplish. You can use Einstein Intent API to analyze text from emails, chats, or web forms  and many other use cases like

  • Determine what products prospects are interested in and send customer inquiries to the appropriate salesperson.
  • Identify topics across unstructured text in emails, meeting notes, or account notes to summarize key points.
  • Route service cases to the correct agents or departments, or provide self-service options.
  • Understand customer posts to provide personalized self-service in your communities

Prerequisites

Salesforce Einstein Platform Services APIs user OAuth token for authenticating. To generate a token, you create a JWT payload, sign the payload with your private key, and then call the API to get the token. So you need to get your own einstein_platform private key. please follow this steps to get your einstein_platform key.

  1. Go to the sign up page.
  2. Click Sign Up Using Salesforce.
  3. On the Salesforce login page, type your username and password, and click Log In.
  4. Click Allow so the page can access basic information, such as your email address, and perform requests.
  5. Download Key to save the key locally. The key file is einstein_platform.pem
  6. Upload the einstein_platform.pem key to Salesforce files.
  7. Copy JWTBearerFlow and JWT Apex Class from this git repository https://github.com/salesforceidentity/jwt

Refer this link for more information on the above steps.

Create custom metadata type or custom setting whatever works for you here to store the service endpoint, token endpoint and account details. Below is the custom metadata type which we are going to use it in this blog post.

Let’s Get Started.
As we are going to user cURL for model upload and training, we need to Generate a token for authentication. Go to this link and generate the token as shown below. We are going to use this generated token for model upload and train the model for predictions.

Remote Site Setting

Add remote site setting as shown below.

 Step 1: DEFINE YOUR CLASSES AND GATHER DATA

In this step, you define the labels that you want the model to output when text is sent into the model for prediction. Then you gather text data for each of those labels, and that text is used to create a model.This is typically the most time-consuming part of the process. To make it easier for you to go through these steps, we provide a case routing .csv file that you can use.

The labels in the case routing dataset define the intent behind the text. The intent can then be used to route that case to the right department. Those labels are:

  • Billing
  • Order Change
  • Password Help
  • Sales Opportunity
  • Shipping Info

STEP 2: CREATE THE DATASET

In this step, you use the data you gathered to create a dataset. In the following command, replace with<TOKEN> your JWT token and run the command. This command:

  • Creates a dataset called case_routing_intent from the specified .csv file by accessing the file via a URL
  • Creates five labels as specified in the .csv file
curl -X POST -H "Authorization: Bearer 7KQH5DBEZNE2Z3H5L55I4POCYTAB3GMTSDA6HV264XGDGDSQGJACCO7M4DF5DTDGTDJI37WR4NGEPNFJZCGRGS2IBDRWF5OHIXF3SPY
" -H "Cache-Control: no-cache" -H "Content-Type: multipart/form-data" -F "data=@C:\Users\rvakati\Desktop\New folder\SFDC Intent\case_routing_intent.csv" -F "type=text-intent"  https://api.einstein.ai/v2/language/datasets/upload
{
  "id": 1035176,
  "name": "case_routing_intent.csv",
  "createdAt": "2017-06-22T19:31:58.000+0000.",
  "updatedAt": "2017-06-22T19:31:58.000+0000",
  "labelSummary": {
    "labels": []
  },
  "totalExamples": 0,
  "available": false,
  "statusMsg": "UPLOADING",
  "type": "text-intent",
  "object": "dataset"
}

To verify that the data has been loaded, make a call to get the dataset. Replace with<TOKEN> your JWT token and with<DATASET_ID> ID of the dataset you created.

curl -X GET -H "Authorization: Bearer 7KQH5DBEZNE2Z3H5L55I4POCYTAB3GMTSDA6HV264XGDGDSQGJACCO7M4DF5DTDGTDJI37WR4NGEPNFJZCGRGS2IBDRWF5OHIXF3SPY" -H "Cache-Control: no-cache" https://api.einstein.ai/v2/language/datasets/1035176

Once you run the above command you will get below response with each label  in your dataset.

{"id":1035176,"name":"case_routing_intent","createdAt":"2018-01-22T06:07:25.000+0000","updatedAt":"2018-01-22T06:07:26.000+0000","labelSummary":{"labels":[{"id":319142,"datasetId":1035176,"name":"Order Change","numExamples":26},{"id":319143,"datasetId":1035176,"name":"Sales Opportunity","numExamples":44},{"id":319144,"datasetId":1035176,"name":"Billing","numExamples":24},{"id":319145,"datasetId":1035176,"name":"Shipping Info","numExamples":30},{"id":319146,"datasetId":1035176,"name":"Password Help","numExamples":26}]},"totalExamples":150,"totalLabels":5,"available":true,"statusMsg":"SUCCEEDED","type":"text-intent","object":"dataset"}

STEP 3: TRAIN THE DATASET 

Now you need to train your data set to create prediction ready model. Use this command to train the dataset and create a model. Replace <TOKEN> with your JWT token and <DATASET_ID> with ID of the dataset you created

curl -X POST -H "Authorization: Bearer 7KQH5DBEZNE2Z3H5L55I4POCYTAB3GMTSDA6HV264XGDGDSQGJACCO7M4DF5DTDGTDJI37WR4NGEPNFJZCGRGS2IBDRWF5OHIXF3SPY" -H "Cache-Control: no-cache" -H "Content-Type: multipart/form-data" -F "name=Case Routing Model" -F "datasetId=1035176" https://api.einstein.ai/v2/language/train

You will get below response from the above service.You will get modelId which we will use it for further predictions.

{"datasetId":1035176,"datasetVersionId":0,"name":"Case Routing Model","status":"QUEUED","progress":0,"createdAt":"2018-01-22T06:16:14.000+0000","updatedAt":"2018-01-22T06:16:14.000+0000","learningRate":0.0,"epochs":0,"queuePosition":1,"object":"training","modelId":"PF4WICRUGR2BOO7QJ5MESD56MU","trainParams":null,"trainStats":null,"modelType":"text-intent"}

 

Use the modelId to make this call and get the training status. Replace<TOKEN> with your JWT token and withMODEL_ID the ID of the model you created.

curl -X GET -H "Authorization: Bearer 7KQH5DBEZNE2Z3H5L55I4POCYTAB3GMTSDA6HV264XGDGDSQGJACCO7M4DF5DTDGTDJI37WR4NGEPNFJZCGRGS2IBDRWF5OHIXF3SPY" -H "Cache-Control: no-cache" https://api.einstein.ai/v2/language/train/PF4WICRUGR2BOO7QJ5MESD56MU

 

{"datasetId":1035176,"datasetVersionId":17909,"name":"Case Routing Model","status":"RUNNING","progress":0.01,"createdAt":"2018-01-22T06:16:14.000+0000","updatedAt":"2018-01-22T06:17:17.000+0000","learningRate":0.0,"epochs":1000,"object":"training","modelId":"PF4WICRUGR2BOO7QJ5MESD56MU","trainParams":null,"trainStats":null,"modelType":"text-intent"}

 

STEP 4: SEND TEXT IN FOR PREDICTION

Now your model is ready to go! To test it out, send some text in for prediction. This cURL call takes the ofmodelId the model from which you want to return a prediction and the text string to analyze. Replace with<TOKEN> your JWT token and with<MODEL_ID> the ID of your model.

curl -X POST -H "Authorization: Bearer 7KQH5DBEZNE2Z3H5L55I4POCYTAB3GMTSDA6HV264XGDGDSQGJACCO7M4DF5DTDGTDJI37WR4NGEPNFJZCGRGS2IBDRWF5OHIXF3SPY" -H "Cache-Control: no-cache" -H "Content-Type: multipart/form-data" -F "modelId=PF4WICRUGR2BOO7QJ5MESD56MU" -F "document=how is my package being shipped?"  https://api.einstein.ai/v2/language/intent

The response looks like this JSON. The model predicts that the text indicates that the user has a comment or question about shipping, so the model returns asShipping Info the top probability. Your app can then use this information to route the case to the right department or agent.

{
  "probabilities": [
    {
      "label": "Shipping Info",
      "probability": 0.82365495
    },
    {
      "label": "Sales Opportunity",
      "probability": 0.12523715
    },
    {
      "label": "Billing",
      "probability": 0.0487557
    },
    {
      "label": "Order Change",
      "probability": 0.0021365683
    },
    {
      "label": "Password Help",
      "probability": 0.0002156619
    }
  ],
  "object": "predictresponse"
}

 

Code :

public class EinsteinIntent {
    
    @AuraEnabled 
    public static List<Probabilities> getIntent(String sentimentModel , String textforIntent){
        
        ContentVersion base64Content = [SELECT  Title, VersionData FROM    ContentVersion WHERE   Title = 'einstein_platform' LIMIT 1 ];
        Einstein_Settings__mdt einsteinSettings = [Select DeveloperName, Label , Account_Email__c , Service_EndPoint__c , Token_EndPoint__c 
                                                   from Einstein_Settings__mdt where DeveloperName ='Intent' Limit 1]  ;   
        DateTime tokenExpireTime = DateTime.now().addMinutes(30);
        String tokenExpireTimeinUnixFormate = ''+tokenExpireTime.getTime()/1000;
        
        String keyContents = base64Content.VersionData.tostring();
        keyContents = keyContents.replace('-----BEGIN RSA PRIVATE KEY-----', '');
        keyContents = keyContents.replace('-----END RSA PRIVATE KEY-----', '');
        keyContents = keyContents.replace('\n', '');
        JWT jwt = new JWT('RS256');
        jwt.pkcs8 = keyContents; 
        jwt.iss = 'developer.force.com';
        jwt.sub = einsteinSettings.Account_Email__c ;
        jwt.aud = einsteinSettings.Token_EndPoint__c;
        jwt.exp = tokenExpireTimeinUnixFormate;
        String access_token = JWTBearerFlow.getAccessToken(einsteinSettings.Token_EndPoint__c, jwt);
        Http http = new Http();        
        HttpRequest req = new HttpRequest();
        req.setMethod('POST');
        req.setEndpoint(einsteinSettings.Service_EndPoint__c);
        req.setHeader('Authorization', 'Bearer ' + access_token);
        req.setHeader('Content-type', 'application/json');        
        String body = '{\"modelId\":\"'+ sentimentModel + '\",\"document\":\"' + textforIntent + '\"}';
        req.setBody(body);        
        HTTPResponse res = http.send(req);   
        System.debug('res'+res.getBody());
        JSONParser  parser = JSON.createParser(res.getBody()) ;
        String label ='';
        Decimal probability = 0 ;
        List<Probabilities> probabilities = new  List<Probabilities>() ;
        while (parser.nextToken() != JSONToken.END_OBJECT) {
            if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                String text = parser.getText();
                if (parser.nextToken() != JSONToken.VALUE_NULL) {
                    if (text == 'probabilities') {
                        probabilities = new List<Probabilities>();
                        while (parser.nextToken() != JSONToken.END_ARRAY) {
                            probabilities.add(new Probabilities(parser));
                        }
                    }   
                }
            }
        }
        return probabilities ;
    }
    public  class Probabilities {
        @AuraEnabled
        public String label { get; set; } 
        @AuraEnabled
        public Double probability { get; set; }
        public Probabilities(JSONParser parser) {
            while (parser.nextToken() != JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != JSONToken.VALUE_NULL) {
                        if (text == 'label') {
                            label = parser.getText();
                        } else if (text == 'probability') {
                            probability = parser.getDoubleValue();
                        }  
                    }
                }
            }
        }
    }
    
    
}

 

Lightning component

<aura:component implements="flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" 
                access="global" controller="EinsteinIntent">
    
    <aura:attribute name="modelName" type="String" default="PF4WICRUGR2BOO7QJ5MESD56MU"/>
    <aura:attribute name="textToAnlyze" type="String" default="Can I change my credit card"/>
    <aura:attribute name="predectionResult" type="List[]"/>
    
    <form class="slds-form--stacked">          
        <lightning:input aura:id="formInp" label="Enter text"
                         name="Intent Text"
                         value="{!v.textToAnlyze}"
                         required="true"/> 
        <lightning:button label="Predict " 
                          class="slds-m-top--medium"
                          variant="brand"
                          onclick="{!c.Predict}"/>
    </form>
    
    <table class="slds-table slds-table--bordered slds-table--striped" style="margin-top:30px;">
        <thead>
            <tr>
                
                <th>Label</th>
                <th>Probability</th>
                
            </tr>
        </thead>
        <tbody>
            <aura:iteration items="{!v.predectionResult}" var="predectionResultVal" >
                <tr>                
                    <td>{!predectionResultVal.label}</td>
                    
                    <td>{!predectionResultVal.probability}</td>
                </tr>
                
                
            </aura:iteration>                            
        </tbody>                  
        
    </table>
    
    
</aura:component>

 

({
    Predict : function(component, event, helper) {
         helper.load(component);
    }
})

 

({
    load: function(component) {
        
        var action = component.get("c.getIntent");
        action.setParams({
            "sentimentModel":  component.get("v.modelName") , 
            "textforIntent":  component.get("v.textToAnlyze") 
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            console.log('state'+state);
            if (state === "SUCCESS"){
                var predectionResult = response.getReturnValue();
                console.log(predectionResult);
                
                component.set("v.predectionResult" , predectionResult) ;
                
            } else if(state == "ERROR"){
                var errors = response.getError();
                console.log(errors);
            }
            
        });
        $A.enqueueAction(action);
        
        
    },
})

 

You can refer this link for additional information .

 

Salesforce Einstein Community Sentiment

Introduction

In this blog, I am going to explain how to analyze the text sentiment by using Salesforce Einstein Language pre-built sentiment model that allows you to classify the predict into positive, negative, neutral classes.Use the community sentiment model to classify text without building your own custom model. This model was created from data that comes from multiple sources. The data is short snippets of text, about one or two sentences, and similar to what you would find in a public community or Chatter group, a review/feedback forum, or enterprise social media. The final output looks below. You can enter the text for the prediction from the input box and you can see  Polar area chart with predictions details.

 

Prerequisites

Salesforce Einstein Platform Services APIs user OAuth token for authenticating. To generate a token, you create a JWT payload, sign the payload with your private key, and then call the API to get the token. So you need to get your own einstein_platform private key. please follow this steps to get your einstein_platform key.

  1. Go to the sign up page.
  2. Click Sign Up Using Salesforce.
  3. On the Salesforce login page, type your username and password, and click Log In.
  4. Click Allow so the page can access basic information, such as your email address, and perform requests.
  5. Download Key to save the key locally. The key file is einstein_platform.pem
  6. Upload the einstein_platform.pem key to Salesforce files.
  7. Copy JWTBearerFlow and JWT Apex Class from this git repository https://github.com/salesforceidentity/jwt

Refer this link for more information on the above steps.

Create custom metadata type or custom setting whatever works for you here to store the service endpoint, token endpoint and account details. Below is the custom metadata type which we are going to use it in this blog post.

 

 Static Resource and Remote Site Setting.

Here I am using d3.js, so upload the d3.js &d3pie.js files to the static resource as shown below.

Add remote site setting as shown below.

Code

Apex class is here below

public class CaseSentimentAnalysis {
    
    @AuraEnabled 
    public static List<Probabilities> getCaseAnalysis(String sentimentModel , String caseId){
        
        ContentVersion base64Content = [SELECT  Title, VersionData FROM    ContentVersion WHERE   Title = 'einstein_platform' LIMIT 1 ];
        Einstein_Settings__mdt einsteinSettings = [Select DeveloperName, Label , Account_Email__c , Service_EndPoint__c , Token_EndPoint__c 
                                                   from Einstein_Settings__mdt where DeveloperName ='CommunitySentiment' Limit 1]  ;   
        DateTime tokenExpireTime = DateTime.now().addMinutes(30);
        String tokenExpireTimeinUnixFormate = ''+tokenExpireTime.getTime()/1000;
        
        String keyContents = base64Content.VersionData.tostring();
        keyContents = keyContents.replace('-----BEGIN RSA PRIVATE KEY-----', '');
        keyContents = keyContents.replace('-----END RSA PRIVATE KEY-----', '');
        keyContents = keyContents.replace('\n', '');
        JWT jwt = new JWT('RS256');
        jwt.pkcs8 = keyContents; 
        jwt.iss = 'developer.force.com';
        jwt.sub = einsteinSettings.Account_Email__c ;
        jwt.aud = einsteinSettings.Token_EndPoint__c;
        jwt.exp = tokenExpireTimeinUnixFormate;
        String access_token = JWTBearerFlow.getAccessToken(einsteinSettings.Token_EndPoint__c, jwt);
        Case caseRec = [Select id , Description ,Subject from Case where id=:caseId] ;
        String textToAnylize = caseRec.Subject+'.'+ caseRec.Description ;
        Http http = new Http();        
        HttpRequest req = new HttpRequest();
        req.setMethod('POST');
        req.setEndpoint(einsteinSettings.Service_EndPoint__c);
        req.setHeader('Authorization', 'Bearer ' + access_token);
        req.setHeader('Content-type', 'application/json');        
        String body = '{\"modelId\":\"'+ sentimentModel + '\",\"document\":\"' + textToAnylize + '\"}';
        req.setBody(body);        
        HTTPResponse res = http.send(req);   
        System.debug('res'+res.getBody());
        JSONParser  parser = JSON.createParser(res.getBody()) ;
        String label ='';
        Decimal probability = 0 ;
        List<Probabilities> probabilities = new  List<Probabilities>() ;
        while (parser.nextToken() != JSONToken.END_OBJECT) {
            if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                String text = parser.getText();
                if (parser.nextToken() != JSONToken.VALUE_NULL) {
                    if (text == 'probabilities') {
                        probabilities = new List<Probabilities>();
                        while (parser.nextToken() != JSONToken.END_ARRAY) {
                            probabilities.add(new Probabilities(parser));
                        }
                    }   
                }
            }
        }
        return probabilities ;
    }
    public  class Probabilities {
        @AuraEnabled
        public String label { get; set; } 
        @AuraEnabled
        public Double probability { get; set; }
        public Probabilities(JSONParser parser) {
            while (parser.nextToken() != JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != JSONToken.VALUE_NULL) {
                        if (text == 'label') {
                            label = parser.getText();
                        } else if (text == 'probability') {
                            probability = parser.getDoubleValue();
                        }  
                    }
                }
            }
        }
    }
    
}

Lightning Component.

<aura:component implements="flexipage:availableForAllPageTypes"
                access="global"
                controller="CaseSentimentAnalysis">
    
    <aura:attribute name="modelName" type="String" default="CommunitySentiment"/>
    <aura:attribute name="caseId" type="String" default="5001N00000Vu19M"/>
    
    <ltng:require scripts="{!join(',',
                           $Resource.d3pie + '/d3pie/d3.min.js',
                           $Resource.d3pie + '/d3pie/d3pie.min.js')}"
                  afterScriptsLoaded="{!c.doInit}"/>
    
        <div id="pieChart"></div>
    
    
    
    
    
</aura:component>

Controller.js

({
    doInit : function(component, event, helper) {
         helper.load(component);
    }
})

helper.js

({
    load: function(component) {
        
        var action = component.get("c.getCaseAnalysis");
        action.setParams({
            "sentimentModel":  component.get("v.modelName") , 
            "caseId":  component.get("v.caseId") 
        });
        var arr = [];
        action.setCallback(this, function(response) {
            var state = response.getState();
            console.log('state'+state);
            if (state === "SUCCESS"){
                var predectionResult = response.getReturnValue();
                console.log(predectionResult);
                predectionResult.forEach((key, value) => {
                    arr.push({
                    "label": predectionResult[value].label,
                    "value": predectionResult[value].probability
                });
            });
            
            var pie = new d3pie("pieChart", {
                "header": {
                    "title": {
                        "text": "Case Sentiment Analysis",
                        "color": "#2a4b95",
                        "fontSize": 24,
                        "font": "verdana"
                    },
                    "location": "pie-center",
                    "titleSubtitlePadding": 11
                },
                "size": {
                    "canvasWidth": 500,
                    "pieInnerRadius": "78%",
                    "pieOuterRadius": "94%"
                },
                "data": {
                    "sortOrder": "value-desc",
                    
                    "content": arr
                },"labels": {
                    "outer": {
                        "pieDistance": 40
                    },
                    "inner": {
                        "hideWhenLessThanPercentage": 3
                    },
                    "mainLabel": {
                        "fontSize": 11
                    },
                    "percentage": {
                        "color": "#ffffff",
                        "decimalPlaces": 0
                    },
                    "value": {
                        "color": "#adadad",
                        "fontSize": 11
                    },
                    "lines": {
                        "enabled": true
                    },
                    "truncation": {
                        "enabled": true
                    }
                },
                "effects": {
                    "pullOutSegmentOnClick": {
                        "effect": "linear",
                        "speed": 400,
                        "size": 8
                    }
                },
                "misc": {
                    "gradient": {
                        "enabled": true,
                        "percentage": 100
                    }
                }
                
            });
            
            
            
        } else if(state == "ERROR"){
            var errors = response.getError();
            console.log(errors);
        }
        
    });
    $A.enqueueAction(action);
    
    
},
 })

 

 

 

 

 

Salesforce Einstein Sentiment

Introduction

In this blog, I am going to explain how to analyze the text sentiment by using Salesforce Einstein Language sentimental services.With Salesforce  Einstein Natural Language Sentiment analysis API you can able to extract meaning out of an unstructured text. A sentiment analysis model is used to analyze a text string and classify it with one of the labels that you provide from the model; for example, you could analyze a tweet to determine whether it is positive or negative or analyze an email to determine whether it is happy, frustrated, or sad. Behind sentiment analysis involves natural language processing to process the models to classify the intent of text or to classify text as positive, negative, and neutral or based on what you labeled. In this blog, we are going to use our own custom data model to analyze the text along with the labels like worry, happiness, sadness, love and etc from the file.You can look into the file from here  . The final output looks below. You can enter the text for the prediction from the input box and you can see  Polar area chart with predictions details.

Prerequisites

Salesforce Einstein Platform Services APIs user OAuth token for authenticating. To generate a token, you create a JWT payload, sign the payload with your private key, and then call the API to get the token. So you need to get your own einstein_platform private key. please follow this steps to get your einstein_platform key.

  1. Go to the sign up page.
  2. Click Sign Up Using Salesforce.
  3. On the Salesforce login page, type your username and password, and click Log In.
  4. Click Allow so the page can access basic information, such as your email address, and perform requests.
  5. Download Key to save the key locally. The key file is einstein_platform.pem
  6. Upload the einstein_platform.pem key to Salesforce files.
  7. Copy JWTBearerFlow and JWT Apex Class from this git repository https://github.com/salesforceidentity/jwt

Refer this link for more information on the above steps.

Create custom metadata type or custom setting whatever works for you here to store the service endpoint, token endpoint and account details. Below is the custom metadata type which we are going to use it in this blog post.

Let’s Get Started.
As we are going to user cURL for model upload and training, we need to Generate a token for authentication. Go to this link and generate the token as shown below. We are going to use this generated token for model upload and train the model for predictions.

Step 1: Collect data.

You must train your sentiment model against examples of the type of data that you are going to see when you use your model. For example, if you are trying to determine the sentiment of text and its labels. You can look into the file from here . which contains certain data set with the text and its label for prediction. Once you have collected your training samples, you will need to pre-classify each sample with a label. A label is a string that you think best describes that example, for example: “happy”, “sad”, “on the fence”.

"sad", "Feeling kind of low....", 
"excited", "OMG! Just had a fabulous day!",
"bored", "Eating eggplant. Why bother?",

Step 2: upload your dataset.

After creating a data set and labels you need to upload to upload the Einstein services API  with the below command

curl -X POST -H "Authorization: Bearer <TOKEN>" -H "Cache-Control: no-cache" -H "Content-Type: multipart/form-data" -F "data=@C:\Data\weather.csv" -F "type=text-sentiment"   https://api.einstein.ai/v2/language/datasets/upload

Replace token with a generated authentication token. And type  “text-sentiment” of HTTP header parameters indicated this prediction is for the sentiment analysis.

curl -X POST -H "Authorization: Bearer GOPCJ6HVTNQWUNN4DXWRBCVE77CJIYUDEKF6UUAEXR4GIBHBSM74HO7BHSBHQAKAW6R4VOCOK5AOOZ3UOYMIVRGYAAB23PI4OGNQ" -H "Cache-Control: no-cache" -H "Content-Type: multipart/form-data" -F "data=@C:\Users\rvakati\Desktop\New folder\SFDC Intent\sentimentsalesforce.csv" -F "type=text-sentiment"  https://api.einstein.ai/v2/language/datasets/upload

The API call is asynchronous, so you receive a dataset ID back immediately .use the dataset Id to track the status

Step 2: Get a Dataset status

Use the below command to get the data set status. Once you get the dataset status is “SUCCEEDED”, you can use that dataset for training.

curl -X GET -H "Authorization: Bearer <TOKEN>" -H "Cache-Control: no-cache" https://api.einstein.ai/v2/language/datasets/1001408
curl -X GET -H "Authorization: Bearer GOPCJ6HVTNQWUNN4DXWRBCVE77CJIYUDEKF6UUAEXR4GIBHBHY2SM74HO7BHSBHQAKAW6R4VOCOK5AOOZ3UOYMIVRGYAAB23PI4OGNQ" -H "Cache-Control: no-cache" https://api.einstein.ai/v2/language/datasets/1035097

 Step 3: train your model

 Once your dataset is upload successfully, you can able to train your data set for prediction. use the following commands to train your model.
curl -X POST -H "Authorization: Bearer <TOKEN>" -H "Cache-Control: no-cache" -H "Content-Type: multipart/form-data" -F "name=Weather Intent Model" -F "datasetId=1001411" https://api.einstein.ai/v2/language/train

 

curl -X POST -H "Authorization: Bearer GOPCJ6HVTNQWUNN4DXWRBCVE77CJIYUDEKF6UUAEXR4GIBHBHY2SM74HO7BHSBHQAKAW6R4VOCOK5AOOZ3UOYMIVRGYAAB23PI4OGNQ" -H "Cache-Control: no-cache" -H "Content-Type: multipart/form-data" -F "name=sentimentsalesforce" -F "datasetId=1035097" https://api.einstein.ai/v2/language/train

After successfully training the model. you will get model Id reference which we will use to predict the sentiment.  You need to pass this model id along with a request to predict the result.

You can use below command to track the progress of your training. When training completes successfully, you can able to use the predictions.

curl -X GET -H "Authorization: Bearer <TOKEN>" -H "Cache-Control: no-cache" https://api.einstein.ai/v2/language/train/TUWBAIRLFB3KKEDZMEGIUR6COM

Step 4: Prediction for sentiment

you can use below command to predict the sentiment from the cURL.

curl -X POST -H "Authorization: Bearer <TOKEN>" -H "Cache-Control: no-cache" -H "Content-Type: multipart/form-data" -F "modelId=WJH4YCA7YX4PCWVNCYNWYHBMY4" -F "document=I can't tell you how much fun it was" https://api.einstein.ai/v2/language/sentiment

Now add the custom metadata with alone with details. Custom metadata developer name is same as model Id.

Step 5: Static Resource and Remote Site Setting.

Here I am using chart.js, so upload the chart.js files to the static resource as shown below.

Add remote site setting as shown below.

Here is the below apex class that use to send the callouts to Einseet Service API.

public class CustomSentimentAnalysis {

    @AuraEnabled 
    public static List<Probabilities> getCaseAnalysis(String sentimentModel , String textToAnylize){
        
        ContentVersion base64Content = [SELECT  Title, VersionData FROM    ContentVersion WHERE   Title = 'einstein_platform' LIMIT 1 ];
        Einstein_Settings__mdt einsteinSettings = [Select DeveloperName, Label , Account_Email__c , Service_EndPoint__c , Token_EndPoint__c 
                                                   from Einstein_Settings__mdt where DeveloperName ='X4VBMVYDQ5RPWRKKM7LXCWM6S4Q' Limit 1]  ;   
        DateTime tokenExpireTime = DateTime.now().addMinutes(30);
        String tokenExpireTimeinUnixFormate = ''+tokenExpireTime.getTime()/1000;
        
        String keyContents = base64Content.VersionData.tostring();
        keyContents = keyContents.replace('-----BEGIN RSA PRIVATE KEY-----', '');
        keyContents = keyContents.replace('-----END RSA PRIVATE KEY-----', '');
        keyContents = keyContents.replace('\n', '');
        JWT jwt = new JWT('RS256');
        jwt.pkcs8 = keyContents; 
        jwt.iss = 'developer.force.com';
        jwt.sub = einsteinSettings.Account_Email__c ;
        jwt.aud = einsteinSettings.Token_EndPoint__c;
        jwt.exp = tokenExpireTimeinUnixFormate;
        String access_token = JWTBearerFlow.getAccessToken(einsteinSettings.Token_EndPoint__c, jwt);
        
        Http http = new Http();        
        HttpRequest req = new HttpRequest();
        req.setMethod('POST');
        req.setEndpoint(einsteinSettings.Service_EndPoint__c);
        req.setHeader('Authorization', 'Bearer ' + access_token);
        req.setHeader('Content-type', 'application/json');        
        String body = '{\"modelId\":\"'+ sentimentModel + '\",\"document\":\"' + textToAnylize + '\"}';
        req.setBody(body);        
        HTTPResponse res = http.send(req);  
       
        System.debug('res'+res.getBody());
        JSONParser  parser = JSON.createParser(res.getBody()) ;
        String label ='';
        Decimal probability = 0 ;
        List<Probabilities> probabilities = new  List<Probabilities>() ;
        while (parser.nextToken() != JSONToken.END_OBJECT) {
            if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                String text = parser.getText();
                if (parser.nextToken() != JSONToken.VALUE_NULL) {
                    if (text == 'probabilities') {
                        probabilities = new List<Probabilities>();
                        while (parser.nextToken() != JSONToken.END_ARRAY) {
                            probabilities.add(new Probabilities(parser));
                        }
                    }   
                }
            }
        }
        return probabilities ;
        
        
    }
    
    public  class Probabilities {
        @AuraEnabled
        public String label { get; set; } 
        @AuraEnabled
        public Double probability { get; set; }
        public Probabilities(JSONParser parser) {
            while (parser.nextToken() != JSONToken.END_OBJECT) {
                if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
                    String text = parser.getText();
                    if (parser.nextToken() != JSONToken.VALUE_NULL) {
                        if (text == 'label') {
                            label = parser.getText();
                        } else if (text == 'probability') {
                            probability = parser.getDoubleValue();
                        }  
                    }
                }
            }
        }
    }
    
}

Here is the lightning component

<aura:component implements="flexipage:availableForAllPageTypes"
                access="global"
                controller="CustomSentimentAnalysis">
    
    <aura:attribute name="sentiment" type="String" required="true" default="a successful shopping day"/>
    <aura:attribute name="modelId" type="String" required="true" default="4VBMVYDQ5RPWRKKM7LXCWM6S4Q"/>
    
    <ltng:require scripts="{!$Resource.ChartJS23}" afterScriptsLoaded="{!c.predictSentimenet}" />
    
        <div class="slds-text-heading_medium slds-text-align_center" style="padding: 0.5rem; background: rgb(22, 50, 92);">
            <div class="slds-text-color_inverse">Enter Custom text to classify the sentiment .</div>
        </div>
        <form class="slds-form--stacked">          
            <lightning:input aura:id="formInp" label="Enter text for Sentiment"
                             name="Sentiment Text"
                             value="{!v.sentiment}"
                             required="true"/> 
            <lightning:button label="Predict Sentiment" 
                              class="slds-m-top--medium"
                              variant="brand"
                              onclick="{!c.predictSentimenet}"/>
        </form>
        
    <canvas aura:id="polar-chart" width="500" height="150"></canvas>
    
    
    
</aura:component>

Controller.js

({
	predictSentimenet : function(component, event, helper) {
		helper.predict(component);
	}
})

helper.js

({
    predict: function(component) {
        
        var action = component.get("c.getCaseAnalysis");
        var ctx = component.find("polar-chart").getElement();
        
        action.setParams({
            "sentimentModel":  component.get("v.modelId") , 
            "textToAnylize":  component.get("v.sentiment") 
        });
        var templabels = [] ; 
        var tempdata = [] ; 
        
        action.setCallback(this, function(response) {
            var state = response.getState();
            console.log('state'+state);
            if (state === "SUCCESS"){
                var predectionResult = response.getReturnValue();
                console.log(predectionResult);
                
                predectionResult.forEach((key, value) => {
                    templabels.push(predectionResult[value].label); 
                    tempdata.push(predectionResult[value].probability*100); 
                });
                    
                    
                    new Chart(ctx, {
                    type: 'polarArea',
                    data: {
                        labels: templabels,
                        datasets: [
                            {
                                label: "Custom Sentiment analysis",
                                backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
                                data: tempdata
                            }
                        ]
                    },
                    options: {
                        title: {
                            display: true,
                            text: 'Predicted Result'
                        }
                    }
                }); 
                
                } else if(state == "ERROR"){
                    var errors = response.getError();
                    console.log(errors);
                }
                });
                    $A.enqueueAction(action);
                    
                             
                
                
            },
        })

You can able to predict the sentiment from the component as shown below.