[PYTHON] Créez une application d'apprentissage automatique avec ABEJA Platform + LINE Bot

Cet article est l'article du deuxième jour du Calendrier de l'Avent ABEJA 2019.

L'année dernière ABEJA Platform Advent Calendar a déclaré: "[Summary of ABEJA Platform Certification](https://qiita.com/ishikawa@github/items/ J'ai introduit l'authentification des appels API dans ABEJA Platform sous le titre "150a0705d9581c1000c6)", mais je l'ai également écrite dans le matériel ABEJA Platform cette année.

Malheureusement, la plate-forme ABEJA ne prend pas en charge Elixir, donc tout le code est écrit en Python.

Aperçu

Publié en juillet 2019 par @yushin_n "[ABEJA Platform + Cloud Functions + LINE Bot pour créer une application d'apprentissage automatique](https: // qiita. com / yushin_n / items / 0d115efa705579a53cfe) "

Le thème était de créer une application d'apprentissage automatique sans serveur en combinant.

Cette fois, je présenterai la procédure pour améliorer cette application de machine learning et ** développer LINE Bot uniquement sur la plateforme ABEJA sans utiliser Google Cloud Functions **.

Pour ce faire, cet article utilise les trois fonctionnalités suivantes de la plate-forme ABEJA:

Nouvelle image de conteneur

La plate-forme ABEJA est à peu près divisée en 18.10 et série 19.x. Nous fournissons deux types d'images (/model-handler-19.04/). Dans la série 19.x, non seulement des bibliothèques et des frameworks plus récents sont installés, mais également la méthode d'implémentation de l'API d'apprentissage automatique a été repensée pour permettre un traitement plus flexible.

Modèle d'inférence

La plateforme ABEJA fournit des modèles d'apprentissage et d'inférence pour certaines tâches d'apprentissage automatique. En utilisant ce modèle, non seulement vous pouvez apprendre et déduire des modèles d'apprentissage automatique sans écrire une seule ligne de code, mais il convient également au domaine commercial (cette fois, le bot LINE pour la classification d'images) que vous souhaitez implémenter en modifiant le code. Peut être amélioré à.

Méthode d'authentification du point de terminaison API

Vous pouvez sélectionner la méthode d'authentification pour l'API déployée. Non seulement vous pouvez choisir entre l'authentification utilisateur intégrée et l'authentification par clé API, mais vous pouvez également désactiver l'authentification elle-même et implémenter votre propre traitement. L'implémentation du bot LINE utilise cette fonctionnalité pour implémenter l'authentification de validation de signature.

Configuration du système

--Envoyer des images à LINE Bot --Recevoir une requête HTTP (webhook) de l'API de messagerie LINE avec le service HTTP de la plate-forme ABEJA

ABEJA_Platform_LINEbot_Arch.png

Implémentation du code d'inférence

Dans «Modèle d'apprentissage machine learning sans programmation à l'aide du modèle de plate-forme ABEJA», la formation réseau est déjà terminée et les paramètres résultants Est stocké en tant que "modèle" de la plateforme ABEJA.

スクリーンショット 2019-12-01 18.18.38.png

Créer la première version à partir du modèle

Je ne veux pas écrire le code d'inférence à partir de zéro, je vais donc modifier le code dans le modèle d'inférence ABEJA Platform. Dans le modèle d'inférence,

--Inférence de classification d'image --Retournez le résultat de l'inférence dans JSON

Le traitement étant implémenté, vous devez ajouter ici le traitement spécifique au bot LINE (les détails seront décrits plus loin).

Afin de générer le code pour le modèle d'inférence, vous devez créer un «déploiement» qui est le conteneur qui gère le code (et les services déployés). Créez un nouveau déploiement à partir du bouton "Créer un déploiement" sur l 'Écran Liste de déploiement.

スクリーンショット 2019-12-01 18.28.45.png

Le déploiement nouvellement créé doit être répertorié comme "version de modèle 0". Ce lien vous mènera à l'écran de gestion du code.

スクリーンショット 2019-12-01 18.33.00.png

L'écran Gestion du code vous permet de contrôler la version du code qui appartient à ce déploiement. Immédiatement, créez une nouvelle version de code à partir de «Créer une version» en haut à droite.

スクリーンショット 2019-12-01 18.33.24.png

Cette fois, je souhaite modifier le code du modèle, alors sélectionnez "Modèle" dans l'onglet et sélectionnez "Classification des images (CPU)".

スクリーンショット 2019-12-01 18.33.43.png

Il s'agit de la version de code nouvellement créée "0.0.1". Cliquez sur le lien pour accéder à l'écran individuel.

スクリーンショット 2019-12-01 18.34.10.png

Vous pouvez télécharger le code source zip à partir du lien "Télécharger" sur l'écran séparé de la version du code.

スクリーンショット 2019-12-01 18.34.20.png

Améliorer le code du modèle

Lorsque vous décompressez le fichier zip téléchargé, vous devriez voir une structure de répertoires comme celle ci-dessous.

$ ls -l 
total 96
-rw-r--r--@ 1 user  staff   1068 10 30 01:31 LICENSE
-rw-r--r--@ 1 user  staff   4452 10 30 01:31 README.md
-rw-r--r--@ 1 user  staff   1909 10 30 01:31 predict.py
-rw-r--r--@ 1 user  staff  12823 10 30 01:31 preprocessor.py
-rw-r--r--@ 1 user  staff     82 10 30 01:31 requirements-local.txt
-rw-r--r--@ 1 user  staff     25 10 30 01:31 requirements.txt
-rw-r--r--@ 1 user  staff   4406 10 30 01:31 train.py
drwxr-xr-x@ 6 user  staff    192 10 30 01:31 utils

Reportez-vous à l 'article original et ajoutez les bibliothèques requises à requirements.txt.

line-bot-sdk
googletrans
...

Et predict.py est un fichier qui implémente le traitement d'inférence, mais voici le traitement requis pour le bot LINE,

  1. Vérification de la signature envoyée dans l'en-tête
  2. Récupérez les données d'image du message LINE
  3. Répondez au résultat sur LINE

Il est nécessaire de mettre en œuvre en plus.

Tout d'abord, placez le predict.py avec ces implémentations terminées. Nous modifions la fonction handler, qui est le point d'entrée de la requête.

import os
import io
import linebot
import linebot.exceptions
import linebot.models
import googletrans

from keras.models import load_model
import numpy as np
from PIL import Image

from preprocessor import preprocessor
from utils import set_categories, IMG_ROWS, IMG_COLS


# Initialize model
model = load_model(os.path.join(os.environ.get(
    'ABEJA_TRAINING_RESULT_DIR', '.'), 'model.h5'))
_, index2label = set_categories(os.environ.get(
    'TRAINING_JOB_DATASET_IDS', '').split())

# (1) Get channel_secret and channel_access_token from your environment variable
channel_secret = os.environ['LINE_CHANNEL_SECRET']
channel_access_token = os.environ['LINE_CHANNEL_ACCESS_TOKEN']

line_bot_api = linebot.LineBotApi(channel_access_token)
parser = linebot.WebhookParser(channel_secret)


def decode_predictions(result):
    result_with_labels = [{"label": index2label[i],
                           "probability": score} for i, score in enumerate(result)]
    return sorted(result_with_labels, key=lambda x: x['probability'], reverse=True)


def handler(request, context):
    headers = request['headers']
    body = request.read().decode('utf-8')

    # (2) get X-Line-Signature header value
    signature = next(h['values'][0]
                     for h in headers if h['key'] == 'x-line-signature')

    try:
        # parse webhook body
        events = parser.parse(body, signature)
        for event in events:
            # initialize reply message
            text = ''

            # if message is TextMessage, then ask for image
            if event.message.type == 'text':
                text = 'Veuillez m'envoyer une image!'

            # (3) if message is ImageMessage, then predict
            if event.message.type == 'image':
                message_id = event.message.id
                message_content = line_bot_api.get_message_content(message_id)

                img_io = io.BytesIO(message_content.content)
                img = Image.open(img_io)
                img = img.resize((IMG_ROWS, IMG_COLS))

                x = preprocessor(img)
                x = np.expand_dims(x, axis=0)

                result = model.predict(x)[0]
                sorted_result = decode_predictions(result.tolist())

                # translate english label to japanese
                label_en = sorted_result[0]['label']
                translator = googletrans.Translator()
                label_ja = translator.translate(label_en.lower(), dest='ja')

                prob = sorted_result[0]['probability']

                # set reply message
                text = f'{int(prob*100)}%Avec une probabilité de{label_ja.text}est!'

            line_bot_api.reply_message(
                event.reply_token,
                linebot.models.TextSendMessage(text=text))

    except linebot.exceptions.InvalidSignatureError:
        raise context.exceptions.ModelError('Invalid signature')

    return {
        'status_code': 200,
        'content_type': 'text/plain; charset=utf8',
        'content': 'OK'
    }

Description du code

Les parties liées à l'implémentation du bot LINE sont numérotées dans les commentaires. Jetons un œil étape par étape. Le code autre que celui décrit ici est le modèle d'inférence et l'article d'origine.

1. Initialisation du SDK du bot LINE

# (1) Get channel_secret and channel_access_token from your environment variable
channel_secret = os.environ['LINE_CHANNEL_SECRET']
channel_access_token = os.environ['LINE_CHANNEL_ACCESS_TOKEN']

line_bot_api = linebot.LineBotApi(channel_access_token)
parser = linebot.WebhookParser(channel_secret)

Ici, le SDK du bot LINE est utilisé pour initialiser le client API et l'analyseur de messages. Les paramètres (clé privée et jeton d'accès) requis pour l'initialisation sont supposés être passés en tant que variables d'environnement.

2. Vérification de la signature

# (2) get X-Line-Signature header value
signature = next(h['values'][0]
                 for h in headers if h['key'] == 'x-line-signature')

try:
  # parse webhook body
  events = parser.parse(body, signature)

Validez la signature «X-Line-Signature» passée dans l'en-tête de la requête HTTP avec le SDK. L'en-tête de la requête HTTP est stocké dans le dict "request" passé à la fonction de gestionnaire.

3. Obtenez l'image envoyée dans le message

# (3) if message is ImageMessage, then predict
if event.message.type == 'image':
  message_id = event.message.id
  message_content = line_bot_api.get_message_content(message_id)

  img_io = io.BytesIO(message_content.content)
  img = Image.open(img_io)
  img = img.resize((IMG_ROWS, IMG_COLS))

Obtient le contenu du message et le convertit en objet Image PIL.

Déployer un modèle d'apprentissage automatique

Maintenant, compressons le code source résultant dans une nouvelle version de code.

スクリーンショット 2019-12-01 19.10.45.png

Nouvelle version de code

Depuis l'écran de gestion de code précédent, affichez l'écran de création de la nouvelle version de code et téléchargez le zip. À ce stade, définissez le runtime (image du conteneur) sur "** abeja-inc / all-cpu: 19.10 **" et définissez les variables d'environnement nécessaires.

スクリーンショット_2019-12-01_17_44_11.png

Déployer l'API

Déployez l'API comme décrit dans «Déployer un modèle d'apprentissage automatique sans programmation à l'aide des modèles de plate-forme ABEJA», alors ne le répétez pas. Hmm.

Cependant, comme je l'ai expliqué au début, j'ai créé un nouveau point de terminaison pour transmettre la demande du bot LINE sans "authentification".

スクリーンショット 2019-12-01 17.49.02.png

Vous pouvez vérifier l'URL du point final nouvellement créé à partir de l'icône d'élève dans la liste des services.

スクリーンショット 2019-12-01 19.20.30.png

Il doit être au format «https: // {ORGANIZATION_NAME} .api.abeja.io / deployments / {DEPLOYMENT_ID}». Enregistrez-le en tant que webhook de bot LINE.

スクリーンショット_2019-12-01_17_49_17.png

Vérification du fonctionnement du bot LINE

Pour vérifier le fonctionnement, j'ai posté quelques photos sur le bot LINE que j'ai créé cette fois. [^ 1] IMG_1528.png

Indépendamment de la vérité du résultat, il semble fonctionner comme un robot (?) LINE.

[^ 1]: Les photos que j'ai utilisées pour ce message sont les suivantes. tournesol par Aiko, Thomas & Juliette + Isaac, [rose par Waldemar Jan](https://www.flickr.com/photos/128905059@ N02 / 22138314909 /), chou-fleur par liz west

Recommended Posts

Créez une application d'apprentissage automatique avec ABEJA Platform + LINE Bot
Créer un LINE BOT avec Minette pour Python
Créez un environnement d'apprentissage automatique à partir de zéro avec Winsows 10
Créer un bot LINE avec Django
[LINE Messaging API] Créez un BOT qui se connecte à quelqu'un avec Python
Comment créer une API de machine learning sans serveur avec AWS Lambda
Une histoire sur l'apprentissage automatique avec Kyasuket
Créer une application graphique avec Tkinter de Python
[Python] [LINE Bot] Créer un robot LINE de retour de perroquet
Créez une application Web simple avec Flask
J'ai fait un robot de remplacement de tampon avec une ligne
J'ai créé un Bot LINE avec Serverless Framework!
Étapes pour créer un bot Twitter avec Python
Procédure de création d'application multi-plateforme avec kivy
Créer un bot LINE WORKS avec Amazon Lex
Créer un environnement d'apprentissage automatique Python avec des conteneurs
[Apprentissage automatique] Créez un modèle d'apprentissage automatique en effectuant un apprentissage par transfert avec votre propre ensemble de données
Créez une application Web typée avec le framework Web de Python «Fast API» et TypeScript / Open API - Pile technique pour les applications Web d'apprentissage automatique
Créer un bot slack
[AWS] J'ai créé un BOT de rappel avec LINE WORKS
Créer une application Todo avec Django REST Framework + Angular
Exécutez un pipeline de machine learning avec Cloud Dataflow (Python)
Créez une application graphique native avec Py2app et Tkinter
Apprentissage automatique facile avec scikit-learn et flask ✕ Application Web
Essayez de créer une application Todo avec le framework Django REST
Sentons-nous comme un chercheur en matériaux avec l'apprentissage automatique
Créer une application Todo avec Django ③ Créer une page de liste de tâches
J'ai essayé de faire LINE BOT avec Python et Heroku
Créer un environnement de développement d'applications d'apprentissage automatique avec Python
Créer une application Todo avec Django ⑤ Créer une fonction d'édition de tâches
[Super facile] Faisons un LINE BOT avec Python.
[LINE Messaging API] Créer un BOT de retour de perroquet avec Python
Comment créer rapidement un environnement d'apprentissage automatique à l'aide de Jupyter Notebook avec UbuntuServer 16.04 LTS
Jusqu'à ce que vous créiez un environnement d'apprentissage automatique avec Python sur Windows 7 et que vous l'exécutiez
L'apprentissage automatique appris avec Pokemon
Créez un bot LINE avec GoogleAppEngine / py. Version nue simple
Créez un environnement d'apprentissage automatique scikit-learn avec VirtualBox et Ubuntu
Créez un bot Mastodon avec une fonction pour répondre automatiquement avec Python
Application correspondante, j'ai essayé de prendre des statistiques de personnes fortes et j'ai essayé de créer un modèle d'apprentissage automatique
Créer une page d'accueil avec django
[Fiche d'apprentissage] Créez un mystérieux jeu de donjon avec Pyhton's Tkinter
Apprentissage automatique avec Python! Préparation
Créer un LINE BOT (chat)
Jusqu'à ce que Django retourne quelque chose avec un robot de ligne!
Créez un Twitter BOT avec le SDK GoogleAppEngine pour Python
Démineur d'apprentissage automatique avec PyTorch
Créer un environnement d'apprentissage automatique
Créer une application Todo avec Django ① Créer un environnement avec Docker
Commencer avec l'apprentissage automatique Python
Créer un répertoire avec python
Essayez le machine learning à la légère avec Kaggle
[AWS] J'ai créé un BOT de rappel avec LINE WORKS (implémentation)
Créez une application de gestion automatique des notes pour Tenho Private Room avec le bot LINE et Python Partie 1
Créez une application de gestion automatique des notes pour Tenho Private Room avec le bot LINE et Python Partie 2
Créez une application de gestion automatique des notes pour la salle privée Tenho avec le bot LINE et la partie Python ③
Étapes rapides pour créer un environnement d'apprentissage automatique à l'aide de Jupyter Notebook sur macOS Sierra avec anaconda
Une histoire coincée avec l'installation de la bibliothèque de machine learning JAX
Création d'un environnement Windows 7 pour une introduction à l'apprentissage automatique avec Python