AidemyのJupyter Notebook
AidemyではJupyter Notebookを利用してユーザーへの学習コンテンツを提供しています。
そもそもJupyter Notebookを利用した理由は展開可能性にあります。
Jupyter Notebookで書いたドキュメントはそのままファイルとしてユーザーへ提供可能なため、
将来的に学習済みのコンテンツやオリジナルコンテンツをユーザー企業様へ配布し、二次利用してもらう想定がありました。
しかし、時は流れ流れ
そういった活用をされないまま、学習コンテンツをJupyter Notebookで書くことの辛みを覚えてきました。
そもそもAidemyではJupyter NotebookをJSONファイルへ変換し、それをDBへ投入してフロントから呼び出して利用しています。
その変換処理はJavascriptを用いていますが、サービス立ち上げ当初に書かれたコードであり、ドキュメントも不足していました。
そこで、将来的にJupyter Notebookからの脱却を夢見つつ、まずはこのJupyter Notebook → JSON変換スクリプトの読み解きが始まりました。
Jupyter Notebookの内部構造
Jupyter Notebookの基本構造は下記のようになっています。
The Notebook file format
{ cells: [ { cell_type: "", metadata: {}, source: [] } ] }
cells
の中にcell Objectが配列として格納され、それぞれ cell_type
, meta_data
, source
が存在します。
sourceは配列を格納しますが、これは1行ずつの文字列が入っています。
また、metadataには独自のパラメータを設定することができ、Aidemyでは { type: "courseId" }
などを設定しています。
これまでの変換ではcellを配列として回しながら内部でJSONを構築していくという方式でしたが、indexを用いて参照していたため、可読性が低く、メンテナンス性がとても悪いものでした。
そこで、これらをJSONとして扱いやすくするために、まずはcellsを展開し、metadataの type
をパラメータのkey, sourceをparamとする処理を行うように修正しました。
const fs = require('fs'); const jupyterFile = fs.readFileSync('some.ipynb') const jupyterJson =JSON.parse(jupyterFile.toString()) jupyterJson.cells.reduce((pre, curr) => ({...pre, [curr.metadata.type]: curr.source}), {})
これにより、typeをkey、sourceをparamとして保持することができます。
{ cells: [ { cell_type: "", metadata: { type: 'courseId' }, source: [ "1" ] } ] }
=>
{ "courseId": ["1"] }
以降は通常のJSONとして扱うことができ、とても扱いやすいものになります。 もちろん、Jupyter Notebookでは自由なパラメータを設定できますので、お手元のJupyter Notebookファイルによって詰め替えるkeyやparamを設定してみてください。
この記事ではJupyter NotebookをJSONに変換する処理について書きましたが、これはまだリファクタリングの途中です。 Jupyter Notebookはとても自由で便利なものではありますが、その分環境構築やデータ構造としての扱いやすさに難があり、チームで扱う際に使い勝手が気になるところではあります。 今後よりコンテンツの拡充を図るため、Jupyter Notebookから脱却し、チーム内共有や反映の迅速化ができるよう、さらに使いやすい方式を求めていきます。