diff --git a/Makefile b/Makefile index 48bb5b8..35f0223 100644 --- a/Makefile +++ b/Makefile @@ -3,19 +3,20 @@ NAME=senpycommunity REPO=gsiupm PLUGINS= $(filter %/, $(wildcard */)) IMAGENAME=gsiupm/senpy-plugins-community -DOCKER_FLAGS= +DOCKER_FLAGS=-e MOCK_REQUESTS=$(MOCK_REQUESTS) DEV_PORT?=5000 ifdef SENPY_FOLDER DOCKER_FLAGS+= -v $(realpath $(SENPY_FOLDER)):/usr/src/app/ endif - all: build run -test-fast: +test-fast-%: docker run $(DOCKER_FLAGS) -v $$PWD/$*:/senpy-plugins/ -v $$PWD/data:/data/ --rm $(IMAGEWTAG) --only-test $(TEST_FLAGS) +test-fast: test-fast-/ + test: docker-build test-fast dev: diff --git a/sentiment-taiger/README.md b/sentiment-taiger/README.md new file mode 100644 index 0000000..7199d4f --- /dev/null +++ b/sentiment-taiger/README.md @@ -0,0 +1,62 @@ +# Senpy Plugin Taiger + +Service that analyzes sentiments from social posts written in Spanish or English. + + +## Usage + +To use this plugin, you should use a GET Requests with the following possible params: +Params: +- Input: text to analyse.(required) +- Endpoint: Enpoint to the Taiger service. + +## Example of Usage + +Example request: +``` +http://senpy.cluster.gsi.dit.upm.es/api/?algo=sentiment-taiger&inputText=This%20is%20amazing +``` + +Example respond: This plugin follows the standard for the senpy plugin response. For more information, please visit [senpy documentation](http://senpy.readthedocs.io). Specifically, NIF API section. + +For example, this would be the example respond for the request done. + +``` +{ + "@context": "http://localhost:5005/api/contexts/Results.jsonld", + "@id": "_:Results_1532449339.5887764", + "@type": "results", + "analysis": [ + "endpoint:plugins/sentiment-taiger_0.1" + ], + "entries": [ + { + "@id": "#", + "@type": "entry", + "emotions": [], + "entities": [], + "nif:isString": "This is amazing", + "sentiments": [ + { + "@id": "Opinion0", + "@type": "sentiment", + "marl:hasPolarity": "marl:Positive", + "marl:polarityValue": -1.4646806570973374, + "normalizedText": "This is amazing", + "prov:wasGeneratedBy": "endpoint:plugins/sentiment-taiger_0.1" + } + ], + "suggestions": [], + "topics": [] + } + ] +} +``` + +As it can be seen, this plugin analyzes sentiment givin three categories or tags: `marl:Positive`, `marl:Neutral` or `marl:Negative`, that will be held in the `marl:hasPolarity` field. Moreover, the plugin retrieves a `marl:polarityValue`. +This plugin supports **python2.7** and **python3**. + +![alt GSI Logo][logoGSI] + +[logoGSI]: http://www.gsi.dit.upm.es/images/stories/logos/gsi.png "GSI Logo" + diff --git a/sentiment-taiger/docker-compose.yml b/sentiment-taiger/docker-compose.yml new file mode 100644 index 0000000..fbcaf03 --- /dev/null +++ b/sentiment-taiger/docker-compose.yml @@ -0,0 +1,11 @@ +version: '3' +services: + dev: + image: gsiupm/senpy:latest + working_dir: "/senpy-plugins" + ports: + - "127.0.0.1:5005:5000" + volumes: + - ".:/senpy-plugins" + environment: + TAIGER_ENDPOINT: 'http://34.244.91.7:8080/sentiment/classifyPositivity' diff --git a/sentiment-taiger/taiger_plugin.py b/sentiment-taiger/taiger_plugin.py new file mode 100644 index 0000000..82460d8 --- /dev/null +++ b/sentiment-taiger/taiger_plugin.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- + +import time +import requests +import json +import string +import os +from os import path +import time +from senpy.plugins import SentimentPlugin +from senpy.models import Results, Entry, Entity, Topic, Sentiment, Error + + +TAIGER_ENDPOINT = os.environ.get("TAIGER_ENDPOINT", 'http://134.244.91.7:8080/sentiment/classifyPositivity') + + +class TaigerPlugin(SentimentPlugin): + ''' + Service that analyzes sentiments from social posts written in Spanish or English. + + Example request: + + http://senpy.cluster.gsi.dit.upm.es/api/?algo=sentiment-taiger&inputText=This%20is%20amazing + ''' + name = 'sentiment-taiger' + author = 'GSI UPM' + version = "0.1" + maxPolarityValue = 0 + minPolarityValue = -10 + + def _polarity(self, value): + + if 'neu' in value: + polarity = 'marl:Neutral' + elif 'neg' in value: + polarity = 'marl:Negative' + elif 'pos' in value: + polarity = 'marl:Positive' + return polarity + + def analyse_entry(self, entry, params): + + txt = entry['nif:isString'] + api = TAIGER_ENDPOINT + parameters = { + 'inputText': txt + } + try: + r = requests.get( + api, params=parameters, timeout=3) + api_response = r.json() + except requests.exceptions.Timeout: + raise Error("No response from the API") + except Exception as ex: + raise Error("There was a problem with the endpoint: {}".format(ex)) + if not api_response.get('positivityCategory'): + raise Error('No positive category in response: {}'.format(r.json())) + self.log.debug(api_response) + agg_polarity = self._polarity(api_response.get('positivityCategory')) + normalized_text = api_response.get('normalizedText', None) + agg_opinion = Sentiment( + id="Opinion0", + marl__hasPolarity=agg_polarity, + marl__polarityValue=api_response['positivityScore'] + ) + agg_opinion["normalizedText"] = api_response['normalizedText'] + agg_opinion.prov(self) + entry.sentiments.append(agg_opinion) + + yield entry + + test_cases = [ + { + 'params': { + 'algo': 'sentiment-taiger', + 'intype': 'direct', + 'expanded-jsonld': 0, + 'informat': 'text', + 'prefix': '', + 'plugin_type': 'analysisPlugin', + 'urischeme': 'RFC5147String', + 'outformat': 'json-ld', + 'conversion': 'full', + 'language': 'en', + 'apikey': '00000', + 'algorithm': 'sentiment-taiger' + }, + 'input': 'I hate to say this', + 'expected': { + 'sentiments': [ + {'marl:hasPolarity': 'marl:Negative'}], + }, + 'responses': [ + { + 'url': TAIGER_ENDPOINT, + 'json': { + "inputText": "I hate to say this", + "normalizedText": "I hate to say this", + "positivityScore": -1.8951251587831475, + "positivityCategory": "neg" + } + } + ] + }, + { + 'params': { + 'algo': 'sentiment-taiger', + 'intype': 'direct', + 'expanded-jsonld': 0, + 'informat': 'text', + 'prefix': '', + 'plugin_type': 'analysisPlugin', + 'urischeme': 'RFC5147String', + 'outformat': 'json-ld', + 'conversion': 'full', + 'language': 'en', + 'apikey': '00000', + 'algorithm': 'sentiment-taiger' + }, + 'input': 'This is amazing', + 'expected': { + 'sentiments': [ + {'marl:hasPolarity': 'marl:Positive'}], + }, + 'responses': [ + { + 'url': TAIGER_ENDPOINT, + 'json': { + "inputText": "This is amazing ", + "normalizedText": "This is amazing", + "positivityScore": -1.4646806570973374, + "positivityCategory": "pos" + } + } + ] + }, + { + 'params': { + 'algo': 'sentiment-taiger', + 'intype': 'direct', + 'expanded-jsonld': 0, + 'informat': 'text', + 'prefix': '', + 'plugin_type': 'analysisPlugin', + 'urischeme': 'RFC5147String', + 'outformat': 'json-ld', + 'conversion': 'full', + 'language': 'en', + 'apikey': '00000', + 'algorithm': 'sentiment-taiger' + }, + 'input': 'The pillow is in the wardrobe', + 'expected': { + 'sentiments': [ + {'marl:hasPolarity': 'marl:Neutral'}], + }, + 'responses': [ + { + 'url': TAIGER_ENDPOINT, + 'json': { + "inputText": "The pillow is in the wardrobe", + "normalizedText": "The pillow is in the wardrobe", + "positivityScore": -2.723999097522657, + "positivityCategory": "neu" + } + } + ] + } + + + ] + + +if __name__ == '__main__': + from senpy import easy_test + easy_test()