「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 Lines 格式,即每行一個 JSON 物件。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(墨量)。 書寫表情符號時可以更換一次毛筆。 |
{"c":"永"} | 宣告接下來要寫的字。此時毛筆會沾墨(沾墨)。若不沾墨,寫作 {"c":"永","no_dip":true}。 |
{"p":[[x,y,…],…]} | 一筆的資料。是點的序列,毛筆依序經過這些點。 |
{"dip":0.6} | 沾墨的量。 |
{"comment":"…"} | 寫完作品後的感想。 |
紙張為直長的半紙,寬 1000 × 高 1376。左上角為 (0, 0),右下角為 (1000, 1376)。
「筆畫」資料的表示
筆畫由點的序列表示,每個點寫作 [x, y, 筆壓, 角度, 速度, 停頓]。不寫或寫 null 即可省略該值。 加入 "k" 則該點成為轉角。
| 值 | 範圍 | 含義 | 省略時 |
|---|---|---|---|
| x, y | 紙張座標 | 筆尖的位置 | (不可省略) |
| 筆壓 | 0〜2 | 毛筆壓入紙面的深度。1 時線寬等於筆的粗細,2 時為兩倍。接近 0 時只有筆尖接觸,線條尖細 | 由前後的點插值(全部省略則為 1) |
| 角度 | 度 | 從筆尖指向筆腹的方向 | 保持前一個點的角度(最初為 42) |
| 速度 | 0.05〜6 | 運筆的速度。1 為每秒「筆的粗細 × 20」 | 由前後的點插值(全部省略則為 1) |
| 停頓 | 秒 | 毛筆在該點停留的時間。越長,墨越濃,輪廓越圓潤鼓脹 | 0 |
| "k" | — | 該點不平滑連接,而是成為轉角(轉折) | 平滑 |
書法引擎用平滑曲線(centripetal Catmull-Rom)連接各點,筆壓、角度、速度也在點與點之間插值。
筆:筆尖與筆腹
毛筆是數百根毛的束(粗細 60 的筆約 300 根,筆越粗越多),形如水滴,筆尖細、筆腹粗。點所在的位置是筆尖, 線條從筆尖沿角度的方向展開,寬度為筆壓 × 筆的粗細。 壓得越深,筆腹越多地落在紙上,線越粗;提起時則收縮回筆尖,線條變細變尖。
角度是筆的傾斜。預設的 42 時,筆腹落在筆尖的右下方(側鋒),粗的部分偏向點的右下方。 當角度與前進方向一致時,筆尖走在線條的中心(中鋒),筆沿筆軸前進,線條較細。 當筆橫切筆軸前進時,線條最粗。
墨:濃淡與墨量
墨由濃淡和墨量兩個值決定,都在毛筆宣告中指定。省略時兩者均為 1,即沾滿濃墨的筆。 這兩個值彼此獨立,組合使用。
墨的濃淡 ink_tone(0〜1)決定顏色的深淺和暈染的難易。1 是濃墨的黑色,調低則變成淡墨的灰色。 淡墨含水多,會向線外暈開,外緣留下一圈略深的水痕。暈染在書寫較慢處更寬,飛白處不會出現。
墨量 ink_load(0.2〜1.5)是毛筆沾的墨量。不改變顏色,只決定是否容易出現飛白。
墨:飛白與停頓
每一根毛都含有墨,隨著在紙上行進而逐漸失去墨。有墨時線條連貫,墨用盡之處則沿著紙的紋理斷開, 形成條狀的飛白。墨量越少、運筆越快、同一個字中越靠後的筆畫,越容易出現飛白。 墨以字為單位({"c":…} 這一行)重新沾取。紙上的墨有雲一般的濃淡不均,飛白並不均勻,而是斑駁地出現。
在筆停住之處(停頓),墨會積聚變濃,輪廓圓潤地暈開。停得越久,暈得越大。 墨越淡,暈得越快。
轉角:轉折
在 "k" 點處,曲線不平滑連接,而是形成轉角。從橫折向豎的地方,在轉角前放慢速度, 在轉角處按住並停頓,改變方向後稍微放鬆筆壓再恢復,轉角處就會留下「肩」。
書法的筆法
sho.js 中沒有針對「鉤」或「撇捺」等筆法的固定處理。與人類的運筆一樣,露鋒、藏鋒、頓、鉤、撇捺、垂露、懸針,都只透過各點的位置與筆壓、角度、速度、停頓的組合來表現。例如撇,是一邊順時針旋轉筆的角度一邊向下行,在左下方先沉下,然後提高速度、放鬆筆壓,向左流出。下面是系統提示詞中示例的「永」字(永字八法)。
對語言模型的要求
僅僅排列座標、描出字的形狀,寫不出好的書法。語言模型需要在每一筆都留意以下幾點,並設計整幅作品。
- 筆的粗細:在整幅作品中選定一支合適的筆。太粗則留白被擠占,太細則書寫顯得瘦弱。
- 筆壓:起筆、行筆、收筆要有輕重變化。只排列筆壓恆定的線條會顯得平板。
- 角度:是側鋒還是中鋒。撇和豎畫的收尾要轉筆。轉筆會改變線寬,要用筆壓來補償。
- 速度與停頓:頓處放慢並停頓,鉤和撇的末端迅速帶出。速度不同,飛白的出法也不同。
- 墨的濃淡與墨量:楷書以濃墨為本。淡墨能帶來柔和與餘韻,墨量略少則可藉飛白寫出有氣勢的書法。
- 筆尖的位置:點是筆尖,而不是線條的中心。側鋒時線條的粗處偏向點的右下,因此要按線條看起來的樣子來考慮字形並落點。
- 筆順與章法:按正確的筆順書寫,並在整張紙中決定字的位置、大小與留白。
亂數由筆的位置決定,所以同樣的資料一定會寫出同樣的書法。作品之間的差異,全部來自語言模型所寫數值的差異。
GitHub
籌備中
參考文獻
- 新装版 書の技法用語100ハンドブック(可成屋書道編輯部 編)
- 脳トレ書道トレーニングブック 書道で長生き!(青山浩之)
- 現代書道全集〈一〉楷書(講談社,1967年)
- 現代書道全集〈二〉行書(講談社,1967年)
- 現代書道全集〈三〉草書(講談社,1967年)
- 現代書道全集〈四〉かな(講談社,1967年)