Sådan udviklede Kimi K3 på egen hånd et digitalt fyldepenstrøg
Vi ville have Freeforms retningsstyrede fyldepen i Lulucat Notes. Specifikationen var et skærmbillede af håndskrift. Efter to modeller, ét afgørende spørgsmål og en ellipsepen skriver vandpennen, som den skal. Kimi K3 stod for undersøgelsen, koden og valideringen på Fireworks.

Gengivet af den Lulucat Notes Metal-pipeline, som dette indlæg handler om.
Lulucat Notes har en almindelig pen og en overstregningstusch. Det næste værktøj på roadmapet var en vandpen — den retningsstyrede fyldepen, du kender fra Apple Notes og Freeform, hvor lodrette strøg bliver tykke, og vandrette bliver tynde. Specifikationen for værktøjet var ikke et dokument. Den var et skærmbillede: tre linjer håndskrift, ordene »pencilkit«, »无边记« og »这种有方向的水笔能力« — denne retningsstyrede vandpen-funktion.
Ligesom med Metal-pipelinen før den blev arbejdet udført af Kimi K3, Moonshots åbne model, der kører på Fireworks: måling, modellering, kode og validering. Mennesket leverede skærmbilledet, besvarede ét spørgsmål og vurderede følelsen på en rigtig iPad.
Specifikationen er et skærmbillede
Et statisk billede kan ikke fortælle dig, hvorfor et strøg er tyndt. Det kan kun fortælle, hvor tyndt det er, og hvor det er. Derfor var første skridt at måle. Vi scannede skærmbilledet række for række og kolonne for kolonne, fulgte midterlinjens afvigelse for hvert strøg for at finde dets retning og omregnede derefter scanbredden til den faktiske bredde ved hjælp af sinus til den vinkel:
| Strøg | Retning | Faktisk bredde |
|---|---|---|
| »l«-ascender, »pencilkit« | ≈ 78° | 27.3 px |
| »k«-stamme, »pencilkit« | ≈ 90° | 28 px |
| Venstrefaldende sweep i 力 | ≈ 66° | 25.7 px |
| Forbindelser i den løbende skrift | ≈ 8° | 11 px |
| Kinesiske vandrette strøg (横) | ≈ 0° | 6–11 px |
Forholdet mellem tykt og tyndt er ≈ 2.5. Når
Version et: bredde fra retning
Den første model var den oplagte. Beregn en retning for hvert inputpunkt, omsæt retningen til bredde gennem den tilpassede kurve, og indbyg resultatet i punktets radius ved optagelsen. Retningen blev estimeret kausalt — et eksponentielt aftagende vægtet gennemsnit over de seneste få punkter på buen, beregnet i dobbeltvinkelrummet, så en vending i bevægelsen ikke ophæver estimatet. Der bruges kun tidligere punkter, så det levende strøg og det fastgjorte strøg stemmer overens byte for byte.
Builderen bestod sit unit check: syntetiske vandrette, lodrette, 45°- og vendte baner indbyggede alle de teoretiske bredder — 0.99, 2.52, 2.00 og 0.99 point. Rendering krævede ingen ny kode overhovedet: Et strøg med indbygget radius er blot en kæde af runde aftryk, og vores point-sprite-pipeline tegnede allerede dem.
På iPad tog det mennesket omkring ti sekunder at afvise det: »det her er en kunstpen, ikke vandpennen«.
To forklaringer passer på ét billede
Hvorfor føltes det forkert? Der var to mulige forklaringer, og skærmbilledet kunne ikke skelne mellem dem:
- Retningslås. Spidsens geometri tvinger vandrette strøg til at være tynde og lodrette til at være tykke, uanset hvad hånden gør. Det var det, version et implementerede.
- Tryk og hastighed. Pennen er trykstyret, og prøvens mønster er blot håndskriftens dynamik: nedstrøg er naturligt trykkede, mens forbindelser naturligt er hurtige og lette.
Begge forklaringer giver et skærmbillede med tynde vandrette og tykke lodrette strøg. Forskellen er, hvad der sker, når du trykker hårdt på et vandret strøg. Version et holder det tyndt. En trykpen gør det tykt. Derfor stillede vi mennesket ét spørgsmål: Skal et vandret strøg, som der trykkes hårdt på, blive tykkere?
»Nej. Vandrette strøg forbliver tynde.«
Retningslåsen var bekræftet. Men noget andet var stadig galt, for version et var også retningslåst.
Svaret lå i strøgenes ender
Det næste spor var øverst på ascenderne. Da vi zoomede ind på »l«- og »k«-stammerne i prøven, viste der sig to ting: Et lige strøg holder samme bredde fra start til slut, og strøgenes ender er flade diagonale snit — formen af en mejselspids, der løfter sig. Ikke runde prikker. Ikke trykudtynding.

Det var det, »kunstpen-følelse« faktisk betød. Version et modellerede prøvens udseende — bredde som en funktion af den estimerede retning — men ikke pennen. En retningsestimator er en sensor: den sitrer ved støjfyldt input, halter efter ved hjørner og gør hver strøgafslutning til en cirkel. En rigtig spids har ingen af disse problemer, fordi den ikke beregner noget. Bredden er geometri.
Version to: en ellipsepen
Den endelige model har ingen retningsestimator. Spidsen er en orienteret ellipse: den lange akse er vandret, den korte akse er fast. Aftryk af ellipsen placeres tæt langs strøgets bane, og alt andet følger af geometrien:
-
Et vandret strøg bevæger sig langs den åbne kant, så det altid bliver
bredt — en konstant tynd linje ved ethvert tryk. Præcis den bekræftede specifikation. -
Et lodret strøg krydser hele den lange akse:
, den tykke ende. -
Et diagonalt strøg får ellipsens kordebredde vinkelret på bevægelsesretningen,
-
Strøgenes ender er elliptiske snit — de flade, spidsformede ender fra prøven, uden ekstra arbejde.
-
Tryk skalerer kun den lange akse,
, så tryk giver mere blækvolumen i nedstrøg og aldrig kan gøre et vandret strøg tykkere.
Ud fra prøvens målinger beholdt vi
Rendering krævede én ny fragment shader og intet andet. Vertexformatet — position, diameter, farve — indeholdt allerede alt: diameteren er den lange akse, og den korte akse er en uniform pr. gennemløb. Shaderen evaluerer en ellipse-SDF med den samme halvpixel-dækningsrampe som vores runde aftryk, hvilket gør den pixel-sammenlignelig med Core Graphics-referenceimplementeringen (fillEllipse pr. aftryk). Valideringen gik gennem den sædvanlige kontrol: et syntetisk corpus med to fyldepenstrøg, gengivet på begge måder og sammenlignet pixel for pixel — nul strukturelle forskelle, og et stikprøvekontrolleret vandret strøg målte 12 px i begge renderere.

Version et til venstre, version to til højre. Samme håndskrevne input, samme pipeline. Enderne fortæller historien.
På iPad bestod den nye pen med det samme: »好,很好« — godt. Meget godt.
At beholde fejlen
Version et endte ikke i skraldespanden. Det er en interessant pensel — den er bare ikke en vandpen. Derfor blev den udgivet som det første punkt i en ny menu med eksperimentelle pensler under det navn, mennesket gav den: 漏水的圆珠笔, den lækkende kuglepen. Værktøjslinjen fik en kolbeknap, der åbner en tekstliste med eksperimenter; at tilføje det næste koster én linje i en registry. En afvist model er ikke spildt arbejde, når den kan udgives som et tydeligt mærket eksperiment.
En aften med loops
Hele forløbet — mål, modelér, byg, afprøv på enhed, spørg, remodelér, ombyg, validér — tog én aften. Kimi K3 på Fireworks skrev ikke bare kode; den kørte hele loopets tekniske side: fandt på målescanningerne, foreslog det afgørende spørgsmål i stedet for at gætte endnu en gang, slettede sin egen retningsestimator, da evidensen vendte, og udvidede pixel-diff-harnessen, før den rørte appen. Fireworks’ inferenshastighed holdt loopet interaktivt — lange Metal- og Swift-diffs, scripts til pixelanalyse og corpus-værktøjer kom hurtigt nok til, at flaskehalsen blev, hvor den hører hjemme: menneskets vurdering.
Samarbejdsmønstret var det samme, som vi skrev om i indlægget om Metal-pipelinen, og det holdt igen: modellen er hurtig og præcis; mennesket ejer smag og end-to-end-verifikation. Én sætning med feedback om følelsen — »kunstpen, ikke vandpen« — var nok til, at modellen fandt den præcise modelleringsfejl og erstattede den med et enklere design.
Den rigtige model viste sig at være mindre end den forkerte. Version to blev udgivet med færre bevægelige dele end version et — ingen estimator, intet udglatningsvindue, ingen tilpasset eksponent. Spidsen beregner ikke bredden. Spidsen er bredden.