Behavior Rules

Version: 4.1.x

Behavior Rules are very flexible in structure to cover most use cases that you will come across. Behavior Rules are clustered in Groups. Behavior Rules are executed sequential within each Group. As soon as one Behavior Rule succeeds, all remaining Behavior Rules in this Group will be skipped. 

Groups
{
  "behaviorGroups": [
    {
      "name": "GroupName",
      "behaviorRules": [
        {
          "name": "RuleName",
          "actions": [
            "action-to-be-triggered"
          ],
          "children": [
            <CONDITIONS> 
          ]
        },
        {
          "name": "DifferentRule",
          "actions": [
            "another-action-to-be-triggered"
          ],
          "children": [
            <CONDITIONS> 
          ]
        },
        <MORE_RULES>
      ]
    }
  ]
}


Each Behavior Rule has a list of conditions, that - depending on the condition - might have a list of sub-conditions. If all conditions are true, than the Behavior Rule is successful and will trigger predefined actions.

Type of Conditions

General Structure

Conditions are always children of either a Behavior Rule or another condition. It always follows that same structure, that is:

typedefines the type of the condition
valuesdefines a key-value list of configurations for this condition (will vary from condition to condition)

Input Matcher

typeinputmatcher
valuesexpressionscomma separated list of expressions such as: expression(value),expression2(value2),yetAnotherExpressions(anotherValue(withASubValue))

occurrence

currentStep - did the user said it in this conversationStep

lastStep - did the user said it in the previous conversationStep

anyStep - did the user said it in any step if this whole conversation

never - if the user has never said that, including the current step


The inputmatcher is used to match user inputs. Not directly the real input of the user, but the meaning of it, represented by expressions that are resolved from by the parser.

If the user would type "hello", and the parser would resolved this as expressions "greeting(hello)" [assuming it has been defined in one of the dictionaries], then a condition could look as following in order to match this user input meaning:

...
"children": [
    {
         "type": "inputmatcher",
         "values": {
           "expressions": "greeting(*)",
           "occurrence": "currentStep"
         }
    }
]
...


This inputmatcher condition will match any Expression of type greeting, may that be "greeting(hello)", "greeting(hi)" or anything else. Of course, if you would want to match greeting(hello) explicitly, you would put "greeting(hello)" as value for the "expressions" field.


Context Matcher

typecontextmatcher
valuescontextKeythe key for this context (defined when handing over context to EDDI)

contextType

expressions

object

string


expressions (if contextType=expressions)

a list of comma separated expressions


objectKeyPath (if contextType=object)

objectValue

allows match via Jsonpath, such as "profile.username" (see: https://github.com/rest-assured/rest-assured/wiki/Usage)

Exp: contextKey: userInfo , contextValue: {"profile":{"username":"John"}}

The value to be match with the extracted JsonPath value


stringsimple string matching (equals)

The contextmatcher is used to match context data that has been handed over to eddi alongside the user input. This is great to check certain conditions that come from another system, such as the day time or to check the existence of user data.

...
"children": [
    {
         "type": "contextmatcher",
         "values": {
           "contextType":"expressions",
           "contextKey": "someContextName",
           "expressions": "contextDataExpression(*)"
         }
    }
]
...


...
"children": [
    {
         "type": "contextmatcher",
         "values": {
           "contextType":"object",
           "contextKey": "userInfo",
           "objectKeyPath": "profile.username",
           "objectValue": "John"
         }
    }
]
...
...
"children": [
    {
         "type": "contextmatcher",
         "values": {
           "contextType":"string",
           "contextKey": "daytime",
           "string": "night"
         }
    }
]
...

Connector

typeconnector
valuesoperatoreither AND or OR

The connector is there to all logical OR conditions within rules. By default all conditions are AND conditions, but in some cases it might be suitable to connect conditions with a logical OR.

...
"children": [
    {
         "type": "connector",
         "values": {
           "operator":"OR"
         },
         "children": [
         	<any other conditions>
		 ]
    }
]
...

Negation

typenegationinverts the overall outcome of the children conditions

In some cases it is more relevant if a condition is false than if it is true, this is where the negation condition comes into play. The logical result of all children together (AND connected), will be inverted.

Example:

Child 1 - true

Child 2 - true

→ Negation = false

Child 1 - false

Child 2 - true

→ Negation = true

...
"children": [
    {
         "type": "negation",
         "children": [
         	<any other conditions>
		 ]
    }
]
...

The API endpoints :

HTTP Method
API Endpoint
Request Body
Response
DELETE /behaviorstore/behaviorsets/{id}N/AN/A
GET /behaviorstore/behaviorsets/{id}N/ABehaviorSet model
PUT /behaviorstore/behaviorsets/{id}BehaviorSet modelN/A
GET /behaviorstore/behaviorsets/descriptorsN/ABehaviorSet model
POST /behaviorstore/behaviorsetsBehaviorSet modelN/A
GET /behaviorstore/behaviorsets/{id}/currentversionN/ABehaviorSet model
POST /behaviorstore/behaviorsets/{id}/currentversionBehaviorSet modelN/A

Example

We will demonstrate here the creation of a BehaviorSet

behaviorsets
Creating a BehaviorSet
Request URL
	POST	http://localhost:7070/behaviorstore/behaviorsets

Request Body

{
  "behaviorGroups": [
    {
      "name": "Smalltalk",
      "behaviorRules": [
        {
          "name": "Welcome",
          "actions": [
            "welcome"
          ],
          "children": [
            {
              "type": "negation",
              "children": [
                {
                  "type": "occurrence",
                  "values": {
                    "maxTimesOccurred": 1,
                    "behaviorRuleName": "Welcome"
                  }
                }
              ]
            }
          ]
        },
        {
          "name": "Greeting",
          "actions": [
            "greet"
          ],
          "children": [
            {
              "type": "inputmatcher",
              "values": {
                "expressions": "greeting(*)",
                "occurrence": "currentStep"
              }
            }
          ]
        },
        {
          "name": "Goodbye",
          "actions": [
            "say_goodbye",
            "CONVERSATION_END"
          ],
          "children": [
            {
              "type": "inputmatcher",
              "values": {
                "expressions": "goodbye(*)"
              }
            }
          ]
        },
        {
          "name": "Thank",
          "actions": [
            "thank"
          ],
          "children": [
            {
              "type": "inputmatcher",
              "values": {
                "expressions": "thank(*)"
              }
            }
          ]
        },
        {
          "name": "how are you",
          "actions": [
            "how_are_you"
          ],
          "children": [
            {
              "type": "inputmatcher",
              "values": {
                "expressions": "how_are_you"
              }
            }
          ]
        }
      ]
    }
  ]
}

Response Body
	no content

Response Code
	201

Response Headers
{
  "access-control-allow-origin": "*",
  "date": "Thu, 21 Jun 2018 01:00:02 GMT",
  "access-control-allow-headers": "authorization, Content-Type",
  "content-length": "0",
  "location": "eddi://ai.labs.behavior/behaviorstore/behaviorsets/5b2af892ee5ee72440ee1b4b?version=1",
  "access-control-allow-methods": "GET, PUT, POST, DELETE, PATCH, OPTIONS",
  "access-control-expose-headers": "location",
  "content-type": null
}