Comment Kimi K3 a conçu un trait de stylo-plume numérique
On voulait le stylo-plume directionnel de Freeform dans Lulucat Notes. La spécification tenait dans une capture d’écran d’écriture manuscrite. Après deux modèles, une question discriminante et une pointe elliptique, le stylo à eau écrit comme prévu. Kimi K3 s’est occupé de la recherche, du code et de la validation sur Fireworks.

Rendu avec le pipeline Metal de Lulucat Notes dont il est question ici.
Lulucat Notes avait déjà un stylo ordinaire et un surligneur. Le prochain outil prévu était un stylo à eau — le stylo-plume directionnel qu’on connaît dans Apple Notes et Freeform, dont les traits verticaux sont épais et les traits horizontaux minces. La spécification n’était pas un document. C’était une capture d’écran : trois lignes d’écriture manuscrite, les mots « pencilkit », « 无边记 » et « 这种有方向的水笔能力 » — cette capacité de stylo à eau directionnel.
Comme pour le pipeline Metal qui l’avait précédé, Kimi K3, le modèle ouvert de Moonshot qui tourne sur Fireworks, a pris en charge la mesure, la modélisation, le code et la validation. La personne a fourni la capture d’écran, répondu à une question et évalué le résultat sur un vrai iPad.
La spécification est une capture d’écran
Une image statique ne peut pas dire pourquoi un trait est mince. Elle indique seulement à quel point il l’est, et à quel endroit. La première étape a donc été de mesurer. Nous avons balayé la capture d’écran rangée par rangée et colonne par colonne, en suivant le déplacement de la ligne centrale de chaque trait pour en obtenir la direction, puis nous avons transformé la largeur balayée en largeur réelle avec le sinus de cet angle :
| Trait | Direction | Largeur réelle |
|---|---|---|
| Montante du « l » dans « pencilkit » | ≈ 78° | 27.3 px |
| Tige du « k » dans « pencilkit » | ≈ 90° | 28 px |
| Mouvement descendant vers la gauche de 力 | ≈ 66° | 25.7 px |
| Traits de liaison cursifs | ≈ 8° | 11 px |
| Horizontales chinoises (横) | ≈ 0° | 6–11 px |
Le rapport entre le trait épais et le trait mince est d’environ 2.5. En ajustant
Version un : la largeur selon la direction
Le premier modèle était le choix évident. Il calculait une direction pour chaque point reçu, convertissait cette direction en largeur avec la courbe ajustée, puis inscrivait le résultat dans le rayon du point au moment de la capture. La direction était estimée de façon causale — une moyenne pondérée à décroissance exponentielle des derniers points de l’arc, calculée dans l’espace des angles doublés pour qu’un renversement du déplacement n’annule pas le résultat. Comme seuls les points précédents sont utilisés, le trait en cours et le trait confirmé correspondent octet par octet.
Le générateur a réussi sa vérification d’unités : les parcours synthétiques horizontal, vertical, à 45° et inversé ont donné les largeurs théoriques — 0.99, 2.52, 2.00 et 0.99 points. Le rendu ne demandait aucun nouveau code : un trait dont le rayon est précalculé n’est qu’une suite de tampons ronds, et notre pipeline de point-sprite les dessinait déjà.
Sur l’iPad, la personne l’a rejeté en une dizaine de secondes : « c’est un stylo artistique, pas le stylo à eau ».
Une image, deux interprétations
Pourquoi le résultat ne fonctionnait-il pas ? Deux interprétations pouvaient expliquer l’image, et la capture d’écran ne permettait pas de les départager :
- Verrouillage directionnel. La géométrie de la pointe force les horizontales à rester minces et les verticales à être épaisses, peu importe le geste de la main. C’est ce que faisait la version un.
- Pression et vitesse. Le stylo réagit à la pression, et le motif observé n’est que la dynamique de l’écriture manuscrite : les traits descendants sont naturellement appuyés, tandis que les liaisons sont naturellement rapides et légères.
Les deux explications produisent une capture avec des horizontales minces et des verticales épaisses. La différence se révèle quand on appuie fort sur un trait horizontal. La version un le garde mince. Un stylo sensible à la pression l’épaissit. Nous avons donc posé une question à la personne : un trait horizontal sur lequel on appuie fort devrait-il devenir plus épais ?
« Non. Les horizontales restent minces. »
Le verrouillage directionnel était confirmé. Mais il y avait autre chose, puisque la version un était elle aussi verrouillée selon la direction.
La réponse se trouvait dans les bouts du trait
L’indice suivant se trouvait en haut des montantes. En agrandissant les tiges du « l » et du « k » dans l’échantillon, on a constaté deux choses : un trait droit garde la même largeur d’un bout à l’autre, et ses extrémités sont des coupes diagonales plates, comme la pointe biseautée d’un stylo quand elle quitte la surface. Pas des points ronds. Pas de rétrécissement dû à la pression.

Voilà ce que voulait vraiment dire la « sensation de stylo artistique ». La version un reproduisait l’apparence de l’échantillon — la largeur en fonction de la direction estimée — mais pas le stylo. Un estimateur de direction est un capteur : il oscille avec une entrée bruitée, accuse un retard dans les coins et arrondit chaque extrémité de trait en cercle. Une vraie pointe n’a aucun de ces problèmes, parce qu’elle ne calcule rien. La largeur est une propriété géométrique.
Version deux : une pointe elliptique
Le modèle final n’utilise aucun estimateur de direction. La pointe est une ellipse orientée : son grand axe est horizontal et son petit axe reste fixe. On place densément des tampons elliptiques le long du chemin du trait, puis la géométrie fait le reste :
-
Un trait horizontal longe le bord ouvert, et sa largeur est donc toujours
— une ligne mince et constante, quelle que soit la pression. C’est exactement la spécification confirmée. -
Un trait vertical traverse tout le grand axe :
, l’extrémité épaisse. -
Un trait diagonal prend la largeur de la corde de l’ellipse perpendiculairement au déplacement,
-
Les extrémités du trait sont des coupes elliptiques — les bouts plats en forme de pointe de l’échantillon, sans effort supplémentaire.
-
La pression ne fait varier que le grand axe,
, ce qui ajoute du volume d’encre aux traits descendants sans pouvoir épaissir une horizontale.
À partir des mesures de l’échantillon, nous avons gardé
Le rendu nécessitait un seul nouveau fragment shader, rien de plus. Le format de sommet — position, diamètre, couleur — transportait déjà toutes les données : le diamètre est le grand axe et le petit axe est un uniform par passe. Le shader évalue une SDF d’ellipse avec la même rampe de couverture d’un demi-pixel que nos tampons ronds, ce qui le rend comparable au pixel près à l’implémentation de référence de Core Graphics (fillEllipse par tampon). La validation a suivi la vérification habituelle : un corpus synthétique contenant deux traits de stylo-plume, rendu des deux manières puis comparé pixel par pixel — aucune différence structurelle, et un trait horizontal vérifié au hasard mesurait 12 px dans les deux moteurs.

La version un à gauche, la version deux à droite. Même entrée manuscrite, même pipeline. Les bouts racontent toute l’histoire.
Sur l’iPad, le nouveau stylo a passé le test du premier coup : « 好,很好 » — Bon. Très bon.
Garder l’essai manqué
La version un n’a pas été jetée. C’est un pinceau intéressant en soi ; ce n’est simplement pas un stylo à eau. Il a donc été livré comme première entrée d’un nouveau menu de pinceaux expérimentaux, sous le nom que la personne lui avait donné : 漏水的圆珠笔, le stylo-bille qui fuit. La barre d’outils a reçu un bouton en forme de fiole qui ouvre une liste textuelle d’expériences ; ajouter la prochaine ne coûte qu’une ligne dans un registre. Un modèle rejeté n’est pas du travail perdu s’il peut devenir une expérience clairement étiquetée.
Une soirée de boucles
Le cycle complet — mesurer, modéliser, construire, essayer sur l’appareil, poser une question, remodéliser, reconstruire, valider — a pris une soirée. Kimi K3 sur Fireworks a mené toute la partie technique : concevoir les balayages de mesure, proposer la question discriminante au lieu de deviner une deuxième fois, supprimer son propre estimateur de direction quand les faits ont changé et étendre le harnais de comparaison de pixels avant de toucher à l’appli. La vitesse d’inférence de Fireworks a gardé la boucle interactive : les longs diffs de Metal et de Swift, les scripts d’analyse de pixels et les outils de corpus arrivaient assez vite pour que le dernier goulot d’étranglement soit le jugement humain.
Le mode de collaboration était le même que dans l’article sur le pipeline Metal, et il s’est encore confirmé : le modèle est rapide et précis ; la personne garde le sens esthétique et la vérification de bout en bout. Une seule phrase de rétroaction sur la sensation — « stylo artistique, pas stylo à eau » — a suffi pour que le modèle trouve l’erreur exacte de modélisation et la remplace par une conception plus simple.
Le bon modèle s’est révélé plus petit que le mauvais. La version deux a été livrée avec moins de pièces mobiles que la version un — pas d’estimateur, pas de fenêtre de lissage, pas d’exposant ajusté. La pointe ne calcule pas la largeur. La pointe est la largeur.