Skip to main content

library-hiroba

Google Colab と PyHiroba で、同じコードが同じように動く教育向けのライブラリです。入口は2つあります。

入口 できること
ui カード・クイズ・進捗バーといった部品を、ノートブックのセル出力に表示します
ai 小さな言語モデルを、その場(ブラウザまたはノートブック)で動かします

PyHiroba は、インストールも登録も必要とせず、ブラウザから Python を学べる、日本の学校現場向けの学習環境です。

from library_hiroba import ai, ui

ui.card("今日の目標", "for文を使って、九九の表を作ってみよう!")
ui.quiz("2の8乗はいくつ?", choices=[128, 256, 512], answer=256,
        explanation="2を8回かけると 256 になるよ。")
# 選択肢を選ぶと色とマークで正誤が表示され、「解説を見る」で解説が開きます

特徴

用意された部品に加えて、HTML と CSS を自由に書けます。教材に必要な見た目の多くは、この2つで作れます。

ui.html('<div class="fukidashi">まずは print() を試してみよう</div>',
        css=".fukidashi { border: 2px solid var(--hui-accent); border-radius: 14px; padding: 10px 16px; }")

CSS が届く範囲はその部品の内側に限られるため、クラス名を気軽に付けてもページの他の部分に影響しません。ふきだし、手順ステップ、単語カード、横棒グラフといった見た目も、この方法で作れます。

そのほかの特徴は次のとおりです。

項目 内容
動作環境 セル最後の式を _repr_html_() で表示する共通のしくみに乗るため、Colab と PyHiroba で表示が一致します
実装方式 表示も操作も HTML と CSS で完結します(クイズの正誤表示は :checked、開閉は <details>
依存関係 ui は純 Python で、依存ライブラリがありません。配布物は py3-none-any の wheel で、Colab の pip でも Pyodide の micropip でも取得できます(ai を Colab で使うときは追加の依存が必要です)
見た目 配色・書体・角丸を PyHiroba 本体のデザインに合わせています
配慮 本文と状態色は WCAG 4.5:1 以上です(アクセント色を塗ったボタンの白文字は 3.87:1 で、UI 部品の基準 3:1 を満たします)。アニメーションは prefers-reduced-motion に従います

インストール

Google Colab と Jupyter:

%pip install library-hiroba

Colab で ai も使うときは、追加の依存(transformers と torch)を含めます。

%pip install "library-hiroba[ai]"

PyHiroba では、同梱されていれば import library_hiroba で使えます。ai の実行はブラウザ側の経路を使うので、追加のインストールは要りません。同梱前の環境では !pip install library-hiroba を実行すると micropip が PyPI から取得します。

部品一覧

部品
説明カード ui.card("今日の目標", "本文", footer="ヒント")
ヒント・注意 ui.alert("メッセージ", kind="warning", title="よくあるまちがい")(kind: info / success / warning / danger
選択式クイズ ui.quiz("問題", choices=[128, 256, 512], answer=256, explanation="解説")answer は値で指定します)
答えの開閉 ui.reveal("答えは42", summary="答えを見る")
進捗バー ui.progress(7, max=10, label="練習問題")
数値タイル ui.stat("正答率", 85, unit="%")
横並び配置 ui.columns(部品1, 部品2, widths=[2, 1])
バッジ ui.badge("重要", color="red")(color: blue / green / red / amber / gray
テーブル ui.table([{"名前": "佐藤", "得点": 90}], caption="結果")
自由 HTML/CSS ui.html('<div class="x">…</div>', css=".x { color: hotpink; }")
入力フォーム ui.form(handler, ui.field("question", label="質問"))
考え中の表示 ui.thinking("考え中")ui.form() が送信中に自動で出します)
会話の表示 ui.chat([{"role": "user", "content": "…"}, {"role": "assistant", "content": "…"}])

複数の部品は次のようにまとめます。

ui.stack(ui.card("目標", "..."), ui.progress(3, max=10))   # 縦に積む
ui.columns(ui.stat("得点", 90), ui.stat("順位", 3))        # 横に並べる

セルの途中で表示したい場合は ui.show(...) を使います。Colab ではその場に表示され、IPython のない PyHiroba では部品を返すので、セル最後の式として置きます。

外部への通信について

部品を表示しても、外部との通信は起きません。書体は PyHiroba と同じ Zen Kaku Gothic New を名前で指定していますが、取りに行くことはしません。PyHiroba ではページ側が読み込み済みのため、これで見た目が揃います。書体を持っていない環境(Colab など)では、端末にある書体で表示されます。

Colab でも同じ書体に揃えたい場合は ui.use_web_font(True) を呼んでください。この場合は表示のたびに Google へ通信が起き、閲覧者の IP アドレスが渡ります。

ai がモデルを受け取るときを除けば、外部へ通信する箇所はありません。

クイズの答えについて

ui.quiz() は JavaScript を使わず、CSS で正誤を表示しています。そのため、答えは出力の HTML に含まれます。ブラウザの「ソースを表示」や検証ツールを開くと読み取れるので、点数をつける試験ではなく、自分で確認するための練習に向いています。

入力を Python に戻す

ui.form() は入力欄とボタンを表示し、押されたときに関数を呼びます。入力欄の名前が、そのままキーワード引数になります。

def ask(question, level):
    return ui.card(question, f"{level} 向けの答えです")

ui.form(ask,
        ui.field("question", label="質問", placeholder="スマホは持っていっていい?"),
        ui.field("level", label="学年", kind="choice", choices=["1年", "2年", "3年"]),
        title="校則について聞いてみよう", submit_label="聞く")

入力欄の種類は text(既定)/ number / multiline / choice です。ui.field の代わりに文字列を渡すと、その名前のテキスト欄になります。

動かし方は環境に合わせて自動で切り替わります。

環境 動作
Colab・Jupyter(ipywidgets あり) テキスト欄とボタンの対話 UI。押すたびに関数が呼ばれます
ipywidgets が無い環境 input() で順に聞いて、結果を表示します
PyHiroba HTML のフォームを表示します。値を受け取るには本体側の対応が必要です(docs/PYHIROBA_FORMS.md に設計をまとめています)

先生が書くコードは1つで済み、環境ごとの切り替えは不要です。

チャット形式にする

ui.chat() は会話を吹き出しで並べます。役割は user / assistant / note の3つで、content には文字列のほか他の部品も入れられます。

会話を変数にためて ui.chat() を返すようにすると、1つのセルでチャットができます。clear_on_submit=True を付けると、送信のたびに入力欄が空になります。

history = []

def ask(question):
    history.append({"role": "user", "content": question})
    history.append({"role": "assistant", "content": f"「{question}」ですね。"})
    return ui.chat(history, names={"user": "あなた", "assistant": "ボット"})

ui.form(ask, ui.field("question", label="質問"),
        submit_label="送信", clear_on_submit=True)

AI(小さな言語モデル)

ai は、小さな言語モデルをその場で動かします。メソッドは4つです。

from library_hiroba import ai

await ai.models()                  # 選べるモデルの一覧
await ai.load()                    # モデルを読み込む(初回は時間がかかります)
print(await ai.ask("日本の四季について、2行で書いて"))

async for chunk in ai.stream("俳句を1つ"):   # 書けたぶんから受け取る
    print(chunk, end="")

await が必要です。ノートブック(Colab / Jupyter / PyHiroba)では、セルの中にそのまま await を書けます。PyHiroba は GitHub Pages 配信のため SharedArrayBuffer を使った同期待ちができず、ブラウザ側は待つ形にせざるを得ません。Colab 側は待つ必要がありませんが、同じコードが両方で動くことを優先して形を揃えています。

ask() には max_tokens を渡せます(既定は 256)。

print(await ai.ask("俳句を1つ作って", max_tokens=64))

動く場所

環境 動かし方 用意するもの
PyHiroba ブラウザの中で動きます(本体が用意した経路を使います) なし
Colab・Jupyter transformerstorch で動きます %pip install "library-hiroba[ai]"

どちらの経路でも、入力した文章が外部に送られることはありません。通信が起きるのは、モデルを受け取るときに限られます。

選べるモデル

load() に名前を渡すとモデルを選べます。

await ai.load("llmjp150m")

軽いものから順に並べています。校内の回線では、右の数字を先に見てください。

名前 内容 目安の通信量(ブラウザ/Colab)
llmjp150m LLM-jp-3 150M。国産でとても軽い一方、文章は不自然です 約 255MB / 約 600MB
qwen3_06 Qwen3 0.6B。qwen05 より新しく、日本語が少し良いです 約 550MB / 約 1.5GB
qwen05(既定) Qwen2.5 0.5B。日本語が使えます 約 900MB / 約 1.0GB
qwen3_17 Qwen3 1.7B。この中でいちばん賢い一方、いちばん重いです 約 1.3GB / 約 3.4GB
qwen15 Qwen2.5 1.5B。日本語がより自然ですが重いです 約 1.6GB / 約 3.1GB

ブラウザ側は同じモデルを精度違いで並べるため qwen05-q8 のように末尾が付いた名前も使えます。精度まで指定したいときはそちらを、そうでなければ上の共通の名前を使ってください。共通の名前はどちらの環境でも通ります。

一覧が短いのは、PyHiroba と Colab の両方で動くものを載せているためです。ブラウザは ONNX に変換されたモデルを読み込むしくみのため、そこが上限になります。増やすときの調べ方は docs/PYHIROBA_INTEGRATION.md の「モデルを増やすとき」にあります。

チャットとして表示する

ui.form()ui.chat() と組み合わせると、1つのセルで対話ができます。

history = []

async def ask(question):
    history.append({"role": "user", "content": question})
    history.append({"role": "assistant", "content": await ai.ask(question)})
    return ui.chat(history, names={"user": "あなた", "assistant": "AI"})

await ai.load()
ui.form(ask, ui.field("question", label="質問"),
        submit_label="送信", clear_on_submit=True)

handlerasync def で書けます。ui.form() は返り値が await の要るものかどうかを見て、必要なら待ってから表示します。送信のたびに会話全体を描き直すので、吹き出しが下に伸びていきます。入力欄は clear_on_submit=True で空に戻ります。

入力を Python に戻す経路は環境によって変わるため、この組み合わせが動くのは今のところ Colab・Jupyter です(PyHiroba は本体側の対応待ちです)。

送信を押すと、答えが返るまで「考え中」の点が動きます。言葉を変えるときは pending="AI が考えています"、出さないときは pending=None を渡してください。

はじめに await ai.load() を済ませておくと、1通目でモデルの読み込み(数十秒〜)を待たされずに済みます。

書けたところから少しずつ出す

ai.stream() は、答えを書けたぶんから返します。handleryield で書くと、届くたびに表示が差し替わります。

history = []

async def talk(question):
    history.append({"role": "user", "content": question})
    text = ""
    async for chunk in ai.stream(question):
        text += chunk
        yield ui.chat(history + [{"role": "assistant", "content": text}],
                      names={"user": "あなた", "assistant": "AI"})
    history.append({"role": "assistant", "content": text})

await ai.load()
ui.form(talk, ui.field("question", label="質問"),
        submit_label="送信", clear_on_submit=True)

ai.stream() を全部つなげると ai.ask() と同じ文になります。少しずつ返せない環境では、書き終えてから一度にまとめて返すため、どちらでも同じコードが動きます。考えている途中(<think>)は、途中で切れても取り除かれます。

モデルのライセンスは配布元をご確認ください(既定の Qwen2.5 は Apache-2.0)。

デザイン

配色・書体・形状は PyHiroba 本体のデザイントークンに合わせています。

項目
ブランドカラー #028DAE(ダーク時 #35aecb
書体 Zen Kaku Gothic New を名前で指定しています。PyHiroba ではページ側が持っているため揃います。持っていない環境では system-ui になります
角丸 カード 14px、行とアラート 8px、バッジと進捗バー 999px
記号 文字記号(i ! ×)を CSS の円形マークに載せて表します

テーマ

既定はライトです。ダークになるのは、祖先要素に data-theme="dark" が付いているとき、すなわち PyHiroba でダークモードに切り替えたときです。OS の配色設定は参照しません。これは PyHiroba 本体と同じ方針で、ページがライト表示のまま部品が暗くなる食い違いを避けるためです。

背景を持つ部品は不透明な色で塗ってあるので、ページの下地が何色でも文字と背景の組み合わせが保たれます。背景を持たない部分(進捗バーのラベルや表のキャプション)はページの文字色を受け継ぎ、暗いページでも読めます。

テーマ変数

配色は CSS カスタムプロパティとして公開しています。ui.html()css から使うと、テーマの切り替えに自動で追従します。

ui.html('<div class="box">ヒント</div>',
        css=".box { border: 2px solid var(--hui-accent); background: var(--hui-accent-soft); }")

主な変数は次のとおりです。

用途 変数
ブランド色 --hui-accent(線・塗り)、--hui-accent-ink(文字)、--hui-accent-soft(背景)
状態色 --hui-ok / --hui-warn / --hui-bad(それぞれ -ink-soft あり)
文字 --hui-ink / --hui-ink-2 / --hui-ink-3--hui-on-accent(アクセント色の上に載せる文字)
--hui-paper / --hui-bg-2 / --hui-line
--hui-radius / --hui-radius-sm / --hui-shadow

しくみと範囲

各部品は、必要な CSS を同梱した自己完結の HTML を返します。同じ CSS が何度出力されても表示は変わりません。渡したテキストはすべて HTML エスケープされ、改行は <br> になります。エスケープしない経路は ui.html() です。

部品の表示と CSS による操作は、どの環境でも同じように動きます。入力を Python に戻す ui.form() は環境によって経路が変わり、PyHiroba では本体側の対応を待っています。

ai も環境によって経路が変わります。PyHiroba では本体が用意した経路を通し、Colab では transformers を使います。書き方は同じですが、動くモデルの実体と読み込みにかかる時間は環境で違います。ui は純 Python のままで、ai を使わないかぎり追加の依存は読み込まれません。

開発

pip install -e ".[dev]"
ruff check src tests tools && pytest        # lint とテスト
python tools/build_gallery.py --shots       # 全部品のギャラリーとスクリーンショットを生成
python tools/check_ai_colab.py              # ai の Colab 経路を実際に動かす([ai] が必要)

ライセンス

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

library_hiroba-0.3.1.tar.gz (91.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

library_hiroba-0.3.1-py3-none-any.whl (42.9 kB view details)

Uploaded Python 3

File details

Details for the file library_hiroba-0.3.1.tar.gz.

File metadata

  • Download URL: library_hiroba-0.3.1.tar.gz
  • Upload date:
  • Size: 91.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for library_hiroba-0.3.1.tar.gz
Algorithm Hash digest
SHA256 4755398dd33d7e6132e60488dea80e46c53b35542db87bd9eb24f0db494654e8
MD5 57ed218eaec7c96247199ff4864748d9
BLAKE2b-256 cc7f4ba98156889be90d8499822cdf540e0c37d985946f36bdce82fad30193e0

See more details on using hashes here.

Provenance

The following attestation bundles were made for library_hiroba-0.3.1.tar.gz:

Publisher: release.yml on funakoshi-takehiro/library-hiroba

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file library_hiroba-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: library_hiroba-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 42.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for library_hiroba-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7d30dcd99941de2bd92213679c911a5e697e43a8a28915e1fa03108ff3c0b295
MD5 7af74db989683f4f83ae692c4419ea0d
BLAKE2b-256 865cea7851ce9bad049af4792c05e3a18223936a56377ad7f31f5265e5ae2809

See more details on using hashes here.

Provenance

The following attestation bundles were made for library_hiroba-0.3.1-py3-none-any.whl:

Publisher: release.yml on funakoshi-takehiro/library-hiroba

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.7.0

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.4

2 files

0.5.3

2 files

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

0.4.0

2 files

0.3.2

2 files

This release

0.3.1 This release

2 files

0.3.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page