endpoint = 'http://senpy.gsi.upm.es/api'

import requests
from IPython.display import Code
     
def query(endpoint, raw=False, **kwargs):
    '''Query a given Senpy endpoint with specific parameters, and prettify the output'''
    res = requests.get(endpoint,
                       params=kwargs)
    if raw:
        return res
    return Code(res.text, language=kwargs.get('outformat', 'json-ld'))

"""
Explanation: Advanced features
This tutorial takes up where the basic tutorial left off.
It covers more advanced tasks such as:

Listing available services in an endpoint
Transforming the results of a service
Calling multiple services in the same request (Pipelines)
Running your own Senpy instance

Requirements
Once again we will use the demo server at http://senpy.gsi.upm.es, and a function to prettify the semantic output.
End of explanation
"""


query(f'{endpoint}/sentiment140',
      input="Senpy is a wonderful service",
      fields='entries[]."nif:isString"')

"""
Explanation: Selecting fields from the output
The full output in the previous tutorials is very useful because it is semantically annotated.
However, it is also quite verbose if we only want to label a piece of text, or get a polarity value.
For such simple cases, the API has a special fields method you can use to get a specific field from the results, and even transform the results. Senpy uses jmespath under the hood, which has its own notation.
To illustrate this, let us get only the text (nif:isString) from each entry:
End of explanation
"""


query(f'{endpoint}/sentiment140',
      input="Senpy is a service. Wonderful service.",
      delimiter="sentence",
      fields='entries[0].["nif:isString", "marl:hasOpinion"[0]."marl:hasPolarity"]')

"""
Explanation: Or we could get both the text and the polarity of the text (assuming there is only one opinion per entry) with a slightly more complicated query:
End of explanation
"""


query(f'{endpoint}/emotion-anew',
      input="Senpy is a wonderful service and I love it",
      emotionmodel="emoml:big6",
      fields='entries[].[["nif:isString","onyx:hasEmotionSet"[]."onyx:hasEmotion"[]."onyx:hasEmotionCategory"][]][]',
      conversion="filtered")

"""
Explanation: jmespath is rather extensive for this tutorial. We will cover only the most simple cases, so you do not need to learn much about the notation.
For more complicated transformations, check out jmespath.
In addition to a fairly complete documentation, they have a live environment you can use to test your queries.
Emotion conversion with field selection
We could mix emotion conversion with field selection to only get the label of an emotion analysis that has been automatically converted:
End of explanation
"""


query(f'{endpoint}/sentiment140/emotion-depechemood',
      input="Senpy is a wonderful service")

"""
Explanation: Building pipelines
You can query several senpy services in the same request.
This feature is called pipelining, and the result of combining several plugins in a request is called a pipeline.
The simplest way to use pipelines is to add every plugin you want to use to the URL, separated by either a slash or a comma.
For instance, to get sentiment (sentiment140) and emotion (depechemood) annotations at the same time:
End of explanation
"""


query(f'{endpoint}/split/sentiment140',
      input="Senpy is awesome. And services are composable.", 
      delimiter="sentence",
      language="en",
      outformat="json-ld")

"""
Explanation: In a senpy pipeline, the call is processed by each plugin in sequence.
The output of a plugin is used as input for the next one.
Pipelines take the same parameters as the plugins they are made of.
For example, if we want to split the original sentence before analysing its sentiment, we can use a pipeline made out of the split and the sentiment140 plugins.
split takes an extra parameter (delimiter) to select the type of splitting (by sentence or by paragraph), and sentiment140 takes a language parameter.
This is how the request looks like:
End of explanation
"""


query(f'{endpoint}/split/sentiment140',
      input="Senpy is awesome. And services are composable.", 
      delimiter="sentence",
      fields='entries[].[["nif:isString","marl:hasOpinion"[]."marl:hasPolarity"][]][]',
      language="en",
      outformat="json-ld")

"""
Explanation: As you can see, split creates two new entries, which are also annotated by sentiment140.
Once again, we could use the fields parameter to get a list of strings and labels:
End of explanation
"""


query(f'{endpoint}/plugins')

"""
Explanation: Listing services
You can get a complete list of plugins in a senpy instance through the API:
End of explanation
"""


query(f'{endpoint}/plugins',
      plugin_type="SentimentPlugin")

"""
Explanation: If you want to get only a specific type of plugin, use the plugin_type parameter.
e.g., this will only return the plugins for sentiment analysis:
End of explanation
"""


query(f'{endpoint}/plugins',
      fields='plugins[].["@id","@type"]')

"""
Explanation: The fields parameter also works on the plugins API:
End of explanation
"""


query(f'{endpoint}/evaluate',
     algo="sentiment-vader",
     dataset="vader,sts",
     outformat='json-ld')

"""
Explanation: Alternatively:
Evaluation
Sentiment analysis plugins can also be evaluated on a series of pre-defined datasets, using the gsitk tool.
For instance, to evaluate the sentiment-vader plugin on the vader and sts datasets, we would simply call:
End of explanation
"""


query(f'{endpoint}/sentiment140',
      input="Senpy is the best framework for semantic sentiment analysis, and very easy to use",
      verbose=True)

"""
Explanation: The same results can be visualized as a table in the Web interface:

note: to evaluate a plugin on a dataset, senpy will need to predict the labels of the entries using the plugin.
This process might take long for plugins that use an external service, such as sentiment140.
Running your own senpy instance with Docker
Now that you're familiar with Senpy, you can deploy your own instance quite easily. e.g. using docker:
shell
docker run -ti --name 'SenpyEndpoint' -d -p 5000:5000 gsiupm/senpy
Alternatively, you can install senpy in your system and run it:
```shell
First install it
pip install --user senpy
Run locally
senpy
or
python -m senpy
```
Once you have an instance running, feel free to change the endpoint variable to run the examples in your own instance.
Advanced topics
Verbose output
By default, senpy does not include information that might be too verbose, such as the parameters that were used in the analysis.
You can instruct senpy to provide a more verbose output with the verbose parameter:
End of explanation
"""


query(f'{endpoint}/',
      help=True)

"""
Explanation: Getting help
End of explanation
"""


query(f'{endpoint}/',
      input="This will tell senpy to only include the context in the headers",
      inheaders=True)

"""
Explanation: Ignoring the context
End of explanation
"""


# We first repeat the query, to get the raw requests response using raw=True
res = query(f'{endpoint}/', input="This will tell senpy to only include the context in the headers", inheaders=True, raw=True)

# The URI of the context is in the headers:
print(res.headers['Link'])

"""
Explanation: To retrieve the context URI, use the LINK header:
End of explanation
"""


