treethought / flask-assistant

Framework for Building Virtual Assistants with Dialogflow and python
Apache License 2.0
379 stars 101 forks source link

How to generate following json using yaml #64

Closed chaoranxie closed 5 years ago

chaoranxie commented 6 years ago

I have the following setup in Dialogflow, i am trying to see how i can reproduce it in the user_says.yaml

dialogflow

Exporting the agent shows the following related json content usersays.json

    "data": [
      {
        "text": "gender",
        "alias": "gender_id",
        "meta": "@gender",
        "userDefined": true
      }
    ],

intent.json

"parameters": [
        {
          "id": "8a88f79d-7001-457d-9616-e3092f83928a",
          "required": false,
          "dataType": "@gender",
          "name": "gender_id",
          "value": "$gender_id",
          "prompts": [],
          "defaultValue": "",
          "isList": false
        },
        {
          "id": "81c29436-1f4a-424f-a5d2-a2d51128adca",
          "dataType": "@gender",
          "name": "gender",
          "value": "$gender_id.original"
        }
      ],

Looking through the source code, i am not sure if I can create this setup in the yaml https://github.com/treethought/flask-assistant/blob/master/api_ai/models.py#L179-L181

        annotation['text'] = word
        annotation['meta'] = '@' + self.entity_map[word]
        annotation['alias'] = self.entity_map[word].replace('sys.', '')

from the code, it looks like meta and alias basically have to be the same name, but in my generated json, i have "alias": "gender_id", "meta": "@gender", Let me know if i am mistaken.

More notes: The way it is setup manually via Dialogflow works the exact the way I want to, but I want to reproduce it in yaml so i can version it better. (I could version the export zip file but not as good).

I will give more info on what i want to do and why and maybe someone can tell me there is better way to do it. I basically have 2 variables for gender. gender_id which can be male or female, this is key that i will use to query database. and gender this is the $gender_id.original which can be man, boy, girl, gal which i will use in response to the user in a more friendly way.

treethought commented 6 years ago

Thanks for pointing this out @chaoranxie. The reason for generating alias and meta as the same value is so that the parameter can then be mapped from the webhook request to the function's arguments.

The request delivers the parsed parameters via their alias (parameter name in the console), but the function args represent or are mapped to an Entity ('meta' value).

You could potentially use the mapping

@assist.action("give-gender", mapping={'gender_id': 'gender'})
def gender_func(gender, gender_id):

However, I think the real issue is the use of two references to a single parsed parameter from a user's phrase.

In my experience with DialogFlow, it is usually an anti-pattern to use the same entity for multiple parameters (often better to use composite entities). However, this double use of the @gender entity isn't really required for what you are trying to accomplish.

Ideally, you would accept a single gender parameter that maps to the @gender entity, and extract the "original" value inside your webhook. Unfortunately, there is no helper for doing that currently so you'd have to grab it from the request payload.

All that said, it would probably be beneficial to allow flexibility in defining the alias. Perhaps this can be incorporated into the User Says template