Hi, i am using Rasa 3 but i didn’t manage to implement a sentiment analysis vader sentiment . I didn’t understand how it works … Is it possible to have a tutorial détailed about it? How to use graph component. How to find the way to put from something import SentimentAnalyzer ? Thank you for all your effort for rasa and i hope i will quickly understand all of this ^^
Hello @Hajer and welcome to the forum!
You can start with this blog post: How to Enhance Rasa NLU Models with Custom Components | Rasa Blog | The Rasa Blog | Rasa hope this will give you a better idea.
Thank you Nik202 but the version of rasa is 2 not 3. I already read it.
@Hajer Hmmm…but try to implement and see the results, coding will be the same?
Graph component is here to connect a new node with other components. In graphcomponent class, i put : from nltk.sentiment.vader import SentimentIntensityAnalyzer In sentiment.py i don’t know how to call SentimentIntensityAnalyzer… do i have to put from rasa.models import SentimentIntensityAnalyzer ?? but it doesn’t work … I don’t understand this part.
share the complete code?
import nltk
from nltk.sentiment.vader import SentimentIntensityAnalyzer
OR
pip install vaderSentiment
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
Yes okay
from __future__ import annotations
from typing import Dict, Text, Any
from rasa.engine.graph import GraphComponent, ExecutionContext
from rasa.engine.storage.resource import Resource
from rasa.engine.storage.storage import ModelStorage
#from rasa.models import SentimentIntensityAnalyzer
import os
from pathlib import Path
from rasa.shared.nlu.training_data.training_data import TrainingData
from rasa.engine.recipes.default_recipe import DefaultV1Recipe
import json
@DefaultV1Recipe.register(
DefaultV1Recipe.ComponentType.MODEL_LOADER, is_trainable=True
)
class SentimentAnalyzer(GraphComponent, SentimentIntensityAnalyzer):
"""A pre-trained sentiment component"""
name = "sentiment"
provides = ["entities"]
requires = []
defaults = {}
language_list = ["fr"]
def __init__(self, component_config= Dict[Text, Any]) -> None:
self.component_config = component_config
@classmethod
def create(
cls,
config: Dict[Text, Any],
model_storage: ModelStorage,
resource: Resource,
execution_context: ExecutionContext,
) -> GraphComponent:
return cls(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."""
pass
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"}
return entity
def process(self, message, **kwargs):
"""Retrieve the text message, pass it to the classifier
and append the prediction results to the message class."""
sid = SentimentIntensityAnalyzer()
res = sid.polarity_scores(message.text)
key, value = max(res.items(), key=lambda x: x[1])
entity = self.convert_to_rasa(key, value)
message.set("entities", [entity], add_to_output=True)
def persist(self, file_name, model_dir):
"""Pass because a pre-trained model is already persisted"""
pass
@classmethod
def load(
cls,
config: Dict[Text, Any],
model_storage: ModelStorage,
resource: Resource,
execution_context: ExecutionContext,
**kwargs: Any,
) -> SentimentAnalyzer:
model_data = {}
try:
with model_storage.read_from(resource) as path:
model_data_file = path / "model_data.json"
model_data = json.loads(rasa.shared.utils.io.read_file(model_data_file))
except (ValueError, FileNotFoundError, FileIOException):
logger.debug(
f"Couldn't load metadata for component '{cls.__name__}' as the persisted "
f"model data couldn't be loaded."
)
return cls(
config, model_data=model_data
)
from __future__ import annotations
import nltk
from nltk.sentiment.vader import SentimentIntensityAnalyzer
from typing import List, Type, Dict, Text, Any, Optional
from rasa.engine.graph import ExecutionContext
from rasa.engine.storage.resource import Resource
from rasa.engine.storage.storage import ModelStorage
class GraphComponent(SentimentIntensityAnalyzer):
"""Interface for any component which will run in a graph."""
@classmethod
def required_components(cls) -> List[Type]:
"""Components that should be included in the pipeline before this component."""
return []
@classmethod
@abstractmethod
def create(
cls,
config: Dict[Text, Any],
model_storage: ModelStorage,
resource: Resource,
execution_context: ExecutionContext,
) -> GraphComponent:
"""Creates a new `GraphComponent`.
config: This config overrides the `default_config`.
model_storage: Storage which graph components can use to persist and load
themselves.
resource: Resource locator for this component which can be used to persist
and load itself from the `model_storage`.
execution_context: Information about the current graph run.
Returns: An instantiated `GraphComponent`.
"""
...
@classmethod
def load(
cls,
config: Dict[Text, Any],
model_storage: ModelStorage,
resource: Resource,
execution_context: ExecutionContext,
**kwargs: Any,
) -> GraphComponent:
"""Creates a component using a persisted version of itself.
If not overridden this method merely calls `create`.
Args:
config: The config for this graph component. This is the default config of
the component merged with config specified by the user.
model_storage: Storage which graph components can use to persist and load
themselves.
resource: Resource locator for this component which can be used to persist
and load itself from the `model_storage`.
execution_context: Information about the current graph run.
kwargs: Output values from previous nodes might be passed in as `kwargs`.
Returns:
An instantiated, loaded `GraphComponent`.
"""
return cls.create(config, model_storage, resource, execution_context)
@staticmethod
def get_default_config() -> Dict[Text, Any]:
"""Returns the component's default config.
Default config and user config are merged by the `GraphNode` before the
config is passed to the `create` and `load` method of the component.
Returns:
The default config of the component.
"""
return {}
@staticmethod
def supported_languages() -> Optional[List[Text]]:
"""Determines which languages this component can work with.
Returns: A list of supported languages, or `None` to signify all are supported.
"""
return None
@staticmethod
def not_supported_languages() -> Optional[List[Text]]:
"""Determines which languages this component cannot work with.
Returns: A list of not supported languages, or
`None` to signify all are supported.
"""
return None
@staticmethod
def required_packages() -> List[Text]:
"""Any extra python dependencies required for this component to run."""
return []
@Hajer please check the above post of mine, and please format the code for me in a single one.
I dit import nltk from nltk.sentiment.vader import SentimentIntensityAnalyzer
I put the two code in one code. i hope it’s okay now. Thank you for your help
@Hajer can you check this thread and code used? Sentiment component - #20 by Fares
when i run my code, i got this message : GraphSchemaValidationException: Your model uses a graph component ‘SentimentAnalyzer’ which does not have the required method ‘provide’. Please make sure you’re either using the right component or that your component is registered with the correct component type.See Custom Graph Components for more information.
import nltk from nltk.sentiment.vader import SentimentIntensityAnalyzer these sentences i put them in graph component if i am not wrong.
I think it’s because i have to replace this : from rasa.models import SentimentIntensityAnalyzer by something else in sentiment.py
Yes, there can be a possibility of the issue checking the code and trying to implement the mentioned code on the blog first or thread I shared with you and then proceeding with others?
ImportError: Cannot retrieve class from path sentiment.SentimentIntensityAnalyzer. I have this error now :’(
I have a file named sentiment.py when i put a SentimentIntensityAnalyzer class inside. Normally it’s okay no?
Is your sentiment.py file is with action.py file in same folder or directory?
it wasn’t but when i put sentiment.py in action folder, it gives me the same error.
do check the code on sentiment.py try run the file using python first and then using rasa.
Thank you Nik202. I tried to do what you had tell to Fares. I run shell --debug and i have this in my screen : 021-12-21 16:21:36 DEBUG h5py._conv - Creating converter from 7 to 5 2021-12-21 16:21:36 DEBUG h5py._conv - Creating converter from 5 to 7 2021-12-21 16:21:36 DEBUG h5py._conv - Creating converter from 7 to 5 2021-12-21 16:21:36 DEBUG h5py._conv - Creating converter from 5 to 7 2021-12-21 16:21:38 INFO rasa_sdk.executor - Registered function for ‘action_conversation’. 2021-12-21 16:21:38 INFO rasa_sdk.endpoint - Action endpoint is up and running on http://0.0.0.0:5055 2021-12-21 16:21:38 DEBUG rasa_sdk.utils - Using the default number of Sanic workers (1).
Is it working ? And i am waiting to run actions --debug.
But all information will be display in the terminal ?
For information, i put sentiment.py and graph_compoenent in actions folder and i add the code action_conversation for dataframe in action.py.
see it’s saying action endpoint up and running on http://0.0.0.0:5055 and later debug you not shared, so yes well done at least you have run the code. Now try to your bot using rasa --shell or whatever is your use case. I already told you I have personally not implemented this use case, and me just trying to help you and motivate you.
@nik202 thank you, i will replace the code of sentiment.py by the code of new cusom action. I think it will be more logical. because now it’s not working about displaying sentiment of text