Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

The code for all the services can be found at https://bitbucket.org/socialroboticshub/processing/src/master/ . Creating a new service can be done as follows, and then included in the repository by opening a Pull Request:

Summarised Steps

  1. create a new folder in https://bitbucket.org/socialroboticshub/processing/src/master/ with the name of the service

  2. copy the certificate file https://bitbucket.org/socialroboticshub/docker/src/master/cbsr/beamforming/cert.pem from any of the other services' folders into the service’s folder

  3. copy any additional files that the services may need into the service’s folder

  4. create a factory file inheriting from the CBSRFactory in the service’s folder, and override the superclass’s methods

  5. create a service file inheriting from CBSRService in the service’s folder, and override the superclass’s methods

  6. update the https://bitbucket.org/socialroboticshub/processing/src/master/deploy_to_docker.sh file in the root folder with the new service files

  7. deploy the new service to the https://bitbucket.org/socialroboticshub/docker/src/master/ folder by running the deploy_to_docker.sh file

  8. update the https://bitbucket.org/socialroboticshub/docker/src/master/docker-compose.yml file in the docker folder with the new service

  9. update the https://bitbucket.org/socialroboticshub/docker/src/master/Dockerfile.python3 file in the docker folder with the new service’s dependencies

  10. update the topics in the constructor of the Abstract Connector from the https://bitbucket.org/socialroboticshub/connectors/src/master/python/social_interaction_cloud/ folder with the name of the new service

  11. update the device listeners in enable_service in the Abstract Connector with the service

  12. update the listened to channels in __listen in the Abstract Connector with the service

  13. create the corresponding event handler method for the service in the Abstract Connector

  14. create the corresponding event handler method for the service in the Basic Connector

  15. use the service in a new file

The detailed explanation of these steps with a sentiment analysis example can be found below:

Detailed Steps

  1. create a new folder in https://bitbucket.org/socialroboticshub/processing/src/master/ with the name of the service. sentiment_analysis (https://bitbucket.org/socialroboticshub/docker/src/master/cbsr/sentiment/ ) will be used as the example folder and service in this case

  2. copy the certificate file https://bitbucket.org/socialroboticshub/docker/src/master/cbsr/beamforming/cert.pem from any of the other services' folders into the sentimentfolder

  3. copy the https://bitbucket.org/socialroboticshub/docker/src/master/cbsr/sentiment/classifier.pickle into the sentiment folder

  4. create a https://bitbucket.org/socialroboticshub/docker/src/master/cbsr/sentiment/sentiment_factory.py file in the sentiment folder

from os import getcwd

from cbsr.factory import CBSRfactory
from nltk import download
from nltk.data import path

from sentiment_service import SentimentAnalysisService


class SentimentAnalysisFactory(CBSRfactory):
    def __init__(self):
        super(SentimentAnalysisFactory, self).__init__()

    def get_connection_channel(self):
        return 'sentiment_analysis'

    def create_service(self, connect, identifier, disconnect):
        return SentimentAnalysisService(connect, identifier, disconnect)


if __name__ == '__main__':
    cwd = getcwd()
    download('punkt', download_dir=cwd)
    download('omw-1.4', download_dir=cwd)
    download('averaged_perceptron_tagger', download_dir=cwd)
    download('wordnet', download_dir=cwd)
    path.append(cwd)

    sentiment_analysis_factory = SentimentAnalysisFactory()
    sentiment_analysis_factory.run()

5. create a https://bitbucket.org/socialroboticshub/docker/src/master/cbsr/sentiment/sentiment_service.py file in the sentiment folder

""" This file shows an example of a sentiment service that uses the text_transcript channel result
    from the Dialogflow speech-to-text to get the the type of sentiment
"""

from pickle import load
from re import sub
from string import punctuation

from cbsr.service import CBSRservice
from nltk.stem.wordnet import WordNetLemmatizer
from nltk.tag import pos_tag
from nltk.tokenize import word_tokenize


class SentimentAnalysisService(CBSRservice):
    def __init__(self, connect, identifier, disconnect):
        super(SentimentAnalysisService, self).__init__(connect, identifier, disconnect)
        with open('classifier.pickle', 'rb') as pickle:
            self.classifier = load(pickle)
        self.lemmatizer = WordNetLemmatizer()

    def get_device_types(self):
        return ['mic']

    def get_channel_action_mapping(self):
        return {self.get_full_channel('text_transcript'): self.execute}

    def execute(self, message):
        sentence = message['data'].decode()
        tokens = self.remove_noise(word_tokenize(sentence))
        sentiment = self.classifier.classify(dict([token, True] for token in tokens))
        print(sentiment)
        self.publish('text_sentiment', sentiment)
...

6. update the https://bitbucket.org/socialroboticshub/processing/src/master/deploy_to_docker.sh file in the root folder with the new service files

...
echo Deploying my_service...
cd ../my_service
cp -f {cert.pem,  *.py, classifier.pickle} ../../docker/cbsr/my_service    # extra files can be copied if used
...

7. deploy the new service to the https://bitbucket.org/socialroboticshub/docker/src/master/ folder by running the deploy_to_docker.sh file

8. update the https://bitbucket.org/socialroboticshub/docker/src/master/docker-compose.yml file in the docker folder with the new service

...
# ------------------------------------------------------------
# Sentiment Analysis
# ------------------------------------------------------------
sentiment_analysis:
  image: python3
  build:
    context: .
    dockerfile: Dockerfile.python3
  hostname: sentiment_analysis
  user: "${NEW_UID}:${NEW_GID}"
  env_file:
    - ./.env

  working_dir: /my_service
  command: python3 sentiment_factory.py
  volumes:
    - ./cbsr/mock:/sentiment:rw${MOUNT_OPTIONS}

  tty: true
  stdin_open: false

  networks:
    app_net:
      ipv4_address: 172.16.238.x   # address has to differ from those of the already existing services' 

  depends_on:
    - redis
    - dialogflow
  # - any other services the service depends on
...

9. update the https://bitbucket.org/socialroboticshub/docker/src/master/Dockerfile.python3 file in the docker folder with the new service’s dependencies

RUN pip3 install --no-cache-dir --upgrade --prefer-binary \
	redis~=4.1 \
	hiredis~=2.0 \
	simplejson~=3.17 \
	Pillow~=9.0 \
	numpy~=1.22 \
	imutils~=0.5 \
	[any other dependendencies] \
	...

10. update the topics in the constructor of the Abstract Connector abstract_connector.py from the https://bitbucket.org/socialroboticshub/connectors/src/master/python/social_interaction_cloud/ folder with the name of the new service

topics = [..., 'text_sentiment']

11. update the corresponding list of devices listeners in enable_service in abstract_connector.py with my_service

...
###########################
# Management              #
###########################

def enable_service(self, name: str) -> None:
    ...
    elif ... and name == 'sentiment_analysis':
        for mic in self.devices[self.device_types['mic']]:
            pipe.publish(name, mic)
    ...

12. update the channels in __listen in abstract_connector.py with my_service

...
elif channel = 'text_sentiment':
    self.on_text_sentiment(message=data.decode('utf-8'))
...

13. create the corresponding event handler method on_my_service in abstract_connector.py

...
###########################
# Event handlers          #
###########################
...
def on_text_sentiment(self, message: str) -> None:
    pass
...

14. create the corresponding inherited event handler method on_my_service in basic_connector.py

...
###########################
# Event handlers          #
###########################
...
def on_text_sentiment(self, message: str) -> None:
    """ :param message: the message published on the text_sentiment channel
        This method notifies the listeners that a new message has been posted on the text_sentiment channel;
        This method can be further inherited and overridden
    """
    self.__notify_listeners('onTextSentiment', message)
...

15. use the new service by creating a new file sentiment_example.py, overriding the on_text_sentiment method and running it

from enum import Enum
from functools import partial
from social_interaction_cloud.action import ActionRunner
from social_interaction_cloud.basic_connector import BasicSICConnector

class SentimentConnector(BasicSICConnector):
    def __init__(self, server_ip: str, dialogflow_key_file: str, dialogflow_agent_id: str):
        super(SentimentConnector, self).__init__(server_ip, 'en-US', dialogflow_key_file, dialogflow_agent_id)
        self.enable_service('sentiment_analysis')
        self.sentiment = None
    
    def on_text_sentiment(self, sentiment: str) -> None:
        print(sentiment)
        self.sentiment = sentiment

class Example:
    def __init__(self, server_ip: str, dialogflow_key_file: str, dialogflow_agent_id: str):
        self.sic = SentimentConnector(server_ip, dialogflow_key_file, dialogflow_agent_id)
        self.action_runner = ActionRunner(self.sic)

        self.recognition_manager = RecognitionManager(2)
        self.user_model = {}
...

  • No labels