diff options
author | Malik Talha <talhamalik727x@gmail.com> | 2023-10-22 21:06:23 +0500 |
---|---|---|
committer | Jan-Simon Moeller <jsmoeller@linuxfoundation.org> | 2023-10-23 14:38:13 +0000 |
commit | 697a1adce1e463079e640b55d6386cf82d7bd6bc (patch) | |
tree | 86e299cc7fe12b10c2e549f640924b61c7d07a95 /snips_inference_agl/result.py | |
parent | 97029ab8141e654a170a2282106f854037da294f (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.py | 342 |
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] + } |