“AI书法”的原理

AI书法不使用图像生成 AI,而是用语言模型来书写书法。

一般的图像生成 AI 直接输出完成的图像。然而书法是一门重视过程的艺术:笔落在何处、按下多重、如何运行又如何收住。图像生成 AI 没有这一过程,因此无法表现书法的本质。
而语言模型虽然无法输出图像,却能把运笔的过程生成为数据。也就是说,借助语言模型,可以模拟“书写”这一行为本身,有可能做出更接近书法本质的表现。

语言模型 × 书法引擎

语言模型会收到以下信息作为输入。

语言模型根据这两项信息,把实际的运笔输出为数据。把这些数据变成实际图像的,是书法引擎 sho.js。sho.js 是再现毛笔特性的原创程序,通过再现毛笔与纸张的物理规律来完成书法作品。

  1. 系统提示词引擎规格与书法心得
    题目文本(例)用楷书写“春風”
  2. 语言模型构思运笔
  3. 运笔数据{"p":[[377,327,0.06,null,0.8],[418,352,1],…
  4. 书法引擎sho.js
  5. 作品

模型的个性

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 根,笔越粗越多),形如水滴,笔尖细、笔腹粗。点所在的位置是笔尖, 线条从笔尖沿角度的方向展开,宽度为笔压 × 笔的粗细。 压得越深,笔腹越多地落在纸上,线越粗;提起时则收缩回笔尖,线条变细变尖。

只改变笔压的 3 条线(从上到下为 0.4、1、1.8)。同一支笔,压入的深度不同,线宽也随之改变。

角度是笔的倾斜。默认的 42 时,笔腹落在笔尖的右下方(侧锋),粗的部分偏向点的右下方。 当角度与前进方向一致时,笔尖走在线条的中心(中锋),笔沿笔轴前进,线条较细。 当笔横切笔轴前进时,线条最粗。

笔压 1.2,只改变角度的 3 条线(从上到下为 42、0、90)。向右行进的线,角度 0 沿行进方向,所以细;90 横切,所以粗。

墨:浓淡与墨量

墨由浓淡和墨量两个值决定,都在毛笔声明中指定。省略时两者均为 1,即蘸满浓墨的笔。 这两个值彼此独立,组合使用。

墨的浓淡 ink_tone(0〜1)决定颜色的深浅和洇染的难易。1 是浓墨的黑色,调低则变成淡墨的灰色。 淡墨含水多,会向线外洇开,外缘留下一圈略深的水痕。洇染在书写较慢处更宽,飞白处不会出现。

浓淡 1
浓淡 0.5
浓淡 0.2

墨量 ink_load(0.2〜1.5)是毛笔蘸的墨量。不改变颜色,只决定是否容易出现飞白。

墨量 1
墨量 0.4

墨:飞白与停顿

每一根毛都含有墨,随着在纸上行进而逐渐失去墨。有墨时线条连贯,墨用尽之处则沿着纸的纹理断开, 形成条状的飞白。墨量越少、运笔越快、同一个字中越靠后的笔画,越容易出现飞白。 墨以字为单位({"c":…} 这一行)重新蘸取。纸上的墨有云一般的浓淡不均,飞白并不均匀,而是斑驳地出现。

只改变速度的 3 条线(从上到下为 0.5、2、5)。越快,飞白越呈条状。

在笔停住之处(停顿),墨会积聚变浓,轮廓圆润地洇开。停得越久,洇得越大。 墨越淡,洇得越快。

淡墨(浓淡 0.5)的线条,只改变中间一点的停顿的 3 条线(从上到下为 0 秒、0.15 秒、1.2 秒)。停得越久,墨积得越圆。

转角:转折

在 "k" 点处,曲线不平滑连接,而是形成转角。从横折向竖的地方,在转角前放慢速度, 在转角处按住并停顿,改变方向后稍微放松笔压再恢复,转角处就会留下“肩”。

从横折向竖的一笔。在转角点加入 "k",在转角处留下“肩”。

书法的笔法

sho.js 中没有针对“钩”或“撇捺”等笔法的固定处理。与人类的运笔一样,露锋、藏锋、顿、钩、撇捺、垂露、悬针,都只通过各点的位置与笔压、角度、速度、停顿的组合来表现。例如撇,是一边顺时针旋转笔的角度一边向下行,在左下方先沉下,然后提高速度、放松笔压,向左流出。下面是系统提示词中示例的“永”字(永字八法)。

“永”。侧、勒、努、趯、策、掠、啄、磔八种笔法,全部只用点的信息写成。

对语言模型的要求

仅仅排列坐标、描出字的形状,写不出好的书法。语言模型需要在每一笔都留意以下几点,并设计整幅作品。

随机数由笔的位置决定,所以同样的数据一定会写出同样的书法。作品之间的差异,全部来自语言模型所写数值的差异。

GitHub

筹备中

参考文献

Published: 2026-11-02 12:00 JST
AI书法大赛组委会(@enpitsu)
“AI书法”的原理|AI书法大赛