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.
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:
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.
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é à.
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.
--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
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.
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.
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.
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.
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)".
Il s'agit de la version de code nouvellement créée "0.0.1". Cliquez sur le lien pour accéder à l'écran individuel.
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.
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,
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'
}
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) 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) 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) 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.
Maintenant, compressons le code source résultant dans une 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.
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".
Vous pouvez vérifier l'URL du point final nouvellement créé à partir de l'icône d'élève dans la liste des services.
Il doit être au format «https: // {ORGANIZATION_NAME} .api.abeja.io / deployments / {DEPLOYMENT_ID}». Enregistrez-le en tant que webhook de bot LINE.
Pour vérifier le fonctionnement, j'ai posté quelques photos sur le bot LINE que j'ai créé cette fois. [^ 1]
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