Sentiment component

hi, @Juste I follow your tutoriel Enhancing Rasa NLU models with Custom Components | by Justina Petraityte | Rasa Blog | Medium to create a sentiment component, so I did this:

  1. create the sentiments.py
  2. update my pipeline in config.yml
  3. create the labels.txt

I have trained my bot but when i run it (rasa shell --debug) i get nothing and i can’t print the sentiment and the confidence?

hello @erohmensing how can i do to print setiment predicted and confidence ?

@Fares Hello! Did you code is working fine? did you checked the logs of actions? I hope you have seen this doc : Testing Your Assistant

Hi @nik202 , Ok i will check it

Hi, @nik202 actually the code run and i have checked the link but i didn’t understand how to print out the pridected sentiment with it’s confidence like this

@Fares I guess you need to use custom action for that, did you tried that?

@Fares Are you able to get the individual score you can store in some variable and then you can print like data frame?

@Fares But, can I ask why you need to see this confidence?

@nik202 the reason is to check if this sentiment component works or not? car when i run rasa train then rasa shell nlu it gives me nothing about pridected sentiment. Allreight, my goal is to use sentiment component to pridect user sentiment (pos, neu or neg) to use it in conversation so my bot check the sentiment every message of user then decide how to response!

@Fares That, infect a great approach but in real time scenario and processing it can be difficult, I hope you know this fact also? I guess you are working on Voice bot. If you need any thing related to Vader Sentiment please feel free to ask. :slight_smile:

Thanks @nik202, yes I still working on voice bot and until know i didn’t understand how can my rasa bot understand voice-message sent from Telegram or Messenger. In the same time Analyzing Sentiments hhhh. I have a lot of work :upside_down_face:

@nik202 please can you tell me how to get the individual score, store it in some variable and print it as data frame?

@Fares If you have developed the Sentiment Analysis and you are able to get the PN& Ne sentiments, you can store this in data frame or excel sheet, and the fetch the data again, for that you need to write the python code. Please try run this code and check what data you are getting it.

class ActionConversation(Action):

    def name(self) -> Text:
        return "action_conversation"

    def run(self, dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:

        conversation = tracker.events
        print(conversation)
         return []

It will show you everything what ever your bot is doing at the backend, while using tracker.events (JSON Data) you can analyse the sentiment of the user. It kind of typical process.

@nik202 so if I understood correctly I will add this class (action_conversation) in my actions.py file then declare it in domaine.yml then run the command rasa run actions?

@Fares yes and check what data is will display in the action server, you will get the idea what I am saying.

hi, @nik202 i did what you said but this what the server action show me

and it still like this even if i run conversation with the bot in other terminal

@Fares Did you chat with your bot in another terminal and see action logs?

Sorry @nik202 I know that i’m not good in developping. I can’t find action log

@Fares you are doing just fine by the way whilst developing the voice bot :slight_smile:

Step1: Run rasa server port 5005

rasa shell --debug

Step2: Run rasa action server on port 5055

rasa run actions --debug

Whilst you chat with your bot or doing anything which are related to custom action you will see in action server screen. I hope you got it now?

thanks @nik yep now i see everything but nothing is indicated about sentiment I check back my config file and the custom component exist and i run rasa train again and every thing run as ok but nothing about this sentiment component

@Fares you need to add print statement in the custom code for sentiments then it will be shown in the logs :slight_smile:

Hi @nik202 I hope I not disturbing you this is my sentiment.py where i put print (sentiment), print (confidence). I added the sentiment component in the registry.py

from rasa.nlu.components import Component
from rasa.nlu import utils
from rasa.nlu.model import Metadata

import nltk
from nltk.classify import NaiveBayesClassifier
import os

import typing
from typing import Any, Optional, Text, Dict

SENTIMENT_MODEL_FILE_NAME = "sentiment_classifier.pkl"

class SentimentAnalyzer(Component):
    """A custom sentiment analysis component"""
    name = "sentiment"
    provides = ["entities"]
    requires = ["tokens"]
    defaults = {}
    language_list = ["en"]
    print('initialised the class')

    def __init__(self, component_config=None):
        super(SentimentAnalyzer, self).__init__(component_config)


def train(self, training_data, cfg, **kwargs):

    """Load the sentiment polarity labels from the text
       file, retrieve training tokens and after formatting
       data train the classifier."""
    with open('labels.txt','r') as f:
        labels = f.read().splitlines()
    training_data = training_data.training_examples #list of Message objects
    tokens = [list(map(lambda x: x.text, t.get('tokens'))) for t in training_data]
    processed_tokens = [self.preprocessing(t) for t in tokens]
    labeled_data = [(t, x) for t,x in zip(processed_tokens, labels)]
    self.clf = NaiveBayesClassifier.train(labeled_data)


    def convert_to_rasa(self, value, confidence):
        """Convert model output into the Rasa NLU compatible output format."""

        entity = {"value": value,
                  "confidence": confidence,
                  "entity": "sentiment",
                  "extractor": "sentiment_extractor"}
        print(entity)
        return entity
        

    def preprocessing(self, tokens):
        """Create bag-of-words representation of the training examples."""
        print(tokens)
        return ({word: True for word in tokens})


    def process(self, message, **kwargs):
        """Retrieve the tokens of the new message, pass it to the classifier
            and append prediction results to the message class."""
        
        if not self.clf:
            # component is either not trained or didn't
            # receive enough training data
            entity = None
        else:
            tokens = [t.text for t in message.get("tokens")]
            tb = self.preprocessing(tokens)
            pred = self.clf.prob_classify(tb)

            sentiment = pred.max()
            confidence = pred.prob(sentiment)

            entity = self.convert_to_rasa(sentiment, confidence)
            print(entity)
            print(sentiment)
            print(confidence)
            message.set("entities", [entity], add_to_output=True)


    def persist(self, file_name, model_dir):
        """Persist this model into the passed directory."""
        classifier_file = os.path.join(model_dir, SENTIMENT_MODEL_FILE_NAME)
        utils.json_pickle(classifier_file, self)

        return {"classifier_file": SENTIMENT_MODEL_FILE_NAME}

    @classmethod
    def load(cls,
             meta: Dict[Text, Any],
             model_dir=None,
             model_metadata=None,
             cached_component=None,
             **kwargs):
        file_name = meta.get("classifier_file")
        classifier_file = os.path.join(model_dir, file_name)
        return utils.json_unpickle(classifier_file)

after that i trained the model then run it with shell --debug and like you see nothing about sentiment entity?