diff --git a/indicoio/__init__.py b/indicoio/__init__.py index 098a4a9..0646c43 100644 --- a/indicoio/__init__.py +++ b/indicoio/__init__.py @@ -1,10 +1,22 @@ +from functools import partial +from utils import config + JSON_HEADERS = {'Content-type': 'application/json', 'Accept': 'text/plain'} -Version, version, __version__, VERSION = ('0.4.4',) * 4 +Version, version, __version__, VERSION = ('0.4.5',) * 4 from text.sentiment import political, posneg from text.sentiment import posneg as sentiment from text.lang import language from images.fer import fer from images.features import facial_features -from images.features import image_features \ No newline at end of file +from images.features import image_features + +political = partial(political, config.api_root) +posneg = partial(posneg, config.api_root) +sentiment = partial(sentiment, config.api_root) +posneg = partial(sentiment, config.api_root) +language = partial(language, config.api_root) +fer = partial(fer, config.api_root) +facial_features = partial(facial_features, config.api_root) +image_features = partial(image_features, config.api_root) diff --git a/indicoio/images/features.py b/indicoio/images/features.py index d6b049b..cd56087 100644 --- a/indicoio/images/features.py +++ b/indicoio/images/features.py @@ -6,7 +6,7 @@ import numpy as np from indicoio import JSON_HEADERS from indicoio.utils import image_preprocess -def facial_features(image): +def facial_features(api_root, image): """ Given an grayscale input image of a face, returns a 48 dimensional feature vector explaining that face. Useful as a form of feature engineering for face oriented tasks. @@ -30,14 +30,14 @@ def facial_features(image): """ data_dict = json.dumps({"face": image}) - response = requests.post("http://api.indico.io/facialfeatures", data=data_dict, headers=JSON_HEADERS) + response = requests.post(api_root + "facialfeatures", data=data_dict, headers=JSON_HEADERS) response_dict = response.json() if 'response' not in response_dict: raise ValueError(response_dict.values()[0]) else: return response_dict['response'] -def image_features(image): +def image_features(api_root, image): """ Given an input image, returns a 2048 dimensional sparse feature vector explaining that image. Useful as a form of feature engineering for image oriented tasks. @@ -69,7 +69,7 @@ def image_features(image): """ image = image_preprocess(image) data_dict = json.dumps({"image": image}) - response = requests.post("http://api.indico.io/imagefeatures", data=data_dict, headers=JSON_HEADERS) + response = requests.post(api_root + "imagefeatures", data=data_dict, headers=JSON_HEADERS) response_dict = response.json() if 'Features' not in response_dict: raise ValueError(response_dict.values()[0]) diff --git a/indicoio/images/fer.py b/indicoio/images/fer.py index f66e063..27f8162 100644 --- a/indicoio/images/fer.py +++ b/indicoio/images/fer.py @@ -4,7 +4,7 @@ import requests import numpy as np from indicoio import JSON_HEADERS -def fer(image): +def fer(api_root, image): """ Given a grayscale input image of a face, returns a probability distribution over emotional state. Input should be in a list of list format, resizing will be attempted internally but for best @@ -29,7 +29,7 @@ def fer(image): """ data_dict = json.dumps({"face": image}) - response = requests.post("http://api.indico.io/fer", data=data_dict, headers=JSON_HEADERS) + response = requests.post(api_root + "fer", data=data_dict, headers=JSON_HEADERS) response_dict = response.json() if len(response_dict) < 2: raise ValueError(response_dict.values()[0]) diff --git a/indicoio/local/__init__.py b/indicoio/local/__init__.py new file mode 100644 index 0000000..2d50e7f --- /dev/null +++ b/indicoio/local/__init__.py @@ -0,0 +1,20 @@ +from functools import partial +from indicoio.utils import config + +JSON_HEADERS = {'Content-type': 'application/json', 'Accept': 'text/plain'} + +from indicoio.text.sentiment import political, posneg +from indicoio.text.sentiment import posneg as sentiment +from indicoio.text.lang import language +from indicoio.images.fer import fer +from indicoio.images.features import facial_features +from indicoio.images.features import image_features + +political = partial(political, config.local_api_root) +posneg = partial(posneg, config.local_api_root) +sentiment = partial(sentiment, config.local_api_root) +posneg = partial(sentiment, config.local_api_root) +language = partial(language, config.local_api_root) +fer = partial(fer, config.local_api_root) +facial_features = partial(facial_features, config.local_api_root) +image_features = partial(image_features, config.local_api_root) diff --git a/indicoio/text/lang.py b/indicoio/text/lang.py index d4b6767..665522d 100644 --- a/indicoio/text/lang.py +++ b/indicoio/text/lang.py @@ -3,7 +3,7 @@ import json from indicoio import JSON_HEADERS -def language(text): +def language(api_root, text): """ Given input text, returns a probability distribution over 33 possible languages of what language the text was written in. @@ -27,7 +27,7 @@ def language(text): """ data_dict = json.dumps({'text': text}) - response = requests.post("http://api.indico.io/language", data=data_dict, headers=JSON_HEADERS) + response = requests.post(api_root + "language", data=data_dict, headers=JSON_HEADERS) response_dict = response.json() if len(response_dict) < 2: raise ValueError(response_dict.values()[0]) diff --git a/indicoio/text/sentiment.py b/indicoio/text/sentiment.py index ba5e8fe..b570f5f 100644 --- a/indicoio/text/sentiment.py +++ b/indicoio/text/sentiment.py @@ -4,7 +4,7 @@ import json from indicoio import JSON_HEADERS from indicoio.utils import normalize -def political(text): +def political(api_root, text): """ Given input text, returns a probability distribution over the political alignment of the speaker. @@ -31,14 +31,14 @@ def political(text): """ data_dict = json.dumps({'text': text}) - response = requests.post("http://api.indico.io/political", data=data_dict, headers=JSON_HEADERS) + response = requests.post(api_root + "political", data=data_dict, headers=JSON_HEADERS) response_dict = response.json() if len(response_dict) < 2: raise ValueError(response_dict.values()[0]) else: return response_dict -def posneg(text): +def posneg(api_root, text): """ Given input text, returns a scalar estimate of the sentiment of that text. Values are roughly in the range 0 to 1 with 0.5 indicating neutral sentiment. @@ -60,7 +60,7 @@ def posneg(text): """ data_dict = json.dumps({'text': text}) - response = requests.post("http://api.indico.io/sentiment", data=data_dict, headers=JSON_HEADERS) + response = requests.post(api_root + "sentiment", data=data_dict, headers=JSON_HEADERS) response_dict = response.json() if 'Sentiment' not in response_dict: raise ValueError(response_dict.values()[0]) diff --git a/indicoio/utils/config.py b/indicoio/utils/config.py new file mode 100644 index 0000000..f6b622e --- /dev/null +++ b/indicoio/utils/config.py @@ -0,0 +1,2 @@ +local_api_root = "http://localhost:9438/" +api_root = "http://api.indico.io/" \ No newline at end of file diff --git a/tests/test_local.py b/tests/test_local.py new file mode 100644 index 0000000..241d7da --- /dev/null +++ b/tests/test_local.py @@ -0,0 +1,90 @@ +import unittest + +import numpy as np + +from indicoio.local import political, sentiment, fer, facial_features, language + + +class FullAPIRun(unittest.TestCase): + + def test_political(self): + political_set = set(['Libertarian', 'Liberal', 'Conservative', 'Green']) + test_string = "Guns don't kill people, people kill people." + response = political(test_string) + + self.assertTrue(isinstance(response, dict)) + self.assertEqual(political_set, set(response.keys())) + + def test_posneg(self): + posneg_set = set(['Sentiment']) + test_string = "Worst song ever." + response = sentiment(test_string) + + self.assertTrue(isinstance(response, float)) + + def test_good_fer(self): + fer_set = set(['Angry', 'Sad', 'Neutral', 'Surprise', 'Fear', 'Happy']) + test_face = np.linspace(0,50,48*48).reshape(48,48).tolist() + response = fer(test_face) + + self.assertTrue(isinstance(response, dict)) + self.assertEqual(fer_set, set(response.keys())) + + def test_bad_fer(self): + fer_set = set(['Angry', 'Sad', 'Neutral', 'Surprise', 'Fear', 'Happy']) + test_face = np.linspace(0,50,56*56).reshape(56,56).tolist() + response = fer(test_face) + + self.assertTrue(isinstance(response, dict)) + self.assertEqual(fer_set, set(response.keys())) + + def test_good_facial_features(self): + test_face = np.linspace(0,50,48*48).reshape(48,48).tolist() + response = facial_features(test_face) + + self.assertTrue(isinstance(response, list)) + self.assertEqual(len(response), 48) + + def test_language(self): + language_set = set([ + 'English', + 'Spanish', + 'Tagalog', + 'Esperanto', + 'French', + 'Chinese', + 'French', + 'Bulgarian', + 'Latin', + 'Slovak', + 'Hebrew', + 'Russian', + 'German', + 'Japanese', + 'Korean', + 'Portuguese', + 'Italian', + 'Polish', + 'Turkish', + 'Dutch', + 'Arabic', + 'Persian (Farsi)', + 'Czech', + 'Swedish', + 'Indonesian', + 'Vietnamese', + 'Romanian', + 'Greek', + 'Danish', + 'Hungarian', + 'Thai', + 'Finnish', + 'Norwegian', + 'Lithuanian' + ]) + language_dict = language('clearly an english sentence') + self.assertEqual(language_set, set(language_dict.keys())) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_run.py b/tests/test_remote.py similarity index 95% rename from tests/test_run.py rename to tests/test_remote.py index d2a3bad..d5169cb 100644 --- a/tests/test_run.py +++ b/tests/test_remote.py @@ -20,8 +20,7 @@ class FullAPIRun(unittest.TestCase): test_string = "Worst song ever." response = sentiment(test_string) - self.assertTrue(isinstance(response, dict)) - self.assertEqual(posneg_set, set(response.keys())) + self.assertTrue(isinstance(response, float)) def test_good_fer(self): fer_set = set(['Angry', 'Sad', 'Neutral', 'Surprise', 'Fear', 'Happy'])