Hur Kimi K3 på egen hand byggde ett digitalt reservoarpennstreck
Vi ville ha Freeforms riktade reservoarpenna i Lulucat Notes. Specifikationen var en skärmbild av handskrift. Två modeller, en avgörande fråga och en elliptisk pennspets senare skriver vattenpennan som den ska. Forskningen, koden och valideringen gjordes av Kimi K3 på Fireworks.

Renderat av Lulucat Notes Metal-pipeline som det här inlägget handlar om.
Lulucat Notes har en vanlig penna och en överstrykningspenna. Nästa verktyg på roadmapen var en vattenpenna — den riktade reservoarpenna du känner igen från Apple Notes och Freeform, där vertikala streck blir tjocka och horisontella tunna. Specifikationen för verktyget var inget dokument. Den var en skärmbild: tre rader handskrift, orden “pencilkit”, “无边记” och “这种有方向的水笔能力” — den här riktade vattenpennsfunktionen.
Precis som med den tidigare Metal-pipelinen gjordes arbetet av Kimi K3, Moonshots öppna modell som körs på Fireworks: mätningarna, modelleringen, koden och valideringen. Människan levererade skärmbilden, svarade på en fråga och bedömde känslan på en riktig iPad.
Specifikationen är en skärmbild
En statisk bild kan inte tala om varför ett streck är tunt. Den kan bara visa hur tunt det är och var. Därför var det första steget att mäta. Vi skannade skärmbilden rad för rad och kolumn för kolumn, följde varje strecks förskjutning från mittlinjen för att få dess riktning och omvandlade sedan skanningsbredden till verklig bredd med sinus för den vinkeln:
| Streck | Riktning | Verklig bredd |
|---|---|---|
| “l”:s uppåtgående stapel, “pencilkit” | ≈ 78° | 27.3 px |
| “k”:s stapel, “pencilkit” | ≈ 90° | 28 px |
| Vänsterfallande svep i 力 | ≈ 66° | 25.7 px |
| Kursiva förbindelser | ≈ 8° | 11 px |
| Kinesiska horisontaler (横) | ≈ 0° | 6–11 px |
Förhållandet tjockt-till-tunt är ≈ 2.5. Att anpassa
Version ett: bredd från riktning
Den första modellen var den uppenbara. Beräkna en riktning för varje indatapunkt, mappa riktningen till bredd genom den anpassade kurvan och baka in resultatet i punktens radie vid infångningen. Riktningen uppskattades med en exponentiellt avklingande viktad medelbild över de senaste bågpunkterna, beräknad i dubbelvinkelrum så att en vändning av färdriktningen inte skulle ta ut uppskattningen. Bara tidigare punkter används, så det levande strecket och det fastställda strecket stämmer överens byte för byte.
Buildern klarade sitt enhetstest: syntetiska horisontella, vertikala, 45°- och vändningsbanor bakade alla in de teoretiska bredderna — 0.99, 2.52, 2.00 och 0.99 punkter. Renderingen behövde ingen ny kod alls: ett streck med inbakad radie är bara en kedja av runda stämplar, och vår point-sprite-pipeline ritade redan sådana.
På iPad tog det människan ungefär tio sekunder att förkasta den: “det här är en konstpenna, inte vattenpennan”.
Två berättelser passar samma bild
Varför kändes den fel? Det fanns två möjliga förklaringar, och skärmbilden kunde inte skilja dem åt:
- Riktningslås. Spetsens geometri tvingar horisontalerna att vara tunna och vertikalerna tjocka, oavsett vad handen gör. Det var vad version ett implementerade.
- Tryck och hastighet. Pennan är tryckstyrd, och mönstret i provet är bara handskriftens dynamik: nedåtgående streck trycks naturligt hårdare, medan förbindelserna naturligt är snabba och lätta.
Båda förklaringarna ger en skärmbild med tunna horisontaler och tjocka vertikaler. Skillnaden är vad som händer när du trycker hårt på ett horisontellt streck. Version ett håller det tunt. En tryckpenna gör det tjockt. Så vi ställde människan en fråga: ska ett hårt pressat horisontellt streck bli tjockare?
“Nej. Horisontalerna förblir tunna.”
Riktningslåset var bekräftat. Men något annat var fel, för version ett var också riktningslåst.
Svaret fanns i streckändarna
Nästa ledtråd fanns högst upp på de uppåtgående strecken. När vi zoomade in på “l”- och “k”-staplarna i provet syntes två saker: ett rakt streck behåller samma bredd från början till slut, och streckändarna är platta diagonala snitt — formen av en mejselspets som lyfter från pappret. Inte runda prickar. Inte tryckavsmalningar.

Det var vad “konstpennskänsla” faktiskt betydde. Version ett modellerade provets utseende — bredd som en funktion av den uppskattade riktningen — men inte pennan. En riktningsuppskattare är en sensor: den skakar vid brusig indata, släpar efter i hörn och rundar varje streckände till en cirkel. En riktig spets har inga av dessa problem, eftersom den inte beräknar något. Bredden är geometri.
Version två: en elliptisk spets
Den slutliga modellen har ingen riktningsuppskattare alls. Spetsen är en orienterad ellips: långaxeln är horisontell och kortaxeln är fast. Stämplar av ellipsen placeras tätt längs streckets bana, och allt annat följer av geometrin:
-
Ett horisontellt streck färdas längs den öppna kanten, så det blir alltid
brett — en konstant tunn linje vid vilket tryck som helst. Exakt den bekräftade specifikationen. -
Ett vertikalt streck korsar hela långaxeln:
, den tjocka änden. -
Ett diagonalt streck tar ellipsens ackordbredd vinkelrätt mot färdriktningen,
-
Streckändarna är elliptiska snitt — de platta spetsformade ändarna från provet, utan extra arbete.
-
Tryck skalar bara långaxeln,
, så trycket ger mer bläckvolym på nedåtgående streck och kan aldrig göra ett horisontellt streck tjockare.
Utifrån provmätningarna behöll vi
Renderingen krävde en ny fragmentshader och inget annat. Vertexformatet — position, diameter, färg — bar redan allt: diametern är långaxeln och kortaxeln är en uniform per pass. Shadern utvärderar en ellips-SDF med samma halvpixelsramp för täckning som våra runda stämplar, vilket gör den pixeljämförbar med Core Graphics referensimplementation (fillEllipse per stamp). Valideringen gick genom den vanliga grinden: en syntetisk korpus med två reservoarpennestreck, renderade på båda sätten och jämförda pixel för pixel — noll strukturella skillnader, och ett stickprovskontrollerat horisontellt streck mätte 12 px i båda renderarna.

Version ett till vänster, version två till höger. Samma handskrivna indata, samma pipeline. Ändarna berättar historien.
På iPad godkändes den nya pennan direkt: “好,很好” — bra. Mycket bra.
Behålla missen
Version ett hamnade inte i papperskorgen. Det är en legitimt intressant pensel — den är bara ingen vattenpenna. Därför skeppades den som det första inslaget i en ny meny för experimentella penslar, under namnet människan gav den: 漏水的圆珠笔, den läckande kulspetspennan. Verktygsfältet fick en flaskknapp som öppnar en textlista med experiment; att lägga till nästa kostar en rad i ett register. En förkastad modell är inte bortkastat arbete när den kan skeppas som ett tydligt märkt experiment.
En kväll av loopar
Hela förloppet — mäta, modellera, bygga, testa på enheten, fråga, modellera om, bygga om, validera — tog en kväll. Kimi K3 på Fireworks drev hela den tekniska sidan av loopen: utformade mätskanningarna, föreslog den avgörande frågan i stället för att gissa en gång till, raderade sin egen riktningsuppskattare när bevisen vände och utökade pixel-diff-harnessen innan den rörde appen. Fireworks inferenshastighet höll loopen interaktiv — långa Metal- och Swift-diffar, pixelanalysskript och korpusverktyg kom tillräckligt snabbt för att flaskhalsen skulle ligga kvar där den ska: i mänskligt omdöme.
Samarbetsmönstret var samma som i inlägget om Metal-pipelinen, och det fungerade igen: modellen är snabb och precis; människan äger smak och verifiering från början till slut. En enda mening av känslobaserad återkoppling — “konstpenna, inte vattenpenna” — räckte för att modellen skulle hitta det exakta modelleringsfelet och ersätta det med en enklare design.
Den rätta modellen visade sig vara mindre än den felaktiga. Version två skeppade färre rörliga delar än version ett — ingen uppskattare, inget utjämningsfönster, ingen anpassad exponent. Spetsen beräknar inte bredden. Spetsen är bredden.