[PYTHON] Je suis à Singapour en ce moment Une histoire sur la création d'un LineBot et la volonté de faire un travail mémorable

"Désolé, je ne peux pas aller en classe"

Ce CM a un fort impact. J'adore ça quand je l'invite à une réunion de classe "** Je suis à Singapour maintenant **" J'ai créé un ** LineBot ** qui vous répondra. De plus, diverses spécifications ont été ajoutées pour améliorer encore le ** sentiment doya **. Même s'il ne reste pas sur la carte, je veux en faire un ** travail mémorable ** pour la personne qui l'a utilisé!

C'est le 4ème jour du Fucking App Advent Calendar 2019. ~~, le sentiment d'une putain d'application qui dérive du titre sans écrire ~~

Comment utiliser:

① ** Tenez une réunion de classe ** ② ** Démarrer la ligne et demander "Ayano, où es-tu maintenant?" ** ③ ** Je reçois une réponse disant "Je suis désolé, je ne peux pas assister à la réunion de classe ~~~" ④ ** Tout le monde y regarde avec le sentiment que "Eh, Singapour" **

État lors de l'exécution:

キャプチャ1.PNG

Si vous souhaitez l'exécuter à portée de main, veuillez vous inscrire en tant qu'ami ici.

Ajouter un ami QR_min.PNG

"Je suis à Singapour maintenant"

Si vous ne l'avez pas encore vu, veuillez consulter le CM lui-même ci-dessous.

[Taisei Construction CM: "Singapour" (youtube)](https://www.youtube.com/watch?v= HQYQ3Me2KLw) https://www.youtube.com/watch?v=HQYQ3Me2KLw

"Emplois qui restent sur la carte"

Diverses fonctions ~~ supplémentaires ~~ sont implémentées. Le premier est "** Emplois qui restent sur la carte **".

**Singapour! !! Pour rendre ** plus attrayant J'ai gentiment essayé de montrer une carte indiquant l'emplacement de Singapour. Avec cela, ** la sensation qui reste sur la carte ** est parfaite ☆

De plus, l'international AYANO ** Volez dans plus de 200 pays et régions (génial) ** Si vous posez une question autre qu'une phrase fixe, Elle n'est pas toujours à Singapour. Vous entendrez des réponses de divers endroits! キャプチャ1-2.PNG

Parce que vous pouvez trouver l'emplacement même avec un nom de pays inconnu ** C'est aussi une application pour étudier la géographie du monde! ** ** ~~ Ce n'était peut-être pas une putain d'application. ~~

Répondez à diverses invitations telles que des buvettes et des fêtes d'adieu

Oups, si vous regardez de plus près, dans la capture d'écran ci-dessus Il semble que vous soyez invité à une "réunion de classe". ** Répondez immédiatement au contenu de la soirée invitée **!

Veuillez nous inviter à faire quoi que ce soit, que ce soit une "** fête commune " ou une " soirée de visionnement des fleurs de cerisier **".

Création de Laputa (~~ Pas laissé sur la carte ~~)

AYANO fabrique aussi des choses autres que le métro. キャプチャ2-1.PNG

Nous fabriquons diverses choses en plus de Laputa! Veuillez vérifier par vous-même les différentes autres créations. ~~ Mettez la jeunesse de quelqu'un sur = Theta & Pazu. Mettez-vous. ~~

Fonction qui répond à vos mots clés (analyse morphologique)

Bien que nous répondrons en fonction du contenu de l'invitation comme la deuxième partie, Avec les fonctions jusqu'à présent, il y a un "sentiment d'affichage de message aléatoire", Peut-être à un ami qui m'a regardé ensemble "** Oh, n'est-ce pas AYANO un Bot? **" Il peut être chauve.

Donc, en réponse aux mots-clés de la conversation que vous avez lancée, Quelque chose ** a ajouté une fonction pour renvoyer des mots significatifs **. (Cadre rouge) キャプチャ_ラーメン.PNG ~~ Conversation très consciente. Il semble que les ramen soient nostalgiques. ~~

Bien sûr, AYANO peut comprendre le japonais, donc ** Vous pouvez reconnaître les "mots importants" qui apparaissent dans la conversation. ** ** Cette fois, j'ai reconnu que «nom / général» était important. S'il n'existe pas, il répondra "Jobs qui restent sur la carte". Dans l'exemple ci-dessus, il semble reconnaître "ramen". ** Cela crée une réalité pour AYANO et est mémorable! ** **

L'analyse morphologique elle-même n'est plus une technique formidable. Cependant, l'implémentation à intégrer dans GAE (comme Serverless / AWS Lambda) Le fait est que ce n'est pas très familier (c'est un peu difficile à réaliser). ** Il n'y a pas d'appel d'API externe, et c'est explosif. Super immédiat moins ☆ **

** Maintenant, à divers endroits tels que les réunions de classe et les buvettes ** ** Vous pouvez maintenant parler avec AYANO partout dans le monde ☆ **

** Lorsqu'il est utilisé avec des amis, il peut être vu avec des yeux blancs chauds, ** ** Il ne fait aucun doute que ce sera un "travail mémorable" ☆ **

Alors c'est tout pour l'introduction du contenu Points d'ingéniosité et code pour l'implémentation, J'écrirai ci-dessous divers savoir-faire pour créer LineBot.

C'est long.

Points de mise en œuvre: table des matières / résumé

  1. Points de toute la méthode
  2. Matériel de référence à la base de l'ensemble
  3. LineBot nécessite HTTPS. Faisons-le avec GAE
  4. LineBot Reply est gratuit. Push est facturé. Faisons-le uniquement avec Reply
  5. Le secret de l'API de messagerie en ligne
  6. L'astuce pour utiliser le «jeton d'accès» en permanence
  7. L'astuce pour tromper la "confirmation de connexion"
  8. Une petite astuce compliquée pour "afficher une carte"
  9. L'histoire selon laquelle "attendre" n'a pas pu se réaliser
  10. Comment échapper aux restrictions de GAE (Google App Engine)
  11. Le traitement du langage naturel est trop lourd pour fonctionner normalement gratuitement
  12. Une histoire quand cela fonctionne localement mais pas dans GAE

1. Points de toute la méthode

1-1. Documents de référence qui forment la base de l'ensemble

Tout d'abord, comment faites-vous LineBot en premier lieu? Alors, veuillez vous référer à la page suivante. (Ceci est un article sur le blog de développement de personnes en ligne.)

J'ai créé un robot qui peut suivre le dernier train en utilisant des messages de carte d'image

La configuration de base sera créée de la même manière que cet article. ** Python + Flask ** (Cependant, la version Python est passée de 3.6 à 3.7) Et l'image de la carte utilise ** Google Static Maps API ** ainsi que l'article.

Tout d'abord, c'est une bonne idée de déployer "Aum Return Bot". Mais ** le simple fait d'écrire et d'exécuter ce code n'en fait pas un LineBot **. Comment dois-je le déplacer?

1-2. LineBot est basé sur HTTPS. Faisons-le avec GAE

La plupart des informations sur la création de LineBot semblent être déployées dans ** Heroku **. La raison d'utiliser Heroku est ** parce que HTTPS est facile à utiliser **.

Pour créer un LineBot, connectez-vous d'abord à LINE Developers. (Vous pouvez utiliser votre propre compte Line tel quel)

Il y a un endroit pour spécifier "URL Webhook" après la connexion, Seul ** HTTPS peut être spécifié pour spécifier l'URL **. De plus, lors de la spécification d'un fichier image à transmettre dans le code, etc. L'API de messagerie de ligne requiert que ** URL HTTPS soit spécifiée **. (Vous ne pouvez pas envoyer de fichier local. Assurez-vous de le spécifier par URL)

En d'autres termes, la création d'un serveur HTTPS est presque essentielle pour le ** développement LineBot **.

Il existe trois options principales ici. ① ** Configurez votre propre serveur et rendez-le HTTPS ** ② ** Utilisez le service sans serveur / PaaS ** (Heroku, GAE, Lambda, etc.) ③ Utilisez un service dédié tel que ** Twilio ** et faites-leur prendre en charge la partie serveur

Pour un robot de réponse simple, ③ est le plus recommandé. Cette fois, j'écris moi-même un code un peu compliqué, donc c'est ① ou ②. Bien que ① puisse être réalisé gratuitement, la préparation / le fonctionnement du serveur est un peu gênant. Par conséquent, ② est la meilleure option.

Probablement à cause de l'exemple officiel de Line et des raisons ci-dessus Informations sur la fabrication de la plupart des LineBots Il semble que Heroku soit une condition préalable. Cependant, ** essentiellement tout va bien tant que HTTPS peut être facilement réalisé **, donc Il n'y a aucun élément qui dépend d'Heroku.

Cette fois j'ai un peu changé d'avis Je souhaite utiliser ** GAE (GoogleAppEngine) **. Le code de l'article pour Heroku fonctionne presque tel quel.

La version d'exécution Python 3 de GAE est uniquement Python 3.7, donc ce point doit être changé

** GAE (Standard Environment) a un niveau gratuit de 28 heures à tout moment par jour. ** ** (En novembre 2019) Hé, je pense que c'est 24 heures sur 24, non? Lorsque plusieurs instances sont lancées en même temps en fonction de l'état de charge, Si vous lancez une meilleure instance en termes de performances C'est un mécanisme qui compte le temps pendant plusieurs minutes. En d'autres termes, si la charge peut être traitée par une instance avec la configuration minimale Même s'il y en a quelques-uns au sommet L'image est qu'elle tient toujours dans un cadre libre.

Toujours gratuit = En dehors du coupon gratuit de 30000 yens pouvant être utilisé la première année avec GCP

La gamme d'utilisation qui peut être utilisée gratuitement même après un an. Par exemple, "Qiita Hall of Fame" utilise ce niveau toujours gratuit dans IaaS.

Exécutez le didacticiel Flask Python 3.7 de GAE (Il suffit de faire git clone et gcloud app deploy et ce sera bientôt fait) Si vous remplacez main.py le code de référence, le LineBot est presque terminé. (Ajoutez également line-bot-sdk == 1.14.0 à requirements.txt)

1 à 3. LineBot Reply est gratuit. Push est facturé. Faisons-le uniquement avec Reply

La meilleure façon d'utiliser l'API Line Messaging dans le développement personnel est Il semble ** concevoir un service avec Reply **.

L'API LineMessaging a une limite de paiement à l'utilisation pour l'envoi de messages de type Push. Avec le niveau gratuit, vous ne pouvez envoyer que 1000 messages par mois. Même si vous facturez, si vous dépassez un certain nombre, vous serez facturé environ 3 à 5 yens par copie. (Pour plus de détails, veuillez consulter le site officiel / les dernières informations, etc.)

Cependant, ** Reply peut être utilisé gratuitement **.

En tant que première conception de la vue d'ensemble du service ** "Conception de service qui permet de répondre naturellement au discours de l'utilisateur" ** Il serait souhaitable d'avoir une forme qui ne dépend pas de la transmission de type Push.

Cependant, Reply ne peut être utilisé que pendant un certain temps après que l'utilisateur parle. Ne répondez qu'une seule fois pour un épisode et seulement 5 éruptions à la fois, Il est également important de noter qu'il ne peut être utilisé.

Par exemple, si vous souhaitez créer "** une application qui compte les nombres premiers et se calme **" Si le bot parle unilatéralement à 13, 17, 19 ... toutes les 3 secondes, Ce sera un type Push. prochain? prochain? Et demandez à l'utilisateur à chaque fois Pour qu'il soit naturel de leur faire répondre 23, 29, etc. Il vaut mieux penser à la conception de l'ensemble du service.

Cette fois, AYANO a dit: "Allons à la réunion de classe!" Tout comme il est tout à fait naturel de répondre à une invitation Il s'intègre dans la conception du service!

2. Le secret de l'API de messagerie en ligne

2-1. L'astuce secrète pour utiliser le «jeton d'accès» en permanence

Les emplacements suivants de l'article source de référence, Pour "YOUR_CHANNEL_ACCESS_TOKEN"

line_bot_api = LineBotApi('YOUR_CHANNEL_ACCESS_TOKEN')

Gratuit / peut être émis autant de fois que vous le souhaitez sur LINE Developers Définissez le «jeton d'accès au canal (long terme)». Il est situé en bas de "Paramètres de l'API de messagerie".

Mais ce jeton d'accès est Il est nécessaire de fixer la date d'expiration au moment de l'émission, "Délai avant que le jeton d'accès au canal actuel ne devienne invalide" ** Vous ne pouvez configurer que jusqu'à 24 heures avec le menu déroulant **.

Normalement réglé sur 24 heures, à un rythme d'environ toutes les 23 heures J'ai besoin de créer un processus d'extension / réécriture, Voici un ** vrai truc ** (à un niveau où vous vous demandez si vous pouvez l'écrire).

Si vous définissez ** time = 0, ce sera un jeton valide en permanence **. (En novembre 2019)

** Awesomely rapide ~~ Hand Sword ~~ Temps effectif, je le manquerai si je ne le fais pas ** Dans cet esprit, nous vous remercions de l'utiliser. (Cette ligne est un drapeau de mort complet)

Ce n'est pas un bug de ligne, mais la date d'expiration du jeton d'accès est Il semble que c'était indéfini au début. Changer pour mettre une limite de temps, Une période de transition de ce changement? De nombreuses oppositions mettent du temps à changer? Semble être Pour cela, définissez essentiellement l'heure effective, Il semble que les gens qui le connaissent peuvent l'utiliser indéfiniment. (Y compris les rumeurs et les suppositions diaboliques. Vérité inconnue)

Je ne connais pas le meilleur moyen d'automatiser l'expiration de ce jeton (Je veux rendre sans serveur essentiellement apatride) Dois-je arrêter de développer LineBot simplement parce qu'il y a une date limite pour ce type? Parce que c'était un point critique ** J'espère sincèrement que vous continuerez à l'utiliser indéfiniment **.

2-2. L'astuce pour tromper la "confirmation de connexion"

Cela provient généralement des développeurs LINE C'est une histoire à moitié buggée. (En novembre 2019)

Comme mentionné ci-dessus, dans l '"URL du Webhook" de LINE Developes, L'URL GAE sera répertoriée comme URL HTTPS. N'est pas OK même si j'appuie sur le bouton "Confirmer la connexion".

Donc, dans la définition de la poignée du code d'origine, comme suit Ajoutez une branche de traitement avec un jeton de réponse spécial.

#Voici la définition de la poignée
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    #Code spécial pour effectuer la "confirmation de connexion" de la ligne OK
    #Lorsque vous appuyez sur "Vérifier la connexion" dans la Developer Console de Line
    #Si vous le faites normalement, répondez_500 retours en raison d'un jeton illégal.
    #Je me fâche si le 200 attendu n'est pas retourné du côté de la confirmation de connexion.
    #Problèmes sur la console de Line à partir de novembre 2019. Sera probablement résolu éventuellement.
    if event.reply_token == "00000000000000000000000000000000":
        return
    #Omis ci-dessous

Cela ne signifie pas que cela ne fonctionnera que si la "confirmation de connexion" est passée. Cependant, c'est toujours une question d'humeur, donc je veux faire une confirmation de connexion = OK. Pour plus d'informations, consultez l'article du grand pionnier Qiita ci-dessous.

À propos du problème qu'une erreur se produit lors de la vérification de la connexion de l'URL Webhook de LINE Developes

2-3. Une petite astuce compliquée pour "afficher la carte"

Le processus le plus déroutant dans ce développement est Le processus d'affichage d'une carte, c'est-à-dire Il s'agit d'un processus pour envoyer le résultat de ** Google Static Maps API ** à Line.

Tout d'abord, qu'est-ce que l'API Google Static Maps? Avec l'API de carte fournie par Google Une chose qui a fait de Google MAP une image statique Il peut être obtenu en spécifiant des paramètres simples.

Ce qui est étonnant, ce n'est pas seulement la désignation par latitude et longitude, mais aussi Singapour, Yokohama, etc. Il prend également en charge le retour des coordonnées en les spécifiant avec un nom de lieu. Une liste des pays et régions du monde où AYANO vole Il contient des informations dans un simple type LIST. Même si vous n'avez pas de coordonnées GPS dans cette LISTE Jetez simplement le nom du pays dans l'API Google Static Maps, On vous apprend les coordonnées. Facile. S'il vous plaît google pour d'autres options détaillées le cas échéant.

Alors ** Comment envoyer cette image de l'API Google Static Maps à Line? ** **

LineMessagingAPI dispose d'une API pour l'envoi d'images, Veuillez spécifier l'image à envoyer avec l'URL https, Est écrit dans la référence.

Et l'API Google Static Maps Accédez à l'image de la carte statique via HTTPS.

** URL de l'API Google Static Maps ** ** Spécifiez-le simplement dans l'argument de LineMessagingAPI! ** ** ** ⇒ Perdu. ** **

L'URL de l'API Google Static Maps est HTTPS. Mais le fichier image "n'existe" pas directement dans ce chemin, Parce qu'il est calculé et affiché dans Google ** Vu du côté Line, ce n'est pas une image, non? Il semble que ça ressemble à ** ** Cette méthode ne semble pas fonctionner. ** ** (* La raison exacte pour laquelle cela ne fonctionne pas ne peut être comprise qu'en interrogeant la personne à l'intérieur. Peut-être parce que la clé API est également incluse dans les paramètres d'URL Je pensais que ce serait impossible à cause de cette certification)

Par conséquent, seules les images créées par l'API Google Static Maps Il semble s'afficher de manière pseudo sur un serveur self-made (cette fois sur GAE) Vous devez avoir le code prêt. C'est la partie de la partie de code décrite plus loin.

@app.route("/imagemap/<path:url>/<size>")
def imagemap(url, size):
#Ce qui suit est omis

La même chose est faite dans l'article de base de la source de référence. À première vue, je n'ai pas compris l'intention du code, j'ai donc ajouté un commentaire.

En outre, à la suite de l'ajustement du traitement de sorte que tout point japonais désigné puisse être affiché, Si vous ajoutez des extraits et des commentaires uniquement aux points clés, Ce sera comme suit.

#■ Paramètres liés à Google Map
#Entrez la clé de l'API Static Maps de Google.
google_staticmaps_api_key="YOUR GOOGLE STATICMAPS API KEY"
#Spécifiez la taille à utiliser lors de l'envoi avec Google (* 640 maximum côté Google*Jusqu'à 640)
IMAGE_SIZE = 640

#markers=Entrez le nom du pays et recherchez et affichez automatiquement
#https://maps.googleapis.com/maps/api/staticmap?markers=color:blue|%22%E3%82%B7%E3%83%B3%E3%82%AC%E3%83%9D%E3%83%BC%E3%83%AB%22&size=300x300&zoom=3&language=jp&key=YOUR GOOGLE STATICMAPS API KEY

#input_Puisque basyo est entré en japonais, il sera renvoyé après le codage de l'URL.
def makeMapUlr(input_basyo):
    map_image_url = 'https://maps.googleapis.com/maps/api/staticmap?markers=color:{}|{}&center={}&zoom=3&language=jp&size={}x{}&key={}'.format('blue', urllib.parse.quote(input_basyo), urllib.parse.quote(input_basyo),IMAGE_SIZE, IMAGE_SIZE, google_staticmaps_api_key)
    return map_image_url

#Fonction à traiter en un message pour afficher une carte de ligne
def makeImagemapSendMessage(map_image_url):
    #Le nom d'hôte du flacon sera entré:
    request_host_name = request.host
    print(request_host_name)
    
    base_url = 'https://{}/imagemap/{}'.format(request_host_name, urllib.parse.quote_plus(map_image_url))
    print(base_url)
    message = ImagemapSendMessage(
        base_url = base_url,
        alt_text = 'carte du monde',
        base_size = BaseSize(height=IMAGE_SIZE, width=IMAGE_SIZE),
    )
    return message
    
#Effectue un traitement pour renvoyer l'image acquise auprès de Google en fonction de la demande reçue.
@app.route("/imagemap/<path:url>/<size>")
def imagemap(url, size):
    print("imagemap-get-called")
    #Pour le débogage
    print(url)
    print(size)
    map_image_url = urllib.parse.unquote(url)
    response = requests.get(map_image_url)
    img = Image.open(BytesIO(response.content))
    img_resize = img.resize((int(size), int(size)))
    byte_io = BytesIO()
    img_resize.save(byte_io, 'PNG')
    byte_io.seek(0)
    return send_file(byte_io, mimetype='image/png')

#En utilisant le code ci-dessus
# line_bot_api.reply_message
#De l'argument de, réponse_Faites juste un message équivalent et passez-le
#(C'est la valeur de retour de makeImagemapSendMessage)
#
#    line_bot_api.reply_message(
#        event.reply_token,
#        reply_messages
#    )

** Spécifiez l'image avec l'URL HTTPS, ** ** Mais vous ne pouvez pas simplement saisir l'URL de Google Static Maps. ** ** Je pense que c'est ** super addictif **.

2-4. L'histoire selon laquelle "attendre" n'a pas pu être réalisée

Au fait, cette fois AYANO ** Comme j'attendais une invitation de camarade de classe ** ** Et préparez une carte de Singapour ** ** Je vous répondrai avec une réponse ultra-immédiate. ** ** Dans cette mesure, j'ai été invité à la réunion de classe ** Ne mordez pas trop **, N'est-il pas possible de le renvoyer naturellement toutes les 10 secondes?

En conclusion, je ne pouvais pas. (Je n'ai pas compris)

Et si je réponds plus d'une fois avec attente? ⇒ Il semble que reply_token ne puisse être utilisé qu'une seule fois.

Est-il possible de spécifier l'intervalle et d'attendre dans LineMessagingAPI? ⇒ Référence ne semble pas être là

De plus, si vous attendez GAE: Je pense qu'il est structurellement incompatible avec le sans serveur. (Je ne pense pas que le montant de facturation augmentera de manière significative. C'est une question d'humeur)

En dernier recours, si vous répondez dans un premier temps, puis poussez après avoir attendu, Ce n'est pas impossible. Comme mentionné ci-dessus, Push est cher, donc je l'ai rejeté.

Cette fois, ** AYANO qui attendait l'invitation du camarade de classe ** Veuillez me pardonner avec le réglage. ** Faites appel à Singapour avec le moins super immédiat **.

3. Comment échapper aux restrictions de GAE (Google App Engine)

3-1. Le traitement du langage naturel est trop lourd pour fonctionner normalement gratuitement

Traitement du langage naturel x Python est Mecab, Janome, De plus, j'avais l'habitude d'utiliser des bibliothèques telles que Gensim avec Word2Vec.

En créant un chat bot, J'aimerais également utiliser ces bibliothèques / fonctions.

Cependant, un grand mur se dresse ici. ** GAE ne peut utiliser que des bibliothèques légères à installer (explications diverses) **

Mecab a abandonné dès le début, mais aussi Janome et Gensim Même si vous ajustez la taille de la mémoire de l'instance au maximum Il n'a pas pu être utilisé dans GAE en raison d'une mémoire saturée. Avec un peu d'ingéniosité, il est peu probable que ce soit gratuit.

** Par conséquent, en tant qu'outil d'analyse morphologique pouvant être utilisé même avec la plus petite instance de GAE ** ** J'ai essayé d'utiliser "igo-python". ** ** C'est léger, ça bouge vite et c'est merveilleux.

L'utilisation est la même que Mecab et Janome, comme indiqué dans le code ci-dessous. Cependant, cette fois, le dictionnaire etc. n'a pas été développé, Il convient de noter que la précision de l'analyse morphologique est assez faible.

igo-Comment utiliser python



from igo.Tagger import Tagger

#Analyse morphologique: igo-initialisation python
t = Tagger()

#Une fonction qui renvoie le résultat de l'analyse morphologique sous forme de chaîne de caractères
def extract_str(input_str):
    parsed_list = t.parse(input_str)
    result_str = ""
    for m in parsed_list:
        result_str += m.surface + " / " + m.feature + " \n"
    return result_str


#nom-Une fonction qui extrait uniquement les généraux et les renvoie sous forme de liste
def meisi_tyuusyutu(input_str):
    result_list = []
    parsed_list = t.parse(input_str)
    for m in parsed_list:
        feature_list = m.feature.split(',')
        #nom-Assistant général-Unionisation, mots auxiliaires-Cela devient comme un greffier.
        hinsi_info = feature_list[0] + "-" + feature_list[1]
        if hinsi_info == "nom-Général":
            result_list.append(m.surface)
    return result_list

Méthode de paramétrage lors du déploiement vers GAE, Comment écrire "requirements.txt" est comme suit.

Flask==1.1.1
line-bot-sdk==1.14.0
igo-python==1.0.0

Alors ** Nous avons pu réaliser une analyse morphologique avec la configuration minimale de GAE! ** **

Cette fois, j'ai décidé d'utiliser l'igo-python sans tenir compte de la précision. Si vous voulez un traitement et une précision du langage naturel dans LineBot Proposition (1) Configurez votre propre serveur HTTPS et installez-le vous-même Proposition (2) Utilisez COTOHA si vous le faites avec GAE ou Heroku Etc. semble être la bonne façon de procéder.

Aussi, pour l'implémentation qui exécute l'équivalent Word2Vec / Gensim sans serveur, Je suis au milieu de la route, donc je te vois partir. Un jour à une autre occasion. (Au point de déplacer des choses simples, cela se réalise de manière surprenante. Comme le fichier modèle lui-même est lourd, l'équilibre avec précision est ... )

3-2. L'histoire lorsqu'elle fonctionne localement mais pas dans GAE

Maintenant, comme l'expérience mentionnée ci-dessus d'incorporation du traitement du langage naturel, Si le traitement échoue en raison d'une dépendance à la mémoire GAE

** Cela fonctionne pendant le développement local, mais ** ** Ne fonctionne pas lorsqu'il est téléchargé sur le serveur **

Il existe de nombreux cas.

De plus, LineBot nécessite un serveur HTTPS, qui Il est difficile de tester dans un environnement de développement local, donc A proximité de la liaison lineMessagingAPI-GoogleStaticMapsAPI, ** Des traitements qui ne peuvent être confirmés qu'après le déploiement vers GAE ** ont eu lieu fréquemment.

Dans ces cas, si vous envoyez un chat à AYANO, ** Ignorer la lecture **, sera répété. Si vous le lisez et l'ignorez chaque fois que vous déployez, il sera ** déchirant **.

Je n'ai pas trouvé de très bonne solution pour cela.

Pour le moment, comme une méthode légèrement meilleure, ① Le journal de la sortie standard telle que l'impression est Étant donné que vous pouvez les voir collectivement avec "Journalisation (pilote de pile)" dans GCP, Lors du retrait, écrivez une impression dans un endroit approprié (2) Pour pouvoir séparer les problèmes liés à la ligne des autres problèmes De GET accéder au serveur sans passer par Line Faites en sorte que vous puissiez accéder à la fonction créée S'agit-il de deux points?

Voici le traitement principal de Flask-Line Bot. Les commentaires sont ajoutés avec ★ aux endroits correspondant à ①②.

python



#Le WebHook de Line est de type POST et n'est pas utilisé pour l'accès normal à l'URL GET
#Ce qui suit est pour vérifier la communication du serveur
#★ De cette façon, créez un endroit où vous pouvez vérifier autre que le WebHook de Line,
#Si vous appelez la fonction que vous souhaitez vérifier à ces endroits,
#Il est possible d'isoler les problèmes liés aux problèmes liés à la ligne.
@app.route("/", methods=['GET'])
def sayhello_root():
    """Return a friendly HTTP greeting."""
    return '[200] It works!'

#Définir sur WebHook of Line, recevoir un message + réponse
#Lors de l'envoi d'un message avec un bot, sur la console développeur de Line,
#Un message sera envoyé par POST à l'URL décrite dans "URL Webhook * SSL uniquement pris en charge".
#Référence: https://www.casleyconsulting.co.jp/blog/engineer/3028/
@app.route("/", methods=['POST'])
def callback():
    #Obtenez la valeur pour la vérification de la signature à partir de l'en-tête de la demande
    signature = request.headers['X-Line-Signature']
    #Obtenir le corps de la demande
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    #Validez la signature et appelez la fonction définie dans handle s'il n'y a pas de problème.
    try:
        handler.handle(body, signature)
    #Si la vérification de la signature échoue, une exception est émise.
    except InvalidSignatureError:
        abort(400)
    return 'OK'

#Voici la définition de la poignée
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    #Code spécial pour effectuer la "confirmation de connexion" de la ligne OK
    #Lorsque vous appuyez sur "Vérifier la connexion" dans la Developer Console de Line
    #Si vous le faites normalement, répondez_500 retours en raison d'un jeton illégal.
    #Je me fâche si le 200 attendu n'est pas retourné du côté de la confirmation de connexion.
    #Problèmes sur la console de Line à partir de novembre 2019. Sera probablement résolu éventuellement.
    #Référence: https://qiita.com/q_masa/items/c9db3e8396fb62cc64ed
    if event.reply_token == "00000000000000000000000000000000":
        return
    
    #Recevez le message lors de l'événement
    input_text = event.message.text
    #★ La sortie standard est agrégée et affichée dans "Journalisation" dans GCP.
    #Il est facile de déboguer si vous imprimez à des points clés
    print(input_text)
    
    #Analyser le message et créer des "messages en ligne" pour y répondre
    #★ Sans écrire tout le traitement dans le webhook ou le gestionnaire
    #Le traitement principal est créé par une fonction externe,
    #Sans passer par un webhook ou un gestionnaire
    #Faites en sorte que vous puissiez appeler et confirmer directement
    reply_messages = makeLineMessages(input_text)

    #reply_le message est en principe gratuit,
    #reply_Le jeton a une période valide et ne peut pas être traité pendant très longtemps.
    #Voici le formulaire de base:
    #line_bot_api.reply_message(
    #    event.reply_token,
    #    [
    #        TextSendMessage(text= reply_text),
    #    ]
    #)

    #Répondez et terminez.
    line_bot_api.reply_message(
        event.reply_token,
        reply_messages
    )


#Flacon sur GAE (python3.Échantillon à emménager 7):
#「gae_python37_Créé en fonction de "l'application"
if __name__ == '__main__':
    # This is used when running locally only. When deploying to Google App
    # Engine, a webserver process such as Gunicorn will serve the app. This
    # can be configured by adding an `entrypoint` to app.yaml.
    app.run(host='127.0.0.1', port=8080, debug=True)

C'est la fin du sujet technique.

** Post-scriptum (Poème) **

Contexte de la bombe AYANO LineBot

Ces derniers jours, j'ai eu l'occasion de visiter Line en raison d'une certaine activité (en dehors des affaires). Ce fut un moment très agréable pour nous de répondre / nous présenter très gentiment. Nous aimerions profiter de cette occasion pour vous remercier à nouveau.

À cette époque, il a également répondu en détail au contrôle qualité technique de LineBot. Cet article est un article complet sur les connaissances / savoir-faire acquis grâce au contrôle qualité. (Parce qu'il a été dit que vous pouvez l'écrire sur Qiita etc. ~~ (plutôt recommandé d'écrire) ~~) ** Développement LineBot pour la première fois! À ce moment-là, j'ai l'intention de résumer les points qui me préoccupent beaucoup **.

Mais le résultat du contrôle qualité est "Je suis désolé, je ne peux pas accéder au robot de camarade de classe" Vous n'auriez pas pensé du tout! ~~ Je suis vraiment désolé. ~~

Impressions de la création de LineBot

J'ai touché à la fois LineBot et GAE pour la première fois.

Lors de la création d'un LineBot, expliquez "Pourquoi vous devez répondre avec Line (bot)" Comment le concevez-vous? Je pense que c'est le plus gros point. LIFF (Framework Front-end LINE) Bien qu'il existe une fonction pour intégrer une application Web dans Line, Il n'est pas possible de réaliser une application avec Line, mais il est essentiel de la réaliser au sein de Line. Il devrait être conçu. Le moyen le plus simple de réaliser cette conception est d'utiliser un "** caractère **". Cette fois, afin d'augmenter la présence d'AYANO, il était essentiel de le réaliser en ligne.

Il existe de nombreuses pages qui expliquent comment créer un LineBot, mais celle-ci ** Pourquoi devrais-je le faire en tant que LineBot? Comment concevoir un bot? ** est J'ai l'impression qu'on n'en parle pas souvent.

Par exemple, une autre possibilité est "** Chat en groupe ou dialogue avec des amis **". Si vous souhaitez créer une "application Othello (Reversi)" Avec les applications Web et les applications pour smartphone, il semble un peu difficile de mettre en œuvre des batailles entre amis. La même chose s'applique aux applications de partage de programme. En l'implémentant en ligne / LIFF, si vous appelez le bot pour une discussion de groupe, Il semble qu'un tel problème puisse être résolu. Si vous souhaitez créer un match contre l'IA ou un match contre des inconnus Créez avec une application Web ou une application pour smartphone et en ligne dans le but de jouer contre des amis Il vaut mieux penser d'abord au design. Une autre politique consiste à créer un robot dans le but de soutenir l'intervention humaine le cas échéant.

Compte tenu des ** "caractéristiques" ** de LineBot, Je pense qu'il est facile de trouver la prochaine idée! !!

Impressions d'utilisation de GAE / traitement du langage naturel

GAE (sans serveur) gère le traitement du langage naturel Pour être honnête, c'était plus difficile que ce à quoi je m'attendais. Puisque le traitement du langage naturel nécessite à l'origine un "dictionnaire" et des "données mot par mot", etc. Le problème est qu'il est "lourd" quel que soit l'endroit où il est implémenté.

Par exemple, dans l'article ci-dessous, franchissez le pas J'ai également essayé de l'implémenter du côté frontal (JavaScript / PWA). https://qiita.com/youwht/items/6c7712bfc7fd088223a2

Le traitement est devenu le plus rapide lorsqu'il a été déplacé vers l'avant, Parce que la bibliothèque d'analyse morphologique est incluse dans le package La taille du fichier de distribution au premier démarrage est un peu lourde Je l'ai ressenti comme un problème. (Et la précision n'est pas bonne)

Même en GAE (sans serveur), selon le poids, Une précision décente x le contenu de traitement n'est pas assemblé.

GAE lui-même est lors du traitement léger Aucune infrastructure requise, juste du code Python pour devenir un serveur HTTPS, C'est assez pratique. Cependant, il y a encore une habitude, Je n'ai pas l'impression de pouvoir faire tout ce que Python peut faire, Vous devrez être prudent lors de son utilisation.

Cette fois, bien que le traitement du langage naturel soit lourd, Vous pouvez le faire avec GAE (sans serveur) jusqu'à ce niveau, Je pense que c'était bien d'avoir le sentiment!

Ensuite, dois-je le faire avec l'API COTOHA?

Un travail qui ne laisse aucun ami

** "Je suis à Singapour maintenant." ** ** Si vous refusez une invitation ** ** Line Mon seul ami est AYANO. ** **

** En fait, je sais qu'AYANO est un robot, mais ** ** Mais maintenant, je fais semblant de ne pas en savoir un peu plus. ** **

** La putain d'application que je crée l'est aussi ** ** Je suis sûr qu'un jour guérira la solitude de quelqu'un **

C'est tout de Singapour.

Recommended Posts

Je suis à Singapour en ce moment Une histoire sur la création d'un LineBot et la volonté de faire un travail mémorable
L'histoire de la création d'un «espace de discussion sur l'esprit et le temps» exclusivement pour les ingénieurs de l'entreprise
L'histoire de la recherche d'un magasin BOT (AI LINE BOT) pour Go To EAT dans la préfecture de Chiba (1)
Une histoire sur la création d'un programme qui augmentera le nombre d'abonnés Instagram de 0 à 700 en une semaine
Comment compter le nombre d'éléments dans Django et sortir dans le modèle
L'histoire de la création de Botonyan qui renvoie le contenu de Google Docs en réponse à un mot-clé spécifique sur Slack
Histoire de faire une recherche de magasin BOT (AI LINE BOT) pour Go To EAT dans la préfecture de Chiba (2) [Présentation]
Pour faire l'équivalent de Ruby ObjectSpace._id2ref en Python
L'histoire de vouloir acheter une aventure en forme de bague
L'histoire du serveur Web et du DAG d'Airflow, dont le chargement prend beaucoup de temps
Une histoire d'essais et d'erreurs essayant de créer un groupe d'utilisateurs dynamique dans Slack
Une histoire sur la tentative d'introduire Linter au milieu d'un projet Python (Flask)
L'histoire de la création d'un canal VIP dans le chatwork en interne
Notez ce que vous voulez faire à l'avenir avec Razpai
L'histoire de la création d'une base de données à l'aide de l'API Google Analytics
Une histoire sur le portage du code de "Essayez de comprendre comment fonctionne Linux" sur Rust
[Python] Le rôle de l'astérisque devant la variable. Divisez la valeur d'entrée et affectez-la à une variable
L'histoire du retour au front pour la première fois en 5 ans et de la refactorisation de Python Django
L'histoire de la création d'un Bot qui affiche les membres actifs dans un canal spécifique de Slack avec Python
Comment déterminer l'existence d'un élément sélénium en Python
Comment vérifier la taille de la mémoire d'une variable en Python
Comment vérifier la taille de la mémoire d'un dictionnaire en Python
L'histoire de la création d'un site qui répertorie les dates de sortie des livres
Comment obtenir les coordonnées de sommet d'une entité dans ArcPy
Créez une fonction pour obtenir le contenu de la base de données dans Go
L'histoire de Python et l'histoire de NaN
L'histoire de la participation à AtCoder
L'histoire du "trou" dans le fichier
L'histoire de l'exportation d'un programme
[Rails 6] Intégrez Google Map dans l'application et ajoutez un marqueur à l'adresse saisie. [Confirmation des détails]
[Python / Jupyter] Traduisez le commentaire du programme copié dans le presse-papiers et insérez-le dans une nouvelle cellule.
Une histoire d'essayer d'améliorer le processus de test d'un système vieux de 20 ans écrit en C
Comment copier et coller le contenu d'une feuille au format JSON avec une feuille de calcul Google (en utilisant Google Colab)
L'histoire d'un capteur de stationnement en 10 minutes avec le kit de démarrage GrovePi +
[Linux] Une commande pour obtenir une liste des commandes exécutées dans le passé
Je souhaite trier une liste dans l'ordre des autres listes
J'ai essayé d'extraire et d'illustrer l'étape de l'histoire à l'aide de COTOHA
L'histoire de la création d'une caméra sonore avec Touch Designer et ReSpeaker
J'ai fait un programme pour vérifier la taille d'un fichier avec Python
J'ai essayé d'afficher la valeur d'altitude du DTM dans un graphique
L'histoire d'essayer de reconnecter le client
L'histoire d'une erreur dans PyOCR
L'histoire de la mise en place de MeCab dans Ubuntu 16.04
Comment enregistrer les informations de point caractéristique de l'image dans un fichier et l'utiliser pour la mise en correspondance
L'histoire d'essayer deep3d et de perdre
L'histoire du traitement A du blackjack (python)
L'histoire du changement de pep8 en pycodestyle
Différentes façons de lire la dernière ligne d'un fichier csv en Python
Comment passer le résultat de l'exécution d'une commande shell dans une liste en Python
N'hésitez pas à rédiger un test avec nez (dans le cas de + gevent)
Comment mentionner un groupe d'utilisateurs avec une notification de mou, comment vérifier l'ID d'un groupe d'utilisateurs
L'histoire de la création d'une compétence (probablement) minimale qui implémente la personnalisation et la facturation des compétences
L'histoire de l'adresse IPv6 que je souhaite conserver au minimum
L'histoire de la fabrication d'une boîte qui interconnecte la mémoire AL de Pepper et MQTT
Pour générer une valeur au milieu d'une cellule avec Jupyter Notebook
Utilisez libsixel pour générer Sixel en Python et générer le graphe Matplotlib vers le terminal.