aboutsummaryrefslogtreecommitdiffstats
path: root/snips_inference_agl/result.py
diff options
context:
space:
mode:
authorMalik Talha <talhamalik727x@gmail.com>2023-10-22 21:06:23 +0500
committerJan-Simon Moeller <jsmoeller@linuxfoundation.org>2023-10-23 14:38:13 +0000
commit697a1adce1e463079e640b55d6386cf82d7bd6bc (patch)
tree86e299cc7fe12b10c2e549f640924b61c7d07a95 /snips_inference_agl/result.py
parent97029ab8141e654a170a2282106f854037da294f (diff)
Add Snips Inference Module
Add slightly modified version of the original Snips NLU library. This module adds support for Python upto version 3.10. Bug-AGL: SPEC-4856 Signed-off-by: Malik Talha <talhamalik727x@gmail.com> Change-Id: I6d7e9eb181e6ff4aed9b6291027877ccb9f0d846
Diffstat (limited to 'snips_inference_agl/result.py')
-rw-r--r--snips_inference_agl/result.py342
1 files changed, 342 insertions, 0 deletions
diff --git a/snips_inference_agl/result.py b/snips_inference_agl/result.py
new file mode 100644
index 0000000..39930c8
--- /dev/null
+++ b/snips_inference_agl/result.py
@@ -0,0 +1,342 @@
+from __future__ import unicode_literals
+
+from snips_inference_agl.constants import (
+ RES_ENTITY, RES_INPUT, RES_INTENT, RES_INTENT_NAME, RES_MATCH_RANGE,
+ RES_PROBA, RES_RAW_VALUE, RES_SLOTS, RES_SLOT_NAME, RES_VALUE, ENTITY_KIND,
+ RESOLVED_VALUE, VALUE)
+
+
+def intent_classification_result(intent_name, probability):
+ """Creates an intent classification result to be returned by
+ :meth:`.IntentClassifier.get_intent`
+
+ Example:
+
+ >>> intent_classification_result("GetWeather", 0.93)
+ {'intentName': 'GetWeather', 'probability': 0.93}
+ """
+ return {
+ RES_INTENT_NAME: intent_name,
+ RES_PROBA: probability
+ }
+
+
+def unresolved_slot(match_range, value, entity, slot_name):
+ """Creates an internal slot yet to be resolved
+
+ Example:
+
+ >>> from snips_inference_agl.common.utils import json_string
+ >>> slot = unresolved_slot([0, 8], "tomorrow", "snips/datetime", \
+ "startDate")
+ >>> print(json_string(slot, indent=4, sort_keys=True))
+ {
+ "entity": "snips/datetime",
+ "range": {
+ "end": 8,
+ "start": 0
+ },
+ "slotName": "startDate",
+ "value": "tomorrow"
+ }
+ """
+ return {
+ RES_MATCH_RANGE: _convert_range(match_range),
+ RES_VALUE: value,
+ RES_ENTITY: entity,
+ RES_SLOT_NAME: slot_name
+ }
+
+
+def custom_slot(internal_slot, resolved_value=None):
+ """Creates a custom slot with *resolved_value* being the reference value
+ of the slot
+
+ Example:
+
+ >>> s = unresolved_slot([10, 19], "earl grey", "beverage", "beverage")
+ >>> from snips_inference_agl.common.utils import json_string
+ >>> print(json_string(custom_slot(s, "tea"), indent=4, sort_keys=True))
+ {
+ "entity": "beverage",
+ "range": {
+ "end": 19,
+ "start": 10
+ },
+ "rawValue": "earl grey",
+ "slotName": "beverage",
+ "value": {
+ "kind": "Custom",
+ "value": "tea"
+ }
+ }
+ """
+
+ if resolved_value is None:
+ resolved_value = internal_slot[RES_VALUE]
+ return {
+ RES_MATCH_RANGE: _convert_range(internal_slot[RES_MATCH_RANGE]),
+ RES_RAW_VALUE: internal_slot[RES_VALUE],
+ RES_VALUE: {
+ "kind": "Custom",
+ "value": resolved_value
+ },
+ RES_ENTITY: internal_slot[RES_ENTITY],
+ RES_SLOT_NAME: internal_slot[RES_SLOT_NAME]
+ }
+
+
+def builtin_slot(internal_slot, resolved_value):
+ """Creates a builtin slot with *resolved_value* being the resolved value
+ of the slot
+
+ Example:
+
+ >>> rng = [10, 32]
+ >>> raw_value = "twenty degrees celsius"
+ >>> entity = "snips/temperature"
+ >>> slot_name = "beverageTemperature"
+ >>> s = unresolved_slot(rng, raw_value, entity, slot_name)
+ >>> resolved = {
+ ... "kind": "Temperature",
+ ... "value": 20,
+ ... "unit": "celsius"
+ ... }
+ >>> from snips_inference_agl.common.utils import json_string
+ >>> print(json_string(builtin_slot(s, resolved), indent=4))
+ {
+ "entity": "snips/temperature",
+ "range": {
+ "end": 32,
+ "start": 10
+ },
+ "rawValue": "twenty degrees celsius",
+ "slotName": "beverageTemperature",
+ "value": {
+ "kind": "Temperature",
+ "unit": "celsius",
+ "value": 20
+ }
+ }
+ """
+ return {
+ RES_MATCH_RANGE: _convert_range(internal_slot[RES_MATCH_RANGE]),
+ RES_RAW_VALUE: internal_slot[RES_VALUE],
+ RES_VALUE: resolved_value,
+ RES_ENTITY: internal_slot[RES_ENTITY],
+ RES_SLOT_NAME: internal_slot[RES_SLOT_NAME]
+ }
+
+
+def resolved_slot(match_range, raw_value, resolved_value, entity, slot_name):
+ """Creates a resolved slot
+
+ Args:
+ match_range (dict): Range of the slot within the sentence
+ (ex: {"start": 3, "end": 10})
+ raw_value (str): Slot value as it appears in the sentence
+ resolved_value (dict): Resolved value of the slot
+ entity (str): Entity which the slot belongs to
+ slot_name (str): Slot type
+
+ Returns:
+ dict: The resolved slot
+
+ Example:
+
+ >>> resolved_value = {
+ ... "kind": "Temperature",
+ ... "value": 20,
+ ... "unit": "celsius"
+ ... }
+ >>> slot = resolved_slot({"start": 10, "end": 19}, "earl grey",
+ ... resolved_value, "beverage", "beverage")
+ >>> from snips_inference_agl.common.utils import json_string
+ >>> print(json_string(slot, indent=4, sort_keys=True))
+ {
+ "entity": "beverage",
+ "range": {
+ "end": 19,
+ "start": 10
+ },
+ "rawValue": "earl grey",
+ "slotName": "beverage",
+ "value": {
+ "kind": "Temperature",
+ "unit": "celsius",
+ "value": 20
+ }
+ }
+ """
+ return {
+ RES_MATCH_RANGE: match_range,
+ RES_RAW_VALUE: raw_value,
+ RES_VALUE: resolved_value,
+ RES_ENTITY: entity,
+ RES_SLOT_NAME: slot_name
+ }
+
+
+def parsing_result(input, intent, slots): # pylint:disable=redefined-builtin
+ """Create the final output of :meth:`.SnipsNLUEngine.parse` or
+ :meth:`.IntentParser.parse`
+
+ Example:
+
+ >>> text = "Hello Bill!"
+ >>> intent_result = intent_classification_result("Greeting", 0.95)
+ >>> internal_slot = unresolved_slot([6, 10], "Bill", "name",
+ ... "greetee")
+ >>> slots = [custom_slot(internal_slot, "William")]
+ >>> res = parsing_result(text, intent_result, slots)
+ >>> from snips_inference_agl.common.utils import json_string
+ >>> print(json_string(res, indent=4, sort_keys=True))
+ {
+ "input": "Hello Bill!",
+ "intent": {
+ "intentName": "Greeting",
+ "probability": 0.95
+ },
+ "slots": [
+ {
+ "entity": "name",
+ "range": {
+ "end": 10,
+ "start": 6
+ },
+ "rawValue": "Bill",
+ "slotName": "greetee",
+ "value": {
+ "kind": "Custom",
+ "value": "William"
+ }
+ }
+ ]
+ }
+ """
+ return {
+ RES_INPUT: input,
+ RES_INTENT: intent,
+ RES_SLOTS: slots
+ }
+
+
+def extraction_result(intent, slots):
+ """Create the items in the output of :meth:`.SnipsNLUEngine.parse` or
+ :meth:`.IntentParser.parse` when called with a defined ``top_n`` value
+
+ This differs from :func:`.parsing_result` in that the input is omitted.
+
+ Example:
+
+ >>> intent_result = intent_classification_result("Greeting", 0.95)
+ >>> internal_slot = unresolved_slot([6, 10], "Bill", "name",
+ ... "greetee")
+ >>> slots = [custom_slot(internal_slot, "William")]
+ >>> res = extraction_result(intent_result, slots)
+ >>> from snips_inference_agl.common.utils import json_string
+ >>> print(json_string(res, indent=4, sort_keys=True))
+ {
+ "intent": {
+ "intentName": "Greeting",
+ "probability": 0.95
+ },
+ "slots": [
+ {
+ "entity": "name",
+ "range": {
+ "end": 10,
+ "start": 6
+ },
+ "rawValue": "Bill",
+ "slotName": "greetee",
+ "value": {
+ "kind": "Custom",
+ "value": "William"
+ }
+ }
+ ]
+ }
+ """
+ return {
+ RES_INTENT: intent,
+ RES_SLOTS: slots
+ }
+
+
+def is_empty(result):
+ """Check if a result is empty
+
+ Example:
+
+ >>> res = empty_result("foo bar", 1.0)
+ >>> is_empty(res)
+ True
+ """
+ return result[RES_INTENT][RES_INTENT_NAME] is None
+
+
+def empty_result(input, probability): # pylint:disable=redefined-builtin
+ """Creates an empty parsing result of the same format as the one of
+ :func:`parsing_result`
+
+ An empty is typically returned by a :class:`.SnipsNLUEngine` or
+ :class:`.IntentParser` when no intent nor slots were found.
+
+ Example:
+
+ >>> res = empty_result("foo bar", 0.8)
+ >>> from snips_inference_agl.common.utils import json_string
+ >>> print(json_string(res, indent=4, sort_keys=True))
+ {
+ "input": "foo bar",
+ "intent": {
+ "intentName": null,
+ "probability": 0.8
+ },
+ "slots": []
+ }
+ """
+ intent = intent_classification_result(None, probability)
+ return parsing_result(input=input, intent=intent, slots=[])
+
+
+def parsed_entity(entity_kind, entity_value, entity_resolved_value,
+ entity_range):
+ """Create the items in the output of
+ :meth:`snips_inference_agl.entity_parser.EntityParser.parse`
+
+ Example:
+ >>> resolved_value = dict(age=28, role="datascientist")
+ >>> range = dict(start=0, end=6)
+ >>> ent = parsed_entity("snipster", "adrien", resolved_value, range)
+ >>> import json
+ >>> print(json.dumps(ent, indent=4, sort_keys=True))
+ {
+ "entity_kind": "snipster",
+ "range": {
+ "end": 6,
+ "start": 0
+ },
+ "resolved_value": {
+ "age": 28,
+ "role": "datascientist"
+ },
+ "value": "adrien"
+ }
+ """
+ return {
+ VALUE: entity_value,
+ RESOLVED_VALUE: entity_resolved_value,
+ ENTITY_KIND: entity_kind,
+ RES_MATCH_RANGE: entity_range
+ }
+
+
+def _convert_range(rng):
+ if isinstance(rng, dict):
+ return rng
+ return {
+ "start": rng[0],
+ "end": rng[1]
+ }