Comprendre le concept de request/action

Partons de notre exemple de départ: réserve-moi un billet de bus de Douala à Yaoundé demain après-midi. Cette requête utilisateur sera interprétée par NTeABot comme l’action BookBus avec les paramètres [startedPlace](Douala), [targetPlace](Yaoundé) et [time](demain après-midi). Tous ces éléments seront envoyés en paramètre au fichier Python qui traite de cette action cooltravel.py (tel que déclaré dans le fichier de configuration du field).

Préalabre

  • Un fichier request dépend essentiellement de la librairie Python plac. Vous devez donc la maîtriser avant de vous lancer.
  • Votre fichier python cooltravel.py doit être écrit en Python >= 3.4

Structure d’un fichier request/action

Notre fichier request cooltravel.py doit avoir cette structure. Vous remarquerez dans l’exemple ci-dessous qu’on injecte les données venant de l’API de cooltravel au template HTML response["cooltravelHtml"] = cooltravel_data["metadata"]. On pourrait aussi injecter des valeurs de paramètres du template spécifier par la clé from: action.

Danger

Vous remarquerez que le fichier Python suivant ne contient pas de clé import servant à importer des librairies externes ou encore l’entête de déclarration de fichier python #!/usr/bin/python3 et l’encodage du fichier # coding: utf-8 . C’est normal et il est déconseillé d’importer des modules externes sauf ceux recommandés, sinon votre field ne fonctionnera pas. Les modules suivants sont les seuls autorisés et sont implicitement injectés dans vos fichiers request: __future__, requests, plac, time, datetime, io.


ACTIONS_COOLTRIP = {
    "bookbus": ["startedPlace", "targetPlace", "travelAgencyName", "cooltravelHtml"],
    "booktrain": ["startedPlace", "targetPlace", "travelAgencyName", "cooltravelHtml"]
} 

@plac.annotations(
    bookbus=plac.Annotation("Request to book bus", "flag"),
    booktrain=plac.Annotation("Request to book train", "flag"),
    actionsparams="Parameters for all requests actions")
def main(bookbus, booktrain,  **actionsparams):

    "Cooltrip field manage all requests for booking trains and bus in Cameroon"

    response = {
        "metadata": {
            "type": "",
            "lenght": "",
            "action": "", 
            "time": "", 
            "url": "",
            "params": ""
        },
        "status": 200,
        "found": True
    }

    PARAMS = {
        'action':"book",
        'depart': "",
        'limit': 5,
        'arrival': "",
        'format':"json"
        'time': ""
    }

    # Initialisation de l'url par défaut
    defaultUrl = "https://api.cooltravel.com"

    # récupération des paramètres de la requête utilisateur
    PARAMS["depart"] = actionsparams['startedPlace']
    PARAMS["arrival"] = actionsparams['targetPlace']
    if "time" in actionsparams: PARAMS["time"] = actionsparams['time']
    if "travelAgencyName" in actionsparams: 
        PARAMS["agency"] = actionsparams['travelAgencyName']

    if bookbus:
        cooltravelsession = requests.Session()
        # éxecution de la requête 
        data = cooltravelsession.get(url=defaultUrl, params=PARAMS)
        cooltravel_data = data.json()
        if len(cooltravel_data["metadata"]) == 0: response['found'] = False
        # construction des paramètres de sorties
        response["status"] = data.status_code
        response["cooltravelHtml"] = cooltravel_data["metadata"]
        response["metadata"]["url"] = data.url
        response["metadata"]["type"] = "list"
        response["metadata"]["time"] = datetime.now().isoformat()
        response["metadata"]["params"] = actionsparams
        yield response

    if booktrain:
        cooltravelsession = requests.Session()
        # éxecution de la requête 
        data = cooltravelsession.get(url=defaultUrl, params=PARAMS)
        cooltravel_data = data.json()
        if len(cooltravel_data["metadata"]) == 0: response['found'] = False
        # construction des paramètres de sorties
        response["status"] = data.status_code
        response["cooltravelHtml"] = cooltravel_data["metadata"]
        response["metadata"]["url"] = data.url
        response["metadata"]["type"] = "list"
        response["metadata"]["time"] = datetime.now().isoformat()
        response["metadata"]["params"] = actionsparams
        yield response


if __name__ == '__main__':
    for output in plac.call(main): 
        print(output)

Il est important de remarquer dans ce fichier l’objet response. Cet objet doit toujours être déclaré tel quel et avant toutes les actions de votre field.

response = {
    "metadata": {
        "type": "",   # le type de sortie de l'action (list=tableau d'éléments | str=chaine de caractères)
        "lenght": "", # la longueur de la sortie de l'action 
        "action": "", # le nom de l'action 
        "time": "",   # l'heure à laquelle l'action a été traitée
        "url": "",    # l'URL de votre API 
        "params": ""  # les paramètres de votre action (slots)
    },
    "status": 200, # le code de statut de la requète API de l'action
    "found": True  # active les templates found lorsque l'action retourne bien un résultat
}

Quelques recommandations

N’oubliez surtout pas, si l’action ne trouve pas les résultats escomptés, de passer la variable found à False: response['found'] = False. Ce qui permet à NTeABot de renvoyer les templates nofound, définit dans la partie responses du template de l’action.

Note

  • bookbus et booktrain correspondent respectivement aux noms de l’action déclaré dans vos utterances BookBus et BookTrain.
  • Vous ne pouvez pas utiliser d’autres librairies externes. Sauf les librairies natives de Python 3 sont autorisées.
  • Il est recommandé de développer et de tester ce fichier python hors du field et de l’intégrer lorsque tout semble fonctionner.
  • Pour tester votre fichier, vous pouvez ajouter les dépendances Python. Et une fois terminé, retirer les.