AI டெமோக்கள் எங்கும் நிறைந்துள்ளன. ஒரு சிறிய Python ஸ்கிரிப்ட் மூலம் ஒரு நிலையான புகைப்படத்தில் முகத்தை மாற்ற முடியும், அதன் முடிவு மாயாஜாலம் போலத் தோன்றும். ஆனால், நிஜ மனிதர்கள் எதையோ பதிவேற்றவும், வேலையை முடித்துவிட்டுச் செல்லவும், மீண்டும் வந்து பார்க்கவும் கூடிய ஒன்றை உருவாக்குவது முற்றிலும் மாறுபட்ட ஒரு பணியாகும். நான் சமீபத்தில் ஒரு இணையக் கருவியை (web tool) உருவாக்கினேன்; இது ஒரு அனிமேஷன் GIF மற்றும் ஒரு குறிப்பு முகத்தை (reference face) எடுத்துக்கொண்டு, ஒவ்வொரு பிரேமிலும் முகத்தை மாற்றியமைத்த அதே அனிமேஷனைத் திருப்பித் தரும். இந்த மாடல் காட்சி ரீதியான கடினமான வேலைகளைச் செய்கிறது, ஆனால் உண்மையான பொறியியல் முயற்சி அதைச் சுற்றியுள்ள கட்டமைப்பிலேயே (architecture) செலவிடப்பட்டது: இணைப்புகளைத் துண்டிக்காமல் வைத்திருப்பது, பக்கத்தைப் புதுப்பித்தாலும் (page refresh) வேலை தொடர்வது மற்றும் இரண்டு நிமிட கால அளவு கொண்ட inference பணி ஒரு 504 Gateway Timeout மூலம் காணாமல் போகாமல் இருப்பதை உறுதி செய்வது போன்றவை இதில் அடங்கும்.
இது ஒரு முன்மாதிரிக்கும் (prototype) ஒரு தயாரிப்பிற்கும் (product) இடையிலான இடைவெளியாகும். பொறியாளர்கள் diffusion architectures மற்றும் inference parameters பற்றிப் பேசுவதை விரும்புகிறார்கள். ஆனால் ஒரு பயனர் நூற்றுக்கணக்கான பிரேம்களைக் கொண்ட ஒரு பெரிய GIF-ஐப் பதிவேற்றும்போது, பிரவுசர் டேப் முப்பது வினாடிகளில் வேலை செய்வதை நிறுத்தினால், உங்கள் மாடல் பற்றி யாருக்கும் கவலை இருக்காது. inference-ஐச் சுற்றியுள்ள உள்கட்டமைப்பு (infrastructure), inference போலவே முக்கியமானது.
காத்திருப்பதில் உள்ள சிக்கல்
வழக்கமான இணையக் கட்டமைப்பு (Standard web architecture) விரைவான பதில்களை எதிர்பார்க்கிறது. ஒரு பயனர் ஒரு பொத்தானைக் கிளிக் செய்கிறார், சர்வர் பதிலளிக்கிறது, மற்றும் பக்கம் புதுப்பிக்கப்படுகிறது. டஜன் கணக்கான GIF பிரேம்களில் முகத்தை மாற்றுவது இந்த அனுமானத்தை உடனடியாக உடைத்துவிடுகிறது. இந்த மாடல் எனது சர்வரில் இயங்காமல் Replicate-ன் GPUs-இல் இயங்குகிறது, மேலும் ஒரு நீண்ட GIF செயலாக்கத்திற்கு ஒரு நிமிடம் அல்லது அதற்கு மேல் எடுக்கலாம். இவ்வளவு நேரம் ஒரு HTTP request-ஐத் திறந்து வைத்திருக்க முயற்சித்தால், அது சிக்கல்களை உருவாக்கும். Load balancers செயலற்ற இணைப்புகளைத் (idle connections) துண்டிக்கும். பிரவுசர்கள் நெட்வொர்க் தோல்வியடைந்துவிட்டதாகக் கருதி மீண்டும் முயற்சிக்கும். பயனர்கள் உறைந்து போன ஒரு ஸ்பின்னரையே (frozen spinner) பார்த்துக் கொண்டிருப்பார்கள், ஆப் பழுதாகிவிட்டது என்று நினைப்பார்கள்.
சமர்ப்பிப்பிற்கும் (submission) முடிவிற்கும் (result) இடையிலான தொடர்பைத் துண்டிப்பதன் (decoupling) மூலம் நான் இதை முற்றிலும் தவிர்த்தேன். ஒரு பயனர் GIF மற்றும் ஒரு முகப் படத்தை பதிவேற்றும்போது, எனது Next.js backend, Replicate-இல் ஒரு கணிப்பைத் (prediction) தொடங்கி உடனடியாக ஒரு job ID-ஐத் திருப்பித் தரும். பயனர் உடனடி உறுதிப்படுத்தலைப் பெறுவார். GPU வேலை முடிந்ததும், ஒரு webhook மூலம் உண்மையான முடிவு பின்னர் வந்து சேரும். இந்த முறை புதியது அல்ல, ஆனால் நீண்ட நேரம் எடுக்கும் மீடியா பணிகளுக்கு இது முற்றிலும் அவசியமானது. இது கணிக்க முடியாத காத்திருப்பை ஒரு நம்பிக்கையான உறுதிமொழியாக மாற்றுகிறது: பணி ஏற்றுக்கொள்ளப்பட்டது, அது முடிந்ததும் உங்களுக்குத் தெரிவிக்கப்படும்.
நீங்கள் நம்பக்கூடிய ஒரு State Machine-ஐ உருவாக்குதல்
நீங்கள் asynchronous முறையைப் பயன்படுத்தத் தொடங்கியதும், உங்களுக்குத் தெளிவான கண்காணிப்புத் திறன் (visibility) தேவைப்படும். பயனர்கள் பக்கத்தைப் புதுப்பிப்பார்கள். அவர்கள் டேப்பை மூடிவிட்டு மீண்டும் திறப்பார்கள். அவர்கள் இணைப்பைப் பிரதி எடுத்து, இரண்டு மணி நேரம் கழித்துச் சரிபார்க்கும் ஒரு சக ஊழியருக்கு அனுப்புவார்கள். என்ன நடந்தது என்பதற்கான நிலையான பதிவு (durable record) இல்லையென்றால், அங்கு குழப்பம் ஏற்படும்.
நான் Supabase-ஐ ஒற்றை உண்மை ஆதாரமாக (single source of truth) பயன்படுத்தினேன். ஒவ்வொரு பதிவேற்றமும் ஒரு தனித்துவமான job ID உடன் ஒரு வரிசையை (row) உருவாக்குகிறது, மேலும் அந்த வரிசை குறிப்பிட்ட நிலைகளைக் (states) கடந்து செல்கிறது: queued, processing, succeeded, failed, அல்லது expired. பயனர் முதன்முதலில் submit செய்யும்போது, அந்த வரிசை queued நிலையில் இருக்கும். Replicate கணிப்பை ஏற்றுக்கொண்ட அடுத்த கணமே, அது processing நிலைக்கு மாறும். Webhook அதை succeeded அல்லது failed நிலைக்குத் தள்ளும். அழைப்பு (callback) வராமல் நீண்ட நேரம் காத்திருக்கும் பணிகளுக்காக நான் expired என்ற நிலையைச் சேர்த்தேன், இதனால் சிஸ்டம் தேவையற்ற விஷயங்களைத் தேடி அலைவதைத் தவிர்க்க முடியும்.
TypeScript-இல் உருவாக்கப்பட்ட frontend, ஒரு குறுகிய இடைவெளியில் Supabase-ஐ polls செய்கிறது மற்றும் தற்போதைய நிலை என்ன சொல்கிறதோ அதைத் திரையில் காட்டுகிறது. இந்த polling முறை பழமையானதாகத் தோன்றலாம், ஆனால் இது refresh சிக்கலை முழுமையாகத் தீர்க்கிறது. ஒரு பயனர் தனது லேப்டாப்பை மூடிவிட்டு, நாளைத் திறந்தாலும், விஷயங்கள் எந்த நிலையில் உள்ளன என்பதைத் துல்லியமாகப் பார்க்க முடியும், ஏனெனில் பிரவுசர் மெமரி அல்ல—தரவுத்தளம் (database) தான் முன்னேற்றத்தைக் கொண்டுள்ளது. Supabase கிரெடிட்களையும் (credits) கண்காணிக்கிறது, எனவே கணக்கீடுகள் நிலையைத் கண்காணிக்கும் அதே job record உடன் இணைந்தே இருக்கும். அனைத்தும் ஒரே இடத்தில் உள்ளன.
உலாவியை (Browser) முடக்காமல் கோப்புகளைக் கையாளுதல்
GIF கோப்புகள் மக்கள் நினைப்பதை விட அதிக எடையைக் கொண்டவை. AI pipeline-க்கு சரியாகத் தகுந்த அளவுள்ள ஒரு கோப்பு கூட பல மெகாபைட் எடையைக் கொண்டிருக்கலாம். அதை ஒரு looping preview ஆக பிரவுசருக்குள் காண்பிப்பது, குறிப்பாகக் குறைந்த திறன் கொண்ட சாதனங்களில் செயல்திறனைப் பாதிக்கும். எனக்கு இரண்டு முற்றிலும் தனித்த file pipelines தேவைப்பட்டன: ஒன்று AI-க்காக, மற்றொன்று பயனர் இடைமுகத்திற்காக (user interface).
முன்னோக்கங்களுக்கு (previews), நான் WebAssembly-க்கு மாற்றப்பட்ட FFmpeg மூலம் பெரிய GIF-களை அனிமேஷன் WebP ஆக மாற்றுகிறேன். இது பிரவுசரில் முழுமையாக client-side-இல் இயங்குகிறது. இதன் முடிவு, அசல் கோப்பைத் தொடாமல் இடைமுகத்தை வேகமாகவும் சுறுசுறுப்பாகவும் (snappy) வைத்திருக்கும் ஒரு இலகுவான முன்னோட்டமாகும். Replicate-க்கு அனுப்பப்படும் GIF மாற்றப்படாமல் அப்படியே இருக்கும். அந்தப் பிரிப்பு மிகவும் முக்கியமானது. ஒரு முன்னோட்டத்திலிருந்து வரும் compression artifacts உங்கள் பயிற்சித் தரவிலோ (training data) அல்லது இறுதி ரெண்டரிலோ (final render) நுழைவதை நீங்கள் விரும்ப மாட்டீர்கள், மேலும் AI இன்னும் சிந்தித்துக் கொண்டிருக்கும்போது, பல மெகாபைட் அளவுள்ள ஒரு கோப்பால் பயனர் இடைமுகம் முடங்குவதையும் நீங்கள் விரும்ப மாட்டீர்கள்.
FFmpeg WASM, பதிவேற்றம் பிரவுஸை விட்டு வெளியேறுவதற்கு முன்பே பிற GIF பணிகளையும் கையாள்கிறது. பிரேம் எண்ணிக்கையைப் பகுப்பாய்வு செய்யவும் (parse frame counts), அளவுகளைச் சரிபார்க்கவும் (validate dimensions), மற்றும் சிதைந்த கோப்புகளை முன்கூட்டியே கண்டறியவும் நான் இதைப் பயன்படுத்துகிறேன். GPU credits-ஐப் பயன்படுத்துவதற்கு முன்பே ஒரு சிக்கலைக் கண்டறிவது பணத்தையும் பயனரின் பொறுமையையும் மிச்சப்படுத்துகிறது.
ஒரு டெமோவை மக்கள் நம்பும் மென்பொருளாக மாற்றுவது
சந்தையில் உள்ள கிட்டத்தட்ட அனைத்து ஜெனரேட்டிவ் AI கருவிகளுக்கும் பொருந்தக்கூடிய ஒரு பரந்த பாடம் இதில் உள்ளது. மாடல் (model) என்பது வேலையில் முப்பது சதவீதம் மட்டுமேயாக இருக்கலாம். மீதமுள்ள எழுபது சதவீதம் யாரும் ட்வீட் செய்யாத, கவர்ச்சியற்ற பின்னணி வேலைகள்: state recovery, webhook signatures, file conversion, credit tracking மற்றும் graceful failure.
எனது stack எளிமையானது மற்றும் திட்டமிடப்பட்டது. Next.js மற்றும் TypeScript ஆகியவை interface மற்றும் API routes-களைக் கையாளுகின்றன. Replicate மாடல்களை இயக்குகிறது. Supabase states, தரவு மற்றும் credits-களை நிர்வகிக்கிறது. FFmpeg WASM client-side media வேலைகளைக் கையாள்கிறது. Animated WebP UI-ஐ வேகப்பயன்பாட்டிற்கு வைக்கிறது. ஒவ்வொரு பகுதியும் ஒரு வேலையைச் செய்கிறது, மேலும் அவை நிலையற்ற, நீண்ட கால requests-களுக்குப் பதிலாக தெளிவான state transitions மூலம் இணைகின்றன.
ஒரு பயனர் face swap-க்காக credits-களைப் பயன்படுத்தும்போது, அவர்கள் நம்பகத்தன்மையையே எதிர்பார்க்கிறார்கள், ஒரு ஆராய்ச்சித் தாளை அல்ல. ஒரு prediction தோல்வியடைந்தால், சிஸ்டம் அதைத் தெரிந்து கொண்டு பயனரிடம் தெரிவிக்க வேண்டும். பயனர் காத்திருக்கும்போது, பார்க்க ஒரு லேசான preview மற்றும் பிரவுசரை மீண்டும் தொடங்கினாலும் அழியாத ஒரு status அவர்களுக்கு இருக்க வேண்டும். இவை சரியாகச் செயல்படும்போது கண்ணுக்குத் தெரிவதில்லை, ஆனால் செயல்படாதபோது பெரும் பாதிப்பை ஏற்படுத்துகின்றன.
Face swap என்பது ஒரு நுணுக்கமான தந்திரம் மட்டுமே. ஆனால், ஒரு பயனர் பதிவேற்றிவிட்டு, இடையில் வெளியேறி, மீண்டும் வரும்போது எதையும் இழக்காமல் தொடர முடிவதால் மட்டுமே இந்த கருவி உண்மையானதாகத் தோன்றுகிறது. ஒரு API அழைப்பை மக்கள் உண்மையில் நம்பும் மென்பொருளாக மாற்றுவது இதுதான்.
