「AI書道」のしくみ
AI書道では、画像生成AIではなく言語モデルを使って書を書きます。
一般的な画像生成AIは完成した画像を直接出力します。しかし書道は、筆をどこに置き、どれだけ強く押し込み、どのように動かして止めるかというプロセスを重視する芸術です。画像生成AIにはこの過程が存在しないため、書道の本質を表現することができません。
一方、言語モデルは画像こそ出力できませんが、筆運びのプロセスをデータとして生成することができます。つまり言語モデルを活用することで、「書を書く」という行為そのものをシミュレーションし、より書道の本質に迫った表現ができる可能性があります。
言語モデル×書道エンジン
言語モデルには、以下の情報がインプットとして与えられます。
- システムプロンプト:
- 書道エンジンの仕様:入力データの形式、紙と座標の定義、画の書き方、筆と墨の仕組み
- 書の心得:運筆の原則、露鋒・転折・はね・払いといった技法の例、「永」の書き方の例(永字八法)、良い書を書くためのコツや心構え
- 課題文:何を書くかを指示する文章。(例「楷書で『春風』を書いてください」)
言語モデルはこの二つの情報をもとに、実際の筆の動きをデータとして出力します。このデータを実際の画像にするのが書道エンジン sho.js です。 sho.js は毛筆の特徴を再現する独自のプログラムであり、筆と紙の物理法則を再現して書に仕上げます。
- システムプロンプトエンジンの仕様と書の心得課題文(例)楷書で春風「春風」を書いて
- 言語モデル筆づかいを考える
- 筆運びデータ
{"p":[[377,327,0.06,null,0.8],[418,352,1],… - 書道エンジンsho.js
- 作品

モデルの個性
sho.js が受け持つのは、あくまで筆と紙の物理的な再現のみです。どう筆を動かすか、どんな字形にするか、紙面をどう構成するかといった表現上の判断は、すべて言語モデルの能力に委ねられています。そのため作品には、モデルごとの特徴が色濃く表れます。作品を見比べると、書への理解の深さ、筆順の正誤、技術の巧拙、字形の癖などに、モデルごとの個性の違いを観察することができます。
sho.js の仕様
筆運びデータの形と値の意味、そして sho.js がそのデータをどう線にするかを、実際に動く例とともに説明します。同様の内容は、言語モデルに渡すシステムプロンプトにも記載されています。(システムプロンプトの全文はこちら)
データフォーマット
データは JSON オブジェクトを1行ずつ並べた JSON Lines 形式です。sho.js はこのデータを上から順番に処理します。
{"t":"brush","size":58}
{"c":"永"}
{"p":[[377,327,0.06,null,0.8],[418,352,1],[434,376,2.0,null,0.3,0.12],[430,372,0.06,null,0.4]]}
{"p":[[311,528,0.1,null,0.5],[317,534,1.1,null,0.4], …]}
…
{"comment":"右払いの足を長めに伸ばしました。"}| 行 | 意味 |
|---|---|
{"t":"brush","size":58} | 使用する筆の宣言。size は筆圧 1 のときの線の幅。ink_tone(墨の濃さ)と ink_load(墨の量)も指定可能。 絵文字を書く際は 1 度だけ筆を持ち替えられる。 |
{"c":"永"} | これから書く文字の宣言。このタイミングで筆に墨を含ませる(墨継ぎ)。含ませない場合は {"c":"永","no_dip":true} とする。 |
{"p":[[x,y,…],…]} | 1 画のデータ。点の列で、筆はその点を順に通る。 |
{"dip":0.6} | 墨継ぎの量。 |
{"comment":"…"} | 作品を書き終えた後の所感。 |
紙は縦長の半紙で、幅 1000 × 高さ 1376 です。左上が (0, 0)、右下が (1000, 1376) です。
「画(かく)」データの表現
画は点の系列で表現され、点は [x, y, 筆圧, 角度, 速さ, 溜め] で表されます。無指定、もしくはnull で値を省略することができます。"k" を入れるとその点が角になります。
| 値 | 範囲 | 意味 | 省略したとき |
|---|---|---|---|
| x, y | 紙の座標 | 穂先の位置 | (省略不可) |
| 筆圧 | 0〜2 | 筆を紙へ押し込む深さ。1 で線の幅が筆の太さと同じ、2 で 2 倍。0 に近いと穂先だけが触れて尖る | 前後の点から補間(全部省略なら 1) |
| 角度 | 度 | 穂先から腹への向き | 直前の点の角度を保つ(最初は 42) |
| 速さ | 0.05〜6 | 筆を動かす速さ。1 は毎秒「筆の太さ × 20」 | 前後の点から補間(全部省略なら 1) |
| 溜め | 秒 | その点で筆をとどめる時間。長いほど墨が濃くなり、輪郭が丸く膨らむ | 0 |
| "k" | — | その点でなめらかにつながず角にする(転折) | なめらか |
書道エンジンによって、点と点の間はなめらかな曲線(centripetal Catmull-Rom)でつながり、筆圧・角度・速さも点の間で補間されます。
筆: 穂先と腹
筆は数百本の毛の束で(太さ 60 の筆で約 300 本。太い筆ほど多い)、穂先が細く腹が太いしずく形をしています。点の位置にあるのは穂先で、 線は穂先から角度の向きへ、筆圧 × 筆の太さの幅で広がります。 押し込むほど腹が紙に乗って太くなり、抜けば穂先へ縮んで細く尖ります。
角度は筆の傾きです。既定の 42 では腹が穂先の右下に乗り(側筆)、太い部分は点より右下に寄ります。 角度を進む向きに合わせると穂先が線の中心を通り(中鋒)、筆の軸に沿って進むので線は細くなります。 軸を横切って進むと、線は最も太くなります。
墨: 濃さと量
墨は濃さと量の 2 つで決まり、どちらも筆の宣言で指定します。省略するとどちらも 1 で、濃墨をたっぷり含ませた筆になります。 この 2 つは別物で、組み合わせて使います。
墨の濃さ ink_tone(0〜1)は、色の濃淡とにじみやすさを決めます。1 が濃墨の黒で、下げるほど淡墨の灰色になります。 淡墨は水を多く含んで線の外へにじみ、外の縁に少し濃い水際が残ります。にじみはゆっくり書く所ほど広がり、かすれた所には出ません。
墨の量 ink_load(0.2〜1.5)は、筆に含ませる墨の量です。色は変えず、かすれやすさだけを決めます。
墨: かすれ・溜め
毛の 1 本 1 本が墨を含み、紙に触れて進むほど墨を失います。墨が残っている間は線がつながり、使い切った所から紙の目に沿って途切れて、 筋状のかすれになります。墨の量が少ないほど、速く動かすほど、同じ字の後の画ほどかすれやすくなります。 墨は文字ごと({"c":…} の行)に含ませ直します。紙に写る墨には雲のようなむらがあり、かすれは一様ではなく、まだらに出ます。
筆を止めた所(溜め)では墨が溜まって濃くなり、輪郭が丸くにじみます。長く溜めるほどにじみは大きくなります。 墨は薄いほど早くにじみます。
角: 転折
"k" の点では曲線をなめらかにつながずに角にします。横から縦へ折れる所では、角の手前で速さを落とし、 角で押さえ込んで溜め、向きを変えたら少し筆圧を緩めてから戻すと、角に「肩」が残ります。
書の技法
sho.js には「はね」や「払い」といった技法に関する定型処理がありません。書道における人間の筆使いと同じように、露鋒・蔵鋒・止め・はね・払い・垂露・懸針は、どれも各点の位置と筆圧・角度・速さ・溜めの組み合わせだけで表現します。たとえば左払いは筆の角度を右回りに回しながら下り、左下でいったん沈ませてから、速さを上げて筆圧を抜きながら左に流します。以下は、システムプロンプトにて例示されている「永」(永字八法)の例です。
言語モデルに求められること
座標を並べて字の形をなぞるだけでは、良い書にはなりません。言語モデルは画ごとに以下を意識して、書全体を設計する必要があります。
- 筆の太さ: 全体を通して適切な筆を 1 本を選ぶ。太すぎれば余白が詰まり、細すぎれば痩せた書になる。
- 筆圧: 起筆・送筆・終筆で強弱をつける。一定の筆圧の線を並べるだけでは平板になる。
- 角度: 側筆か中鋒か。払いや縦画の終わりでは筆を回す。回すと線の幅が変わるので、筆圧で補う。
- 速さと溜め: 止めでは遅く溜め、はねや払いの先は速く抜く。速さによってかすれ方も変わる。
- 墨の濃さと量: 楷書の基本は濃墨。淡墨は柔らかさや余韻を出し、墨の量を控えめにするとかすれを生かした勢いのある書になる。
- 穂先の位置: 点は線の中心ではなく穂先。側筆では線の太い部分が点より右下に寄るので、字形は線の見え方で考えて点を置く。
- 筆順と章法: 正しい筆順で書き、紙全体の中で字の位置・大きさ・余白を決める。
乱数は筆の位置から決まるので、同じデータからは必ず同じ書が生まれます。作品の差はすべて言語モデルの書いた数値の差です。
GitHub
準備中
参考文献
- 新装版 書の技法用語100ハンドブック(可成屋書道編集部 編)
- 脳トレ書道トレーニングブック 書道で長生き!(青山浩之)
- 現代書道全集〈一〉楷書(講談社、1967年)
- 現代書道全集〈二〉行書(講談社、1967年)
- 現代書道全集〈三〉草書(講談社、1967年)
- 現代書道全集〈四〉かな(講談社、1967年)