airbnb/knowledge-repoを導入する(ローカル解析編)

# knowledge-repoとは
- 一言で言うならDataScienceに特化したCI/CDパイプラインを持つFlask (WebApplication)です
- データサイエンティストは既存のGithubを使ったWorkflowを利用することで解析のコアな作業に集中することができます。
- 実際使うには以下の2つのWorkflowを理解する必要があります。
    - ローカルでの解析
    - デプロイ
- この記事では「ローカルでの解析」を記載し、次回デプロイ編をまとめたいと思います。

### 参考情報
- [Github Repository](https://github.com/airbnb/knowledge-repo)
- [MidiumPost](https://medium.com/airbnb-engineering/scaling-knowledge-at-airbnb-875d73eff091)


### なぜknowledge-repoを使うか
MidiumPostに問題となるケースが書かれています。

> 新人DataScientist, Jenniferの場合を考えてみましょう。
1. ジェニファーがチームのメンバーに、以前行った解析結果を見せてほしいと尋ねると、プレゼンテーション、電子メール、Googleドキュメントなどの混在で送られてきます。
2. 以前解析に使ったコードは最新ではありません。Jenniferは元の解析者のマシンをローカルに再現したり、古いGitHubリンクを追跡します。
3. コードを操作した後、Jenniferはそれが以前のプロットを作ったものとは若干異なることに気づきます。Jenniferは、ずれのあるコードを調整するか、スクラッチで書き直すことになります。
4. 結果を再現する時間を費やしたり、一から作りなおしたりしてやっと、彼女は仕事を始められます。
5. そしてJenniferはプレゼンテーション、電子メール、またはGoogle Docを使用して結果を配信し、そのサイクルを永続させます。

データ解析の仕事をしたことがある人にとっては、あるあるですよね。
このような問題を解決するためにknowledge-repoを使います。

### 目指しているもの
こちらもMidiumPostに記載があります。

> 再現性  - 解析に使われたコードは分割されてはならない。queries, transforms, visualizations, write-upのすべての作業が、各投稿に含まれていて、最新のものでなければならない。
品質  - 正確性と精度についてレビューされることなく、解析結果を共有されてはいけない。
使いやすさ  - 結果は、解析者以外のメンバーにも理解できるものでなければならない。一貫性があり、on-brand(訳不明)でなければならない。
見つけやさ  - 誰でも自分が調べたいトピックに関する既存の解析を見つけることができ、最新の状態に保つことができなければならない。
学習しやすさ  - 解析結果を再現することで、他のメンバーは、解析者が書いたコードやツールから学習できなければならない

どれも重要なことです。それではそれをどうやって実現していくか見てみましょう。

# ローカルでのワークフロー(全体)
一通り使ってみても**実際に何が行われているのか？**が見えにくいので図解してみました。
黒文字が実際に打っているコマンドで吹き出しがその内部で行われていることです。

<img width="600" alt="Untitled.png" src="https://qiita-image-store.s3.amazonaws.com/0/127651/dcfd6770-5e6d-06ee-f3a1-da3a555b1ea9.png">

図解してみてフローが理解し辛い理由に気づきました。

- 解析をした(実装をした)後にbranchを作るので一般的な開発フローと違う
- git fetchは手動なのにgit pushは隠蔽されている

が原因なのではないでしょうか？どちらも一度理解してしまえば、そうなんだ、くらいのことですよね。

# ローカルでのワークフロー(詳細)
[Quickstart](http://knowledge-repo.readthedocs.io/en/latest/quickstart.html)に従いつつ、足りない情報を追加しながら進めて行きます。

### repositoryを作成する

```bash
$ cd your_target_dir
$ knowledge_repo --repo . init
```

これで設定ファイルが作られます。


```
$ ls -a
.knowledge_repo_config.yml # 残りは省略
```


### 新しいnotebookを作成する

```bash
$ knowledge_repo --repo . create {format} {file_name}
```

現状では`{format}`は`'ipynb', 'Rmd', 'md'`のどれかです。

例えばこんな感じで作成できます。

```bash
$ knowledge_repo --repo . create ipynb my-analysis.ipynb
INFO:knowledge_repo.repositories.gitrepository:Fetching updates to the knowledge repository...
Created a ipynb knowledge post template at 'my-analysis.ipynb'.
```


### Data解析を行う

テンプレートからnotebookを作成したらいつも通り解析を行いましょう

```bash
$ jupyter notebook my-analysis.ipynb
```

<img width="500" alt="screencapture-localhost-8890-notebooks-my-analysis-ipynb-2018-06-04-18_04_35_png.png" src="https://qiita-image-store.s3.amazonaws.com/0/127651/41249559-70e8-7989-818c-17ea9b058fbb.png">



ポイントは一番上のmeta情報が入っているセルです。こんな情報が入っています。
この情報はあとでアプリケーションを起動したときに使われます。

```
---
title: This is a Knowledge Template Header
authors:
- ikedayu
tags:
- knowledge
- example
created_at: 2016-06-29
updated_at: 2016-06-30
tldr: This is short description of the content and findings of the post.
---
```

### knowledge-repoにnotebookを追加する

解析が上手くいき、チームにシェアしたい状態になったらnotebookをknowledge-repoに追加しましょう。下記コマンドで行うことができます。knowledge-repoに追加とは？となるかもしれませんが、つまりmaster branchのことです。

```bash
$ knowledge_repo --repo . add {file_name} -p {project_name}
```

`{project-name}`はknowledge-repo(master)内のpathにもなります
今までの例だと下記のようなコマンドを打つことになります。

```bash
$ knowledge_repo --repo . add my-analysis.ipynb -p project/my-analysis
NFO:knowledge_repo.repositories.gitrepository:Fetching updates to the knowledge repository...
INFO:knowledge_repo.repositories.gitrepository:Checking out (and/or creating) a new branch `project/my-analysis.kp`...
INFO:knowledge_repo.repositories.gitrepository:Adding and committing 'project/my-analysis.kp' to local branch `project/my-analysis.kp`...
Please enter a commit message for this post: {commit_message}
```

commit messageを聞かれるので入力します。
すると、markdownファイルなどが作成されます。

```bash
$ tree -L 3
.
├── README.md
├── my-analysis.ipynb
└── project
    └── my-analysis.kp
        ├── REVISION
        ├── UUID
        ├── images
        ├── knowledge.md
        └── src
```

またcommitもされています。ここで最初に作成したnotebookはcommitされていないのもポイントです。

```bash
$ git log --stat
commit **** (HEAD -> project/my-analysis.kp)
Author: ****
Date:   Mon Jun 4 21:56:59 2018 +0900

    Add my-analysis

 project/my-analysis.kp/REVISION              |   1 +
 project/my-analysis.kp/UUID                  |   1 +
 project/my-analysis.kp/images/output_5_1.png | Bin 0 -> 64413 bytes
 project/my-analysis.kp/knowledge.md          |  72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 project/my-analysis.kp/src/my-analysis.ipynb | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
```

### 追加したファイルをプレビューする
追加したnotebook(をmarkdownに変換したもの)をローカルでプレビューします。

```
$ knowledge_repo --repo . preview {project_name}
```

今までの例だとこうなります。

```
$ knowledge_repo --repo . preview project/my-analysis
```

この時Faskが立ち上がっています。

デフォルトでは`http://127.0.0.1:7000/post/project/my-analysis.kp`のようなURLがブラウザで開かれます。

<img width="600" alt="This_is_a_Knowledge_Template_Header.png" src="https://qiita-image-store.s3.amazonaws.com/0/127651/ad074b1e-d87a-b148-693a-8cdc1107c3f8.png">

先程のnotebookで1セル目に入力されていたmeta情報はこのように表示されます。

もしここで修正したければ↓のコマンドで可能です。(addに--updateをつけるだけです)

```
$ knowledge_repo --repo . add --update my-analysis.ipynb -p project/my-analysis
```

### PRを作成します
プレビューを見て問題なければPRを作成します。下記のコマンド

```
$ knowledge_repo --repo . submit {project_name}
```

今までの例だと↓です。

```
$ knowledge_repo --repo . submit project/my-analysis
```

内側では`git push origin {branch}`が走っているだけです。
なのでPR作成は手動で行い、通常通りレビュー＆Mergeします。

<img width="502" alt="kaizenplatform_knowledge-repo__A_platform_is_based_on_sharing_knowledge_of_data_analytics_.png" src="https://qiita-image-store.s3.amazonaws.com/0/242836/f3dad1d9-e484-a28f-009b-1598fcdf5309.png">

これでローカル解析編は終了です。

# まとめ
- airbnb/knowledge-repoのローカル解析のworkflowを解説しました。
- 次回はデプロイ編を書きます。