Custom Components - Getting Started with Rasa / Tutorials, Resources & Videos - Rasa Community Forum

👋 Introducing the Rasa Playground

Custom Components


post by shreyasap on Jan 2, 2019

Hi

I want to have a sentiment analyzer in my RASA NLU and trying to add it by using a library called TextBlob but unable to do so Here is my code so that you can help me in this

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from textblob import TextBlob

from rasa_nlu.components import Component

class SentimentAnalyzer(Component):
    """A new component"""

# Name of the component to be used when integrating it in a
    # pipeline. E.g. ``[ComponentA, ComponentB]``
    name = "SentimentAnalyzer"

# Defines what attributes the pipeline component will
    # provide when called.
    provides = ["polarity","subjectivity","sentiment_indicator"]

# Which attributes on a message are required by this
    # component.
    requires = ["tokens"]

# Defines the default configuration parameters of a component
    defaults = {}

# Defines what language(s) this component can handle.
    language_list = None

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

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

def process(self, message, **kwargs):
        testimonial = TextBlob(str(message))
        if(testimonial.sentiment.polarity > 0):
            sentiment_indicator = "Positive"
        elif(testimonial.sentiment.polarity < 0):
            sentiment_indicator = "Negative"
        else:
            sentiment_indicator = "Neutral"
        polarity = testimonial.sentiment.polarity
        subjectivity = testimonial.sentiment.polarity
        return [polarity, subjectivity, sentiment_indicator]

def persist(self, model_dir):
        pass

@classmethod
    def load(cls, model_dir=None, model_metadata=None, cached_component=None, **kwargs):
        if cached_component:
            return cached_component
        else:
            component_config = model_metadata.for_component(cls.name)
            return cls(component_config)

post by akelad on Jan 10, 2019

what exactly are you unable to do? Have you followed the advice in the documentation?

post by shreyasap on Jan 11, 2019

yes I have followed the documentation and have pasted it in the forum to know what was going wrong I am using textblob library for sentiment analysis and the output is not reflecting in NLU output So can you just check the code so that you can point out where I am going wrong and is there any video link or other link which can explain how to build an end to end custom component for NLU or how we can integrate sentiment analyzer in NLU I am doing this as a Proof of concept for my company so that I can showcase this to potential client as a solution. My email Id is Shreyas.a.p@accenture.com so that if we can connect on this problem I am ready to go forward

post by darkblueorange on Apr 18, 2020

import typing
from typing import Any, Optional, Text, Dict, List, Type
from rasa.nlu.components import Component
from rasa.nlu import utils
if typing.TYPE_CHECKING:
   from rasa.nlu.model import Metadata
import rasa.utils.io as io_utils
from textblob import TextBlob

from rasa.nlu.config import RasaNLUModelConfig
from rasa.nlu.training_data import Message, TrainingData
from rasa.nlu.tokenizers.tokenizer import Tokenizer

class SentimentAnalyzer(Component):
    """A custom sentiment analysis component"""

@classmethod
    def required_components(cls) -> List[Type[Component]]:
        return [Tokenizer]

language_list = None
    defaults = {}
    provides = ["entities"]
    name = "sentiment"

def __init__(self, component_config: Optional[Dict[Text, Any]] = None) -> None:
        super().__init__(component_config)

def train(
        self,
        training_data: TrainingData,
        config: Optional[RasaNLUModelConfig] = None,
        **kwargs: Any,
    ) -> None:
        pass

def convert_to_rasa(self, sentiment, confidence):
        entity = {"value": sentiment,
                  "entity": "sentiment",
                  "confidence": confidence,
                  "extractor": "sentiment_extractor"}
        return entity

def preprocessing(self, tokens):
        pass

def process(self, message: Message, **kwargs: Any) -> None:
        testimonial = TextBlob(str(message.text))
        if (testimonial.sentiment.polarity > 0):
                sentiment = "pos"
        elif (testimonial.sentiment.polarity < 0):
                sentiment = "neg"
        else:
                sentiment = "neu"
        confidence = (abs(abs(testimonial.sentiment.polarity) - 0.5)) / 0.5
        entity = self.convert_to_rasa(sentiment, confidence)
        message.set("entities", [entity], add_to_output=True)

def persist(self, file_name: Text, model_dir: Text) -> Optional[Dict[Text, Any]]:
        pass

@classmethod
    def load(
        cls,
        meta: Dict[Text, Any],
        model_dir: Optional[Text] = None,
        model_metadata: Optional["Metadata"] = None,
        cached_component: Optional["Component"] = None,
        **kwargs: Any,
    ) -> "Component":
        if cached_component:
            return cached_component
        else:
            return cls(meta)

Based on RASA 1.9.4

All in Docker (added TextBlob in RASA Docker requirements.txt)
It works (much better in english than in french, I guess due to TextBlob performance)