Lulucat

Kimi K3 ஒரு டிஜிட்டல் ஃபவுண்டெய்ன் பேனா ஸ்ட்ரோக்கை எப்படி உருவாக்கியது

Gaoge ZhangGaoge Zhang

Lulucat Notes-ல் Freeform-ன் திசையமைந்த ஃபவுண்டெய்ன் பேனா ஸ்ட்ரோக் வேண்டும் என்று விரும்பினோம். ஸ்பெக் கையெழுத்தின் ஒரு ஸ்கிரீன்ஷாட் மட்டுமே. இரண்டு மாடல்கள், ஒரு வேறுபடுத்தும் கேள்வி, ஒரு நீள்வட்ட நிப் ஆகியவற்றுக்குப் பிறகு, தண்ணீர் பேனா இருக்க வேண்டிய விதத்தில் எழுதுகிறது. ஆராய்ச்சி, குறியீடு மற்றும் சரிபார்ப்பு Fireworks-ல் இயங்கிய Kimi K3-ஆல் செய்யப்பட்டது.

புதுப்பிக்கப்பட்டது

கிரீம் நிறக் காகிதத்தில் நீள்வட்ட நிப் கொண்ட ஃபவுண்டெய்ன் பேனாவால் எழுதப்பட்ட, மேலே ஆங்கில கர்சிவ் “fountain pen” என்றும் கீழே ஒரு வரி சீனக் கேலிகிராஃபி என்றும் தெரியும் கையெழுத்து: செங்குத்துகளில் தடித்து, கிடைமட்டங்களில் மெல்லியதாக.

இந்தப் பதிவில் பேசப்படும் Lulucat Notes Metal பைப்லைனால் render செய்யப்பட்டது.

Lulucat Notes-ல் ஒரு சாதாரண பேனாவும் ஒரு highlighter-ம் உள்ளன. roadmap-இன் அடுத்த கருவி ஒரு தண்ணீர் பேனா — Apple Notes மற்றும் Freeform-ல் நீங்கள் அறிந்திருக்கும் திசையமைந்த ஃபவுண்டெய்ன் பேனா; இதில் செங்குத்து ஸ்ட்ரோக்குகள் தடித்தும் கிடைமட்ட ஸ்ட்ரோக்குகள் மெல்லியதாகவும் தோன்றும். இந்தக் கருவிக்கான ஸ்பெக் ஒரு ஆவணம் அல்ல; அது ஒரு ஸ்கிரீன்ஷாட்: மூன்று வரி கையெழுத்து, “pencilkit”, “无边记”, “这种有方向的水笔能力” என்ற சொற்கள் — இந்தத் திசையமைந்த தண்ணீர் பேனா திறன்.

இதற்கு முன் இருந்த Metal பைப்லைனைப் போலவே, இந்தப் பணியையும் Fireworks-ல் இயங்கும் Moonshot-இன் open model Kimi K3 செய்தது: அளவீடு, மாடலிங், குறியீடு மற்றும் சரிபார்ப்பு. மனிதர் ஸ்கிரீன்ஷாட்டை வழங்கினார், ஒரு கேள்விக்குப் பதிலளித்தார், உண்மையான iPad-ல் அதன் feel-ஐ மதிப்பிட்டார்.

ஸ்பெக் ஒரு ஸ்கிரீன்ஷாட்

ஒரு நிலையான படம் ஒரு ஸ்ட்ரோக் ஏன் மெல்லியதாக இருக்கிறது என்று சொல்ல முடியாது. அது எவ்வளவு மெல்லியது, எங்கே இருக்கிறது என்பதையே சொல்ல முடியும். எனவே முதல் படி அளவீடு. ஸ்கிரீன்ஷாட்டை வரிசை வரிசையாகவும் நெடுவரிசை நெடுவரிசையாகவும் scan செய்து, ஒவ்வொரு ஸ்ட்ரோக்கின் centerline drift-ஐக் கண்காணித்து அதன் திசையைப் பெற்றோம்; பின்னர் அந்தக் கோணத்தின் sine-ஐப் பயன்படுத்தி scan width-ஐ உண்மையான width-ஆக மாற்றினோம்:

ஸ்ட்ரோக்திசைஉண்மையான width
“l” இன் ascender, “pencilkit”≈ 78°27.3 px
“k” இன் stem, “pencilkit”≈ 90°28 px
力 இன் இடப்புறம் கீழிறங்கும் sweep≈ 66°25.7 px
கர்சிவ் இணைப்புகள்≈ 8°11 px
சீனக் கிடைமட்டங்கள் (横)≈ 0°6–11 px

தடிப்புக்கும் மெல்லியதற்கும் உள்ள விகிதம் ≈ 2.5. 66° புள்ளியுடன் -ஐ fit செய்ததில் கிடைத்தது — -க்கு கிட்டத்தட்ட நேரியல், செங்குத்து அச்சில் உச்சத்தை அடைகிறது. இது விளைவில் ஒரு italic nib: கிடைமட்ட எழுத்து ஒருபோதும் திறக்காத ஒரு கிடைமட்டப் பிளவு.

பதிப்பு ஒன்று: திசையிலிருந்து width

முதல் மாடல் நேரடியானது: ஒவ்வொரு input point-க்கும் ஒரு திசையைக் கணக்கிட்டு, fit செய்யப்பட்ட வளைவு மூலம் திசையை width-ஆக map செய்து, capture நேரத்தில் அந்த முடிவை point-இன் radius-ல் bake செய்வது. திசை causally மதிப்பிடப்பட்டது — arc-இன் கடைசி சில point-களின் மீது exponentially decaying weighted average; பயணத் திசை மாறும்போது மதிப்பீடு ஒன்றையொன்று ரத்து செய்யாமல் இருக்க இது doubled-angle space-ல் கணக்கிடப்பட்டது. கடந்த கால point-கள் மட்டுமே பயன்படுத்தப்பட்டதால், live stroke மற்றும் committed stroke byte-க்கு-byte ஒரே மாதிரியாக இருந்தன.

Builder அதன் unit check-ஐத் தாண்டியது: synthetic horizontal, vertical, 45° மற்றும் reversal paths அனைத்தும் theoretical widths-ஐ — 0.99, 2.52, 2.00 மற்றும் 0.99 points — bake செய்தன. Rendering-க்கு புதிய code எதுவும் தேவையில்லை: baked-radius stroke என்பது round stamps-ன் ஒரு சங்கிலி மட்டுமே, எங்கள் point-sprite pipeline ஏற்கனவே அவற்றை வரைந்துகொண்டிருந்தது.

iPad-ல், மனிதர் அதை நிராகரிக்க சுமார் பத்து விநாடிகள் மட்டுமே எடுத்துக்கொண்டார்: “இது ஒரு art pen, தண்ணீர் பேனா அல்ல.”

இரண்டு விளக்கங்கள் ஒரே படத்துடன் பொருந்தின

அது ஏன் தவறாக உணர்ந்தது? இரண்டு சாத்தியமான விளக்கங்கள் இருந்தன; ஸ்கிரீன்ஷாட் அவற்றை வேறுபடுத்த முடியவில்லை:

  • திசை பூட்டு. Nib geometry, கை எதைச் செய்தாலும், கிடைமட்டங்களை மெல்லியதாகவும் செங்குத்துகளைத் தடித்ததாகவும் கட்டாயப்படுத்துகிறது. பதிப்பு ஒன்று செயல்படுத்தியது இதைத்தான்.
  • அழுத்தமும் வேகமும். பேனா pressure-driven; மாதிரியின் pattern வெறும் கையெழுத்தின் dynamics: downstroke-கள் இயல்பாக அதிக அழுத்தத்துடன் இருக்கும், connectors இயல்பாக வேகமாகவும் லேசாகவும் இருக்கும்.

இரண்டும் மெல்லிய கிடைமட்டங்களும் தடித்த செங்குத்துகளும் கொண்ட ஒரு ஸ்கிரீன்ஷாட்டை உருவாக்கும். வேறுபாடு, ஒரு கிடைமட்ட ஸ்ட்ரோக்கை வலுவாக அழுத்தும்போது என்ன நடக்கிறது என்பதில் உள்ளது. பதிப்பு ஒன்று அதை மெல்லியதாகவே வைத்திருக்கும். Pressure pen அதைத் தடிப்பாக்கும். ஆகவே மனிதரிடம் ஒரு கேள்வி கேட்டோம்: வலுவாக அழுத்திய கிடைமட்ட ஸ்ட்ரோக் தடிப்பாக வேண்டுமா?

“இல்லை. கிடைமட்டங்கள் மெல்லியதாகவே இருக்கும்.”

திசை பூட்டு உறுதி செய்யப்பட்டது. ஆனால் வேறு ஏதோவும் தவறாக இருந்தது, ஏனெனில் பதிப்பு ஒன்றும் direction-locked ஆகத்தான் இருந்தது.

பதில் ஸ்ட்ரோக்கின் முனைகளில் இருந்தது

அடுத்த குறிப்பு ascender-களின் உச்சியில் இருந்தது. மாதிரியில் உள்ள “l” மற்றும் “k” stem-களைப் பெரிதாக்கிப் பார்த்தபோது இரண்டு விஷயங்கள் தெரிந்தன: ஒரு நேரான ஸ்ட்ரோக் தொடக்கம் முதல் முடிவு வரை ஒரே width-ஐ வைத்திருக்கிறது; ஸ்ட்ரோக்கின் முனைகள் flat diagonal cuts — ஒரு chisel nib காகிதத்திலிருந்து உயரும்போது உருவாகும் வடிவம். அவை round dots அல்ல; pressure tapers-ம் அல்ல.

மாதிரியில் உள்ள இரண்டு handwritten ascender stem-களின் நெருக்கக் காட்சி; ஒவ்வொன்றும் மேலே flat diagonal cut-ஆக முடிகிறது, stem முழுவதும் ஒரே thickness உள்ளது.

“art pen feel” என்று மனிதர் சொன்னதன் பொருள் இதுதான். பதிப்பு ஒன்று மாதிரியின் look-ஐ — மதிப்பிடப்பட்ட direction-ன் function-ஆக width-ஐ — model செய்தது; ஆனால் pen-ஐ model செய்யவில்லை. Direction estimator ஒரு sensor: noisy input-ல் jitter செய்யும், corners அருகே lag செய்யும், ஒவ்வொரு ஸ்ட்ரோக்கின் முனையையும் ஒரு circle-ஆக round செய்யும். உண்மையான nib-க்கு இத்தகைய பிரச்சினைகள் எதுவும் இல்லை, ஏனெனில் அது எதையும் compute செய்வதில்லை. Width என்பதே geometry.

பதிப்பு இரண்டு: ஒரு ellipse nib

இறுதி மாடலில் direction estimator ஒன்றுமே இல்லை. Nib ஒரு oriented ellipse: long axis கிடைமட்டமாகவும், short axis fixed-ஆகவும் உள்ளது. இந்த ellipse-ன் stamps ஸ்ட்ரோக்கின் path முழுவதும் அடர்த்தியாக வைக்கப்படுகின்றன; மீதமுள்ள அனைத்தும் geometry-யிலிருந்து தானாக வெளிப்படும்:

  • ஒரு கிடைமட்ட ஸ்ட்ரோக் திறந்த விளிம்பின் வழியாக நகர்கிறது, எனவே அது எப்போதும் width-ஆகவே வரும் — எந்த pressure-லுமான மாறாத மெல்லிய கோடு. உறுதி செய்யப்பட்ட spec இதுதான்.

  • ஒரு செங்குத்து ஸ்ட்ரோக் முழு long axis-ஐக் கடக்கிறது: , தடித்த முனை.

  • ஒரு diagonal ஸ்ட்ரோக், பயணத் திசைக்குச் செங்குத்தாக உள்ள ellipse-ன் chord width-ஐ எடுக்கிறது,

  • ஸ்ட்ரோக்கின் முனைகள் elliptical cuts — மாதிரியில் இருந்த flat nib-shaped ends, வேறு வேலை இல்லாமலே கிடைக்கும்.

  • Pressure long axis-ஐ மட்டும் scale செய்கிறது, ; ஆகவே downstroke-களில் ink volume கிடைக்கும், ஆனால் கிடைமட்டத்தை ஒருபோதும் தடிப்பாக்க முடியாது.

மாதிரி அளவீடுகளிலிருந்து pt மற்றும் pt-ஐ வைத்துக்கொண்டோம்; அதே 2.5 ratio. Stamps arc-இன் வழியாக 0.5 points இடைவெளியில் வைக்கப்படுகின்றன; 0.55-point short radius-உடன், worst-case edge ripple சுமார் ஒரு pixel-ன் பத்தில் ஒரு பங்காகும்.

Rendering-க்கு ஒரு புதிய fragment shader மட்டும் தேவைப்பட்டது. Vertex format — position, diameter, color — ஏற்கனவே அனைத்தையும் கொண்டிருந்தது: diameter என்பது long axis, short axis ஒரு per-pass uniform. Shader, எங்கள் round stamps பயன்படுத்தும் அதே half-pixel coverage ramp-ஐக் கொண்டு ellipse SDF-ஐ evaluate செய்கிறது; இதனால் Core Graphics reference implementation-உடன் (fillEllipse per stamp) pixel அளவில் ஒப்பிட முடிகிறது. Validation வழக்கமான gate வழியே நடந்தது: இரண்டு fountain strokes கொண்ட synthetic corpus-ஐ இரு முறைகளிலும் render செய்து pixel by pixel ஒப்பிட்டோம் — structural differences பூஜ்ஜியம்; spot-check செய்த ஒரு horizontal stroke இரண்டு renderers-லும் 12 px ஆக அளவிடப்பட்டது.

ஒரே handwritten “fountain” என்ற சொல்லின் இரண்டு renderings அருகருகே: இடதுபுறம் direction-scaled diameter கொண்ட round stamps-ஆல் வரையப்பட்டு rounded ends தெரிகின்றன; வலதுபுறம் ellipse stamps-ஆல் flat nib-cut ends மற்றும் steady width தெரிகின்றன.

இடப்புறம் பதிப்பு ஒன்று, வலப்புறம் பதிப்பு இரண்டு. அதே handwritten input, அதே pipeline. முனைகளே கதையைச் சொல்கின்றன.

iPad-ல், புதிய பேனா உடனடியாக தேர்ச்சி பெற்றது: “好,很好” — நல்லது. மிக நல்லது.

இந்தத் தவறை வைத்துக்கொள்வது

பதிப்பு ஒன்று குப்பைத்தொட்டிக்குச் செல்லவில்லை. அது உண்மையில் சுவாரஸ்யமான ஒரு brush; அது தண்ணீர் பேனா அல்ல, அவ்வளவுதான். எனவே மனிதர் கொடுத்த பெயரான 漏水的圆珠笔, அதாவது leaky ballpoint, என்ற பெயரில் புதிய experimental-brush menu-வின் முதல் entry-ஆக அது ship செய்யப்பட்டது. Toolbar-ல் ஒரு flask button சேர்க்கப்பட்டது; அது experiments-ன் text list-ஐத் திறக்கும். அடுத்ததைச் சேர்க்க registry-யில் ஒரு வரி போதும். தெளிவாகக் குறிக்கப்பட்ட experiment-ஆக ship செய்ய முடிந்தால், நிராகரிக்கப்பட்ட model வீணான வேலை அல்ல.

ஒரே மாலையில் நடந்த loops

முழு arc — measure, model, build, device, question, remodel, rebuild, validate — ஒரு மாலை எடுத்தது. Fireworks-ல் இயங்கிய Kimi K3 loop-ன் முழு technical பக்கத்தையும் நடத்தியது: measurement scans-ஐ வடிவமைத்தல், மறுபடியும் ஊகிப்பதற்குப் பதிலாக discriminating question-ஐ முன்வைத்தல், ஆதாரம் மாறியபோது தன் direction estimator-ஐ நீக்குதல், app-ஐத் தொடுவதற்கு முன் pixel-diff harness-ஐ விரிவுபடுத்துதல். Fireworks-ன் inference speed loop-ஐ interactive-ஆக வைத்தது — நீண்ட Metal மற்றும் Swift diffs, pixel-analysis scripts, corpus tooling ஆகியவை மனித judgment-ஐத் தவிர வேறு bottleneck இல்லாத அளவுக்கு வேகமாக வந்தன.

Metal pipeline பற்றிய பதிவில் நாங்கள் எழுதிய அதே collaboration pattern இங்கும் நிலைத்தது: model வேகமானதும் துல்லியமானதும்; human taste மற்றும் end-to-end verification-ஐக் கவனித்தார். feel-ஐ அடிப்படையாகக் கொண்ட ஒரே ஒரு feedback sentence — “art pen, தண்ணீர் பேனா அல்ல” — model சரியான modeling error-ஐக் கண்டுபிடித்து, அதற்குப் பதிலாக எளிய design-ஐ வைக்கப் போதுமானதாக இருந்தது.

சரியான model தவறானதைவிடச் சிறியதாக இருந்தது. பதிப்பு இரண்டு, பதிப்பு ஒன்றைவிடக் குறைவான moving parts-உடன் ship ஆனது — estimator இல்லை, smoothing window இல்லை, fitted exponent இல்லை. Nib width-ஐ compute செய்வதில்லை. Nib தானே width.