Hiển thị Jupyter notebook trên Hugo như thế nào?

Ừ thì mình là Machine Learning Engineer (thậm chí thỉnh thoảng còn được gọi là Data Scientist :v) thế mà không viết blog về ML rồi toán rồi data các thứ nghe nó cũng không hợp lý cho lắm. Nhưng giờ viết lý thuyết thì chẳng ai đọc mà viết về thực nghiệm thì phải có cách nào hiển thị cái notebook cho nó đẹp một chút chứ :))))

Thế với ý tưởng xl trên, mình thử search tầm 15p và có luôn cách cực kỳ đơn giản được giới thiệu trong https://miguelrodrigues.org/post/jupyter/, đại thể là sẽ dùng nbconvert để convert jupyter notebook markdown, sau đó sẽ Hugo render như bình thường, ví dụ như ngay bài viết này được render từ notebook này

OK ngon, vậy thì để xem nó sẽ trông như thế nào :)))

Biểu đồ các thứ

Thứ đầu tiên mà mình sẽ thử tất nhiên là thư viện vẽ biểu đồ quốc dân matplotlib rồi :b Nhìn chung thì cũng khá ổn, mình vẽ barchart thì biểu đồ này hiển thị đúng như những gì có trong notebook. Cách nbconvert xử lý khá hợp lý, khi mà biểu đồ được export ra thành ảnh và nhúng vào trang markdown.

import matplotlib.pyplot as plt
fig, ax = plt.subplots()

fruits = ["apple", "blueberry", "cherry", "orange"]
counts = [40, 100, 30, 55]
bar_labels = ["red", "blue", "_red", "orange"]
bar_colors = ["tab:red", "tab:blue", "tab:red", "tab:orange"]

ax.bar(fruits, counts, label=bar_labels, color=bar_colors)

ax.set_ylabel("fruit supply")
ax.set_title("Fruit supply by kind and color")
ax.legend(title="Fruit color")

plt.show()

png

Vậy còn biểu đồ có tương tác thì sao, mình có thử plotly để vẽ một ví dụ bằng đoạn code như sau:

import plotly.express as px

df = px.data.gapminder()
px.scatter(
    df,
    x="gdpPercap",
    y="lifeExp",
    animation_frame="year",
    animation_group="country",
    size="pop",
    color="continent",
    hover_name="country",
    log_x=True,
    size_max=55,
    range_x=[100, 100000],
    range_y=[25, 90],
)

Khá là đáng buồn khi nbconvert sẽ không convert được biểu đồ của plotly khi chúng ta sẽ thu được log nói rằng loại mime có tên là application/vnd.plotly.v1+json không được hỗ trợ như sau:

jupyter nbconvert --to markdown --NbConvertApp.output_files_dir=. index.ipynb
[NbConvertApp] Converting notebook index.ipynb to markdown
/Users/niits/miniconda3/share/jupyter/nbconvert/templates/base/display_priority.j2:32: UserWarning: Your element with mimetype(s) dict_keys(['application/vnd.plotly.v1+json']) is not able to be represented.
  {%- elif type == 'text/vnd.mermaid' -%}
[NbConvertApp] Support files will be in ./
[NbConvertApp] Writing 515582 bytes to index.md

Vậy nên biểu đồ dưới đây sẽ không được hiển thị khi convert notebook sang markdown :(

plotly

Một vài thứ khác

Ừ thì hiển thị được biểu đồ của matplotlib cũng khá OK rồi chứ button các thứ của IPython là chắc kèo không có tác dụng rồi. Tuy vậy mình vẫn muốn thử một vài thứ nữa kiểu Audio chẳng hạn. Kết quả thì khá bất ngờ khi nbconvert convert byte data của file audio thành base64, sau đó đặt luôn trong file markdown. Thôi thì méo mó có hơn không, demo file có vài giây chắc cũng không nặng quá đâu :v

from IPython.display import Audio
Audio('https://ccrma.stanford.edu/workshops/mir2014/audio/CongaGroove-mono.wav')

Update thì bằng một cách magic nào đấy Hugo lại không hiển thị thẻ audio ở trên, nói chung là bỏ qua vụ audio cũng được tại nó cũng không cần thiết lắm.

Tổng kết

Ờ thì việc hiển thị notebook có vẻ có hope. Chắc là trong tương lai mình sẽ viết mấy bài nho nhỏ để code các thứ linh tinh. Nội dung thì đến đây là hết rồi nhé chứ chẳng có gì để viết nữa đâu :v