MindMeldを初めて触ってみた

この記事はシスコの同志による Cisco Systems Japan Advent Calendar 2019 の 10 日目として投稿されました。
過去のカレンダーはこちら
2017年度版：https://qiita.com/advent-calendar/2017/cisco
--> [ポリシータグをLISPで配布、TrustSecをCML/VIRLでやってみた](https://qiita.com/yunambu/items/8b88d0d660464ab70599)
2018年度版：https://qiita.com/advent-calendar/2018/cisco
--> [シスコの SaaS 型監視・振る舞い検知ツールをマルチクラウド環境監視用に使ってみた](https://qiita.com/yunambu/items/d0cfd2ab48a0134f1505)

入社3年目(Advent Calendarも3年連続参加！)の今年は「機械学習・AI」周りを勉強してきたので、シスコのテクノロジーと合わせたテーマとして**MindMeld**を記事にします。 
＊余談：勉強のアウトプットも兼ねて初めて参加したハッカソン@米国では、サクラメントローカルですが賞ももらうことができました。

## Mindmeld とは？
Mindmeldはシスコが2017年に買収した業界型の対話型AIプラットフォームで、2019年5月にオープンソースとして公開された開発者向けツールキットです。
もう少しだけ噛み砕いた説明をしますと、MindMeld は開発者や利用者がしたいこと（インテント）を反映し作成した MindMeld ボットを使って、「○○がしたい」「XXを探して欲しい」「△△の情報を引っ張ってきて欲しい」などの要望をボットとの会話を通じて実現するためのカスタマイザブルなツールキットです。
詳細な説明は、[こちらのブログ](https://www.google.co.jp/amp/s/gblogs.cisco.com/jp/2019/06/mindmeld-ai/amp/) と公開済みの [GitHubレポジトリ](https://github.com/cisco/mindmeld/blob/master/README.md) をご参照ください。

## この記事でやること
この記事を機に触ってみようという心持ちなので、芸がなく恐縮ですが、サンプルとして用意されている **Video Discovery** のブループリントを使った対話型 AI をプレイブックに沿って作ってみたいと思います。
将来的には、これを参考にカスタムで読みたい論文を発見してくれるカスタムブループリントを作りたいなと思います。
環境準備から行いますので、「日本語のドキュメントがあれば、興味があるから試してみたい」、という方はこちらの記事をぜひ参考にご活用ください。

### 始める前に
まずMindMeldを利用するにあたり事前の準備として、MindMeldをインストールするところから開始します。
インストールオプションは 2 パターンあり、
1.  Docker
2.  virtualenv
から選択可能です。今後、MindMeldをヘビーユースしたい方は、2. virtualenv がおすすめです。
この記事も、2. virtualenv で作っていきたいと思います。
＊1. Dockerは、MindMeldをちょっと触ってみたい方におすすめです。


<details><summary>利用している環境と事前準備</summary><div>

```
sw_vers
  ProductName:	Mac OS X
  ProductVersion:	10.15.1
  BuildVersion:	19B88
java -version
  openjdk version "12" 2019-03-19
  OpenJDK Runtime Environment (build 12+33)
  OpenJDK 64-Bit Server VM (build 12+33, mixed mode, sharing)

# Homebrew のアップデート
brew update

# virtualenv のインストール
# Python には仮想環境を作れるモジュールがあり、この virtualenv を使って、
# 仮想環境ごとに Python のバージョンを分けたりすることができます。
sudo -H pip install --upgrade virtualenv

# Elasticsearch 6.7 の利用準備
# Java の利用ポリシー変更に伴い、macOS ユーザの方は Elasticsearch の環境が必要になります。
export JAVA_HOME=/path/to/java
curl https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.7.0.tar.gz -o elasticsearch-6.7.0.tar.gz
tar -zxvf elasticsearch-6.7.0.tar.gz
cd elasticsearch-6.7.0/bin
./elasticsearch

# Elasticsearch の起動確認
curl localhost:9200
{
  "name" : "hoBpMt3",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "5G91TzSLTDO4WCFg9h5hhg",
  "version" : {
    "number" : "6.7.0",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "8453f77",
    "build_date" : "2019-03-21T15:32:29.844721Z",
    "build_snapshot" : false,
    "lucene_version" : "7.7.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

# 仮想環境の準備
mkdir my_mm_workspace4advent
cd my_mm_workspace4advent
virtualenv -p python3 .
source bin/activate
(deactivate)

# MindMeld パッケージのインストールと起動確認
pip install mindmeld # ここでエラーが発生した場合、エラーが出た特定のパッケージについて再インストールしてください。
mindmeld # cautionWarning が表示されても無視して構いません。
  Usage: mindmeld [OPTIONS] COMMAND [ARGS]...

    Command line interface for MindMeld.

  Options:
    -V, --version        Show the version and exit.
    -v, --verbosity LVL  Either CRITICAL, ERROR, WARNING, 
  INFO or DEBUG
    -h, --help           Show this message and exit.

  Commands:
    blueprint  Sets up a blueprint application.
    convert    Converts a Rasa or DialogueFlow project to a...
    load-kb    Loads data into a question answerer index.
    num-parse  Starts or stops the local numerical parser...

# Numeric Parsers の開始。
# (注) ここでエラーが発生すると先に進めません。必ず成功するか確認してから先に進んでください。
mindmeld num-parse --start
  ...
  Numerical parser running, PID XXXXX
# もしくは、下記のコマンドでも確認可。
mindmeld num-parse --start -p 9000
```

</div></details>


【補足】
MindMeld は [Haskell](https://ja.wikipedia.org/wiki/Haskell) という純粋関数型プログラミング言語ベースの数値パーサを使用して、ユーザクエリ内の特定の数値表現(時刻や日付など)を検出しています。
ポートを指定しない場合、デフォルト 7151 番ポートでローカルに開始されます。
```mindmeld num-parse --start -p 9000```を実行した場合、9000 番ポートで開始され、```http://0.0.0.0:9000``` にアクセスすると```quack!```とだけ表示されます。

### ブループリントの開始
MindMeld を初めて触られる方は、まず用意されたブループリントアプリケーションを試すことから始めることがおすすめです。
サンプルとして用意されているブループリントは、以下 4 種類です。
1. Food Ordering (```food_ordering```)
2. Home Assistant (```home_assistaant```)
3. Video Discovery (```video_discovery```) <-- この記事で扱うブループリント
4. Kwik-E-Mart (```kwik_e_mart```)
この記事で扱う **Video Discovery** のゴールは、以下のイメージのように MindMeld との対話を通じて、私が探している映画やTV番組を見つけることです。
<img width="590" alt="スクリーンショット 2019-11-26 17.32.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214756/6ebc9852-a3fd-9dba-8cd3-bf0a14676c3f.png">

```python
# Python を起動
python

# MindMeld ブループリントアプリケーションのダウンロードとセットアップ
import mindmeld as mm
mm.configure_logs()
bp_name = 'video_discovery'
mm.blueprint(bp_name)
# セットアップが完了すると以下のログが表示されます。
# Created 'video_discovery' knowledge base at 'localhost'
# '/Users/XXX/my_mm_workspace4advent/video_discovery'
```

【補足】
```bp_name = 'video_discovery'``` の行をスキップして、直接 ```mm.blueprint('video_discovery')``` としても実行できます。
MindMeld プロジェクトフォルダー(```video_discovery```) が作成されると以下のイメージのようにディレクトリが作成されます。
<img width="554" alt="スクリーンショット 2019-11-26 17.50.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214756/7193a949-1cbc-f24b-ce05-6dcb2ff32d16.png">

### テストラン①
```python
# QuestionAnswerer アプリケーションのインポートとセットアップ
from mindmeld.components.question_answerer import QuestionAnswerer
qa = QuestionAnswerer(app_path='video_discovery')

# ナレッジベースのエントリーから「映画ミニオンズ」を検索
qa.get(index='videos', title='Minions')[0]
```

【補足】
テストランの結果は以下の通りです。

```
{'overview': 'Minions Stuart, Kevin and Bob are recruited by Scarlet Overkill, a super-villain who, alongside her inventor husband Herb, hatches a plot to take over the world.', 'imdb_id': 'tt2293640', 'directors': ['Kyle Balda', 'Pierre Coffin'], 'release_year': 2015, 'runtime': 91, 'doc_type': 'movie', 'countries': ['US'], 'title': 'Minions', 'cast': ['Sandra Bullock', 'Jon Hamm', 'Michael Keaton', 'Allison Janney', 'Steve Coogan', 'Jennifer Saunders', 'Geoffrey Rush', 'Steve Carell', 'Pierre Coffin', 'Katy Mixon', 'Michael Beattie', 'Hiroyuki Sanada', 'Dave Rosenbaum', 'Alex Dowding', 'Paul Thornley', 'Kyle Balda', 'Ava Acres'], 'img_url': 'http://image.tmdb.org/t/p/w185//q0R4crx2SehcEEQEkYObktdeFy.jpg', 'release_date': '2015-06-17', 'genres': ['Family', 'Animation', 'Adventure', 'Comedy'], 'vote_average': 6.4, 'popularity': 2.295467321653707, 'id': 'movie_211672', 'vote_count': 3660}
```

この **Video Discovery** アプリケーションはナレッジベースとして [The Movie DB](https://www.themoviedb.org/) というウェブサイトを参照しています。

### MindMeld ブループリントアプリケーションのベースライン NLP システムのトレーニング
ラベル付きデータを食わせることで、NLPシステム(```NaturalLanguageProcessor``` クラス)を訓練させます。

```python
# (オプション) ログレベルの変更
import logging
logging.getLogger('mindmeld').setLevel(logging.INFO)

# ベースライン NLP システムのトレーニングの実行
from mindmeld import configure_logs; configure_logs()
from mindmeld.components.nlp import NaturalLanguageProcessor
nlp = NaturalLanguageProcessor(app_path='video_discovery')
nlp.build()
```

【補足】
ログレベルを変更すると、機械学習のプロセスを以下のように覗くことができます。


<details><summary>```nlp.build()```のエラーログ</summary><div>

```
Fitting domain classifier
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/unrelated/compliment/train.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/unrelated/general/train.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/unrelated/insult/train.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/browse/train_00.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/browse/train_01.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/browse/train_02.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/browse/train_03.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/browse/train_04.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/browse/train_05.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/browse/train_mturk_00.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/browse/train_range_00.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/exit/train.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/greet/train.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/help/train.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/start_over/train.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/unsupported/train_get_channel_00.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/unsupported/train_get_channel_01.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/unsupported/train_get_channel_02.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/unsupported/train_get_time_00.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/unsupported/train_get_time_01.txt
Loading raw queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/video_content/unsupported/train_get_time_02.txt
Loading queries from file /Users/yunambu/my_mm_workspace4advent/video_discovery/domains/unrelated/compliment/train.txt
Unable to connect to the system entity recognizer. Make sure it's running by typing 'mindmeld num-parse' at the command line.
```

</div></detail>


エラーが吐かれました。。。言われた通り、```mindmeld num-parse```で確認してみると、```Num-parse```はきちんと動いているように見えます。

```
mindmeld num-parse
  ...
  Numerical parser running, PID 94958
```

この```system entity```がまず何か調べてみます。すると、このような記載がドキュメントにありました。

"""
Entities in MindMeld are categorized into two types:

System Entities
Generic entities that are application-agnostic and are automatically detected by MindMeld. Examples include numbers, time expressions, email addresses, URLs and measured quantities like distance, volume, currency and temperature.

Custom Entities
...

System entities are generic application-agnostic entities that all MindMeld applications detect automatically. There is no need to train models to learn system entities; they just work.
...
MindMeld does not assume that any of the system entities are needed in your app. It is the system entities that you annotate in your training data that MindMeld knows are needed.
"""

要するに、MindMeld が用意しているアプリケーション全てに同じように利用される汎用エンティティ (数値、時間表現、Email アドレス、URL や、距離・体積・通貨・温度などの測定など) のことで、これに接続できていないというエラーメッセージが出ています。ここで使おうとしている```nlp.py```そのものに問題があるのかもしれないと思って、せっかくなのでソースコードも以下の通り少し見てみました


<details><summary>```nlp.py```の確認</summary><div>

```nlp.py
# 該当しそうな箇所のみ抜粋
# system_entity_recognizer モジュール (nlp.py の親モジュール) から SystemEntityRecongnizer クラスをインポート
from ..system_entity_recognizer import SystemEntityRecognizer

"""
詳細は、system_entity_recongizer.py にコメントアウトしてあります。
この SystemEntityRecognizer は singleton (つまり、このクラスのインスタンスが常に 1 つであることを保証すること) として利用されることを想定しています。
そのため、NLPオブジェクトの構築中に一度だけ初期化されるような仕様になっています。
その初期化を行う作業が以下の一行になります。
"""
# initialize the system entity recognizer singleton
SystemEntityRecognizer.get_instance(app_path)
```

</div></details>


<details><summary>```system_entity_recognizer.py```の確認</summary><div>

```system_entity_recognizer.py
# 該当しそうな箇所のみ抜粋
# nlp.py など他のアプリで利用する外部パースサービス用のクラスの作成。
class SystemEntityRecognizer:
    """SystemEntityRecognizer is the external parsing service used to extract
    system entities. It is intended to be used as a singleton, so it's
    initialized only once during NLP object construction.

    TODO: Abstract this class into an interface and implement the duckling
    service as one such service.
    """

    _instance = None # Singleton 使うときに必ず出てくるおまじない的なもの

    def __init__(self, app_path=None): 
　　　　　# インスタンス生成時に呼び出されるインスタンスの初期化するための特殊メソッド__init__の定義。app_path はデフォルト変数として None を持つ
        # このコンストラクタは SystemEntityReconizer 専用のものだと言っています。使うときは必ず gettter を使いなさいという注釈
        """Private constructor for SystemEntityRecognizer. Do not directly
        construct the SystemEntityRecognizer object. Instead, use the
        static get_instance method.

        Args:
            app_path (str): A application path
        """
        if SystemEntityRecognizer._instance:
            raise Exception("SystemEntityRecognizer is a singleton") # raise 文を使って、この条件下で例外を発生させる
        else: # 以下の duckling api (Duckling = オープンソース自然言語テキスト分析) を使って自然言語の情報から、日付・時間や測定値を持ってきているようです。
            if not app_path:
                # The service is turned on by default
                self._use_duckling_api = True
            else:
                self._use_duckling_api = is_duckling_configured(app_path)

        self.app_path = app_path
        SystemEntityRecognizer._instance = self

    @staticmethod # クラスメソッドとして使用
    def get_instance(app_path=None):
        """ Static access method.

        Args:
            app_path (str): A application path

        Returns:
            (SystemEntityRecognizer): A SystemEntityRecognizer instance
        """
        if not SystemEntityRecognizer._instance:
            SystemEntityRecognizer(app_path)
        return SystemEntityRecognizer._instance

    def get_response(self, data):

        if not self._use_duckling_api:
            return [], NO_RESPONSE_CODE

        url = get_system_entity_url_config(app_path=self.app_path)

        try: # 例外発生時も強行する処理を記述
            response = requests.request('POST', url, data=data, timeout=1)

            if response.status_code == requests.codes['ok']:
                response_json = response.json()

                # Remove the redundant 'values' key in the response['value'] dictionary
                for i, entity_dict in enumerate(response_json):
                    if 'values' in entity_dict['value']:
                        del response_json[i]['value']['values']

                return response_json, response.status_code
            else:
                raise SystemEntityError('System entity status code is not 200.')
        except requests.ConnectionError: # 例外発生時の処理を記述
            sys.exit("Unable to connect to the system entity recognizer. Make sure it's "
                     "running by typing 'mindmeld num-parse' at the command line.") # 実行しているプログラムの中のメインプロセスを終了
        except Exception as ex:  # pylint: disable=broad-except
            logger.error('Numerical Entity Recognizer Error: %s\nURL: %r\nData: %s', ex, url,
                         json.dumps(data))
            sys.exit('\nThe system entity recognizer encountered the following ' +
                     'error:\n' + str(ex) + '\nURL: ' + url + '\nRaw data: ' + str(data) +
                     "\nPlease check your data and ensure Numerical parsing service is running. "
                     "Make sure it's running by typing "
                     "'mindmeld num-parse' at the command line.")

```

</div></details>


見る限り、```system_entity_recognizer.py```の最後の```try-except```文の例外時の処理が動いていて、結局```Parsing Service```に到達できていないようなので、```virtualenv```でやることを一旦諦めて、Dockerコンテナを使った方法でやり直します。
＊投稿日までに原因特定できなかったため、トラブルシュートが終わり次第追記したいとおもいます。

## Docker 環境の構築

<details><summary>Docker環境での再準備</summary><div>


```
# Docker バージョンの確認
docker version
Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea
 Built:             Wed Nov 13 07:22:34 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea
  Built:            Wed Nov 13 07:29:19 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

# MindMeld の最新イメージをレジストリから取得 
docker pull mindmeldworkbench/dep:latest
# 新たなコンテナを、9200/7151/9300 番のコンテナポートをそれぞれ 0.0.0.0 上の 9200/7151/9300 番ポートにバインドした形にして、バックグラウンドで実行。
docker run -p 0.0.0.0:9200:9200 -p 0.0.0.0:7151:7151 -p 0.0.0.0:9300:9300 mindmeldworkbench/dep -ti -d

# 仮想環境の準備と起動
mkdir my_mm_workspace4advent2
cd my_mm_workspace4advent2
virtualenv -p python3 .
source bin/activate

# MindMeld パッケージのインストールと起動
pip install mindmeld
mindmeld

# MindMeld ブループリントのダウンロード
mindmeld blueprint video_discovery # Python Shell からでなく、ターミナルから実行することもできます

```

</div></details>


### テストラン②
```python
# QuestionAnswerer アプリケーションのインポートとセットアップ
from mindmeld.components.question_answerer import QuestionAnswerer
qa = QuestionAnswerer(app_path='video_discovery')

# ナレッジベースのエントリーから「映画ミニオンズ」を検索
qa.get(index='videos', title='Minions')[0]
```

【補足】
テストランの結果は以下の通りです。

```
{'overview': 'Minions Stuart, Kevin and Bob are recruited by Scarlet Overkill, a super-villain who, alongside her inventor husband Herb, hatches a plot to take over the world.', 'imdb_id': 'tt2293640', 'directors': ['Kyle Balda', 'Pierre Coffin'], 'release_year': 2015, 'runtime': 91, 'doc_type': 'movie', 'countries': ['US'], 'title': 'Minions', 'cast': ['Sandra Bullock', 'Jon Hamm', 'Michael Keaton', 'Allison Janney', 'Steve Coogan', 'Jennifer Saunders', 'Geoffrey Rush', 'Steve Carell', 'Pierre Coffin', 'Katy Mixon', 'Michael Beattie', 'Hiroyuki Sanada', 'Dave Rosenbaum', 'Alex Dowding', 'Paul Thornley', 'Kyle Balda', 'Ava Acres'], 'img_url': 'http://image.tmdb.org/t/p/w185//q0R4crx2SehcEEQEkYObktdeFy.jpg', 'release_date': '2015-06-17', 'genres': ['Family', 'Animation', 'Adventure', 'Comedy'], 'vote_average': 6.4, 'popularity': 2.295467321653707, 'id': 'movie_211672', 'vote_count': 3660}
```

### NLP システムのトレーニングの再試行
```python
# (オプション) ログレベルの変更
import logging
logging.getLogger('mindmeld').setLevel(logging.DEBUG) # DEBUG に変更して、詳細のログをみてみることにします。

# ベースライン NLP システムのトレーニングの実行
from mindmeld import configure_logs; configure_logs()
from mindmeld.components.nlp import NaturalLanguageProcessor
nlp = NaturalLanguageProcessor(app_path='video_discovery')
nlp.build()
```


<details><summary>```nlp.build()```の詳細ログ</summary><div>

```
Fitting domain classifier
Loading raw queries from file video_discovery/domains/unrelated/compliment/train.txt
Loading raw queries from file video_discovery/domains/unrelated/general/train.txt
Loading raw queries from file video_discovery/domains/unrelated/insult/train.txt
Loading raw queries from file video_discovery/domains/video_content/browse/train_00.txt
Loading raw queries from file video_discovery/domains/video_content/browse/train_01.txt
Loading raw queries from file video_discovery/domains/video_content/browse/train_02.txt
Loading raw queries from file video_discovery/domains/video_content/browse/train_03.txt
Loading raw queries from file video_discovery/domains/video_content/browse/train_04.txt
Loading raw queries from file video_discovery/domains/video_content/browse/train_05.txt
Loading raw queries from file video_discovery/domains/video_content/browse/train_mturk_00.txt
Loading raw queries from file video_discovery/domains/video_content/browse/train_range_00.txt
Loading raw queries from file video_discovery/domains/video_content/exit/train.txt
Loading raw queries from file video_discovery/domains/video_content/greet/train.txt
Loading raw queries from file video_discovery/domains/video_content/help/train.txt
Loading raw queries from file video_discovery/domains/video_content/start_over/train.txt
Loading raw queries from file video_discovery/domains/video_content/unsupported/train_get_channel_00.txt
Loading raw queries from file video_discovery/domains/video_content/unsupported/train_get_channel_01.txt
Loading raw queries from file video_discovery/domains/video_content/unsupported/train_get_channel_02.txt
Loading raw queries from file video_discovery/domains/video_content/unsupported/train_get_time_00.txt
Loading raw queries from file video_discovery/domains/video_content/unsupported/train_get_time_01.txt
Loading raw queries from file video_discovery/domains/video_content/unsupported/train_get_time_02.txt
Loading queries from file video_discovery/domains/unrelated/compliment/train.txt
Loading queries from file video_discovery/domains/unrelated/general/train.txt
Loading queries from file video_discovery/domains/unrelated/insult/train.txt
Loading queries from file video_discovery/domains/video_content/browse/train_00.txt
Loading queries from file video_discovery/domains/video_content/browse/train_01.txt
Loading queries from file video_discovery/domains/video_content/browse/train_02.txt
Loading queries from file video_discovery/domains/video_content/browse/train_03.txt
Loading queries from file video_discovery/domains/video_content/browse/train_04.txt
Loading queries from file video_discovery/domains/video_content/browse/train_05.txt
Loading queries from file video_discovery/domains/video_content/browse/train_mturk_00.txt
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for "80's".
Unable to load query: Unable to resolve system entity of type 'sys_interval' for "1990's".
Unable to load query: Unable to resolve system entity of type 'sys_interval' for "1990's".
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1980s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for 'all time'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '70s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for "80's".
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1980s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for "90's".
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for 'all time'.
Unable to load query: Unable to resolve system entity of type 'sys_time' for 'the year'.
Unable to load query: Unable to resolve system entity of type 'sys_time' for 'this moment'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for "90's".
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '2010-2015'. Entities found for the following types ['sys_temperature', 'sys_amount-of-money', 'sys_phone-number']
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1980s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1980s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '2000s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for "90's".
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '2000 to now'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '2000s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for 'last year'. Entities found for the following types ['sys_time']
Unable to load query: Unable to resolve system entity of type 'sys_interval' for "40's".
Unable to load query: Unable to resolve system entity of type 'sys_interval' for 'last decade'.
Unable to load query: Unable to resolve system entity of type 'sys_time' for 'this summer'. Entities found for the following types ['sys_interval']
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1950s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '2000s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1960s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Loading queries from file video_discovery/domains/video_content/browse/train_range_00.txt
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90 s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '2000 s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1970s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1900s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1970s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80 s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1970 s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1970s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1990 to 1995'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80 s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '60s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90 s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for 'eighties'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '70s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1980s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for 'last year'. Entities found for the following types ['sys_time']
Unable to load query: Unable to resolve system entity of type 'sys_interval' for 'last year'. Entities found for the following types ['sys_time']
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80 s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1960s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for 'late 1990 s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for 'past year'. Entities found for the following types ['sys_time']
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80 s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '2000s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90 s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '60s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '2010s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1980s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90 s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '80s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '90s'.
Unable to load query: Unable to resolve system entity of type 'sys_interval' for '1950s'.
Loading queries from file video_discovery/domains/video_content/exit/train.txt
Loading queries from file video_discovery/domains/video_content/greet/train.txt
Loading queries from file video_discovery/domains/video_content/help/train.txt
Loading queries from file video_discovery/domains/video_content/start_over/train.txt
Loading queries from file video_discovery/domains/video_content/unsupported/train_get_channel_00.txt
Loading queries from file video_discovery/domains/video_content/unsupported/train_get_channel_01.txt
Loading queries from file video_discovery/domains/video_content/unsupported/train_get_channel_02.txt
Loading queries from file video_discovery/domains/video_content/unsupported/train_get_time_00.txt
Loading queries from file video_discovery/domains/video_content/unsupported/train_get_time_01.txt
Loading queries from file video_discovery/domains/video_content/unsupported/train_get_time_02.txt
Building gazetteer 'sort'
Loading entity data from 'video_discovery/entities/sort/gazetteer.txt'
52/52 entities in entity data file exceeded popularity cutoff and were added to the gazetteer
Loading synonyms from entity mapping
Added 49/49 synonyms from file into gazetteer
Building gazetteer 'director'
Loading entity data from 'video_discovery/entities/director/gazetteer.txt'
89750/89750 entities in entity data file exceeded popularity cutoff and were added to the gazetteer
Loading synonyms from entity mapping
Added 0/0 synonyms from file into gazetteer
Building gazetteer 'title'
Loading entity data from 'video_discovery/entities/title/gazetteer.txt'
276728/276728 entities in entity data file exceeded popularity cutoff and were added to the gazetteer
Loading synonyms from entity mapping
Added 0/0 synonyms from file into gazetteer
Building gazetteer 'cast'
Loading entity data from 'video_discovery/entities/cast/gazetteer.txt'
486719/486719 entities in entity data file exceeded popularity cutoff and were added to the gazetteer
Loading synonyms from entity mapping
Added 0/0 synonyms from file into gazetteer
Building gazetteer 'genre'
Loading entity data from 'video_discovery/entities/genre/gazetteer.txt'
101/101 entities in entity data file exceeded popularity cutoff and were added to the gazetteer
Loading synonyms from entity mapping
Added 70/70 synonyms from file into gazetteer
Building gazetteer 'type'
Loading entity data from 'video_discovery/entities/type/gazetteer.txt'
18/18 entities in entity data file exceeded popularity cutoff and were added to the gazetteer
Loading synonyms from entity mapping
Added 20/20 synonyms from file into gazetteer
Building gazetteer 'country'
Loading entity data from 'video_discovery/entities/country/gazetteer.txt'
477/477 entities in entity data file exceeded popularity cutoff and were added to the gazetteer
Loading synonyms from entity mapping
Added 243/243 synonyms from file into gazetteer
Fitting intent classifier: domain='video_content'
Selecting hyperparameters using k-fold cross-validation with 5 splits
Best accuracy: 98.12%, params: {'C': 10, 'class_weight': {0: 0.5805006811989102, 1: 3.431368821292776, 2: 0.9903185247275775, 3: 5.1444117647058825, 4: 2.906170886075949, 5: 0.6776020174232005}, 'fit_intercept': True}
Fitting entity recognizer: domain='video_content', intent='browse'
No entity_resolution model configuration set. Using default.
No entity_resolution model configuration set. Using default.
No entity_resolution model configuration set. Using default.
No entity_resolution model configuration set. Using default.
No entity_resolution model configuration set. Using default.
No entity_resolution model configuration set. Using default.
No entity_resolution model configuration set. Using default.
No entity_resolution model configuration set. Using default.
No entity_resolution model configuration set. Using default.
Fitting role classifier: domain='video_content', intent='browse', entity_type='type'
No role model configuration set. Using default.
Importing synonym data to synonym index 'synonym_type'
Creating index 'synonym_type'
100%|████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<00:00, 23.57it/s]
Loaded 2 documents
Fitting role classifier: domain='video_content', intent='browse', entity_type='country'
No role model configuration set. Using default.
Importing synonym data to synonym index 'synonym_country'
Creating index 'synonym_country'
100%|███████████████████████████████████████████████████████████████████████████| 235/235 [00:00<00:00, 555.92it/s]
Loaded 235 documents
Fitting role classifier: domain='video_content', intent='browse', entity_type='sys_interval'
No role model configuration set. Using default.
Fitting role classifier: domain='video_content', intent='browse', entity_type='cast'
No role model configuration set. Using default.
Importing synonym data to synonym index 'synonym_cast'
Creating index 'synonym_cast'
0it [00:00, ?it/s]
Loaded 0 documents
Fitting role classifier: domain='video_content', intent='browse', entity_type='genre'
No role model configuration set. Using default.
Importing synonym data to synonym index 'synonym_genre'
Creating index 'synonym_genre'
100%|█████████████████████████████████████████████████████████████████████████████| 31/31 [00:00<00:00, 270.29it/s]
Loaded 31 documents
Fitting role classifier: domain='video_content', intent='browse', entity_type='sort'
No role model configuration set. Using default.
Importing synonym data to synonym index 'synonym_sort'
Creating index 'synonym_sort'
100%|████████████████████████████████████████████████████████████████████████████████| 4/4 [00:00<00:00, 43.20it/s]
Loaded 4 documents
Fitting role classifier: domain='video_content', intent='browse', entity_type='sys_time'
No role model configuration set. Using default.
Fitting role classifier: domain='video_content', intent='browse', entity_type='director'
No role model configuration set. Using default.
Importing synonym data to synonym index 'synonym_director'
Creating index 'synonym_director'
0it [00:00, ?it/s]
Loaded 0 documents
Fitting role classifier: domain='video_content', intent='browse', entity_type='title'
No role model configuration set. Using default.
Importing synonym data to synonym index 'synonym_title'
Creating index 'synonym_title'
0it [00:00, ?it/s]
Loaded 0 documents
Fitting entity recognizer: domain='video_content', intent='greet'
There are no labels in this label set, so we don't fit the model.
Fitting entity recognizer: domain='video_content', intent='help'
There are no labels in this label set, so we don't fit the model.
Fitting entity recognizer: domain='video_content', intent='start_over'
There are no labels in this label set, so we don't fit the model.
Fitting entity recognizer: domain='video_content', intent='exit'
There are no labels in this label set, so we don't fit the model.
Fitting entity recognizer: domain='video_content', intent='unsupported'
There are no labels in this label set, so we don't fit the model.
Fitting intent classifier: domain='unrelated'
Selecting hyperparameters using k-fold cross-validation with 5 splits
Best accuracy: 70.87%, params: {'C': 1, 'class_weight': {0: 0.9618644067796609, 1: 1.009, 2: 1.0395604395604394}, 'fit_intercept': True}
Fitting entity recognizer: domain='unrelated', intent='insult'
There are no labels in this label set, so we don't fit the model.
Fitting entity recognizer: domain='unrelated', intent='general'
There are no labels in this label set, so we don't fit the model.
Fitting entity recognizer: domain='unrelated', intent='compliment'
There are no labels in this label set, so we don't fit the model.
```

</div></detail>


ひとまずエラーは回避でき、```Best accuracy: 70.87%, params: {'C': 1, 'class_weight': {0: 0.9618644067796609, 1: 1.009, 2: 1.0395604395604394}, 'fit_intercept': True}```という結果を受け取っていました。
```Unable to load query: Unable to resolve system entity of type 'sys_interval'```、```Unable to load query: Unable to resolve system entity of type 'sys_time'```と言ったログが出ているのが気になりましたがこちらも投稿日までに原因が追求できなかったため分かり次第追記します。
また、この時点では```No entity_resolution model configuration set. Using default.```とあり、精度が 70% 弱と低くなっていますが、この後のテストラン③の中で、フィーチャーの抽出方法を選択してフィッティングをすることで精度を上げていきます。


### テストラン③
```python
# トレーニング済みの NLP システムに対してテストクエリを投げる 
nlp.process("Show me movies with Yo Oizumi")
```

```
{'text': 'Show me movies with Yo Oizumi', 'domain': 'video_content', 'intent': 'browse', 'entities': [{'text': 'movies', 'type': 'type', 'role': None, 'value': [{'cname': 'movie', 'score': 19.448803, 'top_synonym': 'movies'}, {'cname': 'tv-show', 'score': 1.684855, 'top_synonym': 'series'}], 'span': {'start': 8, 'end': 13}}, {'text': 'Yo Oizumi', 'type': 'cast', 'role': None, 'value': [], 'span': {'start': 20, 'end': 28}}]}
```

```python
# Intent Classifier の作成。これを用いて、モデルやフィーチャーの抽出設定にアクセスする
>>> ic = nlp.domains['video_content'].intent_classifier
>>> ic.config.model_settings['classifier_type']
'logreg'

>>> ic.config.features
{'bag-of-words': {'lengths': [1, 2]}, 'edge-ngrams': {'lengths': [1, 2]}, 'in-gaz': {}, 'exact': {'scaling': 10}, 'gaz-freq': {}, 'freq': {'bins': 5}}

# この分類器は、fit()メソッドを使って適切なパラメータを渡すことで、様々な学習アルゴリズム・機能・ハイパーパラメータ・相互検証設定などを試すことができる。
# 例えば、デフォルトでは、bag-of-words がフィーチャー抽出で用いられているが、bag-of-N-grams を追加して使用することもできる。
# ここではサンプルブループリントを使っているため、既に入っている。
>>> ic.config.features['bag-of-words']['lengths'].append(3)
>>> ic.fit() # fit(learan_data, learn_label)メソッドを用いて、学習用データと結果を学習できる
Fitting intent classifier: domain='video_content'
Selecting hyperparameters using k-fold cross-validation with 5 splits
Best accuracy: 98.12%, params: {'C': 10, 'class_weight': {0: 0.8202145776566757, 1: 2.0420152091254753, 2: 0.9958507963118188, 3: 2.7761764705882355, 4: 1.8169303797468355, 5: 0.8618294360385144}, 'fit_intercept': True}
```

## デプロイメント
ここまでのステップが全て終了したら、```Conversation```クラスを使って対話型アプリケーションのテストを実施します。

```python
from mindmeld.components.dialogue import Conversation
conv = Conversation(nlp=nlp, app_path='video_discovery')
res = conv.say("Show me movies with Yo Oizumi")
print(res[1])
```


<details><summary>結果</summary><div>

```
{
    "popularity": 1.6843605812038211,
    "release_year": 2001,
    "title": "Spirited Away",
    "type": "movie"
}
{
    "popularity": 1.331518694517026,
    "release_year": 2004,
    "title": "Howl's Moving Castle",
    "type": "movie"
}
{
    "popularity": 0.9276412700980977,
    "release_year": 2014,
    "title": "When Marnie Was There",
    "type": "movie"
}
{
    "popularity": 0.5483075183578056,
    "release_year": 2002,
    "title": "The Cat Returns",
    "type": "movie"
}
{
    "popularity": 0.48987671974559993,
    "release_year": 2015,
    "title": "I Am a Hero",
    "type": "movie"
}
{
    "popularity": 0.40345108131710566,
    "release_year": 2015,
    "title": "The Boy and the Beast",
    "type": "movie"
}
{
    "popularity": 0.21568218441881915,
    "release_year": 2006,
    "title": "Brave Story",
    "type": "movie"
}
{
    "popularity": 0.14845276320241113,
    "release_year": 2015,
    "title": "Kakekomi",
    "type": "movie"
}
{
    "popularity": 0.12538694143866852,
    "release_year": 2009,
    "title": "Professor Layton and the Eternal Diva",
    "type": "movie"
}
{
    "popularity": 0.0982032635261464,
    "release_year": 2007,
    "title": "Kitaro",
    "type": "movie"
}
```

</div></detail>


## 対話のシミュレーション
```say()```メソッドは、入力テキストをユーザ要求オブジェクトにパッケージ化し、MindMeld Application Manager に渡して、ユーザがアプリケーションと対話するのをシミュレートしてくれます。このメソッドは、Dialogue Manager によって送信された応答テキスト部分を出力します。

```python
>>> conv.say('Hi, there!')
['Hi!', 'Talk to me to browse movies and TV shows.', '{\n    "popularity": 4.904354681204688,\n    "release_year": 2017,\n    "title": "Wonder Woman",\n    "type": "movie"\n}\n{\n    "popularity": 4.743179401930947,\n    "release_year": 2017,\n    "title": "Beauty and the Beast",\n    "type": "movie"\n}\n{\n    "popularity": 4.390633761852561,\n    "release_year": 2017,\n    "title": "Transformers: The Last Knight",\n    "type": "movie"\n}\n{\n    "popularity": 4.316296603970634,\n    "release_year": 2017,\n    "title": "Logan",\n    "type": "movie"\n}\n{\n    "popularity": 4.088732678349925,\n    "release_year": 2017,\n    "title": "The Mummy",\n    "type": "movie"\n}\n{\n    "popularity": 3.9604223694356175,\n    "release_year": 2017,\n    "title": "Kong: Skull Island",\n    "type": "movie"\n}\n{\n    "popularity": 3.920513974901613,\n    "release_year": 2005,\n    "title": "Doctor Who",\n    "type": "tv-show"\n}\n{\n    "popularity": 3.8653508696521426,\n    "release_year": 2011,\n    "title": "Game of Thrones",\n    "type": "tv-show"\n}\n{\n    "popularity": 3.7942142869419615,\n    "release_year": 2010,\n    "title": "The Walking Dead",\n    "type": "tv-show"\n}\n{\n    "popularity": 3.575316921466775,\n    "release_year": 2017,\n    "title": "Pirates of the Caribbean: Dead Men Tell No Tales",\n    "type": "movie"\n}', "Suggestions: 'Most popular', 'Most recent', 'Movies', 'TV Shows', 'Action', 'Dramas', 'Sci-Fi'"]
>>> 
>>> conv.say('Show me Yo Oizumi movies')
['Ok. Here are some results:', '{\n    "popularity": 1.6843605812038211,\n    "release_year": 2001,\n    "title": "Spirited Away",\n    "type": "movie"\n}\n{\n    "popularity": 1.331518694517026,\n    "release_year": 2004,\n    "title": "Howl\'s Moving Castle",\n    "type": "movie"\n}\n{\n    "popularity": 0.9276412700980977,\n    "release_year": 2014,\n    "title": "When Marnie Was There",\n    "type": "movie"\n}\n{\n    "popularity": 0.5483075183578056,\n    "release_year": 2002,\n    "title": "The Cat Returns",\n    "type": "movie"\n}\n{\n    "popularity": 0.48987671974559993,\n    "release_year": 2015,\n    "title": "I Am a Hero",\n    "type": "movie"\n}\n{\n    "popularity": 0.40345108131710566,\n    "release_year": 2015,\n    "title": "The Boy and the Beast",\n    "type": "movie"\n}\n{\n    "popularity": 0.21568218441881915,\n    "release_year": 2006,\n    "title": "Brave Story",\n    "type": "movie"\n}\n{\n    "popularity": 0.14845276320241113,\n    "release_year": 2015,\n    "title": "Kakekomi",\n    "type": "movie"\n}\n{\n    "popularity": 0.12538694143866852,\n    "release_year": 2009,\n    "title": "Professor Layton and the Eternal Diva",\n    "type": "movie"\n}\n{\n    "popularity": 0.0982032635261464,\n    "release_year": 2007,\n    "title": "Kitaro",\n    "type": "movie"\n}']
>>> 
>>> conv.say('from 2015')
['Perfect. Here are some movies with Yo Oizumi:', '{\n    "popularity": 0.48987671974559993,\n    "release_year": 2015,\n    "title": "I Am a Hero",\n    "type": "movie"\n}\n{\n    "popularity": 0.40345108131710566,\n    "release_year": 2015,\n    "title": "The Boy and the Beast",\n    "type": "movie"\n}\n{\n    "popularity": 0.14845276320241113,\n    "release_year": 2015,\n    "title": "Kakekomi",\n    "type": "movie"\n}']
>>>
>>> conv.say('Thank you')
['See you later.']
>>>
>>> conv.say('do you have comedy movies?')
['Perfect. Here are some results:', '{\n    "popularity": 3.575316921466775,\n    "release_year": 2017,\n    "title": "Pirates of the Caribbean: Dead Men Tell No Tales",\n    "type": "movie"\n}\n{\n    "popularity": 3.16142885645921,\n    "release_year": 2017,\n    "title": "Guardians of the Galaxy Vol. 2",\n    "type": "movie"\n}\n{\n    "popularity": 2.864445217663442,\n    "release_year": 2017,\n    "title": "Despicable Me 3",\n    "type": "movie"\n}\n{\n    "popularity": 2.8304034588472593,\n    "release_year": 2017,\n    "title": "Cars 3",\n    "type": "movie"\n}\n{\n    "popularity": 2.824917558393832,\n    "release_year": 2017,\n    "title": "Baywatch",\n    "type": "movie"\n}\n{\n    "popularity": 2.7538905585490667,\n    "release_year": 2016,\n    "title": "Deadpool",\n    "type": "movie"\n}\n{\n    "popularity": 2.6281775734086983,\n    "release_year": 2016,\n    "title": "Tomorrow Everything Starts",\n    "type": "movie"\n}\n{\n    "popularity": 2.561422298541789,\n    "release_year": 2017,\n    "title": "The Lego Batman Movie",\n    "type": "movie"\n}\n{\n    "popularity": 2.4652902501503737,\n    "release_year": 2000,\n    "title": "DragonHeart: A New Beginning",\n    "type": "movie"\n}\n{\n    "popularity": 2.4633532858463862,\n    "release_year": 2017,\n    "title": "Smurfs: The Lost Village",\n    "type": "movie"\n}']
>>> 
>>> conv.say('show me the ones with Yo Oizumi')
['Ok. Here are some comedy movies:', '{\n    "popularity": 0.14845276320241113,\n    "release_year": 2015,\n    "title": "Kakekomi",\n    "type": "movie"\n}\n{\n    "popularity": 0.08592812381604169,\n    "release_year": 2013,\n    "title": "Detective in the Bar",\n    "type": "movie"\n}\n{\n    "popularity": 0.058488695289761736,\n    "release_year": 2013,\n    "title": "The Kiyosu Conference",\n    "type": "movie"\n}\n{\n    "popularity": 0.015350574738277112,\n    "release_year": 2016,\n    "title": "Gold Medal Man",\n    "type": "movie"\n}\n{\n    "popularity": 0.015203833742272778,\n    "release_year": 2011,\n    "title": "Drucker in the Dug-Out",\n    "type": "movie"\n}\n{\n    "popularity": 0.01330410659551587,\n    "release_year": 2012,\n    "title": "Bread of Happiness",\n    "type": "movie"\n}\n{\n    "popularity": 0.011187189390564376,\n    "release_year": 2006,\n    "title": "Sugar & Spice: F\\u00fbmi zekka",\n    "type": "movie"\n}\n{\n    "popularity": 0.006566393969770445,\n    "release_year": 2014,\n    "title": "A Drop of the Grapevine",\n    "type": "movie"\n}\n{\n    "popularity": 0.0005218638053935734,\n    "release_year": 2006,\n    "title": "Simsons",\n    "type": "movie"\n}']
>>> 
>>> conv.say('Released in 2012')
['Done. Here are some comedy movies starring Yo Oizumi:', '{\n    "popularity": 0.01330410659551587,\n    "release_year": 2012,\n    "title": "Bread of Happiness",\n    "type": "movie"\n}']
>>> conv.say('Thank you')
['Bye!']
```

# ひとまずできた！
ということで、ひとまずベーシックなところ一通り試してみることができました。
MindMeld のよいところはカスタマイズできる点だと思うので、今後カスタムアプリの作成(```Article_Discovery```ブループリント)、日本語化、Chat Bot連携など試してみたいと思います。

# 免責事項 
本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。