先日、「flaskでチャットボットのサンプルアプリ作ってみた【概要編】」という記事を書いたのですが、今回は管理画面の実装について触れてみたいと思います。
- flaskでチャットボットのサンプルアプリ作ってみた【概要編】
- flaskでチャットボットのサンプルアプリ作ってみた【管理画面編】← この記事
- flaskでチャットボットのサンプルアプリ作ってみた【応答API編】
リポジトリ
ディレクトリ構成
chatbot
├── admin 管理画面側アプリケーション
│ ├── controllers コントローラー(flask的にはview function)
│ ├── domain ドメイン層
│ │ ├── repositories リポジトリ(インフラ層のインターフェース)
│ │ ├── services サービス層(ドメインロジック)
│ │ └── tasks 非同期処理(ボットの学習)
│ ├── helpers コントローラーで使用するヘルパー
│ │ └── forms formヘルパー(バリデーションの実装)
│ └── infrastructure インフラ層(リポジトリの実装)
├── api API側アプリケーション
│ ├── controllers
│ ├── domain
│ │ ├── repositories
│ │ └── services
│ ├── exceptions 独自例外の定義
│ ├── helpers
│ │ ├── forms
│ │ └── responses レスポンス用ヘルパー
│ └── infrastructure
├── common 共通利用するモジュール(機械学習など)
├── front フロント⇔バックのインターフェース(メモとして使用)
├── ml_vars 機械学習で使用する変数の保存先
├── models モデル定義(sqlalchemyのmodel継承)
├── scss フロント画面用SCSS
├── static 静的ファイル置き場
│ └── admin 管理画面用
│ ├── bower_components AdminLTE用ファイル置き場
│ ├── dist 同上
│ └── plugins 同上
├── templates HTMLファイル置き場
│ ├── admin 管理画面用
│ │ ├── bot
│ │ ├── faq
│ │ ├── faq_list
│ │ ├── site
│ │ └── site_url_setting
│ └── front フロント用
└── upload アップロードファイル置き場(FAQリスト)
DBへの接続
DBにはmsqlを使用しているのですが、DB操作のライブラリとしてflask公式サイトに記載があったので、SQLAlchemy を利用することにしました。
[参考] https://a2c.bitbucket.io/flask/patterns/sqlalchemy.html
ORMとして使っており、その定義を models 配下の各クラスに記述しています。定義はSQLAlchemyが提供するAPIを使っているので、今回は自分でSQLを記述するということはありませんでした。
リレーションの記述が直感と違っていたので期待するデータが取得できるようになるまで時間がかかってしまいましたが、1対多、多対1、多対多のリレーションが実現できたので、とりあえず良しとしています。
リレーションの実装箇所
- 1対多
- ボット 対 FAQリスト
- BotModel.faq_lists に ボットに含まれるFAQリスト一覧を保持
- FAQリスト 対 FAQ
- FaqListModel.faqs にリストに含まれるFAQ一覧を保持
- ボット 対 FAQリスト
- 多対1
- FAQリスト 対 ボット
- FaqListModel.bot に自身を保持しているボットデータを保持
- FAQ 対 FAQリスト
- FaqModel.faq_list に自身を保持しているFAQリストデータを保持
- FAQリスト 対 ボット
- 多対多
- FAQ 対 関連FAQ
- FaqModel.related_faqs に自身と関連しているFAQ一覧を保持
- 中間テーブルとして faqs_faqs テーブルを定義
- FAQ 対 関連FAQ
ボット、FAQ、サイトといったデータのCRUD
SQLAlchemyを使ってデータの取得、追加、更新を行っているだけなので、詳細は割愛します。
バリデーションは、こちらも公式サイトで紹介されていたwfformsを使用しています。
[参考] https://a2c.bitbucket.io/flask/patterns/wtforms.html
ボットの学習について
FAQには質問と回答があるので、エンドユーザーから入力されたテキストが質問文に近ければその回答を返すというものにしています。
機械学習の手法なのですが tensorflow を使ってみたいこともありDeepLearningによる学習を行っています。また、テキストの形態素解析にはMeCabを使用しました。
学習時に気をつけたこと
学習時の入力データとしてFAQの質問を形態素解析し、そのまま特徴量として利用するだけだと柔軟性がなかったので、下記3つの学習データを作成し回答(ラベル)と紐づけました。
学習データ3パターン
- 質問を形態素解析した結果のうち、以下のものを抽出し学習データにする
- 名詞
- 動詞、形容詞の原形
- 例
- 映ら → 映る
- 新しく → 新しい
- 助動詞で2文字以上の原形
- 例
- 映らないの「ない」
- 1の単語リストをすべてひらがなに変換した単語を学習データにする
- 2のひらがな化した単語を改めて形態素解析し、2文字以上の単語を学習データにする
3パターンの目的
- 名詞以外は原形を利用する事で活用による表記ゆれを吸収
- ひらがな入力対応
- 同上
学習データを水増しすることで、より柔軟な入力に対応できるようになりました。
DeepLearningのレイヤーについて
レイヤーや次元を変えて何パターンか試してみたのですが、目に見えた改善がみられなかったので、中間レイヤー1つで次元数は入力次元の20%にしています。
学習データを増やしたり、良い検証方法の準備ができれば良かったかと思うのですが、現状の知識ではモデルの改善は十分にはできませんでした。
フロントからのAPI呼び出しで学習した内容を使うために
学習後のモデルや入力として想定している単語リストなどをAPIで使用可能にするため、以下のファイルを ml_vars/[bot_id] ディレクトリに保存しています。
- 学習したモデル
- 単語リスト
- id_to_word
- キーが単語ID、値が単語となってる辞書
- word_to_id
- キーが単語、値が単語IDとなっている辞書
- id_to_word
- FAQリスト
- 予測結果からFAQデータを導くためのリスト
これらのデータをAPIでどのように使っているかは別の記事で説明する予定です。
以上、flaskでチャットボットのサンプルアプリ作ってみた【管理画面編】でした。