mirror of
https://github.com/wassname/IndicoIo-python.git
synced 2026-06-27 16:10:34 +08:00
Merge pull request #65 from IndicoDataSolutions/development
Development
This commit is contained in:
@@ -24,3 +24,4 @@ v0.5.2, Tue March 7 -- Required API keys, configuration settings
|
||||
v0.5.3, Wed Apr 15 -- Added scipy to requirements, edited Readme to not break pypi page
|
||||
v0.6.0, Thu May 29 -- Remove numpy / scipy dependency in favor of Pillow
|
||||
v0.7.0, Tue Jun 9 -- Added support for calling multiple APIs in a single function and accepting filenames as image API inputs
|
||||
v0.7.1 Thu Jun 11 -- High quality sentiment API for private beta, fix for multi API support
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from functools import partial
|
||||
|
||||
Version, version, __version__, VERSION = ('0.7.0',) * 4
|
||||
Version, version, __version__, VERSION = ('0.7.1',) * 4
|
||||
|
||||
JSON_HEADERS = {
|
||||
'Content-type': 'application/json',
|
||||
@@ -9,7 +9,7 @@ JSON_HEADERS = {
|
||||
'version-number': VERSION
|
||||
}
|
||||
|
||||
from indicoio.text.sentiment import political, posneg
|
||||
from indicoio.text.sentiment import political, posneg, sentiment_hq
|
||||
from indicoio.text.sentiment import posneg as sentiment
|
||||
from indicoio.text.lang import language
|
||||
from indicoio.text.tagging import text_tags
|
||||
|
||||
+2
-1
@@ -49,7 +49,8 @@ TEXT_APIS = [
|
||||
'text_tags',
|
||||
'political',
|
||||
'sentiment',
|
||||
'language'
|
||||
'language',
|
||||
'sentiment_hq'
|
||||
]
|
||||
|
||||
IMAGE_APIS = [
|
||||
|
||||
@@ -50,3 +50,26 @@ def posneg(text, cloud=None, batch=False, api_key=None, **kwargs):
|
||||
"""
|
||||
|
||||
return api_handler(text, cloud=cloud, api="sentiment", url_params={"batch":batch, "api_key":api_key}, **kwargs)
|
||||
|
||||
def sentiment_hq(text, cloud=None, batch=False, api_key=None, **kwargs):
|
||||
"""
|
||||
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.
|
||||
For reference, 0 suggests very negative sentiment and 1 suggests very positive sentiment.
|
||||
|
||||
Example usage:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> from indicoio import sentimenthq
|
||||
>>> text = 'Thanks everyone for the birthday wishes!! It was a crazy few days ><'
|
||||
>>> sentiment = sentimenthq(text)
|
||||
>>> sentiment
|
||||
0.6210052967071533
|
||||
|
||||
:param text: The text to be analyzed.
|
||||
:type text: str or unicode
|
||||
:rtype: Float
|
||||
"""
|
||||
|
||||
return api_handler(text, cloud=cloud, api="sentimenthq", url_params={"batch":batch, "api_key":api_key}, **kwargs)
|
||||
|
||||
@@ -17,6 +17,7 @@ def api_handler(arg, cloud, api, url_params = {"batch":False, "api_key":None}, *
|
||||
|
||||
if cloud:
|
||||
host = "%s.indico.domains" % cloud
|
||||
|
||||
else:
|
||||
# default to indico public cloud
|
||||
host = config.PUBLIC_API_HOST
|
||||
@@ -24,8 +25,14 @@ def api_handler(arg, cloud, api, url_params = {"batch":False, "api_key":None}, *
|
||||
url = config.url_protocol + "//%s/%s" % (host, api)
|
||||
url = url + "/batch" if url_params.get("batch", False) else url
|
||||
url += "?key=%s" % (url_params.get("api_key", None) or config.api_key)
|
||||
if "apis" in url_params:
|
||||
url += "&apis=%s" % ",".join(url_params["apis"])
|
||||
apis = url_params.get("apis", [])
|
||||
if apis:
|
||||
url += "&apis=%s" % ",".join(apis)
|
||||
|
||||
# private beta
|
||||
if host == config.PUBLIC_API_HOST:
|
||||
if (api == 'sentimenthq') or ('sentimenthq' in apis):
|
||||
raise IndicoError("The high quality sentiment API is currently in private beta.")
|
||||
|
||||
response = requests.post(url, data=json_data, headers=JSON_HEADERS)
|
||||
if response.status_code == 503 and cloud != None:
|
||||
|
||||
+41
-15
@@ -6,8 +6,12 @@ from indicoio.utils.errors import IndicoError
|
||||
|
||||
CLIENT_SERVER_MAP = dict((api, api.strip().replace("_", "").lower()) for api in API_NAMES)
|
||||
SERVER_CLIENT_MAP = dict((v, k) for k, v in CLIENT_SERVER_MAP.iteritems())
|
||||
AVAILABLE_APIS = {
|
||||
'text': TEXT_APIS,
|
||||
'image': IMAGE_APIS
|
||||
}
|
||||
|
||||
def multi(data, type, apis, available, batch=False, **kwargs):
|
||||
def multi(data, datatype, apis, batch=False, **kwargs):
|
||||
"""
|
||||
Helper to make multi requests of different types.
|
||||
|
||||
@@ -22,23 +26,39 @@ def multi(data, type, apis, available, batch=False, **kwargs):
|
||||
:rtype: Dictionary of api responses
|
||||
"""
|
||||
# Client side api name checking - strictly only accept func name api
|
||||
available = AVAILABLE_APIS.get(datatype)
|
||||
invalid_apis = [api for api in apis if api not in available]
|
||||
if invalid_apis:
|
||||
raise IndicoError("%s are not valid %s APIs. Please reference the available APIs below:\n%s"
|
||||
% (", ".join(invalid_apis), type, ", ".join(available))
|
||||
)
|
||||
raise IndicoError(
|
||||
"%s are not valid %s APIs. Please reference the available APIs below:\n%s"
|
||||
% (", ".join(invalid_apis), datatype, ", ".join(available))
|
||||
)
|
||||
|
||||
# Convert client api names to server names before sending request
|
||||
apis = map(CLIENT_SERVER_MAP.get, apis)
|
||||
result = api_handler(data, url_params = {"apis":apis, "batch":batch}, **kwargs)
|
||||
cloud = kwargs.pop("cloud", None)
|
||||
api_key = kwargs.pop('api_key', None)
|
||||
result = api_handler(
|
||||
data,
|
||||
cloud=cloud,
|
||||
api='apis',
|
||||
url_params={
|
||||
"apis":apis,
|
||||
"batch":batch,
|
||||
"api_key":api_key
|
||||
},
|
||||
**kwargs
|
||||
)
|
||||
return handle_response(result)
|
||||
|
||||
|
||||
def handle_response(result):
|
||||
# Parse out the results to a dicionary of api: result
|
||||
return dict((SERVER_CLIENT_MAP[api], parsed_response(api, res))
|
||||
for api, res in result.iteritems())
|
||||
|
||||
|
||||
def predict_text(input_text, apis=TEXT_APIS, cloud=None, batch=False, api_key=None, **kwargs):
|
||||
def predict_text(input_text, apis=TEXT_APIS, **kwargs):
|
||||
"""
|
||||
Given input text, returns the results of specified text apis. Possible apis
|
||||
include: [ 'text_tags', 'political', 'sentiment', 'language' ]
|
||||
@@ -60,19 +80,22 @@ def predict_text(input_text, apis=TEXT_APIS, cloud=None, batch=False, api_key=No
|
||||
:rtype: Dictionary of api responses
|
||||
"""
|
||||
|
||||
cloud = kwargs.pop('cloud', None)
|
||||
batch = kwargs.pop('batch', False)
|
||||
api_key = kwargs.pop('api_key', None)
|
||||
|
||||
return multi(
|
||||
api="apis",
|
||||
data=input_text,
|
||||
type="text",
|
||||
available = TEXT_APIS,
|
||||
datatype="text",
|
||||
cloud=cloud,
|
||||
batch=batch,
|
||||
api_key=api_key,
|
||||
apis=apis,
|
||||
**kwargs)
|
||||
**kwargs
|
||||
)
|
||||
|
||||
|
||||
def predict_image(image, apis=IMAGE_APIS, cloud=None, batch=False, api_key=None, **kwargs):
|
||||
def predict_image(image, apis=IMAGE_APIS, **kwargs):
|
||||
"""
|
||||
Given input image, returns the results of specified image apis. Possible apis
|
||||
include: ['fer', 'facial_features', 'image_features']
|
||||
@@ -95,16 +118,19 @@ def predict_image(image, apis=IMAGE_APIS, cloud=None, batch=False, api_key=None,
|
||||
:rtype: Dictionary of api responses
|
||||
"""
|
||||
|
||||
cloud = kwargs.pop('cloud', None)
|
||||
batch = kwargs.pop('batch', False)
|
||||
api_key = kwargs.pop('api_key', None)
|
||||
|
||||
return multi(
|
||||
api="apis",
|
||||
data=image_preprocess(image, batch=batch),
|
||||
type="image",
|
||||
available=IMAGE_APIS,
|
||||
datatype="image",
|
||||
cloud=cloud,
|
||||
batch=batch,
|
||||
api_key=api_key,
|
||||
apis=apis,
|
||||
**kwargs)
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def parsed_response(api, response):
|
||||
result = response.get('results', False)
|
||||
|
||||
@@ -9,9 +9,13 @@ from indicoio import config
|
||||
from indicoio import political, sentiment, fer, facial_features, language, image_features, text_tags
|
||||
from indicoio import batch_political, batch_sentiment, batch_fer, batch_facial_features
|
||||
from indicoio import batch_language, batch_image_features, batch_text_tags
|
||||
from indicoio import sentiment_hq, batch_sentiment_hq
|
||||
from indicoio import predict_image, predict_text, batch_predict_image, batch_predict_text
|
||||
from indicoio.utils.errors import IndicoError
|
||||
|
||||
# TODO: remove once sentiment_hq is added to the public API
|
||||
config.TEXT_APIS.remove("sentiment_hq")
|
||||
|
||||
DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
class BatchAPIRun(unittest.TestCase):
|
||||
@@ -37,6 +41,13 @@ class BatchAPIRun(unittest.TestCase):
|
||||
self.assertTrue(isinstance(response, list))
|
||||
self.assertTrue(response[0] < 0.5)
|
||||
|
||||
# TODO: uncomment once the high quality sentiment API is publicly released
|
||||
# def test_batch_sentiment_hq(self):
|
||||
# test_data = ['Worst song ever', 'Best song ever']
|
||||
# response = batch_sentiment_hq(test_data, api_key=self.api_key)
|
||||
# self.assertTrue(isinstance(response, list))
|
||||
# self.assertTrue(response[0] < 0.5)
|
||||
|
||||
def test_batch_political(self):
|
||||
test_data = ["Guns don't kill people, people kill people."]
|
||||
response = batch_political(test_data, api_key=self.api_key)
|
||||
@@ -220,6 +231,19 @@ class FullAPIRun(unittest.TestCase):
|
||||
self.assertTrue(isinstance(response, float))
|
||||
self.assertTrue(response > 0.5)
|
||||
|
||||
# TODO: uncomment when the high quality sentiment API is publicly released
|
||||
# def test_sentiment_hq(self):
|
||||
# test_string = "Worst song ever."
|
||||
# response = sentiment_hq(test_string)
|
||||
|
||||
# self.assertTrue(isinstance(response, float))
|
||||
# self.assertTrue(response < 0.5)
|
||||
|
||||
# test_string = "Best song ever."
|
||||
# response = sentiment_hq(test_string)
|
||||
# self.assertTrue(isinstance(response, float))
|
||||
# self.assertTrue(response > 0.5)
|
||||
|
||||
def test_good_fer(self):
|
||||
fer_set = set(['Angry', 'Sad', 'Neutral', 'Surprise', 'Fear', 'Happy'])
|
||||
test_face = generate_array((48,48))
|
||||
|
||||
Reference in New Issue
Block a user