Giter VIP home page Giter VIP logo

plan4dial's Introduction

Plan4Dial

Generates a chatbot given a simple YAML configuration using automated planning for conversation navigation and machine learning for NLU.

Documentation

https://dialogue-planning.github.io/plan4dial/

Requirements - Docker

To ensure development works identically accross systems, Docker should be used to run Plan4Dial. Inside the repository, follow these steps to run with Docker:

  1. Retrieve a copy of the rbp.sif executable from Christian Muise ([email protected]) and place this in the cloned repository.
  2. Build the docker image from Dockerfile: docker build -t plan4dial:latest .
  3. Run a bash session inside a new docker container: docker run -it --name plan4dial --rm --volume $(pwd)/plan4dial:/root/app/plan4dial --net=host --privileged plan4dial:latest sh
    • OR if you are using Windows in CMD run: docker run -it --name plan4dial --rm --volume %cd%/plan4dial:/root/app/plan4dial --net=host --privileged plan4dial:latest sh
  4. Run the command in the bash session: python plan4dial/main.py gold_standard_bot
  5. Now you should see output files were created and successful output in the bash session in the container. You can copy these output files out from the filesystem outside the container, the /plan4dial subdirectory is mounted.

Note: You can make changes to python files inside subfolder /plan4dial without rebuilding the docker container as it is mounted as as simple volume.

Usage/Tutorial

See here for the full tutorial.

Citing This Work

Coming soon!

plan4dial's People

Contributors

beckydvn avatar haz avatar jlaframboise avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

plan4dial's Issues

Make "known" values implicit when a value is changed to anything other than "none"

When explicitly defining an action, the known value has to be stated explicitly when a value is updated. Take this example from plan4dial's bank_bot:

  offer-new:
    type: dialogue
    message_variants:
      - Would you like to create a new account?
      - I can also create a new account for you. Would you like to do that today?
    condition:
      tried-create:
        value: false
      task:
        known: false
    effect:
      start-task:
        oneof:
          outcomes:
            want-create:
              updates:
                task:
                  known: true
                  value: create account
              intent: confirm

It's a small change, but it would be less mental overhead for the user if the system could infer that known be set to true when the value is updated to something other than none.

Add more complex follow-up functionality; auto-apply to "slot_fill" actions

There are many circumstances in which a simple "follow up" specification is not quite accomplishing what the user is trying to capture, and enhancements can be made to accomplish this.

Suppose in a restaurant ordering bot we have a slot_fill action get_order which extracts three entities from the user; pizza, drink, and side. We want to ensure that get_order is the next action run after the bot's initial greeting greet, so we specify follow_up: get_order as necessary in the YAML.

Now, get_order will follow up greet as specified. But what if the action is only able to extract pizza, and with an unsure confidence at that? Although the relevant clarify and slot_fill actions have been generated, there's currently no way to specify that all three entities will be extracted before the bot moves on to anything else. This sometimes lead to awkward conversations where the bot does the following:

  • extract entity A without a "maybe" confidence
  • perform some unrelated action
  • clarify entity A

As a result, it would be more intuitive to have a follow_up option where instead of specifying only the action name, the user can optionally also specify the goal they're trying to accomplish. This goal may be an entity extraction, a successful API call, or a setting to context variables (maybe eventually we can up the complexity to include arbitrary formulas once #4 is resolved). Additionally, the user would have to specify in each action what goal it accomplishes, i.e. something like

action: example
  goal:
    extract_entities:  
        - pizza  
        - drink  
        - side
   ...

So, if a goal is specified under a follow_up like this,

follow_up:
  name: example
  goal:
    extract_entities:  
      - pizza  

then all actions with that goal (or that include that goal) will not be disabled. Then, instead of painstakingly iterating through all the actions with that goal to figure out when it was accomplished (which might be difficult or impossible for some goals, i.e. extracting multiple entities which could take place over multiple actions), you auto-generate a system action that takes the follow_up goal as a precondition and sets forcing__{action} to False as a result.

For example, if the user wanted to force the action which extracts/clarifies 5 entities through a slot_fill action, instead of having to settle for only having the initial ask forced, they can now easily force the bot to find all 5 entities before proceeding. The goal could even be somewhat unrelated to the forced action, which allows for more complex forcing, for example, forcing that we then find entity which could only be extracted farther down the line. This essentially allows the bot designer to tell the bot to “go up until a certain point, and then continue and do whatever you want.”

This functionality would also improve conversation quality on slot_fill actions by auto-forcing the goal of entity extraction when the bot wasn't able to extract all the entities (with full certainty) from the initial input.

Simplify effect configuration

Right now, the default action configuration is a bit cluttered. Take this action from bank_bot:

  offer-pay:
    type: dialogue
    message_variants:
      - Would you like to pay off your outstanding bills today?
      - You have a few outstanding bills. Would you like to pay them off now?
    condition:
      tried-pay-bills:
        value: false
      task:
        known: false
    effect:
      start-task:
        oneof:
          outcomes:
            want-pay:
              updates:
                task:
                  known: true
                  value: pay bills
              intent: confirm
            dont-want:
              updates:
                tried-pay-bills:
                  value: true
              intent: deny
              response_variants:
                - Ok! I won't pay off your outstanding bills today.

Mainly the effect configuration could be simplified by removing the "oneof" and "outcomes" labels, which are the same every time:

  offer-pay:
    type: dialogue
    message_variants:
      - Would you like to pay off your outstanding bills today?
      - You have a few outstanding bills. Would you like to pay them off now?
    condition:
      tried-pay-bills:
        value: false
      task:
        known: false
    effect:
      start-task:
        want-pay:
          updates:
            task:
              known: true
              value: pay bills
          intent: confirm
        dont-want:
          updates:
            tried-pay-bills:
              value: true
          intent: deny
          response_variants:
            - Ok! I won't pay off your outstanding bills today.

This combined with #15 could make an even simpler configuration:

  offer-pay:
    type: dialogue
    message_variants:
      - Would you like to pay off your outstanding bills today?
      - You have a few outstanding bills. Would you like to pay them off now?
    condition:
      tried-pay-bills:
        value: false
      task:
        known: false
    effect:
      start-task:
        want-pay:
          updates:
            task:
              value: pay bills
          intent: confirm
        dont-want:
          updates:
            tried-pay-bills:
              value: true
          intent: deny
          response_variants:
            - Ok! I won't pay off your outstanding bills today.

Intent type listing

In the generated json, intents should have a type associated with it. For now, fallback and regular can be the only two options. Example from the gold json:

"intents": {
"ask-for-title-outcome-fallback": {
    "type": "fallback",
    "utterances": [],
    "variables": []
},
"ask-for-title-outcome-found": {
    "type": "regular",
    "utterances": [
        "Make the title [regex]{parsed_title:=[\\w ]+}",
        "Change the title to [regex]{parsed_title:=[\\w ]+}",
        "Please change the title to [regex]{parsed_title:=[\\w ]+}"
    ],
    "variables": []
}

Add functionality to swap in custom disambiguators

Allow the bot designer to add custom disambiguators to differentiate between >1 Spacy entity in the same utterance (see #1). In the future, this would apply not only to Spacy but any extraction method that would cause ambiguity (Rasa included).

For example, in the utterance "I want to fly from London to Berlin," Spacy would extract two GPE entities: London and Berlin. However, without extra help it is unable to tell you which is the origin city and which is the destination. A very basic custom disambiguator would assign London to the origin city as it is preceded by "from" and Berlin to the destination as it is preceded by "to."

While it is true that Rasa has "roles" and "groups" functionality to address this, binding dialogue disambiguation to Rasa that tightly significantly complicates things, given that not all entities are extracted with Rasa. Additionally, Hovor has no notion of "roles" or "groups" and changes would have to be made to accommodate that. Separate context variables would be needed in the end, which defeats the purpose of Rasa's roles/groups of removing the need for "duplicate variables." So, some functionality detached from the extraction method is needed to handle cases like these.

Catch YAML specification errors

  • Raise exception if user tries to create a clarify action (through slot_fill or otherwise) for a context variable with a flag type known
  • Raise exception if the user uses names that would be invalid in PDDL (spaces, etc.)
  • Any actions with generated names (e.g. action names or intents from slot_fill) need to be checked against existing names in the YAML. Raise an exception if a duplicate occurs.
  • For slot_fill actions, enforce you can’t have single-slot specifications if you only have one entity

Allow bot designers to specify "when" conditions in action effects in the YAML

Implementation on this has started: https://github.com/QuMuLab/plan4dial/blob/ee208d2849a40a68ac9d358e03ea6c4988b7cd3e/plan4dial/parsing/json_config_parser.py#L407

So far, we can handle "or"s in "when" conditions by converting the "when" statements to multiple outcomes. Note that "when" statements must come in this format: https://github.com/QuMuLab/plan4dial/blob/ee208d2849a40a68ac9d358e03ea6c4988b7cd3e/plan4dial/yaml_samples/when_test.yml#L68

We can see that the when statements have been divided here: https://github.com/QuMuLab/plan4dial/blob/ee208d2849a40a68ac9d358e03ea6c4988b7cd3e/output_files/when_test/when_test.json#L104

It has not yet been tested how Hovor handles "when" statements, though. It may have trouble recognizing how to apply the effect. PDDL parsing would also have to be updated. It might be easiest to, instead of leaving the effects as "when" statements, to set some variable True instead, i.e. run-when-statements. Then, the "when" statements would be converted to separate actions predicated on run-when-statements. This would also make it a simpler task to handle complex nestings (see #4 ) and handle "value" conditions, and no extra PDDL parsing would have to be added.

Use DNFs to allow bot designers to specify arbitrary logical formulas for preconditions, "when" conditions, and context dependent system actions

Implementation has started here (see this function): https://github.com/QuMuLab/plan4dial/blob/ee7654440b3e2a6632e1b215d2ecb96a93c09700/plan4dial/parsing/json_config_parser.py#L90

This function converts an and/or nesting from the YAML into a logical formula, and converts it to DNF.

The issue is that the naive implementation for converting to CNF (without using auxiliary variables) has yet to be implemented: QuMuLab/python-nnf#21

Once it is, you should be able to use the results returned from this function to generate actions that carry out the equivalent condition. This is based on the idea that having an action with the precondition "a or b" is equivalent to having two adjacent actions with the same effects, one with the precondition a, the other with the precondition b. We avoid using "or" conditions directly because of the tendency to create axioms.

Note that currently, the user is able to specify "or"s in the precondition, as well as "or"s of "and's" by listing multiple conditions under an "or" bullet (see https://github.com/QuMuLab/plan4dial/blob/ee208d2849a40a68ac9d358e03ea6c4988b7cd3e/plan4dial/yaml_samples/or_test.yml#L75) and the equivalent actions will be generated (see https://github.com/QuMuLab/plan4dial/blob/ee7654440b3e2a6632e1b215d2ecb96a93c09700/output_files/or_test/or_test_domain.pddl#L56). Further nestings like "and"s of "or"s are not currently allowed, which is what this issue hopes to solve.

Ideally we can also apply this to "when" conditions, although "when" conditions may end up being converted to regular actions, in which case no extra work would need to be done (see #3 ).

Finally, it should also be applied to "context" specifications for context dependent system action, replacing the current context setting with the possibility for more complex formulas.

Fix Rasa Versioning Issue

  • Newer Rasa version seems to make old NLU models obsolete.
  • Need to update to the newest Rasa version (and make that a requirement) and retrain the local files we want to keep.
  • Should also update the gold_standard_bot model in contingent-plan-executor.

Indicate ambiguity

Add a warning that indicates ambiguity to the user when they try to extract >1 Spacy entities of the same type (i.e. 2 GPE entities) in the same utterance. This warning should only be raised if a custom disambiguator was not provided (see #2). In the future, this would apply not only to Spacy entities but to any entity extractor that would cause ambiguity with multiple of the same "type" of entity in an utterance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.