بایگانی برچسب: s

کسب و کار در بحران

در طی دورانی که به آن جنگ دوازده روزه می‌گوییم و از ۲۳ خرداد تا ۵ تیرماه، طول کشید؛ شاهد بحرانی بودیم که کسب و کارها را تحت‌الشعاع قرار داد. خیلی واضح و ساده بخواهیم صحبت کنیم، اثر گرفتن کسب و کار از بحران بخشی از بحران است و طبیعی است که مردم، جوانب حیاتی‌تر زندگی خود را در اولویت بالاتری قرار دهند که شامل موارد زیادی من‌جمله تهیه خوراک و مسکن و … می‌شود.

در این پست، قصد دارم در مورد دو تجربه خاموشی اخیر و این که چقدر می‌توانست کسب و کارها را مورد عنایت قرار دهد، صحبت کنم. البته خاموشی اخیر، طولانی‌تر، دور از انتظارتر و عجیب‌تر بود و حتی پروژه‌های آزاد مانند پارچ‌لینوکس نیز از آن ضربات زیادی خوردند.

در جنگ ۱۲ روزه چه گذشت؟

پیش از جنگ ۱۲ روزه به یاد دارم که نسخه جدید مانی را دپلوی کرده بودم و حتی از دوستانم دعوت کردم که در وبیناری که به مناسبت ریلیز نسخه جدید برگزار کردم، شرکت کنند.

اما چندین ماه بعد در طی همان اتفاقات، به سبب قطعی اینترنت در سطحی مانند دیتاسنترها و عدم اتصال دیتاسنترهای ایرانی به اینترنت بین‌الملل و دسترسی نداشتن به زیرساخت، تا حد زیادی به کسب و کار؛ علی‌رغم این که همچنان در طی این ۱۲ روز بالا بود، به دلیل نداشتن مشتری؛ ضربات جبران‌ناپذیر وارد شد.

بسیاری از کاربران نیز در طی این مدت، از پلتفرم‌هایی که در خارج از ایران میزبانی می‌شدند به پلتفرم‌های داخلی کوچ کردند. و طبیعتا یک عده نیز فرصت را غنیمت شمارده و خود را به «خط سفید» و «لیست سفید» آغشته نمودند که بعدها در مورد آن صحبت خواهیم کرد و این پست، مجالی برای آن بحث ندارد.

موضوع مهم این است، در حالی که ضربات زیادی به جوانب مختلف زندگی مردم وارد شد، با بهانه‌های واهی، عده‌ای – که اصلا کاره‌ای هم نبودند – تلاش داشتند قطعی اینترنت در آن ابعاد گسترده را توجیه کنند که این هم در جای خود مایه تاسف و تعجب است.

موضوع مهم این است که طی چند ماه پس از آن ۱۲ روز، بسیاری از کسب و کارها، من‌جمله خود ما تصمیم گرفتیم که کرکره‌ها را پایین بکشیم و طبیعتا کسب و کارهایی که تعداد نیروی انسانی آن‌ها زیاد بود، دست به تعدیل نیرو زدند. این هم از نتایجی بود که خاموشی‌ها و شاید بهتر بگوییم، غیرقابل پیش‌بینی بودن رفتار تصمیم‌گیری در مورد حد و اندازه دسترسی‌ها به اینترنت، رقم زد. کسب و کارهای کوچک و متوسط تصمیم به تعطیلی گرفتند و بزرگترها هم در ابعاد بزرگ نیروهای خود را تعدیل کردند.

در وقایع اخیر چه گذشت؟

وقایع اخیر نیز دست‌کمی نداشت. کما این که در طی جنگ دوازده روزه، روز سیزدهم (پس از این که آتش‌بس پذیرفته شد و اوضاع تا حدی به حالت عادی خود باز گشت) اینترنت نیز به صورت فاز به فاز طی ۲۴ تا ۷۲ ساعت به حالت قبلی خود برگشت.

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

بهرحال کاری با این نداریم. در شرایط اخیر نیز همچنان وضعیت همان است. کسب و کارهایی که تصمیم به تعطیلی گرفتند و بسیاری در آستانه فروپاشی و تعطیلی هستند. بسیاری نیز منتظر فرصت مناسبی هستند تا تعدیل مودبانه انجام دهند (فی‌الواقع، عدم تمدید قرارداد برای سال جدید یا اعلام به نیروها که در سال جدید پذیرای ایشان نخواهند بود) و یا این که به شکل کلاسیک، تعدیل را انجام دهند.

از طرف دیگر، حجم مشتریان کاهش بسزایی دارد. نه به این خاطر که به اینترنت دسترسی ندارند، بلکه بخاطر این که وضعیت اقتصادی خوبی را تجربه نمی‌کنیم و منطقی و درست است که شخص، به جای آن که هوش مصنوعی تولید تصویر یا پلتفرم پخش موسیقی‌اش را شارژ کند، ترجیحش بر آن باشد که همان مبلغ را برای تهیه اقلام غذایی یا دارو پس‌انداز کند و این هم به خوبی قابل درک است.

کسب و کار در بحران، چگونه دوام بیاوریم؟

حقیقت این است که در چنین شرایطی، هیچ شخصی نمی‌تواند به شما یک رسپی درست برای دوام آوردن ارائه کند. با این که بسیاری از پاهای ثابت وبسایت ایسمینار (یا همان پکیج‌فروشانی که نهایت هنرشان این باشد که دستور poweroff در لینوکس را بدون تپق زدن به شما آموزش دهند و آن را به یک ویدئوی بیست دقیقه‌ای در آپارات تبدیل کنند) در حال فروختن پکیج‌ها «کسب و کار در بحران» و «کسب و کار در اینترنت ملی» و … به شما هستند، اما معمولا این افراد محتوایی کاملا تاریخ‌مصرف‌دار و سوپرمارکتی را به شما ارائه می‌کنند.

در طول این مدت هم زیاد پیش می‌آمد که در بسترهایی مانند «بله» با دوستان خود بحث کنیم که چطور می‌توانیم در این شرایط، دوام بیاوریم و خب در نهایت این پرسش‌ها با بن‌بست‌های تاریخی روبرو می‌شد. اما شاید بتوان در این مورد کمی بحث کرد و به نتایجی رسید.

در ادامه، بخشی از نتایجی که به آن رسیدیم را با شما به اشتراک می‌گذارم.

ایجاد درآمد خارجی، فقط توهم است.

شاید یک سال پیش توهم نبود اما در حال حاضر فقط توهم است. در ایران شما نمی‌توانید به راحتی درگاه پرداخت خارجی تهیه کنید و درگاه رمزارزی، مقبولیت چندانی ندارد (بخصوص اگر رمز تنها گزینه پرداختی باشد، معمولا شک زیادی در مخاطب خارجی ایجاد می‌کند که شما کلاهبردار باشید و …) و طبیعتا برای دریافت درگاه خارجی شما ملزم به ایجاد ارتباطی در خارج از کشور هستید.

کارهای فری‌لنسری و کار از راه دور نیز از روی میز حذف می‌شوند چرا که هیچ‌کس نمی‌داند چه زمانی و به چه مقدار قرار است دسترسی‌ها محدود شود و طبیعی است که به این شکل، تمامی کارفرماهای خارج از کشور (حتی ایرانی‌ها) ترجیحشان کار با افرادی از هند یا ویتنام باشد و به نیروهای انسانی داخل ایران اهمیتی ندهند.

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

کسب و کارهای مدرن، نیازمند حجم زیادی از منابع سخت‌افزاری مانند GPU یا TPU یا حتی مقدار زیادی رم و پردازنده هستند و حتی بهترین(!) پرووایدرهای ایرانی نیز از تامین سخت‌افزار کافی برای آن‌ها، عاجز. چیزی که مشخص است این است که با این که بسیاری از افراد به دنبال کپی مدل‌ کسب و کارهای چینی برای بقا هستند، زیرساختی به گستردگی چین در اختیار نداریم.

یک مثال برای شما بیاورم آن هم این است که در طول دو قطعی اینترنت اخیر، وبسایت گپ‌جی‌پی‌تی که یکی از خدمات‌دهندگان سامانه‌های هوش مصنوعی است، در این مدت به جای مدل‌هایی مانند GPT-5.2 و یا Grok 4 و …، در حال ارائه مدل‌های کوچکتر احتمالا کوئن ۸ یا ۱۴ میلیارد پارامتری بود. حتی همین مدل‌ها، با این که به شدت سبک هستند و به سادگی می‌توانند روی یک گرافیک خوب مانند ۴۰۹۰ پاسخگوی تعداد زیادی کاربر باشند با کندی‌های شدید مواجه بود.

سوال این است، وقتی که یک استارتاپ قادر به تامین حتی یک ۴۰۹۰ نیست و دلیلش هم درآمد نیست (قاعدتا اگر قیمت‌های همان پلتفرم را چک کنید متوجه منظور خواهید شد) چه دلیلی دارد جز این که زیرساخت کافی در کشور وجود ندارد؟

انتظارات کاربران را نمی‌شود برآورده کرد!

مهم‌ترین رکن کسب و کار دیجیتال، میزان رضایت کاربران است تا با ریزش یا به عبارتی churn روبرو نشویم. اما در چنین شرایطی، برآورده‌سازی انتظارات کاربران تقریبا محال است.

به ابتدای مطلب و موضوع پارچ‌لینوکس برگردیم. پارچ‌لینوکس حتی در دسته کسب و کار هم قرار نمی‌گیرد و صرفا یک پروژه آزاد است و اصولا در پروژه آزاد و ناسودبر، شما تعهدی نسبت به کاربران ندارید. اما با این حال بسیاری از کاربران با علم به شرایط شاکی بودند که چرا قادر به نصب بسته و یا بروزرسانی سیستم‌عامل خود نیستند.

حالا در همین حال، تصور کنید که کسب و کاری که پول دریافت کرده و سودبر است، تعهداتی دارد که باید به آن عمل کند. در واقع همین تعهدات می‌تواند کسب و کار را زمین بزند. بسیاری از کسب و کارها، قول پشتیبانی در زمان بحران می‌دهند، قول جبران مافات می‌دهند و جالب این است که این موضوع همیشه در کسب و کارهای کوچک رخ می‌دهد و دانه‌درشت‌های اکوسیستم(!) معمولا به هیچ کجایشان هم نیست که چقدر از اعتبار، بسته یا آستانه مصرف مشتری هدر شده تا جبران کنند.

کسب و کار جدید تقریبا نشدنی است.

این هم نیازی به توضیح ندارد. کسب و کار جدید، امریست تقریبا نشدنی. چرا که شما باید بتوانید کاربر جذب کنید، کاربر را وفادار کنید و بتوانید از کاربرانتان پول دریافت کنید.

و در شرایطی که همه چیز ناپایدار است، این واقعا نشدنی‌ترین امر ممکن است. واقعا توضیح بیشتری برای این بخش به ذهنم نمی‌رسد. مگر این که اتفاق دیگری بخواهد رخ دهد که نمی‌دانیم چیست. بهرحال، فعلا بهتر است کمی دست نگه داریم.

جمع‌بندی

در پایان، باید بگویم که نوشتن بلاگ‌های طولانی برای من طاقت‌فرسا شده است چرا که نمی‌توانم تمرکز درستی داشته باشم. با این که تلاش می‌کنم در ادامه بیشتر بنویسم و احتمالا دو یا سه پست دیگر در طی روزهای آتی منتشر کنم (حداقل تا زمانی که به بلاگ دسترسی دارم و اینترنت خاموش نشده است) و موضوعات مختلفی در این پست‌ها پوشش داده خواهد شد.

در این پست، در مورد این که بحران‌ها چطور به ابربحران تبدیل می‌شوند و چطور باعث نابودی کسب و کار شما می‌شوند صحبت کردیم. مشخص نیست چه زمانی می‌شود اعلام کرد که می‌توانیم یک کسب و کار بدون دردسر ایجاد کنیم، اما خب نکته اصلی اینجاست که کسب و کار بدون مشتری به هیچ دردی نخواهد خورد.

در نهایت هم باید گفت که در حال حاضر اگر کمی دست نگه داریم و شرایط را بررسی درعمق‌تری کنیم، بهتر است و در نتیجه بهتر می‌توانیم پیرامون ایجاد یک کسب و کار، تصمیم‌گیری کنیم.

Share

چطور MCPها مشکل زبان‌نفهمی مدل‌ها را حل می‌کنند؟

از زمانی که مدل‌های هوش مصنوعی متنی یا همان مدل‌های بزرگ زبانی (Large Language Model) مثل ChatGPT ارائه شدند، همیشه یک مشکل بزرگ داشتند، این که زبان‌نفهم بودند! در واقع این زبان نفهمی در مدل‌های کوچک‌تر مثل مارال شاید بیش‌تر دیده می‌شد اما منظور و مقصود این مطلب، هذیان‌گویی یا درک نکردن مطالب ورودی نیست، بلکه عدم درک درست از ابزارهاییه که به خورد مدل‌ها داده میشه. این مساله، در ابتداء با عوامل هوش مصنوعی یا همان ایجنت‌ها حل شد. ساخت یک ایجنت کار بسیار ساده‌ایه و خب این موضوع اینجا پوشش داده شده و می‌تونید اون رو بخونید.

اما در سال گذشته شرکت Anthropic که سازنده مدل Claudeئه ابزاری ارائه کرد به اسم MCP که باید ببینیم چیه و چطور کار می‌کنه. در این پست، تمام تلاشم اینه که به ساده‌ترین زبان ممکن، MCP Serverها و این که چطور مشکل زبان‌نفهمی رو حل کردند رو برای شما توضیح بدم چون تا جایی که گشتم مطالب فارسی خوبی در موردش نبود یا اگر هم بود، در صفحات اینستاگرامی و تلگرامی بود که در وب قابل دسترسی نیستند.

اصلا MCP چیه و چطور کار می‌کنه؟

خب این یک سوال خیلی مهمه. ابتدا باید ببینیم MCP یعنی چی و چطور کار می‌کنه و چرا انقدر مهمه. پس اول بیایید یک فرض داشته باشیم. این فرض ممکنه خیلی شبیه به تست اتاق چینی (یکی از تست‌های مطرح و مشهور هوش مصنوعی) به نظر بیاد و خب تا حد زیادی همونه. اول اتاق چینی رو توضیح میدم و بعد یک مثال ملموس‌تر می‌زنم و بعد می‌ریم سراغ ادامه ماجرا.

تست اتاق چینی به این شکله که اگر شما در یک اتاق گیر بیفتید و یک سری ابزار و وسایل باشه، همراه اونا هم یه سری راهنما به زبان چینی، احتمالا صرفا با دنبال کردن نمادهایی که در راهنماها وجود داره می‌تونید در اون اتاق زنده بمونید و یا ازش بیایید بیرون. این موضوع در زبان‌آموزی و مثال ملموس‌تر ما، کاربردیه. چطور؟

فرض کنیم شما بخواهید زبان اسپانیایی یاد بگیرید (زبانی به شدت راحت‌تر از چینی) و خب احتمالا یکی از کارهایی که می‌کنید اینه که زبان گوشی یا رایانه شخصیتون رو به زبان اسپانیایی تغییر می‌دید. در این حالت جاهای آشنا رو می‌بینید. مثلا می‌تونید درک کنید که دکمه‌های قرمز احتمالا برای پاک یا متوقف کردن هستند، دکمه‌های سبز برای تایید و اجرا و الی آخر.

حالا MCP دقیقا همینه، یک راهنماست که مدل هوش مصنوعی بتونه از اتاق چینی بیاد بیرون. چطوری؟ با کمک Context. در واقع اسمش روشه Model Context Protocol یا «شیوه‌نامه متن مدل». و حتی چیز خیلی جدیدی هم نیست، فقط یک روش متفاوت از روش‌های پیشینه که برای اجرای ایجنت‌ها داشتیم.

ساز و کار  MCP زیر ذره‌بین

به جای این که این قسمت رو با دیاگرام‌های غیرقابل فهم پر کنم، خیلی ساده در مورد یک مساله فرضی توضیح می‌دم و MCP رو بیشتر می‌شکافم.

اول از همه، اگر دقت کنید اکثر MCP ها عنوان Server رو یدک می‌کشن، یعنی یک خدمتی ارائه میدن. پس کلاینت ما اینجا، خود مدل هوش مصنوعیمونه. مثلا Claude, ChatGPT یا حتی مدلی که توسط Ollama داریم روی کامپیوتر شخصیمون ران می‌کنیم.

یک سناریوی فرضی داریم. مثلا شما می‌خواهید از جایی مثل «اسنپ‌فود» سفارش ثبت کنید. وارد رابط هوش مصنوعی می‌شید و بهش می‌گید «برای من از رستوران X یک کارامل ماکیاتو ۱۰۰٪ عربیکا سفارش بده».

حالا چه اتفاقاتی در پشت صحنه رخ می‌ده؟

  • اول، MCP Server لیست ابزارهای خودش رو برمی‌گردونه. اینجا می‌تونه list_cafes باشه، می‌تونه get_order باشه و … . هرکدوم از این ابزارها، همراه یک توضیح ریزی بر می‌گردند. شبیه به چیزی که در Open API یا همون Swagger داریم.
  • اینجا مطابق ابزارها و توضیحاتشون، مدل ما باید درخواست رو بشکنه. پس چه کار می‌کنه؟
    • طبق پرامپت اولیه ما، اسم رستوران رو تشخیص میده و منوش رو از ابزار مورد استفاده، دریافت می‌کنه.
    • با ابزار جست و جو در منو، درک می‌کنه آیا کارامل ماکیاتو به صورت ۱۰۰ عربیکا موجود دارند یا نه. ممکنه اینجا از ابزار «بررسی موجودی» هم استفاده کنه.
    • در صورت موجود بودن، ممکنه به ما بگه موجوده و قیمتش ۱۰۰ هزار تومان به ازای هر فنجانه. ۲۰ هزار تومان هم هزینه ارسالش به آدرس شماست.
    • اینجا شما می‌گید «بسیار عالی سفارش رو ثبت کن».
    • بعد اینجا، ابزار ثبت سفارش رو صدا می‌زنه. بعد از اون، به شما یک سفارش تایید نشده میده، همراه لینک پرداخت. بعد از پرداخت شما، احتمالا یک ریکوئست دیگه میره سمت سرور که چک کنه پرداخت شده یا نه. حتی اینجا ممکنه شماره پرداخت و … هم از شما دریافت بشه که با ابزار متناسب، چک کنند آیا این پرداختی انجام شده که سفارش انجام شه یا خیر.
    • بعد از اون شما صرفا با «چت کردن» می‌تونید از وضعیت سفارشتون آگاه شید.
  • پس از این، هربار بخواهید سفارشی ثبت کنید، یک MCP بین شما و اسنپ‌فود هست که سفارشتون رو مثل سابق (زنگ زدن به رستوران و درخواست یک سفارش خاص) ثبت و پردازش کنه.

عملکرد MCP به این شکله و خب همونطوری که می‌بینید، در واقع به جای این که چند ابزار رو به زور بخواهیم به خورد مدل زبانی بدیم، همه رو می‌بریم زیر پرچم یک ابزار و اون رو تبدیل می‌کنیم به یک MCP سرور.

مزایا و معایب MCP ها

طبیعتا وقتی یک ابزار جدید معرفی میشه، مزایا و معایب اون هم باید زیر نظر داشته باشبم. به همین خاطر، اینجا مزایا و معایبی که خودم بهش رسیدم رو هم براتون لیست می‌کنم که خب شاید در استفاده از MCPها مد نظر داشته باشیدش.

مزایای MCPها

  • استانداردسازی ارتباط با ابزارها: از اونجایی که MCP یک پروتکل یا شیوه‌نامه به حساب میاد، میشه گفت که همه چیز رو به شکل استانداردی درمیاره. پس این موضوع، موضوع مهم و حائز اهمیتی خواهد بود. در واقع می‌دونیم که یک استاندارد جامع داریم که مدل‌های زبانیمون بتونن بفهمنشون.
  • کنترل بهتر روی جریان داده: از اونجایی که وظیفه اصلی مدل زبانی ما میشه تبدیل محتوای «قابل خواندن برای انسان» یا Human Readable به محتوای «قابل خواندن برای کامپیوتر» یا Machine Readable (محتوایی مثل XML, JSON, YAML و …) کنترل بهتری روی جریان داده‌ها هم خواهیم داشت. در واقع می‌تونیم اینجا داده‌های ورودی کاربر رو هم ذخیره کنیم و مورد بررسی قرار بدیم (طبیعتا با اطلاع کاربر).
  • مقیاس‌پذیری: یکی از بزرگترین گلوگاه‌های بیزنس‌های هوش مصنوعی، همیشه مقیاس‌پذیری نسبتا پایینیه که دارند. تقریبا هرجایی که مانی رو پرزنت می‌کردم، بعد از این سوال کلیشه‌ای مسخره که با میدجرنی چه فرقی داره می‌پرسیدند شما چطوری اسکیل می‌کنید؟ خب MCPها این مساله رو هم حل می‌کنند. در واقع می‌تونن برای چند مدل، چندین و چند کاربر و … همزمان کار کنند و مشکلات مرتبط رو به راحتی کاهش بدن.

معایب MCPها

  • پیچیدگی در پیاده‌سازی اولیه: از اونجایی که میشه MCPها رو نوعی از IaC یا Infrastructure as Code دونست، میشه گفت این مشکل جهان‌شمول پیاده‌سازی اولیه طولانی رو همه ابزارهای این‌چنینی دارند. حداقل روی خوب ماجرا اینه که این کار «فقط یک بار» انجام داده میشه و بعدش نیاز به تکرار مکررات نیست.
  • وابستگی به کیفیت مدل: طبیعتا مدلی مثل Gemma 27B با مدلی مثل OpenAI GPT 5 در کیفیت یکسان نیست و باید این رو هم خودتون و هم مشتری‌های احتمالیتون در نظر بگیره. حالا باز با استفاده از مدل‌های بزرگتر، این مشکل تا حد زیادی پوشش داده میشه. یعنی رفتن سمت مدلی مثل GLM یا Kimi K2 یا DeepSeek V3.1 و …، این مسائل رو می‌تونیم تا حد بسیار خوبی حل کنیم.
  • استفاده زیاد از توکن: در نهایت، از اونجایی که هربار مدل رو در نقش «کلاینت» قرار می‌دیم، تعداد زیادی توکن مصرف میشه که البته این موضوع هم تا حد خیلی خوبی، توسط شرکت‌هایی مثل Cloudflare یا حتی خود آنتروپیک، در حال حل شدنه که در آینده نه چندان دور در موردش خواهم نوشت.

همانطور که می‌بینید، MCP هم روش خالی از عیب و ایرادی نیست ولی روش مطمئن و خوبی برای اجرای ابزارهامون از طریق مدل‌های زبانیه. شما می‌تونید از این روش استفاده کنید و مثلا گوگل کلندر یا اینستاگرامتون رو مدیریت کنید یا چند مدل رو به هم متصل کنید و یک ابرابزار بسازید. در نهایت، همه چیز برمی‌گرده به این که خودتون قصد انجام چه کاری داشته باشید.

سخن پایانی

در پایان باید این موضوع رو متذکر بشم که هوش مصنوعی، مثل همه ابزارهایی که تا الان ازش استفاده کردیم، یک ابزاره. یک ابزار برای پیش‌برد کارهامون و به قول سرمایه‌گذاران سیلیکون‌ولی، برای انجام کارهای بیشتر در زمان کوتاهتر و خب دلیل محبوبیت و جذابیت زیادش هم برای عموم مردم، تا الان همین بوده. هرچیزی که هم که حول هوش مصنوعی ساخته شده مثل همین MCP ها، دقیقا برای اینه که زندگی ما راحتتر بشه و کارهای تکرار پذیرمون کمتر.

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

Share

اقتصاد API محور – چگونه Wrapper ها ما را به کشتن خواهند داد؟

مدت زیادی می‌شد که هرجا برای جذب سرمایه یا حتی حمایتی برای پلتفرم هوش مصنوعی مانی می‌رفتم، سوال اصلی این بود «چرا یک API از دالی یا میدجرنی نمی‌گیری خودتو راحت کنی؟» و حتی با این که خیلی هم حرف بی‌راهی نیست و تولیدکننده تصویر چیز خاصی نیست که بابت دیتا بخواهیم نگرانی بزرگی داشته باشیم، پاسخ‌های متعددی می‌دادم.

و خب طبیعیه که در طی چند سال گذشته سرویس‌های زیادی مانند اول‌ای‌آی اومدند که به شما امکان ساخت wrapper روی APIهای مدل‌های زبانی و تصویری متعددی رو میدن. در این مطلب، میخواهیم یک بررسی جامعه داشته باشیم که چرا این API wrapper ها می‌تونن ما و کسب و کارمون رو به ته دره هدایت کنند 🙂

اصلا API Wrapper یعنی چی؟

در دنیای هوش مصنوعی ما دو تا راه داریم که یک محصول بسازیم. تقریبا میشه گفت بسته به شرایط، یکی می‌تونه نسبت به اون یکی برتری داشته باشه اما در این مطلب، میخواهیم ببینیم که «معایب» ساخت API Wrapper چیه. به همین خاطر اول به این پرسش باید پاسخ داد که «اصلا API Wrapper یعنی چی؟»

فعل wrap در زبان انگلیسی یعنی چیزی که به چیز دیگر احاطه پیدا می‌کنه و اون رو می‌پوشونه. یعنی ما ابزاری بسازیم که در واقع فقط فرانت‌اند یک API معروف (مثل OpenAI) باشه.

حالا خیلی‌ها این API رو مستقیم از OpenAI یا DeepSeek یا MiniMax تهیه می‌کنند، یا از واسطه‌های خارجی مثل UseAPI و OpenRouter و یا این که از واسطه داخلی مثل اول‌ای‌آی و لیارا.

در این مقاله، کاری نداریم که API از کجا تهیه میشه، بلکه اصل داستان اینه که چرا این روش، در خیلی موارد روش خوبی برای توسعه محصول نیست و راه‌حل‌های جایگزین چی می‌تونه باشه.

چرا ساخت API Wrapper ایده خوبی نیست؟

در اینجا مواردی رو میارم که ساخت API Wrapper ایده خوبی نیست. شاید در پستی در آینده، مواردی رو برشمردم که اتفاقا می‌تونه ایده خوبی هم باشه.

در حال حاضر، تمرکز ما روی اون دوستانیه که با API دمو می‌کنند و مدعی میشن مدل خودشونه و این داستانا که اتفاقا عمدتا هم وقتی به سیستم‌های Air Gap یا لوکال میان، تازه مشخص میشه دموشون چقدر دروغ و دغل بوده.

خلاقیت رو ازمون می‌گیره

اولین و شاید مهم‌ترین بخش استفاده از APIها دقیقا اینه که خلاقیت ما رو می‌گیره. مثلا در نسخه‌های اولیه مانی، یک جا روشی که «میدجرنی» برای تولید عکس پیش می‌گرفت رو برای ساخت تصویر با کمک مدل خودمون تست کردم و نتیجه‌ش رو می‌تونید از این لینک مطالعه کنید.

اینجا، اگر خودم دست به Google Colab و Stable Diffusion نمی‌بردم، قاعدتا امکان این که بتونم پروسه میدجرنی رو تا حد زیادی مهندسی معکوس کنم، وجود نداشت.

جریان داده دست خودمون نیست

جریان داده در کسب و کارهای مختلف مهمه، کدهای شما، نامه‌های اداری و اطلاعات مشتریانتون مهمه. نتیجتا اگر میخواهید امنیت بالاتری رو داشته باشید، بهتره از APIها استفاده نکنید.

یا اگر هم سراغ API ها می‌رین، برید سراغ خود تامین‌کننده‌های رسمی. به جز خود OpenAI و Anthropic و DeepSeek معمولا Open Router و Together AI هم جزء تامین‌کنندگان رسمی مدل‌های زبانی هستند. همچنین Fal AI, Runware و Replicate هم جزء تامین‌کنندگان رسمی مدل‌های ویدئویی و تصویری هستند و می‌تونید از این دوستان هم API رو تهیه کنید.

آفلاین نیست

آخرین و شاید یکی از مهم‌ترین ارکان APIها – بخصوص برای مایی که در ایران زندگی می‌کنیم – این موضوعه. این موضوع یک عیب بزرگه و خب میشه با ابزارهایی مانند Ollama تا حدی از پسش بر اومد.

چطور ممکنه API Wrapper به کشتنمون بده؟

سناریوها رو به ترتیب می‌نویسم، این‌ها توضیحات زیادی ندارند چون کاملا موردی بهشون رسیدم و اگر توضیحات اضافه‌ای به ذهنم برسه قطع به یقین، در مطلبی جداگانه همه رو توضیح میدم.

  • تعطیلی ارائه‌دهنده
  • قطع و وصل شدن API (چیزی که بخصوص در APIهای واسط مثل اول‌ای‌آی کاملا پیش میاد)
  • هک شدن API و لو رفتن دیتا
  • ارسال دیتا به واسطه‌هایی که ازشون مطمئن نیستیم
  • عدم کنترل روی محصول وقتی اینترنت با مشکل مواجه می‌شه.

ممکنه مشکلات دیگری هم در میان باشه، اگر شما هم چیزی به ذهنتون رسید می‌تونید همینجا در بخش نظرات بهم بگید.

جمع‌بندی

در کل API Wrapper نوشتن برای پروژه‌های عام‌منظوره، کار عجیب و بدی نیست و خب هزینه خروج و شکست رو به وضوح کمتر می‌کنه، در حالی که برای انجام کار جدی و حساس، گزینه مناسبی نیست. اگر هرکدوم از معایبی که برشمرده شد رو تونستید برطرف کنید، احتمالا گزینه مناسبی برای شما، پروژه یا کسب و کارتونه؛ در غیر اینصورت باید کمی Local تر فکر کنید.

در نهایت، ازتون ممنونم که وقت گذاشتید و این مطلب رو خوندید. باز هم اگر نظر و پیشنهادی پیرامونش داشتید، ممنون میشم در بخش نظرات همین بلاگ یا بخش گفتگوی کانال تلگرام به من بگید.

Share

یک تخم مرغ اضافه کن: رساله‌ای در باب اثر IKEA

احتمالا شما هم در دهه هشتاد شمسی، تبلیغ معروف تلویزیونی «به همین سادگی، به همین خوشمزگی، پودر کیک رشد» رو یادتون باشه. پودرهای کیک آماده، یکی از اختراعات جالب بشر بودند که هنوز هم فکر کردن بهشون برای من شخصا جالبه. اما موضوعی که وجود داره، اینه که این پودرها، باعث شدند مفهومی به اسم اثر IKEA یا IKEA Effect به وجود بیاد.

در این مقاله، قصد دارم که ربط پودر کیک آماده به آیکیا رو توضیح بدم و بگم که چرا مهمه که از اثر آیکیا در تولید محصول استفاده کنیم و در نهایت هم یک نمونه خیلی خوبی از اثر آیکیا رو با هم نظاره‌گر خواهیم بود.

پودر کیک آماده: مردها هم آشپزی می‌کنند!

در سال ۱۹۳۰ میلادی شرکتی با نام Duff and Sons محصولی به بازار ارائه کرد. پودر کیک آماده! این محصول با شعار مردها هم آشپزی می‌کنند سعی داشت بگه در حدی کار پختن کیک رو ساده کرده که آقایون هم می‌تونن صرفا با اضافه کردن آب یا شیر به این پودر و قرار دادنش در فر، کیک بپزند.

اما یک مشکلی به مدت دو دهه، گریبان این محصول رو گرفت. نه فقط شرکت Duff and Sons بلکه هر شرکت دیگری که پودر کیک تولید می‌کرد، چنین معضلی رو باهاش روبرو بود. نمی‌تونستند بفروشند.

اما چرا یک محصولی که همه جوره کامل بود نمی‌تونست بفروشه؟ آیا مساله اعتماد بود؟ آیا مساله کیفیت بود؟ نه. اتفاقا مشتریان هرچند اندک این شرکت‌ها، از کیفیت کیکی که به دست می‌آوردند راضی بودند و کاملا به تولیدکننده اعتماد می‌کردند.

باگ ماجرا جای دیگری بود. شاید جایی که این محصول سعی داشت به طور کلی دخالت انسان در پخت کیک رو حذف کنه و این خوشایند خیلی از افراد نبود. مثل همون کاری که خیلی‌ها انتظار دارند ایجنت‌های هوش مصنوعی انجام بدند.

یک تخم مرغ اضافه کنید!

بالاخره بعد از دو دهه که محصول «پودر کیک آماده» در بازار موجود بود، شرکتی به نام Betty Crocker اومد و یک ایده بهتری داد. این‌ها گفتند که چطوره خود مشتری هم بخشی از پروسه تولید کیک بشه؟

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

همین هک ساده، باعث افزایش چند برابری فروش این محصول شد. اما حالا ربطش به آیکیا چیه؟ بهتره یه بررسی روی آیکیا داشته باشیم!

آیکیا: کسب و کار اضافه کردن تخم مرغ به پودر کیک

اگر در فضای کسب و کار و بخصوص حوزه لوازم خانگی فعال باشید حتما اسم آیکیا رو شنیدید. یک برند سوئدی که بخاطر یک موضوع خیلی معروفه:

هرچیزی که ازش می‌خرید رو خودتون باید سر هم کنید.

در واقع آیکیا کار طراحی، برش، سوراخ‌کاری و به طور کلی فرایندهای کارگاهی رو روی محصول مورد نظر مثل کتابخونه، انجام داده. شما فقط و فقط باید این‌ها رو به هم وصل کنید. حتی می‌تونید هزینه‌ای پرداخت کنید که کارشناسی از آیکیا بیاد و برای شما چنین کاری کنه.

اما چرا این موضوع «سرهم کردن کتابخونه توسط خودمون» خیلی مهمه؟ چون داره مشتری رو وارد پروسه تولید می‌کنه و این یعنی فروش حس به مشتری.

اگر دقت کنید، خیلی از برندهای معروف جهان، مثل اپل، رولکس، گوچی، لامبورگینی و … بیش از این که روی محصول تمرکز کنند دارند روی حسی که مشتری از محصولشون دریافت می‌کنه تمرکز می‌کنند. برای مثال شعار خودروساز ایتالیایی، فراری؛ این بوده که شما وقتی یک فراری می‌خرید که بخواهید برای خودتون کسی باشید. در واقع به این شکل خاص بودن خودروهای خودش رو نشون داده و این خاص بودن رو به مشتری هم انتقال داده.

این مورد که مشتری رو بخشی از فرایند تولید محصول کنیم، بخاطر همین حرکت آیکیا به اثر آیکیا معروف شده و حتی باعث شده که آیکیا طرفدار خاص خودش رو پیدا کنه. یک برندی که نه لاکچریه نه حتی عقبه خیلی خاصی داره و صرفا یک برند مبلمان و لوازم خانگی با کیفیت مطلوبه، بتونه برای خودش یک جامعه هواداری تشکیل بده و این رو با ایجاد یک حس خوب در مشتری تونسته داشته باشه!

اثر آیکیا در خدمت تکنولوژی

قبل از این که بخوام از نمونه‌های عملی اثر آیکیا در تکنولوژی صحبت کنم، لازمه ذکر کنم خود آیکیا، از اثر آیکیا در تکنولوژی استفاده کرده. چطور؟ خیلی ساده‌ست.

آیکیا از اولین برندهای لوازم خانگی بوده که تکنولوژی واقعیت افزوده رو به سیستم‌های نرم‌افزاریش من‌جمله وبسایت و اپلیکیشنش اضافه کرد و اینطوری حتی حس داشتن محصولاتش رو قبل از خرید هم تونست به کاربران منتقل کنه.

اما در یک سال اخیر، ابزارهای جالبی مثل Bolt یا v0 دیدیم. این ابزارها هم در واقع همین اثر آیکیا رو دارند در زمینه برنامه‌نویسی و تولید نرم‌افزار پیاده‌سازی می‌کنند.

این ابزارها به افرادی که تجربه زیادی در راه‌اندازی استارتاپ یا ساخت نرم‌افزار ندارند، کمک می‌کننده ایده‌هاشون رو بتونن پیاده‌سازی و ارزیابی کنند و اون دسته افرادی که کمی کارکشته‌تر بودند، تونستند از این ابزارها برای جلو انداختن کار خودشون نهایت استفاده رو ببرند و در مدت‌زمان بسیار کوتاهی، نرم‌افزارهایی بسازند که بتونه درآمدزایی داشته باشه یا اصلا به صورت کامل توسط یک موجودیت دیگر تملیک بشه.

خلاصه اثر آیکیا، یک حجم خوبی دوپامین رو در مغز مشتری شما ترشح می‌کنه و این امر باعث میشه مشتری شما نوعی اعتیاد به محصولتون پیدا کنه. احتمالا در آینده از این که چطور می‌تونیم این اثر رو در محصولاتمون داشته باشیم، بنویسم!

جمع‌بندی

در عصر امروز، جذب مشتری سخت‌تر از گذشته شده. بسیاری از محصولاتی که ما می‌سازیم، بهترش توسط غول‌های بازار ساخته و عرضه میشه و ما باید بتونیم از چنین آشفته‌بازاری، جان سالم به در ببریم. استفاده از هک‌های ساده‌ای مثل یک تخم‌مرغ اضافه کن یا همین اثر آیکیا، می‌تونه به راحتی جذب تعداد خوبی از مشتری‌های ما رو تضمین کنه. به همین دلیل، پس از مدت نسبتا طولانی دست به قلم (کی‌برد؟) شدم و این مطلب رو نوشتم تا اگر شما هم در حال توسعه محصولی هستید، به نکاتی که حول جذب مشتری با این هک‌های شناختی وجود داره توجهی دوچندان کنید.

ضمنا در حال حاضر که بحث اتوماسین و ایجنت‌ها داغه، لازمه بگم که یک دوره n8n ضبط کردم که از طریق آکادمی نُد در دسترسه و به صورت هفتگی هم آپدیت روی اون میاد. اگر علاقمندید می‌تونید در این دوره هم شرکت کنید.

در پایان امیدوارم موفق و موید باشید و از خیزش ربات‌ها هم نترسید 🙂

Share

برای ساخت agent های هوش مصنوعی، فقط به پایتون نیاز دارید!

پاییز دو سال پیش بود که ChatGPT آمد و به شکل خاصی بازار همه چیز رو عوض کرد یا بهتره بگم که به هم ریخت 😁 در این مدت نه فقط OpenAI که هزاران شرکت دیگر هم دست به کار شدند و شروع کردند به ارائه مدل‌های زبانی بزرگ یا همون LLMها و خواستند که به شکلی با OpenAI رقابت کنند.

الان که دو سالی از اون روزها گذشته منتها موضوع کمی تفاوت داره و بیش از این که سمت ارائه مدل بریم، بهتره به سمت agent یا «عامل» بریم که خب خودش یک بحث مفصله.

دیشب، در بلاگ انگلیسیم کمی در مورد مدل‌های بزرگ و ایجنت‌ها صحبت کردم و امروز تصمیم گرفتم که بلاگ فارسیش رو هم بنویسم که هر دو طرف، محتوای مناسب رو داشته باشیم.

ایجنت‌ها، عملگرایی به LLMها اضافه می‌کنند.

اگر دنبال‌کننده بلاگ و در کل محتوای من باشید، احتمالا می‌دونید که من هم در بازی LLM بودم و مثلا یکی از LLMهای اوپن سورسی که روش کار کردم مدل مارال هفت میلیارد پارامتری بود که روی Alpaca Persian تمرین داده شد.

اما آیا یک مدلی که سوال-جواب کنه کافیه یا به چیزی بیشتر نیاز داریم؟ در واقع برای این که LLMها بتونن موثر واقع بشن، باید بتونن با ابزارهای مختلف تعامل کنند. حالا شما فرض کنید که بخواهیم این تعامل رو در سطح فاین‌تیون کردن، به مدل اضافه کنیم.

یعنی فرض کنید که ما APIهایی از دیجی‌کالا، اسنپ، دیوار و مثلا ابر آروان بگیریم. سعی کنیم با کمک تعدادی API Call نمونه، مدل رو تیون کنیم. حالا فرض کنید یک نفر بخواد این مدل رو برای استفاده از تپسی یا باسلام به کار بگیره. چی میشه؟ هیچی! مجددا بار فاین‌تیون با APIهای جدید میفته روی دوش کاربر.

برای حل این مشکل، ما نیاز به agentها داریم. در واقع در مثال‌های فوق هر API و ابزاری که لازم داریم رو برمیداریم، می‌بریم یک جایی براشون توابع درستی می‌نویسیم و سپس با کمک LLMها خروجی رو «انسانی» یا Humanize می‌کنیم. به این شکل بار فاین‌تیون کردن LLMهم به دوش نمی‌کشیم و همه چیز هم عالی پیش خواهد رفت.

ساخت ایجنت بدون استفاده از فریمورک

دقیقا از زمانی که OpenAI و سایر شرکت‌هایی که LLM ارائه دادند APIهای چت و یا Instruction Following خودشون رو هم ارائه کردند، فریمورک‌های زیادی مثل Flowise یا Crew AI ساخته شدند که به شما کمک کنند تا ایجنت بسازید.

اما راستش رو بخواهید – همونطور که در بلاگ انگلیسی هم توضیح داده بودم – خیلی از این فریمورک‌ها یه حجم عجیب و غریبی از پیچیدگی رو به فرایند ساخت ایجنت دارند اضافه می‌کنند.

نتیجه این شد که شخصا به دنبال روشی گشتم که بتونم بدون استفاده از فریمورک خاصی، به راحتی بتونیم یک ایجنت بسازیم. برای همین لازم بود که درک کنم ایجنت اصلا چی کار می‌کنه؟ چرا انقدر مهمه که ما بتونیم ایجنت رو درک کنیم؟ و صدالبته از هر ایجنتی که اسمش «اسمیت» باشه دوری بجوییم 😂

ایجنت‌ها یک سری «وظیفه» و «ورودی مناسب هر وظیفه» رو درک می‌کنند. این وظایف یا تسک‌ها در واقع توابعی هستند که در برنامه‌مون قرار ادادیم که بتونن یک کاری رو انجام بدن (مثلا بره رخداد n ام سری فیبوناچی رو حساب کنه) و ورودی‌هاشون هم دیتاییه که ایجنت باید با هوش خودش تشخیص بده و بسازه.

در نهایت نیاز به مکانیزمی داریم که بیاد این وظایف و ورودی‌ها رو اجرا کنه، خروجیشون رو دوباره بده به LLM و ازش بخواد که Humanizeش کنه. گذشته از این بد نیست که ایجنت ما یک حافظه کوچکی هم داشته باشه.

نمونه یک ایجنت ساده با پایتون

سلب ادعا: از اونجایی که کد این ایجنت رو در گیتهاب گذاشتم، صرفا مراحل ساخت ایجنت ساده رو توضیح میدم و باقیش رو میتونید از گیتهابم ببینید و ایده بگیرید.

اولین گام ما برای ساخت ایجنت باید این باشه که یک LLM مناسب انتخاب کنیم. شما مختارید هر LLMای که یک OpenAI Compatible API ارائه می‌ده انتخاب کنید اما من شخصا دارم از پروژه جبیر خودم استفاده می‌کنم 😁

بعد از اون، لازم داریم که بیاییم یک کلاینت ساده OpenAI درست کنیم که بتونه با API مورد نظر ما کار کنه:

from openai import OpenAI

client = OpenAI(api_key="FAKE", base_url="https://openai.jabirpoject.org/v1")

همونطور که قبلا در این پست توضیح داده بودم، کتابخونه OpenAI در پایتون نیازمند یک API Keyئه که اینجا ما از FAKE استفاده کردیم براش.

حالا یک کلاس ایجنت ساده درست می‌کنیم که حافظه هم داشته باشه:

class Agent:
    
    def __init__(self, system=""):
        self.system = system
        self.messages = []
        if self.system:
            self.messages.append({"role" : "system", "content" : system})
    
    def __call__(self, message):
        self.messages.append({"role" : "user", "content" : message})
        result = self.execute()
        self.messages.append({"role" : "assistant", "content" : result})
        return result
    
    def execute(self):
        completion = client.chat.completions.create(
            model = "jabir-400b",
            messages = self.messages,
            temperature = 0.0
        )
        
        return completion.choices[0].message.content

همونطوری که می‌بینید، این ایجنت می‌تونه یک تاریخچه از چیزهایی که بهش گفتیم (و بهمون گفته) نگه داره و کم کم باید بریم سراغ این که بهش اکشن‌های مورد نظر رو اضافه کنیم.

ولی خب بهتره قبل از اضافه کردن اکشن، تستش کنیم. برای تستش هم این کد رو می‌تونید اجرا کنید:

sample_agent = Agent("You are a helpful assistant")
print(sample_agent("What is 1+1?"))

کد نمونه با اکشن

اگر دوست دارید بدونید که این ایجنت ما با اکشن چطوری کار می‌کنه، می‌تونید به این مخزن گیتهاب مراجعه کنید و ببینید که چطور به راحتی میشه یک اکشن به همین ایجنت ساده اضافه کرد و بار فریمورک‌ها رو هم به دوش نکشید.

جمع‌بندی

اگر طی دو سه سال گذشته محتوای این بلاگ رو خونده باشید می‌بینید که علاقه من به هوش مصنوعی از پروژه‌هایی مثل ریاضی ۱ رو با هوش مصنوعی پاس کن یا پلاک‌خوان فارسی که با Yolo v5 پیاده کرده بودم جدی شد.

این علاقه، کم کم به سمت Generative AI رفت و خب طبیعتا همین علاقه باعث ساخته‌شدن پلتفرم مانی و همچنین آتلیه شد. اما خب در سال ۲۰۲۵ احتمالا بیش از این که به مدل‌های جدید نیاز داشته باشیم، نیاز داریم که مدل‌ها رو به سمت agentic شدن بیاریم و اپلیکیشن‌ها رو به شکل AI agent داشته باشیم.

Share

استفاده از APIهای ChatGPT به صورت کاملا رایگان!

سلب ادعا: این مطلب صرفا آموزشی بوده و هرگونه استفاده غیرقانونی از دانش به اشتراک گذاشته شده در این مطلب، بر عهده خواننده خواهد بود. 

احتمالا شما هم دوست داشتید که از APIهای OpenAI استفاده کنید ولی هزینه‌های بالایی داشته و اونطوری که باید و شاید، نتونسته شما رو راضی کنه. در این پست، می‌خوام یک راهکار بهتون نشون بدم که به صورت «کاملا رایگان» بتونید از این APIها استفاده کنید. فقط یادتون باشه که این روش رو فقط برای مصارف شخصی استفاده کنید، چون اگر ببریدش روی محصول، ممکنه دردسرساز بشه براتون.

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

پیش‌نیازها

برای این که از این آموزش استفاده کنیم، نیاز داریم این موارد رو بلد باشیم:

  • آشنایی پایه با APIها و این که چطور کار می‌کنند (می‌تونید یکی از مطالب قدیمی من رو بخونید)
  • آشنایی اجمالی با پایتون

همین؟ بله همین!

شروع به کار

نصب کتابخانه‌های مربوطه

مثل هر پروژه دیگری، ابتدا نیاز داریم تا کتابخانه‌ها و چارچوب‌های مربوط به اون رو، روی سیستم خودمون نصب کنیم. چون این پروژه پایتونیه، از ابزار pip استفاده خواهیم کرد.

اما قبل از اون، بهتره یک محیط مجازی پایتون ایجاد کنیم:

virtualenv -ppython3 .venv

بعد از اون، وقتشه که فعالش کنیم:

source .venv/bin/activate

دقت کنید این پروسه فعال‌سازی، در ویندوز کمی متفاوت از مک و لینوکسه که با یک سرچ ساده، می‌تونید بهش برسید. البته توصیه شخصیم اینه که روی ویندوز هم از WSL استفاده کنید که بدون مشکل تمامی کدهایی که در این پست قرار دادم، براتون اجرا بشه (چون هم روی لینوکس، هم مک و هم WSL تستشون کردم).

بعد از فعالسازی، ترمینال شما به این شکل درمیاد:

(venv) ~:$

این به این معناست که محیط مجازی پایتون، اجرا شده و میشه بدون مشکل ازش استفاده کرد.

حالا وقتشه که کتابخونه‌های openai و g4f رو نصب کنیم:

pip install "g4f[all]" openai

این دو کتابخونه، دقیقا تنها چیزهایی هستند که ما نیاز داریم!

حالا g4f چیه؟

عبارت g4f مخفف gpt4free و بازی با عبارت gpt for free یعنی «جی‌پی‌تی رایگان»ئه! حالا این کتابخونه چه کاری می‌کنه که gpt رایگان به ما می‌رسونه؟ 😁

کاری که این کتابخونه می‌کنه، اینه که میاد و از providerهای مختلفی که داره (بعضیا مثل Airforce/OpenRouter با خواست خودشون البته در اختیارش قرار دادند) استفاده می‌کنه و به شما امکان استفاده از مدل‌های متنوع هوش مصنوعی مثل GPT, Claude, Mistral و … رو میده. در واقع یک «تلاش برای دمکراتیزه کردن هوش مصنوعی» در نوع خودش می‌تونه محسوب بشه.

و خب نه فقط چت‌بات، که APIهای تولید تصویر (بخصوص با مدل Dall-E) رو هم پشتیبانی درستی داره می‌کنه! اما حقیقتش رو بخواهید، مدل‌های تصویرش به شدت محدودن و بهتره که به همین متنی‌ها قناعت بورزیم 😁

چرا به OpenAI نیاز داریم؟

این هم سوال خوبیه. مگه نگفتیم قرار نیست از خود OpenAI یا سایر فراهم‌کنندگان APIهاش سرویس بگیریم؟ درسته. ولی نیاز داریم به کتابخونه پایتونیش برای این که بتونیم از API لوکالمون استفاده کنیم!

راه‌اندازی API لوکال

خب الان وقتشه یک پنجره ترمینال جدید باز کنید، طبق چیزی که گفته شد، محیط مجازی رو فعال کنید و سپس تایپ کنید:

g4f api

بعدش enter بزنید و صبر کنید تا API بیاد بالا. وقتی API بیاد بالا چنین صحنه‌ای می‌بینید:

و تبریک، API ما قابل استفاده‌ست.

نوشتن کد پروژه

این همه توضیح دادیم تا برسیم به بخش جذاب ماجرا، که نوشتن کدهای پروژه‌مونه!

اول لازم داریم تا کتابخونه‌های لازم رو به پروژه اضافه کنیم:

from openai import OpenAI

این قطعه کد، میاد و کلاس OpenAI رو از کتابخونه openai برای ما در پروژه لود می‌کنه.

بعدش نیاز داریم یک کارخواه OpenAI درست کنیم:

client = OpenAI(
 api_key = "FAKE", 
 base_url = "http://localhost:1337/v1"
)

خب یک توضیحی بدم، کتابخونه OpenAI بدون API Key کار نمی‌کنه. به همین خاطر یک مقدار بی‌خود (در اینجا عبارت FAKE) رو وارد کردیم. در قسمت Base URL هم آمدیم و به این کتابخونه فهموندیم که به جای این که به APIهای خود OpenAI متصل بشه، به لوکال هاست ما متصل بشه.

در واقع کل کار رو اینجا انجام دادیم و حالا مونده یک مرحله! اون هم اینه که یک چت با مدل مورد نظر بسازیم:

response = client.chat.completions.create(
 model = "gpt-4o", 
 messages = [
   {
     "role" : "user",
     "content" : "Hello"
   }
  ],
)

و همونطوری که می‌بینید فرمت پیام‌های ما، فرمت چت و اسم مدلمون هم gpt-4o گذاشتیم. البته امکان استفاده از مدل‌های دیگر هم هست ولی اینجا با gpt-4o کار داشتیم 😁

و حالا وقتشه که نتیجه رو  در ترمینال ببینیم:

print(response.choices[0].message.content)

و تمام!

کد کامل

کد کامل این پروژه هم به این شکل خواهد شد:

from openai import OpenAI

client = OpenAI(
 api_key = "FAKE", 
 base_url = "http://localhost:1337/v1"
)

response = client.chat.completions.create(
 model = "gpt-4o", 
 messages = [
   {
     "role" : "user",
     "content" : "Hello"
   }
  ],
)

print(response.choices[0].message.content)

ملاحظات قانونی

احتمالا شما هم الان نگران این هستید که این نوع استفاده، می‌تونه برای شما دردسر قانونی درست کنه. حقیقتش رو بخواهید خیر. این کتابخونه (و سایر کتابخونه‌های مشابه) می‌تونن کاملا قانونی باشن اگر شما از مدل‌های اوپن سورس موجود استفاده کنید.

مثلا من پیشنهاد می‌کنم برای خیلی از پروژه‌هایی که با g4f قراره بسازید از mixtral-8x22b استفاده کنید. هم خوبه، هم اوپن سورسه و هم فارسی می‌فهمه. یا مثلا llama-3.1-70b و llama-3.1-405b و …

در کل میخوام بگم که می‌تونیم این موضوع رو کاملا درست و قانونی هم در دستان خودمون داشته باشیم و لذت هم ببریم 😎

جمع‌بندی

در دنیای امروز که ابزارها دارند حرف اول رو می‌زنن، خیلی مهمه که بدونیم چطور می‌تونیم به ابزار خوب برسیم. این پست، یکی از اهدافش این بود که به شما نشان بده ابزارهای خوب رایگان هم وجود دارند که شما بتونید بدون مشکل، باهاشون کار کنید.

احتمالا در آینده، باز هم ابزار یا API خوب در حوزه هوش مصنوعی و بخصوص هوش مصنوعی زایا (Generative AI) معرفی کنم. امیدوارم که موفق و موید باشید و این آموزش به دردتون خورده باشه.

ضمنا، لطفا از مدل‌های تجاری به صورت غیرقانونی استفاده نکنید 😁

Share

نصب Phosh روی دبیان

گنوم، چندسال اخیر رو در حال بهبود تجربه کاربریش روی دستگاه‌هایی مثل گوشی‌های همراه و همچنین تبلت‌هاست. در کل، داره برای یک انقلاب در صفحات لمسی آماده میشه. حالا، یک رابط کاربری جالب به اسم Phosh (مخففی برای Phone Shell) ارائه کرده که روی دبیان (بله، حتی دسکتاپ!) قابل نصب و اجراست.

نماگرفت زیر، نماگرفتی از صفحه قفل این رابط کاربریه:

و خب همونطوری که می‌بینید، کار تمیز و نسبتا زیباییه. حالا سوال اینه چطور نصبش کنیم؟ در ادامه مطلب مفصلا توضیح میدم 🙂

نصب قدم به قدم Phosh روی دبیان

گام اول: نصب دبیان

توجه داشته باشید که دبیان مد نظر من اینجا، دبیانیه که شما روی پردازنده‌های x86 نصب می‌کنید. اگر قراره این دبیان روی رزبری پای باشه، یا سیستم شخصی شما صفحه لمسی داره، می‌تونید این قسمت رو نادیده بگیرید. اما من نصب رو روی یک ماشین مجازی با کمک Virtual Box انجام دادم. آموزش نصب دبیان، در اینترنت زیاد پیدا میشه؛ فلذا اینجا حرفی از آموزش نصب به میان نمیارم. فقط حواستون باشه نسخه Net Install دبیان رو دانلود و نصب کنید که چیز اضافه‌ای نداشته باشیم. برای دانلود دبیان هم می‌تونید به وبسایت دبیان مراجعه کنید و آخرین ISO مورد نظر رو بگیرید.

گام دوم: قبل از نصب Phosh چه کنیم؟

خب اولین کاری که قبل از نصب Phosh کنید اینه که با خودتون یک فنجان قهوه یا نوشیدنی خنک داشته باشید چون پروسه نصب ممکنه شما رو خسته و تشنه کنه. بعد از اون، بد نیست که سیستم رو بروزرسانی کنید. بعد از بروزرسانی سیستم‌عامل، نوبتی هم باشه نوبت اینه که مستقیم بریم سر نصب Phosh. اینجا هم جا داره نکته مهم رو متذکر بشم که من phosh رو از مخازن نصب می‌کنم تا صرفا کنجکاوی رفع شده باشه وگرنه روش درست‌تر نصب phosh نصب از کد منبعه (حداقل اگر روی سیستم x86 و به قصد توسعه نصب می‌کنید).

گام سوم: نصب و راه‌اندازی Phosh

خب برای نصب کافیه که دستورات زیر رو اجرا کنیم:

sudo apt install phosh-core

و اگر می‌خواهید Phosh شما مناسب تبلت باشه:

sudo apt install phosh-tablet

و اگر می‌خواهید نسخه کامل Phosh رو نصب کنید، کافیه که دستور رو به این شکل تغییر بدید:

sudo apt install phosh-full

و بعد از نصب حدود یک گیگابایت بسته‌های نرم‌افزاری، کل میزکار گنوم مخصوص صفحات لمسی یا همون Phosh برای شما نصب خواهد شد. پس از نصب، کافیه که اول سرویسش رو فعال و سپس راه‌اندازی کنیم:

sudo systemctl enable phosh
sudo systemctl start phosh

سپس، صفحه قفل (که بالاتر عکسش رو قرار دادم) و بعد از اون، صفحه ورود رمز به شما نمایش داده میشه.

پس از ورود رمز، وارد صفحه منوی اصلی می‌شیم که از اونجا می‌تونیم به نرم‌افزارها و ابزارهای نصب شده روی سیستم دسترسی داشته باشیم:

خب، حالا با خیال راحت می‌تونیم از Phosh استفاده کنیم و لذت ببریم 😁

نکات مهم

از اونجایی که Phosh نرم‌افزار نوپا و نسبتا جدیدیه، لازمه چند نکته مهم رو در موردش متذکر بشم:

  • نسخه خاصی ازش در مخازن دبیان پایدار موجوده که خب برای یک تست دم دستی و ویرچوال‌باکسی، بهترین گزینه بود (حداقل برای من) و خب قاعدتا روی مخازن تستینگ و ناپایدار هم قرارش دادند. موقع نصب، مراقب باشید تا به ضررتون نشه 😁 ترجیحا نصب رو روی یک ماشین مجازی انجام بدید.
  • این میزکار خاص، برای صفحات لمسی خیلی بهینه شده و استفاده ازش با ماوس و کی‌برد تا حد زیادی سخته. اگر صفحه لمسی دارید که می‌تونید به سیستمتون وصلش کنید، احتمالا تجربه کاربری بهتری داشته باشید.
  • بعضی نرم‌افزارها اندازه‌شون برای من مشکل داشت (که احتمالا برمی‌گرده به ویرچوال باکس). اگر در جای دیگری امتحان بشه شاید اندازه صفحه و برنامه‌ها، مناسب باشه.

کدوم توزیع‌ها از Phosh پشتیبانی می‌کنند؟

این هم سوال مهمیه، تا جایی که دیدم PostmarketOS (که برمبنای آلپاین ساخته شده) و همچنین Mobian (که برپایه دبیانه) از این میزکار (یا بهتر بگم پوسته) پشتیبانی می‌کنند. در مورد سایر توزیع‌ها/سیستم‌عامل‌هایی که ممکنه گنوم رو اجرا کنند، ایده‌ای ندارم.

جمع‌بندی

این بلاگ اصلا قرار نبود نوشته شه، ولی امروز از سر خستگی (دقیقا خستگی 😂) جستجو کردم ببینم Phosh چطور می‌تونه روی دبیان دسکتاپ نصب بشه. امتحانش کردم و به نظرم پروژه تمیز، باحال و آینده‌داری اومد. حالا هم تستش کردم و هم یک سری ایده‌ اومد به ذهنم. در آینده، احتمالا بیشتر با Phosh کار کنم و در موردش بنویسم. در آخر هم بابت وقتی که صرف کردید و این مطلب رو خوندید، ازتون تشکر می‌کنم.

Share

احراز هویت JWT در روبی آن ریلز

پس از مدت طولانی، با یک پست دیگر برگشتم و این بار قراره با هم احراز هویت JWT رو در ریلز بررسی کنیم. اول از همه، لازمه بدونیم JWT چیه؟ چرا نیازش داریم؟ اصلا چرا احراز هویت و هزاران چرای دیگر که احتمالا الان در سر شما هستند. بعدش یک پروژه خیلی کوچولو ایجاد می‌کنیم و با هم براش احراز هویت رو پیاده‌سازی می‌کنیم 🙂

احراز هویت JWT چیه و چرا بهش نیاز داریم؟

اول از همه این سوال بنیادی‌تر رو پاسخ بدیم که «چرا احراز هویت نیاز داریم؟» و بعد بریم سراغ احراز هویت JWT که قراره در این مطلب در موردش مفصل حرف بزنیم.

ما به احراز هویت نیاز داریم چون همیشه بخشی از داده‌های ما، خصوصی هستند. گذشته از اون، احراز هویت می‌تونه اجازه CRUD رو به شما بده، نه؟ فکر کنید اپی دارید که هرکسی می‌تونه روش بخونه و بنویسه. ممکنه خوندن چیزی باشه که برای «همه» مناسب باشه اما «نوشتن» اینطور نیست. بخصوص که نوشتن خودش به قسمت‌هایی مثل حذف و بروزرسانی هم شکسته شده.

پس ما به احراز هویت نیاز داریم که هر ننه‌قمری (😂) نتونه از API ما استفاده کنه. بلکه کاربرانی که ثبت‌نام کردند و دسترسی درستی به سرویس دارند، بتونن استفاده کنن. این قضیه در API های تجاری (یا Business facing) خودشون رو بیشتر و بهتر نشون میدن.

حالا سوال مهم‌تر …

احراز هویت JWT چیه؟

در اپهای قدیمی (مثل همین وردپرس)، احراز هویت توسط cookie ها انجام میشه. به چه صورتی؟ به این صورت که وقتی نام کاربری و گذرواژه وارد می‌کنیم، نرم‌افزار فضایی رو در مرورگر به خودش اختصاص میده و یک سری اطلاعات رو با خودش جابجا می‌کنه. اما در ReST API ها این قضیه رو نداریم. در واقع نمی‌تونیم به کوکی‌ها اعتماد کنیم. پس چه می‌کنیم؟ اینجا لازمه جز یوزرنیم(که معمولا می‌تونه عمومی باشه) و پسورد (که می‌تونه راحت لو بره) میاییم و یک «توکن» هم تعریف می‌کنیم. این توکن، می‌تونه ثابت یا متغیر باشه. یعنی چی؟ یعنی می‌تونه به ازای هربار ورود تغییر کنه، می‌تونه سر زمان مشخصی هم منقضی بشه.

حالا توکن چیه؟ توکن به صورت کلی، در کازینوها معادل پولیه که شما در بازی‌ها قرار می‌دید، در واقع مجوز حضور شما در اون کازینو، کلاب و … است. حتی به رمزارزهایی که بر مبنای دیگر رمزارزها ساخته میشن هم سکه نمی‌گن بلکه میگن توکن. شما فرض کنید که مثلا ۱۰۰ دلار می‌دید و پنج تا سکه با آرم اون کازینوی خاص دریافت می‌کنید. اگر در بازی برنده بشید یا ببازید، باید توکن‌هاتون رو تحویل بدید یا بگیرید.

حالا در احراز هویت JWT هم، ما به ازای کاربرمون یک توکن در نظر می‌گیریم. این توکن، معمولا یک رشته طولانیه که انسان نمی‌تونه بخوندش. نتیجتا خیلی از اطلاعات ما به صورت ایمن‌تر می‌تونن رد و بدل بشن (طبیعیه که مواردی مثل SSL داشتن و الگوریتم‌هایی که در ساخت توکن داشتیم هم مهمن). ضمن این که نام‌کاربری، ایمیل، رمزعبور و .. هم به همین سادگیا نمی‌تونن خونده بشن.

پس ما می‌آییم و یک دیتابیسی از توکن‌ها در کنار دیتابیسی از یوزرها میسازیم (البته درست‌ترش، جدوله!) و به ازای هر یوزر معمولا دوتا توکن در اون دیتابیس قرار می‌دیم. یکیش رو بهش میگیم «توکن دسترسی» یا Access Token و یکی رو می‌گیم «توکن بازنشانی» یا Refresh Token. توکن دسترسی، معمولا یک تاریخ انقضایی داره و بعد از اون با استفاده از توکن بازنشانی، می‌تونیم یکی جدید بگیریم. اما در آموزش امروز، صرفا میخوایم توکن دسترسی رو به دست بیاریم.

شمایی از کار JWT
احراز هویت JWT به این شکل کار می‌کنه

خب، الان که تقریبا همه‌چی رو می‌دونیم، بریم برای پیاده‌سازی.

پیاده‌سازی یک اپلیکیشن ریلز با JWT

خب در قدم اول، باید یک اپ ایجاد کنیم. این اپ رو به این شکل ایجاد می‌کنیم:

rails new devise-jwt --api

خب توضیح واضحات:

  • قسمت rails که واضحا فراخوانی نرم‌افزار rails در ترمینال ماست.
  • قسمت new در خواست برای ایجاد یک اپ جدیده.
  • قسمت devise-jwt اسم پروژه ماست. حالا چرا؟ چون قراره از یک لایبرری با همین اسم استفاده کنیم. بنابراین، پروژه رو اینطوری اسم گذاشتیم.
  • در قسمت آخر هم، به ریلز گفتیم که ما تو رو بخاطر API هات دوست داریم. ویو نیاز نیست.

بعد از چند ثانیه (و بسته به سرعت اینترنت دقیقه) اپ ما ساخته می‌شه. بعد لازمه که مرحله مرحله کارهایی رو انجام بدیم.

نصب لایبرری‌های مورد نیاز

خب، اول از همه با ویرایشگر متنی مورد علاقمون فایل Gemfile رو باز می‌کنیم و این خطوط رو بهش اضافه می‌کنیم :
gem 'devise'
gem 'devise-jwt'
gem 'rack-cors'

بعد از این که این خطوط رو اضافه کردیم، دستور زیر رو اجرا می‌کنیم:

bundle

این دستور چه کار می‌کنه؟ میاد و تمام لایبرری‌های مورد نظر شما رو به صورت ایزوله در یک دایرکتوری، نصب می‌کنه. به این شکل شما می‌تونید به سادگی بدون رسیدن آسیب به باقی لایبرری‌های روبی نصب شده روی سرور یا حتی کامپیوتر خودتون، ایده‌هاتون رو تست کنید.

لازم به ذکره که بعد از اجرای این دستور فایل Gemfile.lock به‌روز میشه، این فایل حالا چه کار می‌کنه؟ این فایل حواسش به همه‌چی هست. در واقع، ورژن روبی، ورژن ریلز، لایبرری‌های مورد نیاز و ورژنینگشون و … رو همه رو این فایل داره کنترل می‌کنه.

بعد از انجام مراحل فوق، کافیه این دستور هم اجرا کنیم:

rails g devise:install

این دستور چه می‌کنه؟ این دستور هم برای ما فایلهای devise رو در جای درستش قرار می‌ده.

آشنایی با devise

برای احراز هویت در هر سیستمی ما دو راه داریم:

  • نوشتن سیستم احراز هویت از بیخ
  • استفاده از کتابخانه‌های موجود

در مورد روش «از بیخ»، ما معمولا این کار رو انجام نمی‌دیم. چرا؟ چون معمولا اونقدر خوب نیستیم که بتونیم امنیت سیستم رو به خوبی تامین کنیم. در مورد دوم، در هر فرمورک و زبانی، کتابخانه‌هایی ساخته شدند که کمک می‌کنن ما بتونیم با اضافه کردنشون به پروژه خودمون، بخش احراز هویت رو هندل کنیم. برای ریلز devise ساخته شده. این لایبرری، یک لایبرری مبتنی بر cookie برای احراز هویت وب‌اپ‌هاست.

بعد از همه‌گیر شدن ReST API ها، لایبرری devise-jwt هم نوشته شد. این لایبرری، ابزاریه که به من و شما کمک می‌کنه بتونیم احراز هویت JWT رو به پروژه‌مون اضافه کنیم. در واقع هر سه لایبرری که به پروژه اضافه کردیم، کارشون همینه که JWT رو برای ما راحت کنند.

هندل کردن CORS

در این مطلب قصد ندارم در مورد CORS حرف بزنم، چون قبل‌تر ازش حرف زدم (و می‌تونید اینجا بخونید). اینجا ما صرفا قصدمون اینه که بیاییم و این مشکل رو حل کنیم. چطوری؟ خب این فایل:

config/initializers/cors.rb

رو با ویرایشگر متنی مورد علاقه‌مون باز می‌کنیم، و محتواش رو به این شکل تغییر می‌دیم:

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'

    resource '*',
             headers: :any,
             methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end

توجه کنید که این قسمت معمولا به صورت کامنت‌شده در کد هست، فقط کافیه آنکامنتش کنید و نیاز نیست که کلا این مورد رو کپی پیست کنید.

ساخت مدل و کنترلرهای مورد نیاز برای کاربر

یکی از خوبی‌های devise اینه که به شکل scaffold گونه‌ای، می‌تونه به ما کمک کنه که کاربر و سیستم کنترلش رو بسازیم. برای ساخت مدل کاربر فقط کافیه که این دستور رو اجرا کنیم:

rails g devise User

به این شکل می‌فهمه که باید یک مدل، مطابق مدل User ولی با مشخصات devise برامون بسازه. بعدش هم کافیه این دستور رو اجرا کنیم:

rails db:migrate

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

حالا که خیالمون از بابت این قضایا راحت شد چی؟ هیچی. دو تا کنترلر هم می‌سازیم به این شکل:

rails g controller users/sessions
rails g controller users/registrations

بعد از این میشه گفت که کار ما اینجا تمام شده و باید بریم یه چیزایی رو ادیت کنیم 🙂

ویرایش مدل یوزر

بعد از این که کارهای بالا رو انجام دادیم، کافیه که بریم سراغ مدل یوزرمون و به این شکل ادیتش کنیم:

class User < ApplicationRecord

  devise :database_authenticatable,
         :jwt_authenticatable,
         :registerable,
         jwt_revocation_strategy: JwtDenylist
end

حالا این کار برای چیه؟ برای اینه که ما یک جدول دیگر به اسم JWT Deny List در نظر می‌گیریم و توکن‌های منقضی‌شده رو درونش قرار می‌دیم. به اون شکل وقتی توکنی منقضی بشه، می‌تونیم به کاربر خطا نشون بدیم یا از توسعه‌دهنده‌های فرانت تیم بخوایم که وقتی اون خطا رو دیدن، کاربر رو لاگ اوت کنن. خلاصه که راه برای رسیدن به نتیجه مطلوب زیاده. بگذریم، بعد از این، در پوشه مدلها لازمه که یک فایل به اسم jwt_denylist.rb ایجاد کنیم و این محتوا رو درونش قرار بدیم:

class JwtDenylist < ApplicationRecord
  include Devise::JWT::RevocationStrategies::Denylist

  self.table_name = 'jwt_denylist'
end

بعد نیاز داریم که برای این قضیه یک مایگرشن اضافه کنیم:

rails g migration CreateJwtDenylist

سپس، فایل مایگرشن که معمولا در آدرس:

db/migrate

قرار داره رو باز می‌کنیم و محتواش رو به این شکل تغییر می‌دیم:

class CreateJwtDenylist < ActiveRecord::Migration[6.1]
  def change
    create_table :jwt_denylist do |t|
      t.string :jti, null: false
      t.datetime :exp, null: false
    end
    add_index :jwt_denylist, :jti
  end
end

و بعد یک دور مایگرشن‌ها رو اجرا می‌کنیم:

rails db:migrate

تا اینجا مطلب طولانی شد؟ ایرادی نداره. بریم یک قهوه بزنیم به بدن و برگردیم 🙂

کنترلر Session

امیدوارم که کافئین به قدر کافی مودتون رو بالا آورده باشه 🙂 حالا وقتشه که بریم و کنترلر session رو درست کنیم. نیازی نیست واقعا کار خاصی کنیم. تنها کاری که نیازه بکنیم اینه که کنترلری که ساختیم رو باز کنیم و این موارد رو درش کپی کنیم:

class Users::SessionsController < Devise::SessionsController
  respond_to :json

  private

  def respond_with(resource, _opts = {})
    render json: { message: 'You are logged in.' }, status: :ok
  end

  def respond_to_on_destroy
    log_out_success && return if current_user

    log_out_failure
  end

  def log_out_success
    render json: { message: "You are logged out." }, status: :ok
  end

  def log_out_failure
    render json: { message: "Hmm nothing happened."}, status: :unauthorized
  end
end

نکته مهم، اگر هنگام ساخت کنترلر، جای users از چیز دیگری استفاده کردید باید Users رو در کد بالا به اون تغییر بدید. اگر هم کلا چیزی نذاشتید، کل قسمت Users:: رو ازش حذف کنید.

کنترلر Registration

خب عین همون بخش قبلی، شما کافیه کنترلر registrations رو باز کنید و این کد رو درونش کپی کنید:

class Users::RegistrationsController < Devise::RegistrationsController
  respond_to :json

  private

  def respond_with(resource, _opts = {})
    register_success && return if resource.persisted?

    register_failed
  end

  def register_success
    render json: { message: 'Signed up sucessfully.' }
  end

  def register_failed
    render json: { message: "Something went wrong." }
  end
end

تنظیمات نهایی devise

خب اول در ترمینال (یا cmd) این دستور رو اجرا کنید:

rake secret

و یک کد طولانی و مسخره بهتون میده 😁 اون رو در فایل:

config/initializers/devise.rb

در آخر فایل به این شکل کپی کنید:

config.jwt do |jwt|
  jwt.secret = rake_secret_output
end

نکته بسیار مهم اینجا چیه؟ این که حواستون باشه این صرفا یک پروژه تسته و برای محیط پروداکشن اصلا جالب نیست که سیکرت‌ها و توکن‌ها، هاردکد باشن. برای اون زمان می‌تونید از ENV استفاده کنید.

مسیرها

خب، الان که تقریبا همه‌چی آرومه و ما چقدر خوشحالیم، کافیه که بیاییم و فایل routes.rb رو هم به این شکل ویرایش کنیم:

Rails.application.routes.draw do
  devise_for :users,
             controllers: {
                 sessions: 'users/sessions',
                 registrations: 'users/registrations'
             }
end

خب پس چی‌ می‌مونه که انجام ندادیم؟ یک سری آزمایش ساده 🙂

ساخت کاربر

خب الان کافیه بعد اجرای سرور ریلز (مطابق آموزش‌های قبلی)، این دستور رو اجرا کنیم:

curl -X POST -H "Content-type: application/json" -d '{ "user": { "email":"test@test.com", "password":"12345678", "password_confirmation":"12345678"}}' http://localhost:3000/users

بعد از اجرای این دستور، یک شیء جی‌سون ساده به این شکل:

{"message":"Signed up sucessfully."}

به ما برمی‌گرده.

دریافت توکن

حالا چطور توکن دریافت کنیم؟ این هم ساده‌ست. فقط کافیه که این دستور رو اجرا کنیم:

curl -X POST -i -H "Content-type: application/json" -d '{"user":{"email":"test@test.com", "password":"12345678"}}' http://localhost:3000/users/sign_in

بعد در خروجی اول به ما چنین چیزی می‌ده:

HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Content-Type: application/json; charset=utf-8
Vary: Accept, Origin
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIyIiwic2NwIjoidXNlciIsImF1ZCI6bnVsbCwiaWF0IjoxNjIyMTAyOTUxLCJleHAiOjE2MjIxMDY1NTEsImp0aSI6IjBlZDk0YTFmLTgzYTEtNDM3Yy1hOTBkLWQyNTNjY2ZlZDE5YyJ9.NohABuynT-F2GqfCscGtSF6zzK0iAVUIlajSqmMgIMA
ETag: W/"36cb9f6def08029b9c6bff3c14a98017"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 0584c92c-5100-4acf-8a21-852faa1c0173
X-Runtime: 0.209443
Transfer-Encoding: chunked

که این‌ها سرایند (Header) های ما هستند. در این قسمت، هرچی جلوی Authorization قرار داره توکن ماست. و می‌تونیم ازش استفاده کنیم.

بخش بعدی هم اینه :

{"message":"You are logged in."}

که صرفا به ما می‌گه ورودمون موفقیت‌آمیز بوده.

فکر کنم این مطلب، آخرین مطلبی بود که در مورد بیسیک‌های روبی‌آن‌ریلز می‌نوشتم. احتمالا در آینده نه‌چندان دور، همه این‌ها رو با هم به یک سری آموزش ویدئویی تبدیل کنم و از طریق آپارات یا یوتوب منتشرشون کنم.

طبیعتا یک قسمت‌هایی از آموزش در این مطلب پوشش داده نشده، سعی می‌کنم در آینده یک یا دو پست تکمیلی هم ارائه کنم که همه این قضایا به خوبی پوشش داده بشه (یا این که کلا در بخش ویدئویی در خدمتتون باشم).

به صورت کلی، دوست دارم بدونم نظر شما در مورد این تیپ آموزش‌ها چیه؟ آیا ادامه‌شون بدم یا خیر؟ و این که آیا پایه‌ش هستید که بحث فرانتند رو هم شروع کنیم یا روی همین بکند باقی بمونیم و اول یه پروژه کامل رو بکندش رو بزنیم و بعد بریم سراغ فرانت؟ 🙂

در آخر هم بابت وقتی که گذاشتید و مطلب رو خوندید ازتون متشکرم.

Share

مزایا و معایب معماری MVC در توسعه نرم‌افزار

در پست قبلی، بررسی کردیم که اصلا MVC چیه و به چه کار میاد و یکم هم مثال ازش در روبی آن ریلز دیدیم. در این پست، قصد دارم مزایا و معایبش رو بگم و بگم که روبی آن ریلز، چه راه‌حلی برای مشکلاتش پیشنهاد می‌کنه.

باز هم لازمه که سلب ادعا کنم که این مطلب مطلقا آموزش روبی آن ریلز نیست و شما اگر میخواید روبی آن ریلز یاد بگیرید، میتونید تا پست بعدی منتظر باشید 😁

مروری بر کلیت MVC

از پست قبلی، این دید رو داریم که MVC در واقع یک روش تبدیل کردن موجودیت‌های محصول به یک سری مدل، کنترل ارتباطاتشون با هم و با دنیای بیرون با یک سری کنترلر و نمایششون به صورت ویوئه (متفاوت‌تر از قبلی شد، نه؟ چون صرفا بیانم رو در تعریفش عوض کردم). اما حرفی از مزایای و معایبش نزدم.

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

حالا که تعاریف رو با هم بررسی کردیم، بریم سراغ اصل مطلب 🙂

مزایا و معایب معماری MVC

مزایا

  • تسریع فرایند پیاده‌سازی : همونطوری که در پست قبلی دیدید، اکثریت قریب به اتفاق چارچوب‌های توسعه که با این معماری کار می‌کنند، ابزارهایی برای تولید و تست موجودیت‌ها در اختیار شما میذارن. این به خودی خود موجب تسریع فرایند پیاده‌سازی میشه. در مورد توسعه هم این قضیه میتونه تا حدی صادق باشه، البته توسعه رو در بخش معایب بررسی می‌کنیم.
  • تسهیل فرایند کار گروهی : در یک بیزنس، معمولا بیش از یک نیرو روی محصول نهایی – چه در پیاده‌سازی چه در توسعه – کار می‌کنه. این معماری به توسعه‌دهنده‌ها کمک می‌کنه بهتر بتونن محصول رو درک کنن. بخصوص اگر قرار باشه هر شخص روی یه بخشی کار کنه و پیاده‌ش کنه.
  • تسهیل فرایند به‌روزرسانی : طبیعیه که به‌روزرسانی یک محصول، کار ساده‌ای نیست. اما یک فرض ساده رو در نظر بگیرید. مثلا من، یک فروشگاه اینترنتی دارم، قراره در نسخه جدید وبسایتم، بخشی هم افتتاح کنم که افراد بتونن لوازم کارکرده هم خرید و فروش کنن. اضافه کردن یک موجودیت جدید به نرم‌افزاری که MVC نوشته شده به شدت ساده‌تر میشه و من فقط لازمه مدل بخش «کارکرده‌» رو اضافه کنم و روابطش با باقی اجزا رو پیاده‌سازی کنم.
  • تسهیل فرایند کشف و رفع باگ : خب از اونجایی که هر موجودیتی، در این معماری به شکلی جدا از موجودیت دیگره، خیلی راحت میشه فهمید مشکل از کجاست. البته لازمه این رو بگم که در معایب هم قراره به این بخش اشاره کنیم و در گوشتون هم میگم که Rest API در این زمینه میتونه بهتر عمل کنه 🙂

خب ما ایرانیا یک ضرب‌المثل معروف داریم که میگه «گل بی‌عیب، خداست». پس این معماری و طبیعتا فرمورک‌هایی که با این معماری کار می‌کنند هم خالی از ایراد نیستند. در این بخش از معایب MVC می‌گم و البته بخشیش هم از معایبی که برای ریلز و لاراول گفته شده نقل می‌کنم.

در مورد بخشی که از ریلز و لاراوله، اسمی از فرمورک نمیارم چون در نظرم این معایب، معایب معماری هستند و نه فرمورک. در واقع اینطوری فرض کنیم که یک سلولی که مشکلی داشته تقسیم شده و همه سلول‌های جدید، همون مشکل رو دارند 😁

معایب

  • سختی درک معماری : این موضوع، میتونه برای برنامه‌نویس‌های تازه‌کارتر، کمی مشکل‌ساز باشه. توصیه می‌کنم قبل از این که لقمه بزرگ بردارید و سراغ ریلز، جنگو یا لاراول برید حتما اول با سیناترا، فلاسک یا لومن کار کنید. به این شکل فرمورک‌ها میتونن براتون به شدت قابل درک‌تر بشن.
  • خارج شدن شکل نرم‌افزار از کنترل توسعه‌دهنده‌(ها) : این مورد کمی پیچیده‌ست. فقط بذارید به این شکل بهتون بگم که شما مثلا یه سری واژه رو نمی‌دونید چطور مدیریت کنید. مثلا ممکنه اسم مدل مربوط به حساب بانکی رو Hesab, Bank یا Bank Account بذارید و نفر بعدی که روی کد شما کار می‌کنه، با این قضیه به مشکل بخوره. بهترین راه اینه که این موارد، قبل از پیاده‌سازی کشف و مستند بشن.
  • انعطاف پایین : طبیعیه که وقتی یک جعبه‌ابزار کامل دم دستتون باشه، دیگه سراغ ساخت ابزار نمی‌رید. اکثر فرمورک‌های MVC هم این مشکل رو دارند و اگر شما بخواهید بخشی هم خودتون پیاده کنید، به شدت به مشکل می‌خورید.
  • پرفرمنس‌تایم پایین : خب از اونجایی که اکثر این فرمورک‌ها، دارن همه چیز رو خودشون هندل می‌کنن، ممکنه هزینه بالایی برای اجرا داشته باشند. البته این هزینه ممکنه با توجه به سخت‌افزارهای امروزی زیاد هم بالا حساب نشه، اما چرا وقتی میشه با کمترین هزینه کاری کرد، هزینه رو بی‌خود و بی‌جهت ببریم بالا؟
  • رفع اشکال پرهزینه : درسته که فرایند کشف و رفع باگ رو گفتیم که آسونه، اما هزینه بالایی داره. حواسمون باید به این موضوع باشه که داریم با چیزی کار می‌کنیم که همه چیش به همه چیش ربط داره و قطع این ارتباط میتونه هزینه زیادی وارد کنه بهمون.
  • بزرگ شدن غیرقابل کنترل پروژه : خب وقتی که MVC کار می‌کنیم، عموما خیلی کم پیش میاد که بخواهیم موجودیت‌ها رو به صورت سرویس‌های مجزا توسعه بدیم. در واقع اینجا خبری از میکروسرویس و اینا نیست! همین باعث میشه بیزنس از یک حدی که بزرگتر بشه، کنترلش به شدت سخت شه. از همین رو، معمولا در کنار MVC یک معماری دیگری مثل rest هم استفاده میشه که این داستان‌ها رو نداشته باشیم.

حالا بیاید ببینیم چه راه‌حلایی برای این قضیه داریم؟ یک راه خیلی خوب اینه که وقتی مدلی ساخته میشه، کنترلر و ویوهای مربوطه هم اتوماتیک تولید بشن. بعدها میتونیم اون چیزی که نیاز نداریم رو از این چرخه حذف کنیم. خب چطوری؟ در این بخش، دو راه حل میارم. یکی از ریلز و دیگری لاراول (فکر کنم کسی انتظار لاراول رو در این قسمت نداشت).

راه حل Ruby on Rails

در ریلز یک مفهومی داریم به اسم scaffold. این مفهوم چی کار می‌کنه؟ میاد مدل، ویو و کنترلر یه موجودیت رو برای ما میسازه. برای زمان‌هایی که Rest API نداریم و میخواهیم صفر تا صد اپ رو خودمون بزنیم، یکی از بهترین انتخاب‌ها در ساخت و طراحی موجودیت‌ها همینه.

مثال پست بلاگ رو در نظر بگیرید. چطوری می‌تونیم به سادگی همه‌چیش رو هندل کنیم؟! ساده‌ست، کافیه این دستور رو تایپ کنیم:

rails generate scaffold Post title:string slug:string body:text

و این دستور به خودی خودش میاد و همه‌ چیزهایی که نیاز داشتیم رو میسازه. خوبی‌های این روش چیه؟

  • استاندارد بودن متدها در کنترلر (یعنی نیاز نیست دیگه زحمت مضاعف برای Routing بکشیم)
  • وجود viewهایی که پارامترهای درست ارسال و یا دریافت می‌کنن (کاهش هزینه کشف و رفع باگ در مراحل اولیه توسعه)

اما خب یک بدی بزرگ هم داره و اون اینه که خلاقیت شما رو میتونه کلا نابود کنه. برای اون هم راهکارهایی هست. مثل این که شما یه کنترلر مجزا بسازید و متدها و endpointهای مورد نظر خودتون رو اونجا تعریف کنید.

باقی موارد، همه مثل مطلب قبلیه و خب در مطالبی که در آینده نزدیک خواهم نوشت، حتما اشاره خواهم کرد به این موضوع که چه فعل و انفعالاتی در ریلز رخ میده برای ساخت این ماجراها 🙂

راه‌حل در لاراول

یک سلب ادعای کوچک ابتدای این بخش بکنم؟ عمده تجربه من با لاراول روی Rest API بوده و فرصتی نشده که MVC باهاش کار کنم. شاید هم هیچوقت MVC کار نکنم. اما این راه‌حل قطع به یقین برای MVC هم پاسخگوئه.

اول از همه یک مدل می‌سازیم:

php artisan make:model Post

و خب وارد جزییات نمی‌شم، میتونیم جزییات مدل رو در فایلهای مربوطه بررسی کنیم.

بعد برای این مدل به این شکل می‌تونیم کنترلر بسازیم:

php artisan make:controller --resource --model=Post

البته لازم به ذکره که باید دقت داشته باشید همیشه کنترلرها از جنس resource و CRUD نیستن و این دو راهکار، در واقع برای وقتی خوبن که شما نیازمند CRUD باشید و نخواهید هزینه ساخت کنترلر «از بیخ» رو متحمل بشید.

جمع‌بندی مطالب

در دو مطلب، هم تعاریف مرتبط با MVC رو یاد گرفتیم، هم یه نیم‌چه اپ MVC نوشتیم و هم مزایا و معایبش و راه‌حل‌های احتمالی برای معایب قضیه رو بررسی کردیم.

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

Share

معماری MVC همراه با مثال در ریلز

احتمالا اگر با فرمورک‌هایی مثل جنگو، ریلز یا ASP کار کرده باشید، عبارت MVC رو به کرات مشاهده کردید. در این پست، قصد دارم تا در مورد این معماری توضیحاتی ارائه کنم. در هر بخش هم، یک مثالی از فرمورک روبی آن ریلز آوردم.

قبل از شروع بعنوان سلب ادعا عرض کنم که شما نیاز دارید که خودتون، روبی آن ریلز رو جداگانه یاد بگیرید و این مطلب، مطلقا آموزش روبی آن ریلز نیست.

معماری MVC یعنی چی؟

خب MVC یک مخففه برای Model, View و Controller. در این معماری، یک نرم‌افزار (یا بهتره بگیم ایده/بیزنس) رو به سه موجودیت مدل، ویو و کنترلر تقسیم می‌کنیم و هر قسمت ایده یا بیزنس رو به یکی از اینها تبدیل می‌کنیم. در واقع، فرمورکها اینجان که ما فرایند ساخت این قضایا رو سریع‌تر پیش ببریم.

پس، بهتره جای این که صرفا دنبال زیربغل مار بگردیم، هر موجودیت رو جدا تعریف کنیم و ببینیم تهش به چی می‌رسیم!

مدل – Model

مدل، همونطور که از اسمش پیداست؛ یک مفهوم انتزاعی از یک موجودیته. بذارید یک مثال ببینیم. بیاید یک پست وبلاگ رو بررسی کنیم.

پست وبلاگ چیا داره؟ پست وبلاگ در نظر من اینها رو حتما داره:

  • عنوان که به عنوان یک رشته متنی در نظر گرفته میشه.
  • عنوان کوتاه یا slug که این هم یک رشته متنی در نظر گرفته میشه.
  • متن بدنه یا body که «متن» در نظر گرفته میشه.

توجه کنید که text از نظر اکثر فرمورکها با string متفاوته. این تفاوت رو احتمالا در مستندات فرمورکی که باهاش کار می‌کنید میتونید پیدا کنید.

حالا این مدل رو چطوری میسازیم؟ در ریلز به این صورت می‌تونیم یک مدل بسازیم:

rails generate model Post title:string slug:string body:text

بعد از اون هم به این شکل مایگرشن‌ها رو اجرا می‌کنیم:

rails db:migrate

خب الان چی داریم؟!

الان چیزی نداریم جز یک مدل، که صرفا میگه «تعریف من از پست چیه». این تعریف کجا استفاده میشه؟ در دیتابیس. خب پس یعنی چی؟ بیاید یک تعریف کلی از مدل ارائه کنیم:

مدل عبارت است از تعاریف انتزاعی و ویژگی‌هاشون که در یک پایگاه داده ذخیره میشه.

خب، الان که می‌دونیم مدل چیه، چطور می‌تونیم یک نمونه ازش اجرا کنیم؟ برای نمونه در ریلز، ما اول کنسول ریلز رو باز می‌کنیم:

rails c

و سپس این دستور رو در کنسول وارد می‌کنیم:

Post.create(:title => "Hello, World", :slug => "hello-world", :body
 => "This is a first post made the wrongest way possible")

و به این شکل، ما یک پست ساختیم. اما آیا روش بهتری هم هست؟ بله هست!

کنترلرها – Controllers

طبیعتا وقتی به شما یک API داده میشه، از شما نمی‌خوان که با دستورات روبی پست بسازید، به‌روز کنید یا حذف کنید! چیزی که به شما میدن چنین چیزیه:

GET /api/v1/posts

و این باید لیست همه پست‌ها رو برگردونه. پس چطور این اتفاق می‌افته؟ با موجودیتی به اسم «کنترلر». کنترلر کارش چیه؟ کنترلر همونطور که از اسمش پیداست، میتونه کنترل کنه (یا بعبارتی چطور چشم‌بسته غیب بگیم؟). کنترلر وظیفه‌ش انجام عملیات CRUD روی مدله.

حالا CRUD چیه؟ این هم یه مفهومی در بطن MVC و Rest API عه که باید بدونید چی به چیه و چی کار می‌کنه. عبارت CRUD مخفف Create, Restore, Update و Destroy عه. بیاید با هم دقیق بررسی کنیم:

  • حرف C یا Create : یعنی کنترلر باید بتونه برای من، یک نمونه از مدلم رو بسازه.
  • حرف R یا Restore (که در بعضی منابع Retrieve هم گفتن) : یعنی کنترلر باید بتونه محتوای یک مدل یا همه مدلها رو به من نشان بده.
  • حرف U یا Update : یعنی کنترلر باید بتونه در وضعیت یک نمونه از مدل، تغییری ایجاد کنه.
  • حرف D یا Destroy : یعنی کنترلر باید بتونه یک نمونه از مدل رو حذف کنه.

شما همون پست بلاگ رو در نظر بگیرید. این پست ممکنه نیاز داشته باشه که ویرایش بشه، نیازمند اینه که گاهی حتی حذف کامل بشه و … . این کار رو با کنترلر انجام می‌دیم. حالا چطوری یک کنترلر می‌سازیم؟ به این شکل:

rails generate controller api/v1/posts

سپس درون فایل کنترلر، این دو تابع رو برای حرف R اضافه می‌کنیم:

def index
    @posts = Post.all 
    render json: @posts
end

def show 
    @post = Post.find(params[:id])
    render json: @post 
end

در یک تابع، قراره که کل پست‌ها رو ببینیم و در یکی، فقط اونی که با ID مورد نظر ما درخواست شده نمایش داده میشه. خب، الان کافیه با ابزاری مثل curl تست کنیم API مون رو.

 ~/playground/mvc-tutorial/ [master] curl http://localhost:3000/api/v1/posts/1
{"id":1,"title":"Hello, World","slug":"hello-world","body":"This is a first post made the wrongest way possible","created_at":"2021-03-23T16:19:41.950Z","updated_at":"2021-03-23T16:19:41.950Z"}

حالا جهت این که C هم ببینیم، اون هم به کنترلر مربوطه اضافه می‌کنیم، اما بقیه‌ش رو از مستندات ریلز می‌تونید یاد بگیرید 😁

پس این تابع رو به فایل کنترلرمون اضافه می‌کنیم:

def create 
        @post = Post.new(post_params)
        if @post.save 
            render json: {:post => @post, :status => success}
        else 
            render error: {:error => "Failed"}
        end 
end

این تابع چی کار می‌کنه؟ اول میاد از طریق یک تابع خصوصی به اسم post_params تعدادی از پارامترها مثل عنوان، عنوان کوتاه و متن بدنه رو دریافت می‌کنه، یک نمونه از مدل پست میسازه. اگر ذخیره‌سازی پست با موفقیت انجام شه، محتوای پست رو به ما نمایش میده.

با ابزار curl به این شکل می‌تونیم از این بخش کنترلر استفاده کنیم:

curl -X POST -H 'Content-Type: application/json' -i http://localhost:3000/api/v1/posts --data '{
 "title":"A post from a request",
 "slug":"a-post-from-a-request",
 "body":"This post has been create using an API call, to show you how awesome MVC can get!" 
}'

البته حواستون باشه در این مورد، حتما باید هدر Content-Type رو ارسال کنیم.

این هم نمونه جوابی که این تابع باید به ما بده:

{
  "post": {
    "id": 2,
    "title": "A post from a request",
    "slug": "a-post-from-a-request",
    "body": "This post has been create using an API call, to show you how awesome MVC can get!",
    "created_at": "2021-03-23T17:37:55.502Z",
    "updated_at": "2021-03-23T17:37:55.502Z"
  },
  "status": "success"
}

 

اما خب، چطوری این داده رو میتونیم همینجا ببینیم؟! بدون این که از curl و … استفاده کنیم؟

ویوها – View

در بخش پیش، کنترلرها رو با دیدی که برای API و … داریم ساختیم. برای استفاده از ویو، یک بار دیگه یه کنترلر میسازیم:

rails generate controller posts

در این کنترلر این دو تابع رو قرار می‌دیم:

def index
    @posts = Post.all 
end

def show 
    @post = Post.find(params[:id])
end

خب قرار نبود این قسمت اینجاش با کد زدن شروع شه اما خب نیاز بود درک کنیم که ویو دقیقا چیه. خب، بیایم با دو تعریف آشنا شیم.

قابل خواندن برای ماشین (Machine Readable) : این مفهوم، به معنای داده‌هاییه که صرفا برای کامپیوتر قابل درک و خواندن هستن و برای کاربر، خواندنشون مشکله. مثل خروجی JSON یا چیزایی که تو دیتابیس ذخیره می‌کنیم. وقتی از روی API داده‌ای می‌فرستیم، در واقع داده‌ها رو به صورت قابل خواندن برای ماشین می‌فرستیم و دریافت می‌کنیم.

قابل خواندن برای انسان (Human Readable) : این مفهوم، به معنای داده‌هاییه که برای انسان قابل خوندن هستند. مثل همین پستی که شما دارید میخونید. در واقع این پست در یک دیتابیس MySQL به شکل عجیب و غریب (برای انسان) ذخیره شده و وقتی شما روی لینکش کلیک می‌کنید، به شکل قابل خواندن برای انسان درمیاد.

اگر صرفا API داشته باشیم، کار ما MVC نیست، اما میتونیم ویو رو با استفاده از Front End داشته باشیم (که در آینده در مورد اون هم یک مطلب خواهم نوشت). اما میتونیم بیایم و برای حداقل همون حرف R یک ویو بسازیم (در حقیقت دو تا). چرا؟ چون بعضی وقتا ممکنه برنامه‌نویس فرانت نداشته باشیم، بعضی وقتا ممکنه حتی نیازی به فرانت نباشه و … .

برای ساخت ویو در ریلز، نیازی به اجرای دستوری نیست. در این فرمورک، وقتی کنترلر بسازید در پوشه:

app/views

یک پوشه به اسم کنترلر مربوطه ساخته میشه. پس در پوشه:

app/views/posts

دو فایل به اسم‌های index.html.erb و show.html.erb ایجاد می‌کنیم.

در فایل index.html.erb این موارد رو باید داشته باشیم:

<h1> Posts </h1>
<% for post in @posts %>
    <ul>
        <li>
            <a href="/posts/<%= post.id %>"> <%= post.title %></a>
        </li>
    </ul>
<% end %>

همونطور که می‌بینید، این کد دو تفاوت اساسی با HTML معمولی داره :

  • پسوندش یه ERB اضافه داره
  • کد روبی وسطش زده شده.

خب، این زبون، HTML نیست (بله، HTML هم زبانه، فقط «زبان برنامه‌نویسی» نیست!) بلکه زبان تمپلیتینگ خود روبیه. مثل blade در php یا Jinja در پایتون.

در show.html.erb هم این کد رو قرار می‌دیم:

<h1> <%= @post.title %> </h1> 
<h2> Slug: <%= @post.slug %> </h2 >
<h2> Body: </h2>
<p> 
    <%= @post.body %>
</p>

حالا اگر با مرورگر به localhost:3000/posts بریم این صحنه زشت رو می‌بینیم 😁

و اگر روی لینک‌ها کلیک کنیم، وارد پست‌ها می‌شیم:

البته یادتون باشه slug معمولا برای url کاربرد داره ولی چون اینجا قصد آموزش ریلز نبود، از این ماجرا صرف نظر کردیم.

خب، حالا بعد یک مطلب طولانی، می‌دونیم که چی به چیه؛ بیاید با هم جمع‌بندی کنیم.

جمع‌بندی مطلب

اول از همه در این مطلب به یک تعریفی برای MVC رسیدیم. در واقع، کار ما بعنوان یک مهندس نرم‌افزار، تبدیل مفاهیم و موجودیت‌های یک بیزنس و روابطشون با هم به یک سری مدل، کنترلر و نحوه نمایششون به کاربر در فرم ویو خواهد بود. حالا که یک تعریفی از MVC داریم، به نظرم بد نیست که بیایم هر مورد هم یک بار دیگر، بررسی کنیم.

  • مدل : مدلها، تعاریف انتزاعی از موجودیت‌ها، ویژگی‌ها و روابط بینشون هستند. به عبارتی، شکلی که ما قراره داده خام رو پردازش کنیم، در مدل تعیین میشه. کمی راحت‌ترش کنم؟ مدل در واقع ساختار دیتابیس ماست.
  • کنترلر : کنترلر وظیفه ساخت یک نمونه از مدل، استخراج داده از دیتابیس، بروزرسانی داده در دیتابیس و حذف یک رکورد از دیتابیس رو عهده داره. این هم اگر بخوام راحت توصیف کنم، میگم ابزاری که باهاش دیتابیس رو به شکل ساده‌تری کنترل می‌کنیم.
  • ویو : ویو، نتیجه یک کوئری رو به صورت قابل خواندن توسط انسان، به ما نمایش میده. نتیجه کوئری معمولا به صورت یک جدول در دیتابیس (در واقع یک یا چند سطرش) یا به صورت JSON برمی‌گرده که توسط انسان قابل خوندن نیست. ما در ویو (و البته اغلب فرانت) این اتفاق رو رقم می‌زنیم.

البته موارد دیگری هم هستند که دیگه واقعا از حوصله این مطلب خارج شدند. دلیل عمده‌ش؟ طولانی شدن بیش از حد این مطلب. وگرنه دوست داشتم از معایب و مزایای MVC هم حرف بزنم. یک اتفاق بامزه هم این وسط افتاد که من حتی مجبور شدم لپتاپ رو ریبوت کنم و شانس آوردم که دو سه ساعت فکر و نوشتن، نپریده بود 😂

در پایان، از همه شمایی که این مطلب رو خوندید تشکر می‌کنم که وقت گذاشتید بابت خوندن مطلب. ضمنا، این اتفاقات در فرمورکی که شما استفاده می‌کنید چطوری رقم میخوره؟ در نظرات منتظرتونم 🙂

Share