dialogy.plugins.text.error_recovery package

Submodules

dialogy.plugins.text.error_recovery.error_recovery module

The goal of this module is to enable:

  1. Richer transitions. Most of our transtions are expressed by maps, we don’t have a way to express transitions as a function over known variables.

  2. We have triggers that map to the next state in the conversation.

  3. triggers are intents in most cases.

  4. ML components produce confidence scores for a prediction. Only in cases of low confidence, should we opt for explicit confirmation.

  5. As per our current capabilities, we always have a prompt to confirm.

  6. Here the rule for transition is (intent, score) -> state instead of {intent: state}.

  7. Handling ambiguity at the interface. We don’t have an expression to implement “Did you mean X or Y” for resolving ambiguities. We have such prompts for certain deployment yet the effort is the same for enabling such for entities other than X, Y and repeats for every deployment.

  8. Conversation level defaults. In the above example, we can should be able to define conversation level defaults for certain entities.

  9. Personalization. We don’t have provisions for handling user information. We have seen cases where speaker’s information has to be passed around microservices and the API design is driven by urgency. Does this speaker like when the prompts are faster? slower? shorter? longer? While such information is not logged, we also don’t have a way to use it.

These requirements are met by a mature, feature-rich, battle-tested high level language. A language that must expose little noise to its users and offer strong guaranatees of reproducibility, safety and consistency. Building such a language would span work over quarters with dedicated bandwidth of an experienced engineer. Hence we will drop a lot of responsibilities to draft a version that does much less but promises to extend itself to offer coverage of the aforementioned features.

  • The language should be approachable for existing engineers in the solutions team.

  • It should take a few hours (< 3) to get productive.

  • We will implement rich transitions and conversation level defaults.

class BinaryCondition(*, variable, value, operator)[source]

Bases: object

This class encodes conditions between two operands.

Currently supported operators are:

  • eq Equality

  • ne Non-equality

  • gte Greater than

  • ge Greater than or equal to

  • lte Less than

  • le Less than or equal to

  • in Inclusion

  • nin Exclusion

Returns

_description_

Return type

_type_

classmethod from_dict(d)[source]
Return type

BinaryCondition

classmethod from_list(d)[source]
Return type

List[BinaryCondition]

operations = {'eq': <function BinaryCondition.<lambda>>, 'gt': <function BinaryCondition.<lambda>>, 'gte': <function BinaryCondition.<lambda>>, 'in': <function BinaryCondition.<lambda>>, 'lt': <function BinaryCondition.<lambda>>, 'lte': <function BinaryCondition.<lambda>>, 'ne': <function BinaryCondition.<lambda>>, 'nin': <function BinaryCondition.<lambda>>}
operator: Callable[[Any, Any], bool]
value: Union[str, Set[str]]
variable: str
class Environment(*, intents, entities, previous_intent=None, current_state=None, expected_slots=NOTHING, bindings=NOTHING)[source]

Bases: object

The scope of variables for error-recovery rules are defined by this class. Referencing SLU input and output variables for filtering and updates.

bindings: Dict[str, Any]

Sub-commands and other variables should be stored here. API is WIP.

current_state: Optional[str]

Read only; used to filter intents/entities if a condition is met. Read More

entities: List[dialogy.types.entity.base_entity.BaseEntity]

Refer to BaseEntity Contains a list of entities of varying types. Iterable field, can also be modified by update queries.

expected_slots: Set[str]

Read only; used to filter intents/entities if a condition is met. Read More

get(item, key)[source]

Seek a variable from the context set in the environment.

Parameters
  • item (Union[Intent, BaseEntity]) – Either an intent or entity.

  • key (str) – A property within the item or environment.

Returns

The value bound to the key.

Return type

Any

intents: List[dialogy.types.intent.Intent]

Refer to Intent

Contains the list of intents predicted expected in sorted order of confidence score. Iterable field, can also be modified by update queries.

iterables = {'entity', 'intent'}
last_day_of_month(item)[source]

Returns the last day of the month for the given TimeEntity.

Parameters

item (TimeEntity) – A time entity.

Returns

The last day of the month

Return type

int

last_day_of_week(item)[source]

Returns the last day of the week for the given TimeEntity.

Parameters

item (TimeEntity) – A time entity.

Returns

The last day of the week.

Return type

int

property predicted_intent: str

We are assuming intents would be sorted in descending order of confidence scores. Hence the first element is the predicted intent as it has the best score.

Return type

str

previous_intent: Optional[str]

Read only; used to filter intents/entities if a condition is met. Read More

resources = {'entities', 'intents'}
set(key, value)[source]

Bind a value to a variable in the environment.

Parameters
  • key (str) – A variable name defined in the environment.

  • value (List[Union[Intent, BaseEntity]]) – The value to bound to the variable.

Returns

None

Return type

None

set_item(item, key, value)[source]

Bind a value to either Intent or Entity.

Parameters
  • item (Union[Intent, BaseEntity]) – Either an intent or entity.

  • key (str) – A property within the item.

  • value (Any) – The value to bound to the property or a function identifier.

Return type

None

class ErrorRecoveryPlugin(rules, dest=None, guards=None, replace_output=True, debug=False)[source]

Bases: dialogy.base.plugin.Plugin

rules:
  -
      find: entities
      where:
          - entity.grain: month
          - entity.entity_type:
              in: ["date", "time", "datetime"]
      update:
          entity.day: :last_day_of_month

We can use the above rule like so:

In [1]: import yaml
   ...: from dialogy.plugins import ErrorRecoveryPlugin, DucklingPlugin
   ...: from dialogy.workflow import Workflow
   ...: from dialogy.base import Input
   ...: from dialogy.types import Intent
   ...: 

In [2]: error_recovery_config = yaml.safe_load('''
   ...:   rules: 
   ...:     -
   ...:         find: entities
   ...:         where:
   ...:             - entity.grain: month
   ...:             - entity.entity_type:
   ...:                 in: ["date", "time", "datetime"]
   ...:             - predicted_intent: "future_date"
   ...:         update:
   ...:             entity.day: :last_day_of_month
   ...: ''')
   ...: 

In [3]: duckling_plugin = DucklingPlugin(dimensions=["time"], dest="output.entities")
   ...: workflow = Workflow([duckling_plugin])
   ...: workflow.set("output.intents", [Intent(name="future_date", score=0.99)])
   ...: _, out = workflow.run(input_=Input(utterances="this month"))
   ...: # The default value is 1st of the month
   ...: out["entities"][0]
   ...: 
Out[3]: 
{'range': {'start': 0, 'end': 10},
 'body': 'this month',
 'type': 'value',
 'parsers': ['DucklingPlugin'],
 'score': 1.0,
 'alternative_index': 0,
 'value': '2022-08-01T00:00:00.000+00:00',
 'entity_type': 'date',
 'grain': 'month'}

In [4]: error_recovery_plugin = ErrorRecoveryPlugin(rules=error_recovery_config["rules"])
   ...: duckling_plugin = DucklingPlugin(dimensions=["time"], dest="output.entities")
   ...: workflow = Workflow([duckling_plugin, error_recovery_plugin])
   ...: workflow.set("output.intents", [Intent(name="future_date", score=0.99)])
   ...: _, out = workflow.run(input_=Input(utterances="this month"))
   ...: # But with error recovery, we get the last day of the month
   ...: out["entities"][0] 
   ...: 
Out[4]: 
{'range': {'start': 0, 'end': 10},
 'body': 'this month',
 'type': 'value',
 'parsers': ['DucklingPlugin'],
 'score': 1.0,
 'alternative_index': 0,
 'value': '2022-08-31T00:00:00+00:00',
 'entity_type': 'date',
 'grain': 'month'}

In [5]: error_recovery_config = yaml.safe_load('''
   ...:   rules: 
   ...:     -
   ...:         find: entities
   ...:         where:
   ...:             - entity.grain: month
   ...:             - entity.entity_type:
   ...:                 in: ["date", "time", "datetime"]
   ...:             - predicted_intent: "some-other-intent" # Hence the rule won't match
   ...:         update:
   ...:             entity.day: :last_day_of_month
   ...: ''')
   ...: 

In [6]: error_recovery_plugin = ErrorRecoveryPlugin(rules=error_recovery_config["rules"])
   ...: duckling_plugin = DucklingPlugin(dimensions=["time"], dest="output.entities")
   ...: workflow = Workflow([duckling_plugin, error_recovery_plugin])
   ...: workflow.set("output.intents", [Intent(name="future_date", score=0.99)])
   ...: _, out = workflow.run(input_=Input(utterances="this month"))
   ...: # Only if the conditions are satisfactory.
   ...: out["entities"][0]
   ...: 
Out[6]: 
{'range': {'start': 0, 'end': 10},
 'body': 'this month',
 'type': 'value',
 'parsers': ['DucklingPlugin'],
 'score': 1.0,
 'alternative_index': 0,
 'value': '2022-08-01T00:00:00.000+00:00',
 'entity_type': 'date',
 'grain': 'month'}

To migrate from the previous intent renaming plugin, here’s an example config:

intent_swap:
- 
    depends_on:
        intent: _confirm_
        state:
            in:
                - CONFIRM_VIEWING_POST_HR
                - CONFIRM_VIEWING_POST_ACCOUNT_RESUMPTION
                - CONFIRM_VIEWING_POST_ACCOUNT_ACTIVATION
                - CONFIRM_VIEWING_POST_ASSET_RESUMPTION
                - CONFIRM_VIEWING_POST_INPUT_CHECK
                - CONFIRM_VIEWING_POST_RECONNECTION
rename: _issue_resolved_

You would express this as:

rules:
    -
        find: intents
        where:
        - intent.name: _confirm_
        - state:
            in:
            - CONFIRM_VIEWING_POST_HR
            - CONFIRM_VIEWING_POST_ACCOUNT_RESUMPTION
            - CONFIRM_VIEWING_POST_ACCOUNT_ACTIVATION
            - CONFIRM_VIEWING_POST_ASSET_RESUMPTION
            - CONFIRM_VIEWING_POST_INPUT_CHECK
            - CONFIRM_VIEWING_POST_RECONNECTION
        update:
            intent.name: _issue_resolved_
utility(input_, output)[source]

An abstract method that describes the plugin’s functionality.

Parameters
  • input (Input) – The workflow’s input.

  • output (Output) – The workflow’s output.

Returns

The value returned by the plugin.

Return type

Any

class Rule(*, find, where, remove, update)[source]

Bases: object

We encode events within a conversation turn as a rule.

A rule can be broken down to 2 operations:

  1. Search: We apply filters to a resource (one of intents or entities).

  2. Action: We perform an action on the resource (one of update, remove).

find: str
classmethod from_dict(rule)[source]
Return type

Rule

classmethod from_list(rules)[source]
Return type

List[Rule]

on_conditions(environment)[source]

Pick items within resources when all conditions match.

We require this to update a set of items that match the conditions.

Parameters

environment (Environment) – A data-structure that describes a set of bound variables.

Returns

A function that can be used to filter a resource.

Return type

Callable[[Union[Intent, BaseEntity]], bool]

on_inverse(environment)[source]

Pick items within resources when no conditions match.

We require this to retain a set of items that don’t match the conditions. That is the remove operation.

Parameters

environment (Environment) – A data-structure that describes a set of bound variables.

Returns

A function that can be used to filter a resource.

Return type

Callable[[Union[Intent, BaseEntity]], bool]

parse(environment)[source]

Parse a rule and update the environment.

We parse the rule and either update or remove items within intents or entities as per the clause described in the rule.

Parameters

environment (Environment) – A data-structure that describes a set of bound variables.

Returns

Remove or Update resources.

Return type

Rule

remove: Optional[str]
update: Optional[Dict[str, Any]]
where: List[dialogy.plugins.text.error_recovery.error_recovery.BinaryCondition]

Module contents