من یک کلاینت چت هوش مصنوعی استریمینگ ساختم بدون اینکه عقلم را از دست بدهم

می‌خواستم یک رابط کاربری چت بسازم که در آن هوش مصنوعی به‌صورت آنی (real-time) پاسخ دهد. آن افکت تایپی روان (typewriter effect) را می‌خواستم.

سخت‌تر از آن چیزی بود که فکر می‌کردم. مشکل از هوش مصنوعی نبود؛ مشکل از خط لوله (pipeline) بین API و مرورگر بود.

من سه روش مختلف را برای حل این مشکل امتحان کردم.

۱. روش انتظار (The Wait Method) من API را فراخوانی می‌کردم و قبل از نمایش پاسخ، منتظر دریافت پاسخ کامل می‌ماندم. این روش کار می‌کرد، اما رابط کاربری (UI) برای چند ثانیه قفل می‌شد. کاربران فکر می‌کردند اپلیکیشن خراب شده است و مکرراً روی دکمه «ارسال» کلیک می‌کردند. این یک تجربه کاربری بد بود.

۲. روش پولینگ (The Polling Method) به این فکر کردم که سرور یک job ID بفرستد و کلاینت سپس هر ثانیه درخواست به‌روزرسانی بدهد. این کار مستلزم مدیریت سنگین سرور بود. به‌روزرسانی‌ها به صورت تکه‌های تصادفی ظاهر می‌شدند و روان نبودند.

۳. روش WebSocket من Socket.IO را امتحان کردم. این کار پیچیدگی بسیار زیادی اضافه کرد. مجبور بودم اتصال‌های مجدد (reconnections)، ضربان‌های قلب (heartbeats) و همگام‌سازی وضعیت (state synchronization) را مدیریت کنم. برای یک اپلیکیشن چت ساده، استفاده از WebSockets زیاده‌روی بود.

راه حل ساده‌تر بود: Server-Sent Events (SSE).

اکثر APIهای هوش مصنوعی از قبل پاسخ‌ها را از طریق SSE روی پروتکل HTTP ارسال می‌کنند. من جستجو برای ابزارهای پیچیده را متوقف کردم و از fetch API بومی استفاده کردم.

با استفاده از response.body.getReader()، جریان بایت‌ها را مستقیماً خواندم. پروتکل SSE را خودم تجزیه (parse) کردم. این رویکرد باعث می‌شود رابط کاربری پاسخگو (responsive) باقی بماند و از HTTP استاندارد استفاده می‌کند.

چرا این روش کار می‌کند:

  • نیازی به سرور WebSocket نیست.
  • منطق پیچیده برای اتصال مجدد نیاز نیست.
  • با هر API که از SSE پشتیبانی می‌کند کار می‌کند.
  • می‌توانید با استفاده از AbortController به‌راحتی استریم را متوقف کنید.

محدودیت‌ها:

  • نمی‌توانید بدون درخواست کلاینت، به‌روزرسانی‌ها را به سمت او ارسال کنید.
  • اگر اتصال قطع شود، پاسخ‌های ناقص را از دست می‌دهید.

اگر یک اپلیکیشن چت می‌سازید، از WebSockets دوری کنید مگر اینکه به ارتباط دوطرفه (bidirectional) نیاز داشته باشید. به استریمینگ HTTP پایبند باشید. این روش ساده‌تر و قابل‌اعتمادتر است.

استراتژی استریمینگ شما چیست؟ از WebSockets استفاده می‌کنید یا SSE؟ در کامنت‌ها به من بگویید.

منبع: https://dev.to/__c1b9e06dc90a7e0a676b/i-built-a-streaming-ai-chat-client-without-losing-my-mind-3gi0