Python
Heroku
bottle
docomoAPI
Pipenv

Bottle と docomo 雑談対話 API で作った会話アプリを Pipenv と Heroku で公開

はじめに

Python の Web フレームワーク Bottle と docomo の雑談対話 API を使って、シンプルな会話アプリを作りました。仮想環境の構築には Pipenv を使用し、作ったアプリは Heroku で公開しました。

作ったものはこちらです。
http://simple-conveasation.herokuapp.com/

会話アプリ作成

アプリ作成に先立ち、docomo の Developer として登録し、雑談対話 API の API key を取得して控えておきます。
https://dev.smt.docomo.ne.jp/?p=docs.api.page&api_name=dialogue&p_name=api_reference

作業用ディレクトリ simple-conversationをつくり、その中でアプリを作成します。まずは画面表示用の HTML テンプレートです。

index.tpl
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>Simble Conversation</title>
  </head>
  <body>
    <h2>Simple Conversation</h2>
    <p>Notes: This app only supports Japanese language.</p>
    <form action="/" method="post">
      <input type="text" id="reqMsg" name="reqMsg">
      <input type="submit" value="Send">
    </form>
    <p>{{ user_msg }}</p>
    <p>{{ res_msg }}</p>
  </body>
  <script type="text/javascript">
    document.getElementById('reqMsg').focus();
  </script>
</html>

純粋な HTML ファイルではなくあくまでテンプレートであることを強調するため、拡張子を .tpl としています。

入力フィールドと送信ボタンのみを持つ form 要素と、結果表示用の p 要素を配置してあります。 p 要素内の{{}}の部分にはテンプレートの機能で、 Python から受け取った変数が埋め込まれます。

スクリプト部分ではページを開いたときに入力フィールドにフォーカスが来るようにしています。この部分は別になくても構いません。

次に、Web アプリの本体を作成します。

app.py
from bottle import get, post, template, request, run
import requests
import json
import os

API_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'

@get('/')
def index():
    user_msg = ''
    res_msg = ''
    return template('index.tpl', user_msg=user_msg, res_msg=res_msg)

@post('/')
def send():
    req_msg = request.forms.reqMsg

    url = 'https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=' + API_KEY
    payload = {'utt': req_msg}
    res = requests.post(url, data=json.dumps(payload))
    res_msg = '<< ' + res.json().get('utt')

    user_msg = '>> ' + req_msg

    return template('index.tpl', user_msg=user_msg, res_msg=res_msg)

if __name__ == '__main__':
    run(host='0.0.0.0', port=int(os.environ.get('PORT', 5000)))

API_KEY = ... の部分には各々、取得した API key を指定します。

ここでは2つのリクエストハンドラ indexsend を定義し、それぞれルートへの GET リクエストと POST リクエストに紐付けています。

send の中では requests ライブラリを使用し、雑談対話 API へのアクセスを行っています。 JSON でリクエストを渡し、 JSON で結果を受け取っています。リクエストには様々な key が設定できるようですが、最低限、発言内容である utt を渡せば動くようなので、 utt のみを設定しています。API からの応答メッセージは同様に utt という key で取得できます。

この時点で動作を確認してみます。

$ python app.py
Bottle v0.12.13 server starting up (using WSGIRefServer())...
Listening on http://0.0.0.0:5000/
Hit Ctrl-C to quit.

ブラウザから localost:5000 へアクセスし、想定どおりに動くことを確認できれば、アプリは完成です。

Heroku で公開

Heroku へのデプロイは Git の commit を push することで行います。

まずはローカルリポジトリを作成し、

$ git init

ここまでの変更を commit します。

$ git add app.py index.tpl.html
$ git commit -m "first commit"

依存ライブラリと起動コマンドを Heroku に伝えるためには、 requirements.txtProcfile を作成することが必要です。このために、まずは Pipenv でローカルに仮想環境を作り、動作を確認してから Heroku にデプロイすることにします。

仮想環境の作成は次のようにします。

$ pipenv install

試しに次のコマンドで仮想環境内でアプリを起動しようとすると、必要なライブラリがないというエラーが出ることが確認できます。

$ pipenv run python app.py
Traceback (most recent call last):
  File "app.py", line 1, in <module>
    from bottle import get, post, template, request, run
ImportError: No module named 'bottle'

次のように仮想環境内に必要なライブラリを導入した後に、

$ pipenv install bottle
$ pipenv install requests

再びアプリを起動すると、

$ pipenv run python app.py
Bottle v0.12.13 server starting up (using WSGIRefServer())...
Listening on http://0.0.0.0:5000/
Hit Ctrl-C to quit.

正常にアプリが動作することが確認できるはずです。

この状態で requirements.txtProcfile を作成します。

$ pipenv run pip freeze > requirements.txt
$ echo web: python app.py > Procfile

ここまでの変更を commit した後、

$ git commit -am "prepared for heroku deployment"

以下のようにして Heroku へデプロイします。

$ heroku apps:create <アプリの名称>
$ git push heroku master

<アプリの名称> の部分は各々わかりやすい名前を付けます。Heroku 全体で一意であることが要求されているようです。(筆者は simple-conveasation としました。これはタイプミスですが、結果的に一意な名称になっていました。)

コンソールログにアクセス用の URL が出ていると思います。そこにブラウザからアクセスして、正常な動作が確認できれば、アプリの公開が完了です。

参考

Heroku×bottleを使って4分33秒でWebアプリを公開する
https://qiita.com/ohbarye/items/55ec574f10685a012baf

pipenv を使ってみたのでメモ
https://qiita.com/subarunari/items/dcbdad68ba1809b721b9

Requests の使い方 (Python Library)
https://qiita.com/sqrtxx/items/49beaa3795925e7de666

雑談対話 | docomo Developer support | NTTドコモ
https://dev.smt.docomo.ne.jp/?p=docs.api.page&api_name=dialogue&p_name=api_reference