Speax.ai — پلتفرم دوبله با هوش مصنوعی
رهبری مهندسی یک پلتفرم دوبله با هوش مصنوعی: استقرار اجایل، استارتر کیت Go، سرویس فایل S3، پایپلاینهای چندنخی ترجمه، استخراج و شبیهسازی صدا و جذب نیرو در فرانت، بک، هوش مصنوعی و دواپس.
- مدت
- ۱۴ ماه
- پایپلاینها
- ۳
- محصول روی یک استارتر کیت
- ۲
زمینه
Limytd AG دو محصول دارد. Speax.ai سرویس دوبله با هوش مصنوعی است: مشتری ویدیویی بارگذاری میکند و آن را به زبانی دیگر و با صدای خود گوینده تحویل میگیرد. پشت صحنه زنجیرهای از مراحل هوش مصنوعی است — رونویسی [پیشنویس]، ترجمه، استخراج صدا، شبیهسازی صدا، سنتز و ترکیب نهایی [پیشنویس] — که هر کدام کند است، به GPU وابسته است و میتواند جداگانه شکست بخورد. ChainMind محصولی در حوزهی رمزارز و بلاکچین است که از نوامبر ۲۰۲۳ بهصورت پارهوقت مدیر ارشد فناوری (CTO) آن بودم؛ در آوریل ۲۰۲۴ بنیانگذار [پیشنویس] از من خواست Speax.ai را هم تماموقت به عهده بگیرم. مأموریت: تبدیل یک دموی کارای هوش مصنوعی به سرویسی که بتواند مشتری پولی بپذیرد، و جذب تیمی که آن را اداره کند. هر دو همکاری در مه ۲۰۲۵ به پایان رسید.
وضعیت. آنچه در آوریل ۲۰۲۴ وجود داشت [پیشنویس]: اسکریپتهای هوش مصنوعی که با اجرای دستی کار میکردند، ایدهی محصول، و هیچ قراردادی میان سرویسهای هوش مصنوعی و بقیهی سیستم. یک کار میتوانست بیست دقیقه [پیشنویس] اجرا شود و در مرحلهی آخر بیصدا شکست بخورد؛ هیچکس نمیتوانست بگوید کدام مرحله، و تنها راه اجرای دوبارهی همهچیز بود — حتی مراحل پرهزینهی GPU که موفق شده بودند. هیچ ابزار پیگیری پروژهای در کار نبود و تیم هنوز باید جذب میشد.
محدودیتهای مهم: زمان GPU یعنی پول و دقیقه؛ تیم بسیار کوچک و دورکار بود؛ بنیانگذار دموهایی میخواست که جلوی مشتری خراب نشوند. موفقیت از نگاه بنیانگذار: مشتری بارگذاری کند و بدون اینکه کسی کار را مراقبت کند نتیجه بگیرد. از نگاه تیم هوش مصنوعی: عرضهی تغییر مدل بدون دستزدن به محصول.
چه کردم
- از استارتر کیت Go شروع کردم. استارتر کیت DDD و معماری ششضلعی را آوردم که از Hoitek و Armo Group صیقل خورده بود: پکیجهای دامنه، پورتها و آداپترها، یک لایهی انتقال برای HTTP و کارگزار پیام، و قراردادهای نوشتهشده. بکاند از هفتهی اول قابل بازبینی بود و هر نیروی جدید بر اساس قراردادها آنبورد شد، نه بر اساس من. گزینهی کنارگذاشته: Python برای بکاند تا تیم هوش مصنوعی مالکش باشد — برای آنها سریعتر بود، اما منطق محصول برای همیشه در نوتبوکها میماند.
- اول قرارداد هوش مصنوعی ↔ بکاند را نوشتم. هر مرحلهی هوش مصنوعی یک worker است که از یک صف میخواند، یک کار انجام میدهد و نتیجه یا خطایی تایپشده منتشر میکند؛ کارها با شناسهی کار و شناسهی مرحله idempotent هستند. کارگزار پیام: RabbitMQ [پیشنویس]. تیم هوش مصنوعی میتوانست مدلی را دوباره مستقر کند بیآنکه محصول بفهمد؛ محصول میتوانست مرحلهای اضافه کند بیآنکه به مدلی دست بزند. گزینهی کنارگذاشته: HTTP همگام میان سرویسها — روز اول سادهتر، و وقتی یک مرحله ده دقیقه طول بکشد ناممکن.
- پایپلاین چندنخی را طراحی کردم. هر کار یک ماشین حالت است که در PostgreSQL [پیشنویس] ذخیره میشود؛ رسانهی طولانی به قطعهها تقسیم میشود، میان استخرهای worker با همروندی محدود در هر مرحله پخش میشود و دوباره به هم میپیوندد. هر مرحله یک checkpoint مینویسد. در Go این یعنی استخر worker، errgroup و لغو با context [پیشنویس] — چیز عجیبی نیست؛ ارزش کار در checkpointهاست.
- الگوهای تلاش مجدد دستی و خودکار را ساختم. دستی: پنل اپراتور با «تلاش مجدد از این مرحله» — اجرای دوباره از آخرین checkpoint سالم بدون تکرار مراحل GPU که موفق شده بودند. خودکار: تلاشهای جداگانه برای هر مرحله با backoff نمایی و صف dead-letter پس از تمامشدن سهمیه. اول دستی عرضه شد، بعد خودکار (بازنگری توضیح میدهد چرا این ترتیب مهم است).
- Bytebase را نوشتم. یک سرویس کوچک Go جلوی AWS S3 که مالک هر فایلی است که میان سرویسها جابهجا میشود: بارگذاری، نشانیهای امضاشده، خروجی مراحل، چرخهی عمر و پاکسازی. هیچ سرویسی مستقیم با S3 حرف نمیزند. گزینهی کنارگذاشته: یک فضای ذخیرهسازی شبکهای مشترک — تا وقتی دو ابر درگیر نشدهاند کار میکند (پردازش روی Azure [پیشنویس]، ذخیرهسازی روی S3).
- تیم را جذب کردم. فرایند مصاحبه را طراحی کردم و با مهندسان ارشد فرانتاند، بکاند، هوش مصنوعی و DevOps مصاحبه کردم؛ تمرین خانگی بهجای معما، بازتاب یک مرحلهی واقعی پایپلاین بود. [۷] نفر در [۳] ماه [پیشنویس].
- Monday.com و یک جلسهی عمیق هفتگی را راه انداختم. چیدمان اجایل روی Monday.com را به تیم آموزش دادم و هر هفته یک جلسهی حل مسئله با تنها یک سؤال روی میز برگزار کردم. این روال تا پایان همکاری ماند [پیشنویس].
- هدایت روزانهی تیم بکاند با من بود و ChainMind را هم بهصورت پارهوقت با همان استارتر کیت و همان الگوی جذب سرپا نگه داشتم.
نتایج (میزان اطمینان در پرانتز)
- کارهای دوبله در پروداکشن از ابتدا تا انتها بدون مراقبت اجرا شدند (دقیق، به حکم ساختار)
- کارهای شکستخوردهای که اجرای کامل دوباره لازم داشتند: از [بیشتر آنها] به [هیچ] پس از checkpointها و تلاش مجدد از مرحله (تقریبی، پیشنویس)
- دقیقههای GPU به ازای هر کار شکستخورده حدود [۴۰٪] کم شد، چون مراحل موفق هرگز تکرار نمیشدند (verify، پیشنویس)
- [۷] نیروی ارشد در فرانتاند، بکاند، هوش مصنوعی و DevOps در [۳] ماه (verify، پیشنویس)
- پس از عرضهی Bytebase هیچ رخداد «فایل پیدا نشد» میان سرویسها رخ نداد (verify، پیشنویس)
- یک استارتر کیت و یک مجموعه قرارداد برای دو محصول (دقیق، رزومه)
- مدت
- ۱۴ ماه
- پایپلاینها
- ۳
- محصول روی یک استارتر کیت
- ۲
آنچه درست پیش رفت
- استارتر کیت باز هم هزینهاش را جبران کرد. قراردادهایی که پیش از جذب نیرو نوشته شده بودند باعث شد بحث بازبینیها دربارهی دامنه باشد، نه نام پوشهها. اعتبارش با دو تیم قبلی است که نسخههای اولش را از سر گذراندند.
- تلاش مجدد از مرحله همان قابلیتی بود که تیم عملیات عاشقش شد. «اجرا شکست خورد» بهجای یک رشته پیام، به یک کلیک تبدیل شد [پیشنویس].
- Bytebase یک دستهی کامل از باگها را حذف کرد. وقتی هیچ سرویسی نمیتوانست مستقیم به S3 دست بزند، دیگر کسی نگفت «فایل یک دقیقه پیش اینجا بود».
- تمرین خانگی آیندهی کار را پیشبینی کرد. کسانی که در تمرین مرحله خوب بودند در کار هم خوب بودند؛ نیروهای جدید در همان اسپرینت اول بهرهور شدند [پیشنویس].
- تیم هوش مصنوعی استقلالش را به دست آورد. تعویض مدلها بدون انتشار محصول انجام میشد.
آنچه اشتباه پیش رفت
روند
[پیشنویس — فرضیه] [ماه دوم]: سرویس شبیهسازی صدا [یک ساعت] از کار افتاد. همهی کارهای در جریان در آن مرحله شکست خوردند و — چون تلاش مجدد خودکار حالا روشن بود — همه همزمان و با یک زمانبندی backoff یکسان دوباره تلاش کردند. صف از تلاشهای مجدد پر شد، کارهای تازهی مشتریها پشت آنها ماندند و سرویس شبیهسازی وقتی برگشت با دیواری از درخواست روبهرو شد و دوباره از پا افتاد. با پیام یک مشتری دربارهی کارهای «گیرکرده» متوجه شدیم، نه با هشدار. علت در [یک روز] روشن شد و رفعش [سه روز] طول کشید.
علتها
- سیاست تلاش مجدد برای هر کار جداگانه بود و دید کلی نداشت؛ هیچ چیز نمیگفت «هزار کار در حال تلاش مجدد روی یک مرحلهاند».
- دور هیچ مرحلهی هوش مصنوعی circuit breaker نبود؛ پایپلاین با سرویس ازکارافتاده مثل سرویسی ناپایدار رفتار میکرد.
- سرویس هوش مصنوعی برای «مدل کرش کرد»، «حافظهی GPU تمام شد» و «ورودی نامعتبر» یک خطای واحد برمیگرداند، پس بکاند نمیتوانست خطای قابلتکرار را از خطای نهایی تشخیص دهد.
- عمق صف و سن قدیمیترین کار روی هیچ داشبوردی نبود؛ هشدار فقط برای خطاهای HTTP وجود داشت.
- تلاش مجدد خودکار بهعنوان یک قابلیت عرضه شد، نه بهعنوان منبع بار؛ هیچکس بدترین حالتش را مدل نکرده بود.
- آهنگ جلسهی هفتگی یعنی تغییر یک تنظیم منتظر جلسه میماند؛ مسیری برای «همین امروز عوضش کن» وجود نداشت.
اثر
[N] کار مشتری [چند ساعت] تأخیر خورد؛ حدود یک روز از وقت تیم بکاند رفت؛ بنیانگذار ایمیلهای مشتریها را دستی جواب داد؛ اعتماد تیم هوش مصنوعی به اینکه «بکاند تلاش مجدد را مدیریت میکند» کمی آسیب دید.
تشخیص و واکنش: پیام مشتری ← بنیانگذار ← کشیک بکاند [پیشنویس]. اولین واکنش: توقف مصرفکنندهی تلاش مجدد و خالیکردن دستی صف dead-letter. سپس jitter و سهمیهی تلاش مجدد برای هر مرحله؛ سپس دستهبندی خطاها.
اقدامها
- jitter و سهمیهی سراسری تلاش مجدد برای هر مرحله — بکاند
- یک circuit breaker برای هر مرحلهی هوش مصنوعی که با شکستهای پیاپی باز میشود و صف همان مرحله را متوقف میکند — بکاند
- پرچم retryable و کد خطا در قرارداد هوش مصنوعی ↔ بکاند — بکاند با سرپرست هوش مصنوعی
- عمق صف و سن قدیمیترین کار روی داشبورد اصلی با آستانههای هشدار — DevOps
- دستورالعمل «توقف یک مرحله» که هر کسی بدون جلسه بتواند اجرا کند
مورد دوم بازنگری [پیشنویس]: دو کلاه CTO بهطور همزمان یعنی محصول پارهوقت — ChainMind — توجه باقیمانده را میگرفت. بکاندش بیش از برنامه در سطح استارتر کیت ماند و جذب نیرو برایش عقب افتاد. علتها: تقسیم صریحی از ساعتهایم وجود نداشت؛ یک جلسهی هفتگی مشترک داشتیم؛ موفقیت ChainMind هرگز به روشنیِ «مشتری بدون مراقبت دوبله کند» تعریف نشد. اقدامی که باید وجود میداشت: تقسیم مکتوب روزها میان دو محصول که هر ماه با بنیانگذار بازبینی شود.
مورد سوم بازنگری [پیشنویس]: پردازش روی Azure و ذخیرهسازی روی S3 یعنی هزینه و تأخیر انتقال میانابری که کسی برایش بودجه نگذاشته بود. علت: دسترسپذیری GPU ابر پردازش را تعیین کرد، وقتی S3 از قبل انتخاب شده بود. در نگاه به عقب، وقتی اولین سهمیهی GPU را درخواست میکنی، یک ابر را انتخاب کن.
اگر برمیگشتم
- نگهداراستارتر کیت، قرارداد صفبهازایمرحله، Bytebase و تلاش مجدد دستی از مرحله، دقیقاً همانطور که بودند
- تغییر بدهدستهبندی خطاها و circuit breaker را پیش از روشنکردن تلاش مجدد خودکار عرضه میکردم — و تلاش مجدد خودکار فقط با سهمیه
- تغییر بدهعمق صف و سن قدیمیترین کار از روز اول روی صفحه، پیش از اولین مشتری
- تغییر بدهیک ابر، که همزمان با سهمیهی GPU انتخاب شود
- تغییر بدههیچ کلاه دوم CTO بدون تقسیم مکتوب روزها
درسها
- پایپلاین فقط به اندازهی checkpointهایش قابل اشکالزدایی است — checkpoint خود محصول است و مرحله جزئیات.
- تمرین مصاحبه باید برشی از خود کار باشد، نه معما.
- «CTO پارهوقت» یک محصول دوم، هزینهای تماموقت برای محصول اول است، مگر اینکه مکتوب شود.