BOTフレームワーク Minette for Python のご紹介

Python向けのチャットボットフレームワークでデファクトスタンダード的なものが見当たらなかったので、作ってみました。

Minette for Python
https://github.com/uezo/minette-python

# 5つの特長

## 1. すぐ動く

pipコマンドでインストールして、データベースやアプリケーションサーバの設定などすることなく、わずか数行のコードを記述すればおうむ返しボットが動作します。

## 2. あらゆるチャネルを統一されたアーキテクチャで

LINEとClova用のアダプターを同梱。初期化コードを追加するだけですぐにLINE BOTやClovaスキルを開発することができます。また、ユーザー実装部分はチャネルの違いに影響を受けないため、どちらも同じ手順で開発を進めることができます。

## 3. コンテキスト・ユーザー管理、タスクスケジューラを標準装備

文脈を意識した対話シナリオを実現するため、発言をまたいでセッション（コンテキスト）を利用することができます。また、ユーザー情報の取得・保存も開発者が意識することなく自動で行われます。さらに、定期的な処理を自動化するためのタスクスケジューラを備えているため、cron等の設定をすることなくBOTアプリケーションのリソースで完結することができます。

## 4. 自然言語解析の支援(形態素解析)

もしMeCabが入っている環境ならば、ユーザーの発話内容を自動で形態素解析し、その結果を受け取ることができます。Pure PythonなJanomeにも対応しており、また、自身で拡張することでGoogle Cloud Platformなどクラウドサービスにも対応可能なため、どんな環境でも自然言語解析を利用した高度な対話を実現することができます。

## 5. マルチスキル・マルチキャラクター化しやすい構造

[いもうとBOT](http://imoutobot.com/)という、10種類以上のスキル(機能)を備えたLINE BOTを開発・運用しており、ここで培ったノウハウをアーキテクチャに反映させています。


# インストール

```
$ pip install minette
```

これ一発でOK。開発中の最新版は以下からインストールできます。

```
$ pip install git+https://github.com/uezo/minette-python
```

# おうむ返しBOTの作成

チャットボット本体を起動したら、あとはユーザーの発話内容を投げつければ応答が返ってきます。

```python:echo.py
from minette import Minette, EchoDialogService

# おうむ返し対話部品（EchoDialogService）を使ってMinetteを起動
bot = Minette(default_dialog_service=EchoDialogService)

# 対話の開始
while True:
    req = input("user> ")
    res = bot.chat(req)
    for message in res.messages:
        print("minette> " + message.text)
```

```
$ python echo.py
user> こんにちは
minette> You said: こんにちは
user> 動いてるね？
minette> You said: 動いてるね？
```

とても簡単。

# カスタムスキルの作成

今度はカスタムスキルとして、何を言ってもサイコロを2個振ってくれるBOTを作ってみます。

```python:dice.py
import random
from minette import Minette, DialogService


# カスタムの対話部品
class DiceDialogService(DialogService):
    # ロジックを処理して結果をコンテキストに格納
    def process_request(self, request, context, connection):
        context.data = {
            "dice1": random.randint(1, 6),
            "dice2": random.randint(1, 6)
        }

    # コンテキスト情報を使って応答データを組み立て
    def compose_response(self, request, context, connection):
        return "Dice1:{} / Dice2:{}".format(
            str(context.data["dice1"]), str(context.data["dice2"]))


if __name__ == "__main__":
    # BOTの起動
    bot = Minette(default_dialog_service=DiceDialogService)
    # 対話の開始
    while True:
        req = input("user> ")
        res = bot.chat(req)
        for message in res.messages:
            print("minette> " + message.text)
```

```:実行結果
$ python dice.py
user> test
minette> Dice1:3 / Dice2:5
user> d
minette> Dice1:4 / Dice2:3
```

簡単に解説すると、`process_request`では1~6のランダムな数値を2つ求めて、それらをcontext.dataにそれぞれ`dice1`と`dice2`というキーで格納しています。`compose_response`では、それらの値を取り出して応答文を作成しています。

この程度の処理ならばすべて`compose_response`にまとめてしまいたいところですが、スキル（機能）とキャラクター（人格）を分離しておくことで複雑な対話シナリオになっても保守性を維持できるので、ちゃんと分けておくことをオススメします。

また、BOTの生成処理（`Minette`）で引数`default_dialog_service`として`DiceDialogService`を渡していることで、BOTを実行すると今回実装した部分に処理が渡ってくるようになっています。


# その他のサンプル

GithubのREADMEに翻訳BOTのコード例を載せていますので参考にしてください。
https://github.com/uezo/minette-python



# Minetteのアーキテクチャ

Minetteを使ったBOT開発では開発者は具体的に何をすればよいか、アーキテクチャ全体図を見て確認しましょう。

[![Architecture](http://uezo.net/img/minette_architecture.png)](http://uezo.net/img/minette_arc.png)

基本的に、以下の4つのメソッドを実装していくことが開発作業の中心となります。

- `register_intents()` 発話意図（インテント）に応じて呼び出す対話部品（DialogService）を設定
- `extract_intent()` 発話内容からインテントとエンティティを抽出
- `process_request()` アプリケーションロジックの処理
- `compose_response()` 応答メッセージの組み立て


# 関連ポスト

※以下、バージョン0.1ベースになっているためアップデート中（現在のバージョンは0.4）

- [Minette for Python でLINE BOTを作成する（LINE連携、雑談API使用）](http://qiita.com/uezo/items/44136ee2486a3cf4fd8d)
- [Raspberry Pi Zero WでLINE BOTを作る](http://qiita.com/uezo/items/1cf7f29dbcd1284a917e)