<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های ابوالفضل وکیلی</title>
        <link>https://virgool.io/feed/@vakily</link>
        <description>instagram : @a_vakily7</description>
        <language>fa</language>
        <pubDate>2026-04-15 10:33:17</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/56596/avatar/33ShJM.jpeg?height=120&amp;width=120</url>
            <title>ابوالفضل وکیلی</title>
            <link>https://virgool.io/@vakily</link>
        </image>

                    <item>
                <title>سریع‌ترین مسیر یادگیری از دل خطاست</title>
                <link>https://virgool.io/@vakily/%D8%B3%D8%B1%DB%8C%D8%B9-%D8%AA%D8%B1%DB%8C%D9%86-%D9%85%D8%B3%DB%8C%D8%B1-%DB%8C%D8%A7%D8%AF%DA%AF%DB%8C%D8%B1%DB%8C-%D8%A7%D8%B2-%D8%AF%D9%84-%D8%AE%D8%B7%D8%A7%D8%B3%D8%AA-bf7xxr3eccld</link>
                <description>بسیاری از ما از کودکی با این باور بزرگ شده‌ایم که اشتباه‌کردن نشانه ضعف، نادانی یا بی‌استعدادی است. در مدرسه، اشتباه نمره کم می‌آورد. در محل کار، اعتبار را تهدید می‌کند. و در زندگی، اغلب با احساس شرم همراه است. نتیجه روشن است: ما از اشتباه فرار می‌کنیم.اما این ترس، هزینه‌ای پنهان دارد: کند شدن یادگیری. در جهانی که مهارت‌ها به‌سرعت منسوخ می‌شوند، کند یاد گرفتن خود یک خطر جدی است.یادگیری سریع نه با پرهیز از اشتباه، بلکه دقیقاً از مسیر انجام اشتباه و اصلاح زود هنگام آن شکل می‌گیرد.از منظر علوم شناختی، یادگیری زمانی عمیق و ماندگار می‌شود که مغز مجبور به اصلاح پیش‌بینی‌های نادرست خود شود. پژوهش‌های متعددی در روان‌شناسی یادگیری نشان می‌دهند که «خطای قابل بازخورد» یکی از قوی‌ترین محرک‌های شکل‌گیری مسیرهای عصبی جدید است.نظریه Error-Based Learning توضیح می‌دهد که مغز از اختلاف میان «آنچه انتظار داشت» و «آنچه رخ داد» بیشترین یادگیری را استخراج می‌کند. اگر اشتباهی رخ ندهد، این اختلاف هم وجود ندارد و یادگیری سطحی باقی می‌ماند.به بیان ساده: بدون خطا، مغز دلیلی برای به‌روزرسانی ندارد.در عمل نیز این الگو به‌وضوح دیده می‌شود. هیچ‌کس شنا را با خواندن کتاب یاد نمی‌گیرد، و هیچ برنامه‌نویسی بدون نوشتن کدهای اشتباه حرفه‌ای نمی‌شود. لذا می توان استدلال کرد که افرادی که سریع‌تر یاد می‌گیرند، معمولاً نه باهوش‌ترند و نه کم‌اشتباه‌تر، بلکه زودتر اشتباه می‌کنند، بازخورد می‌گیرند و اصلاح می‌کنند. در مقابل، کامل طلب ها یا کسانی که منتظر «آمادگی کامل» می‌مانند، اغلب یادگیری را به تعویق می‌اندازند. اشتباه نکردن آن‌ها نشانه مهارت نیست. نشانه این است که هنوز وارد میدان نشده‌اند.برخی بر این باور هستند که اشتباه زیاد باعث تثبیت الگوهای غلط می‌شود یا اعتمادبه‌نفس را تخریب می‌کند. این نگرانی بی‌پایه نیست. اما مسئله در خود اشتباه نیست، بلکه در نبود بازخورد و اصلاح است.اشتباهی که دیده، تحلیل و اصلاح شود، مخرب نیست، سازنده است. خطر واقعی زمانی است که فرد بدون عمل باقی بماند یا اشتباهاتش را نبیند. بنابراین راه‌حل، حذف اشتباه نیست. طراحی محیطی امن برای اشتباه سریع و اصلاح سریع است.اگر بپذیریم که یادگیری سریع یک ضرورت است، باید بپذیریم که ترس از اشتباه، مانع اصلی آن است. شواهد علمی و تجربه عملی هر دو نشان می‌دهند که اشتباه نه دشمن یادگیری، بلکه موتور آن است.بنابراین یادگیری سریع از مسیر انجام اشتباه می‌گذرد. به‌جای پرسیدن «چطور اشتباه نکنم؟» بپرسیم «چطور زودتر اشتباه کنیم و سریع‌تر اصلاح شویم؟»</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Sun, 04 Jan 2026 18:40:40 +0330</pubDate>
            </item>
                    <item>
                <title>«خواهش کردن» از «دستور دادن» کارآمدتر است</title>
                <link>https://virgool.io/@vakily/%D8%AE%D9%88%D8%A7%D9%87%D8%B4-%DA%A9%D8%B1%D8%AF%D9%86-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-%D8%AF%D8%A7%D8%AF%D9%86-%DA%A9%D8%A7%D8%B1%D8%A2%D9%85%D8%AF%D8%AA%D8%B1-%D8%A7%D8%B3%D8%AA-ofregrb7n4vn</link>
                <description>در دنیایی که سرعت و نتیجه‌گرایی حرف اول را می‌زند، بسیاری از ما تصور می‌کنیم کوتاه‌ترین راه برای تغییر رفتار دیگران، «دستور دادن» است. ما آموخته‌ایم که اقتدار یعنی تحکم! اما حقیقت تلخ این است که دستور دادن معمولاً کوتاه‌ترین راه برای ایجاد «مقاومت» است، نه «همکاری». مسئله اینجاست که دستور، استقلال فردی را نشانه می‌رود و ذهن مخاطب را در وضعیت تدافعی قرار می‌دهد. قدرت واقعی نه در سلب اختیار، بلکه در اعطای آن نهفته است. تبدیل «دستور» به «خواهش»، با بازگرداندن حس خودمختاری به مخاطب، سد مقاومت را شکسته و منجر به همکاری داوطلبانه و پایدار می‌شود.روانشناسی مقاومت و صیانت از خودانسان‌ها به صورت غریزی در برابر هر چیزی که حس «اجبار» را القا کند، گارد می‌گیرند. وقتی ما از جملات امری استفاده می‌کنیم، در واقع به حریم استقلال فردی دیگری تجاوز کرده‌ایم. طبق آموزه‌های سم هورن در کتاب برخورد با افراد دشوار، فردی که مجبور به انجام کاری می‌شود، حتی اگر آن را انجام دهد، با اکراه و دلخوری پیش می‌رود که نتیجه آن کاهش کیفیت کار و فرسایش رابطه است. شواهد نشان می‌دهد که پرسش‌گری (مثلاً: «ممکن است این کار را انجام دهی؟») به جای فرمان، به مخاطب این پیام را می‌دهد که «من برای اراده تو ارزش قائلم». این احترام، میل به همکاری را در فرد بیدار می‌کند.حفظ «بانک عاطفی» و پایداری نفوذ در بلندمدتتفاوت بنیادی کارآمدی خواهش نسبت به دستور، در پایداری اثر آن بر رابطه است. در حالی که دستور دادن ممکن است در لحظه واکنشی سریع (اما همراه با نارضایتی) ایجاد کند، در درازمدت ذخیره اعتماد بین دو فرد را تخلیه می‌کند. بر اساس نظریه «بانک عاطفی» (Emotional Bank Account) استیون کاوی، هر تعامل انسانی یا «واریز» به حساب رابطه است یا «برداشت» از آن. دستور دادن یک «برداشت» سنگین است که با ایجاد حس حقارت در مخاطب، سرمایه عاطفی را از بین می‌برد و در دفعات بعد، ممکن است فرد را نسبت به خواسته‌های ما ناشنوا می‌کند. اما «خواهش کردن» به عنوان یک واریز عاطفی عمل کرده و با حفظ احترام و کرامت طرف مقابل، نفوذ ما را برای دفعات آینده بیمه می‌کند. بنابراین، خواهش کردن نه تنها برای حل مسئله فعلی، بلکه برای تضمین کارآمدی درخواست‌های ما در آینده، ابزاری استراتژیک و اقتصادی‌تر است.آیا خواهش کردن نشانه ضعف نیست؟در شرایط بحرانی یا با افراد چموش، خواهش کردن باعث سوءاستفاده شده و اقتدار را از بین می‌برد! این یک سوءتفاهم رایج است. پاسخ منطقی این است که قاطعیت با پرخاشگری تفاوت دارد. تبدیل دستور به خواهش به معنای عقب‌نشینی از هدف نیست، بلکه تغییر روش رسیدن به هدف است. اتفاقاً فردی که آنقدر به نفوذ خود اعتماد دارد که نیازی به فریاد زدن و دستور دادن نمی‌بیند، مقتدرتر به نظر می‌رسد. ادب، ضعف نیست. بلکه رویکردی استراتژیک برای خلع سلاح کردن افراد دشوار است.نتیجهزمان آن رسیده است که باور قدیمی «اقتدار برابر با تحکم است» را کنار بگذاریم. دستور دادن شاید در لحظه فرد را به حرکت وادارد، اما قلب و فکر او را با شما همراه نمی‌کند. ما با جایگزین کردن «خواهش» و «پرسش» به جای «فرمان»، به جای یک پیرو ناراضی، یک همراه مشتاق خلق می‌کنیم. از امروز به جای شلیک کردن کلمات امری، با یک تقاضای محترمانه، راه را برای همکاری داوطلبانه باز کنید. قدرت واقعی در دستان کسی است که بتواند دیگران را به «خواستن» وادارد، نه به «مجبور بودن».</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Sat, 03 Jan 2026 20:21:52 +0330</pubDate>
            </item>
                    <item>
                <title>چرا برای حل مشکلات بزرگ به مغزهای پیچیده نیاز نداریم؟</title>
                <link>https://virgool.io/@vakily/%DA%86%D8%B1%D8%A7-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%AD%D9%84-%D9%85%D8%B4%DA%A9%D9%84%D8%A7%D8%AA-%D8%A8%D8%B2%D8%B1%DA%AF-%D8%A8%D9%87-%D9%85%D8%BA%D8%B2%D9%87%D8%A7%DB%8C-%D9%BE%DB%8C%DA%86%DB%8C%D8%AF%D9%87-%D9%86%DB%8C%D8%A7%D8%B2-%D9%86%D8%AF%D8%A7%D8%B1%DB%8C%D9%85-b1j0aepxjhei</link>
                <description>ما در عصری زندگی می‌کنیم که پیچیدگی را با هوش و سادگی را با ناآگاهی اشتباه می‌گیریم. وقتی با بحرانی مانند نرخ بالای مرگ‌ومیر در بیمارستان‌ها یا شکست پروژه‌های بزرگ صنعتی روبرو می‌شویم، غریزه ما بلافاصله به دنبال راه‌حل‌های گران‌قیمت، فناوری‌های فوق‌پیشرفته و الگوریتم‌های هوش مصنوعی می‌رود. اما حقیقت تکان‌دهنده این است که بسیاری از شکست‌های ما نه از «کمبود دانش»، بلکه از «ناتوانی در اجرای اصول اولیه» ناشی می‌شوند. آنچه که می خواهم بگویم این است که در دنیای اشباع شده از اطلاعات، «سادگی منسجم» (مانند یک چک‌لیست) ابزاری به‌مراتب قدرتمندتر و نجات‌بخش‌تر از «پیچیدگی گسسته» است.دانش کافی نیست، انضباط لازم استبزرگترین خطای منطقی ما این است که تصور می‌کنیم اگر کسی «می‌داند»، حتماً «انجام می‌دهد». شواهد علمی در حوزه پزشکی نشان می‌دهد که حتی مجرب‌ترین جراحان جهان نیز مستعد خطاهای ابتدایی هستند. تنها با اجباری کردن یک چک‌لیست ۵ مرحله‌ای ساده برای شستن دست‌ها و استریل کردن محل تزریق در بیمارستان‌های میشیگان، نرخ عفونت 66٪ کاهش یافت و جان ۱۵۰۰ نفر نجات یافت. (کتاب قدرت شروع ناقص)این نشان می‌دهد که قدرت واقعی در «استانداردسازی دانسته‌ها» نهفته است، نه در انباشتِ بی‌پایان اطلاعات جدید.بهره‌وری در بازگشت به اصولسادگی به معنای تنبلی نیست، بلکه به معنای حذف نویز برای تمرکز بر سیگنال‌های حیاتی است. همانطور که چک‌لیست آتول گوانده ثابت می‌کند که صرفه‌جویی ۷۵ میلیون دلاری در هزینه‌ها، نه از طریق خرید دستگاه‌های جدید، بلکه با تغییر در «رفتار» حاصل شد. (کتاب قدرت شروع ناقص) در هر سیستمی (چه یک سازمان بزرگ و چه زندگی شخصی)، 80٪ نتایج حاصل انجام درست 20٪ از کارهای بنیادی است. (اصل پارتو) وقتی مراحل ساده را به یک پروتکل غیرقابل مذاکره تبدیل می‌کنیم، مغز را از درگیری با جزئیات بدیهی آزاد کرده و ظرفیت آن را برای حل چالش‌های واقعاً پیچیده ذخیره می‌کنیم.آیا سادگی، خلاقیت و تخصص را نمی‌کشد؟برخی از متخصصان اغلب فکر می‌کنند که تقلیل دادن شغل پیچیده‌ی آن‌ها به چند مرحله‌ی ساده در یک چک‌لیست، توهین به تخصص آن‌هاست و روح خلاقیت را از بین می‌برد. آن‌ها می‌ترسند که تبدیل به روبات‌هایی شوند که فقط تیک می‌زنند. اما این یک برداشت نادرست است. پاسخ منطقی این است که چک‌لیست برای جایگزینی تفکر نیست، بلکه برای «آزاد کردن تفکر» است. وقتی یک خلبان یا پزشک خیالی آسوده از بابت چک کردن پیچ و مهره‌های اولیه دارد، می‌تواند تمام توان ذهنی خود را صرف مدیریت بحران‌های غیرمنتظره کند.لذا می توان استدلال نمود که سادگی، بستری است که خلاقیت ایمن روی آن بنا می‌شود.نتیجه‌زمان آن رسیده است که علیه «پیچیدگی» شورش کنیم. موفقیت در میشیگان ثابت کرد که گاهی یک تکه‌کاغذ ارزان‌قیمت از یک اتاق فکر میلیارد دلاری کارآمدتر است. گاهی ما به ابزارهای جدیدتر نیاز نداریم، بلکه به اراده‌ای برای انجام درست همان چیزهایی نیاز داریم که از قبل می‌دانیم. از خود بپرسید در زندگی حرفه‌ای یا شخصی شما، کدام «چک‌لیست ساده» وجود دارد که به دلیل پیش‌پاافتاده بودن، نادیده‌اش می‌گیرید؟ آیا می‌خواهید در هزارتوی پیچیدگی غرق شوید یا با سلاح سادگی، نتایج خیره‌کننده خلق کنید؟ قضاوت و تصمیم با شماست.</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Sat, 03 Jan 2026 00:59:37 +0330</pubDate>
            </item>
                    <item>
                <title>ایده‌های اولیه خود را به وب‌سایت‌های زنده تبدیل کنید</title>
                <link>https://virgool.io/@vakily/%D8%A7%DB%8C%D8%AF%D9%87-%D9%87%D8%A7%DB%8C-%D8%A7%D9%88%D9%84%DB%8C%D9%87-%D8%AE%D9%88%D8%AF-%D8%B1%D8%A7-%D8%A8%D9%87-%D9%88%D8%A8-%D8%B3%D8%A7%DB%8C%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B2%D9%86%D8%AF%D9%87-%D8%AA%D8%A8%D8%AF%DB%8C%D9%84-%DA%A9%D9%86%DB%8C%D8%AF-yyvh7m8maalk</link>
                <description>با استفاده از پلتفرم YouWare می‌توانید ایده‌های اولیه خود را بدون کد نویسی و با کمک هوش مصنوعی با زبان طبیعی به وب‌سایت‌های واقعی و قابل اشتراک تبدیل کنید. افزون بر این، امکان مرور و استفاده از ایده‌ها و پروژه‌های دیگران نیز فراهم است تا الهام بیشتری برای خلاقیت داشته باشید.خاستگاه ایدهایده شکل‌گیری YouWare زمانی به ذهن لئون مینگ، بنیان‌گذار و مدیرعامل این پلتفرم، خطور کرد که در حال مرور شبکه اجتماعی X بود. او مشاهده کرد که برنامه‌نویسان تکه‌کدهای تولیدشده با هوش مصنوعی را به اشتراک می‌گذارند، اما ابزار ساده و مستقیمی برای تبدیل این کدها به پروژه‌های زنده و تعاملی وجود ندارد. همان شب، مینگ بی‌وقفه دست به کار شد و تا ساعت دو بامداد نسخه اولیه را آماده و منتشر کرد. در کمتر از ۴۸ ساعت، بازدید پلتفرم از یک‌هزار نفر به بیش از یک‌میلیون کاربر رسید و خالقان محتوا در سراسر جهان شروع به ساخت و اشتراک‌گذاری پروژه‌های خود کردند.مأموریت و چشم‌اندازمینگ درباره فلسفه شکل‌گیری این محصول می‌گوید:«ما YouWare را ساختیم زیرا خلاقیت باید در دسترس همگان باشد، نه فقط نخبگان فنی. هوش مصنوعی قرار است خلاقیت انسانی را تقویت کند، نه جایگزین آن شود. هدف ما این است که هر فردی بتواند ایده‌های خود را آزادانه بیان کرده و با جهان به اشتراک بگذارد.»قابلیت‌های کلیدیYouWare امکان می‌دهد تنها با یک کلیک، کد تولیدشده توسط ابزارهای مختلف از جمله ChatGPT و Claude به یک وب‌سایت زنده و قابل اشتراک تبدیل شود. این پلتفرم از قابلیت‌هایی نظیر تبدیل مستقیم پرامپت به وب‌سایت، بهبود خودکار طراحی داخلی و سایر امکانات تعاملی بهره می‌برد. نتیجه آن است که فرآیند کدنویسی بیش از هر زمان دیگری شهودی و سریع شده است.رشد و دستاوردهااز آغاز فعالیت تاکنون، YouWare در دو مرحله جذب سرمایه توانسته ده‌ها میلیون دلار سرمایه جلب کند و ارزش فعلی آن به حدود ۸۰ میلیون دلار رسیده است. تاکنون کاربران از سراسر جهان بیش از ۲۰۰ هزار پروژه در این پلتفرم ایجاد کرده‌اند.جمع‌بندیYouWare را می‌توان نخستین پلتفرم کدنویسی هوش مصنوعی دانست که با محوریت خالقان محتوا (Creators) طراحی شده است. این سرویس با ترکیب ابزارهای هوش مصنوعی شهودی، پیش‌نمایش بلادرنگ و اکوسیستم اجتماعی قابل بازآفرینی (remixable) به نسل تازه‌ای از خالقان قدرت می‌دهد تا ایده‌های خود را به پروژه‌های زنده و تعاملی بدل کنند.با افتخار از:https://www.prnewswire.com/news-releases/youware-launches-as-the-first-ai-coding-platform-for-creators-302466538.html</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Sun, 14 Sep 2025 00:16:54 +0330</pubDate>
            </item>
                    <item>
                <title>معرفی Elasticsearch 9</title>
                <link>https://virgool.io/@vakily/%D9%85%D8%B9%D8%B1%D9%81%DB%8C-elasticsearch-9-huvvz5a1cju8</link>
                <description>بالاخره Elasticsearch 9.0 به نسخه پایدار (GA) رسید؛ نسخه‌ای که پر از قابلیت‌های تازه و قدرتمند است و مرزهای جستجو، رصدپذیری (observability) و تحلیل داده مبتنی بر هوش مصنوعی (AI-driven analytics) را جابه‌جا می‌کند. چه بخواهید اپلیکیشن‌های جستجوی معنایی (semantic search) بسازید، چه حجم عظیمی از داده‌ها را مدیریت کنید، یا عملکرد مدل‌های زبانی بزرگ (LLM) را زیر نظر بگیرید، این نسخه مجموعه‌ای از نوآوری‌ها را ارائه می‌دهد که برای پاسخ‌گویی به چالش‌های روز دنیای داده طراحی شده‌اند.در ادامه، مهم‌ترین تغییرات و قابلیت‌های نسخه ۹.۰ از نگاه ما را مرور می‌کنیم.۱. Better Binary Quantization (BBQ) – حالا به‌صورت پایدار است.یکی از ستاره‌های این نسخه، انتشار پایدار فناوری اختصاصی Better Binary Quantization (به اختصار BBQ) است؛ تکنیکی ویژه‌ی فشرده‌سازی بردار که برای جستجوی معنایی فوق‌سریع ساخته شده است.دستاوردهای BBQ:تا ۵ برابر سرعت بیشتر در اجرای پرس‌وجو۳.۹ برابر توان عملیاتی بیشتر در تمام سطوح Recallبدون کاهش دقتبرخلاف روش‌های سنتی، BBQ با یک پیش‌بینی‌گر سبک (lightweight predictor vector) کل ایندکس را اسکن می‌کند، نتایج بالقوه را بیش‌نمونه‌برداری کرده (oversample) و سپس با بردار بزرگ‌تر دوباره رتبه‌بندی می‌کند و همه‌ی این‌ها با یک API ساده انجام می شود. حالا توسعه‌دهندگان می‌توانند نرخ oversampling را تنظیم کنند و باقی کار را به Elasticsearch بسپارند.۲. پشتیبانی از JOIN و بهبودهای بلادرنگ در ES|QLزبان پرس‌وجوی Elasticsearch یا همان ES|QL همچنان در حال تکامل است و حالا به قابلیتی رسیده که مدت‌ها لقب «جام مقدس» تحلیل داده را داشت: یعنی پشتیبانی از join.قابلیت‌های تازه در نسخه ۹.۰:LOOKUP JOIN برای پرس‌وجوهای بلادرنگ بین ایندکس‌ها و مجموعه‌داده‌های مختلفدریافت نتایج جزئی برای پرس‌وجوهای طولانی‌مدتتوابع پیشرفته گروه‌بندی متنفیلترهای KQL برای فیلترینگ انعطاف‌پذیر و گویااین تغییرات، ES|QL را به یک ابزار قدرتمند برای کاوش داده به‌صورت تعاملی و مقیاس‌پذیر تبدیل کرده است.۳. ارتقاء Lucene به نسخه ۱۰در پشت صحنه، Elasticsearch 9.0 حالا بر پایه Lucene 10 کار می‌کند؛ آخرین نسخه از کتابخانه متن‌باز جستجو که قلب تپنده Elasticsearch است.مزایای Lucene 10:بهبود عملکرد پرس‌وجو و کاهش تأخیراستفاده بهینه‌تر از منابع سخت‌افزاریAPIهای تازه برای ساده‌سازی مدیریت ایندکس و فرآیند ارتقاءنتیجه این ارتقاء، هم افزایش سرعت و هم روان‌تر شدن نگهداری عملیاتی است.۴. پشتیبانی بومی از OpenTelemetry: نسخه پایدار EDOTانتشار پایدار Elastic Distributions of OpenTelemetry یا همان EDOT، پشتیبانی بومی از استانداردهای OpenTelemetry را برای تمام سیگنال‌های تله‌متری (از جمله لاگ‌ها، متریک‌ها و تریس‌ها) به ارمغان می‌آورد.مزایا:رصدپذیری آماده‌به‌کار بدون قفل شدن به محصولات اختصاصی (proprietary lock-in) بهبود همبستگی داده‌ها بین سرویس‌هایکپارچگی روان با ابزارهای بومی OpenTelemetryاین قابلیت، Elasticsearch را به یک بازیگر کلیدی در اکوسیستم رصدپذیری متن‌باز تبدیل می‌کند.۵. رصدپذیری LLM برای اپلیکیشن‌های GenAIبا رشد هوش مصنوعی مولد (Generative AI)، رصدپذیری از یک انتخاب به یک ضرورت تبدیل شده است. Elasticsearch 9.0 ابزار بومی پایش مدل‌های زبانی بزرگ را معرفی کرده که شامل موارد زیر است:متریک‌های عملکرد و تحلیل تأخیرردیابی پرسش و پاسخگزارش‌گیری از مصرف و هزینهارزیابی امنیت و قابلیت اطمیناناین ویژگی از پلتفرم‌های محبوب میزبانی LLM مانند Amazon Bedrock، Google Vertex AI، Azure OpenAI و OpenAI پشتیبانی می‌کند تا نظارت و بهینه‌سازی بارهای کاری GenAI آسان‌تر شود.۶. بهبودهای امنیتی: کشف حمله و خودکارسازی قوانین تشخیصعملیات امنیتی در این نسخه یک جهش جدی دارد:انتشار پایدار Attack Discovery برای کشف خودکار تهدیدهاوارد کردن خودکار قوانین تشخیص برای مدیریت ساده‌تر قوانینقوانین تشخیص از پیش‌ساخته و قابل‌سفارشی‌سازیپیش‌نمایش مهاجرت خودکار از قوانین قدیمی SIEMاین قابلیت‌ها، تیم‌های امنیتی را در پیشگیری و واکنش سریع به تهدیدات نوظهور توانمندتر می‌کند.۷. موارد حذف و تغییرات ناسازگارمثل هر نسخه بزرگ دیگر، در این نسخه هم تغییراتی وجود دارد که باید به آن‌ها توجه کنید:حذف Enterprise Search Node، AppSearch و Workplace Search (اگر به این قابلیت‌ها وابسته‌اید، باید راهکار جایگزین بیابید)حذف پشتیبانی از رمزنگاری TLS_RSA در JDK 24توقف پشتیبانی از APIهای Behavioral Analytics CRUDحذف پشتیبانی از ایندکس‌های فریز شده (Frozen Indices)سایر حذف‌ها: تنظیم client.type، پشتیبانی از TLSv1.1 و چند API منسوخ دیگرپیش از ارتقاء، حتماً راهنمای کامل تغییرات و حذف‌ها را مطالعه کنید تا با قطعی یا ناسازگاری روبه‌رو نشوید.منبع:https://mcplusa.com/whats-new-in-elasticsearch-9-0/#:~:text=One%20of%20the%20standout%20features,to%205x%20faster%20query%20speed</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Wed, 13 Aug 2025 18:51:12 +0330</pubDate>
            </item>
                    <item>
                <title>الگوهای غلط در استفاده از Redis</title>
                <link>https://virgool.io/@vakily/%D8%A7%D9%84%DA%AF%D9%88%D9%87%D8%A7%DB%8C-%D8%BA%D9%84%D8%B7-%D8%AF%D8%B1-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-redis-bbc2pgf5ark1</link>
                <description>توسعه‌دهندگان فقط از Redis استفاده نمی‌کنند؛ آن را واقعاً دوست دارند. طبق نظرسنجی سالانه Stack Overflow در سال ۲۰۲۱، Redis برای پنجمین سال پیاپی به عنوان «محبوب‌ترین پلتفرم پایگاه‌داده» شناخته شده است.با این حال، مهم است در نظر داشته باشیم که تنظیمات پیش‌فرض Redis لزوماً برای همه مناسب نیست. میلیون‌ها توسعه‌دهنده Redis را به خاطر سرعت و کارایی‌اش انتخاب می‌کنند، اما نکته حیاتی این است که اطمینان پیدا کنیم استفاده‌مان از آن درست و اصولی است.«الگوی اشتباه» یا Antipattern در واقع به روش‌ها و راه‌حل‌هایی گفته می‌شود که در نگاه اول مناسب به نظر می‌رسند، اما در مرحله اجرا باعث پیچیدگی بیشتر کد و کاهش کارایی می‌شوند. در ادامه به مهم‌ترین الگوهای غلط در استفاده از Redis می‌پردازیم:۱. اجرای پایگاه‌داده‌های بزرگ روی یک شارد یا یک نمونه Redisوقتی یک پایگاه‌داده بزرگ را روی یک شارد یا یک نمونه از Redis اجرا می‌کنید، عملیات‌هایی مانند failover (تغییر خودکار سرور در صورت خرابی)، پشتیبان‌گیری و بازیابی، همگی زمان بیشتری خواهند برد.بنابراین، همیشه توصیه می‌شود حجم هر شارد را در محدوده استاندارد نگه دارید. قاعده محافظه‌کارانه و رایج این است:حداکثر ۲۵ گیگابایت دادهیا ۲۵ هزار عملیات بر ثانیهدر Redis Cloud اگر داده‌های شما بیش از ۲۵ گیگابایت باشد و تعداد عملیات نیز بالا باشد، شارد کردن می‌تواند کارایی را افزایش دهد. حتی با حجم کمتر عملیات، Redis می‌تواند تا ۵۰ گیگابایت داده را نیز مدیریت کند.۱. استفاده از redis-pyکتابخانه redis-py از یک connection pool برای مدیریت اتصال‌ها به سرور Redis استفاده می‌کند. به‌طور پیش‌فرض، هر نمونه Redis که ایجاد کنید، یک connection pool اختصاصی خواهد داشت.شما می‌توانید این رفتار را تغییر دهید و از یک connection pool موجود استفاده کنید. این کار با ارسال نمونه connection pool به پارامتر connection_pool کلاس Redis انجام می‌شود. این روش زمانی کاربرد دارد که بخواهید شاردینگ سمت کلاینت پیاده‌سازی کنید یا کنترل دقیق‌تری روی مدیریت اتصال‌ها داشته باشید:pool = redis.ConnectionPool(host=&#039;localhost&#039;, port=6379, db=0)
r = redis.Redis(connection_pool=pool)
۲. اتصال مستقیم به نمونه‌های Redisوقتی تعداد زیادی کلاینت دارید، موجی از تلاش‌ها برای اتصال مجدد (Reconnect Flood) می‌تواند یک پردازش single threaded را از کار بیندازد و باعث failover شود.برای جلوگیری از این مشکل، باید از ابزاری مناسب برای کاهش تعداد اتصال‌های باز به سرور Redis استفاده کنید.به‌عنوان نمونه:Redis Enterprise DMC Proxy می‌تواند با نقش پروکسی، تعداد اتصال‌ها به سرور کش شما را کاهش دهد.Twemproxy یک پروکسی سبک و سریع است که با هدف کاهش تعداد اتصال‌های باز به سرورهای کش ساخته شده است. این ابزار همراه با ویژگی‌هایی مانند Protocol Pipelining و Sharding به شما کمک می‌کند معماری کش توزیع‌شده خود را به‌صورت افقی (Horizontal) مقیاس‌دهی کنید.۳. بیش از یک شارد ثانویه (Redis OSS)در Redis نسخه متن‌باز (Redis OSS) برای اجماع داده‌ها (Quorum) از مدل شاردبندی استفاده می‌شود. توصیه می‌شود حداقل ۳ نسخه از داده‌ها (دو شارد Replica برای هر شارد Master) داشته باشید تا از مشکل Split-Brain جلوگیری شود.به‌طور خلاصه، Redis OSS با داشتن تعداد فردی از شاردها (یک Primary + دو Replica) این چالش را حل می‌کند.در Redis Cloud این مشکل با تعداد فردی از نودها (Nodes) برطرف می‌شود و حتی با داشتن تنها دو نسخه از داده‌ها نیز از Split-Brain جلوگیری می‌کند که این کار از نظر هزینه به‌صرفه‌تر است. در صورت نیاز می‌توان از «Quorum-Only Node» استفاده کرد تا تعداد نودها فرد شود، بدون این که نود داده اضافه و پرهزینه‌ای ایجاد کنیم.۴. اجرای عملیات‌ها به‌صورت تک‌به‌تکاجرای چندین عملیات به‌صورت سری باعث افزایش سربار ارتباطی می‌شود. راه‌حل بهتر Pipelining است؛ یعنی ارسال چندین دستور پشت سر هم، بدون صبر کردن برای پاسخ هرکدام، و پردازش پاسخ‌ها در انتها.Pipelining کاملاً سمت کلاینت پیاده‌سازی می‌شود و برای کاهش تأخیر پاسخ در شبکه‌های با Latency بالا استفاده می‌گردد. این روش با Buffering زمان رفت‌و‌برگشت داده در شبکه را کاهش می‌دهد. در اتصال به localhost این روش می‌تواند سرعت را تا ۵ برابر افزایش دهد و در ارتباطات اینترنتی کند حتی بیش از ۱۰۰ برابر بهبود ایجاد کند.۵. کش‌کردن کلیدها بدون TTLRedis در اصل یک ذخیره‌ساز کلید-مقدار است و می‌توان برای هر کلید زمان انقضا (TTL) تعیین کرد. با رسیدن این زمان، کلید به‌طور خودکار حذف می‌شود. بدون TTL، کلیدها انباشته شده و در نهایت منجر به Eviction خواهند شد.پیشنهاد می‌شود برای تمام کلیدهای کش، TTL مشخص کنید. دستور TTL مدت زمان باقی‌مانده عمر یک کلید را برحسب ثانیه بازمی‌گرداند و به شما اجازه می‌دهد نظارت دقیقی روی چرخه عمر داده‌ها داشته باشید.۶. حلقه بی‌پایان Redis Replicationاگر بخواهید یک پایگاه‌داده فعال و بسیار بزرگ را روی یک لینک کند یا اشباع‌شده replicate کنید، فرآیند Replication هیچ‌وقت تمام نمی‌شود، چون داده‌ها دائماً در حال تغییرند.برای حل این مشکل باید بافرهای Slave و Client را برای replication کندتر بهینه‌سازی کنید.۷. کلیدهای داغ (Hot Keys)وقتی حجم زیادی از درخواست‌ها روی یک کلید خاص متمرکز می‌شود، همان نود یا شارد مسئول آن کلید زیر فشار شدیدی قرار می‌گیرد. به‌عنوان مثال، اگر خوشه Redis شما ۹۹ نود داشته باشد و یک کلید خاص در هر ثانیه یک میلیون بار درخواست شود، همه این یک میلیون درخواست به یک نود خواهند رفت، نه بین ۹۸ نود دیگر پخش شوند.Redis ابزاری برای شناسایی کلیدهای داغ دارد:redis-cli --hotkeys
بهترین راه‌حل، طراحی مناسب است تا این وضعیت اصلاً ایجاد نشود. می‌توانید داده را با کلیدهای مختلف و در شاردهای متفاوت ذخیره کنید یا از الگوریتم‌های هش برای توزیع درخواست‌ها استفاده کنید.۸. استفاده از دستور KEYSدستور KEYS تمام کلیدهای ذخیره‌شده را با یک الگو جستجو می‌کند و در پایگاه‌داده‌های بزرگ این کار بسیار کند و پرهزینه است (O(N) با N تعداد کلیدها). معادل این کار در SQL، اجرای SELECT * FROM ... بدون WHERE است.به‌جای آن از دستور SCAN استفاده کنید که جستجو را در چند مرحله انجام می‌دهد و کل سرور را متوقف نمی‌کند. برای جستجو بر اساس محتوا نیز می‌توانید از Redis Search استفاده کنید.۹. استفاده از Redis گذرا (Ephemeral Redis) به‌عنوان پایگاه‌داده اصلیوقتی Redis را به‌عنوان پایگاه‌داده اصلی استفاده می‌کنید (نه فقط کش)، باید دسترس‌پذیری بالا (High Availability) و دوام داده (Durability) را تضمین کنید. در نسخه متن‌باز این کار با Redis Sentinel انجام می‌شود. در Redis Cloud این قابلیت به‌صورت پیش‌فرض وجود دارد. همچنین برای دوام، می‌توانید از AOF یا Snapshotting استفاده کنید.۱۰. ذخیره JSON به‌صورت رشته (String)ذخیره JSON به‌صورت رشته باعث مشکلاتی در هماهنگی بین سرویس‌ها و افزایش هزینه پردازش می‌شود. به‌جای آن از ساختار داده HASH یا ماژول Redis JSON استفاده کنید.۱۱. نگاشت جدول یا JSON به HASH بدون توجه به الگوی کوئریاگر تنها روش پرس‌وجو SCAN باشد، فیلترگذاری محدودی خواهید داشت. بهتر است داده را به‌صورت رشته ذخیره کنید و ایندکس‌های معکوس را با SET یا SORTED SET بسازید و به کلید اصلی ارجاع دهید.همچنین استفاده از چند پایگاه‌داده در یک نمونه Redis (با دستور SELECT) یک ضدالگو است و بهتر است برای هر نیاز یک نمونه Redis اختصاصی داشته باشید.برای داده‌های سری زمانی (Time Series) اگر تنها بر اساس ترتیب کوئری دارید، استفاده از ماژول Redis Time Series پیچیدگی اضافی است؛ به‌جای آن از SORTED SET با امتیاز (Score) زمان استفاده کنید.با افتخار ترجمه شده ازhttps://redis.io/learn/howtos/antipatterns</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Mon, 11 Aug 2025 23:44:35 +0330</pubDate>
            </item>
                    <item>
                <title>۹ افسانه توسعه‌دهندگان که وقت شما را می‌گیرند</title>
                <link>https://virgool.io/@vakily/%DB%B9-%D8%A7%D9%81%D8%B3%D8%A7%D9%86%D9%87-%D8%AA%D9%88%D8%B3%D8%B9%D9%87-%D8%AF%D9%87%D9%86%D8%AF%DA%AF%D8%A7%D9%86-%DA%A9%D9%87-%D9%88%D9%82%D8%AA-%D8%B4%D9%85%D8%A7-%D8%B1%D8%A7-%D9%85%DB%8C-%DA%AF%DB%8C%D8%B1%D9%86%D8%AF-owcev3kuatxu</link>
                <description>«همیشه کد تمیز بنویس.»«با جدیدترین استک به‌روز باش.»«پوشش صددرصدی تست ها ضروری است.»همه‌مان این جملات را شنیده‌ایم. بعضی‌ها حتی آن‌ها را در جریان کار خود حک کرده‌اند.اما اگر این «بهترین روش‌ها» همیشه درست نباشند چه؟در دنیای واقعی، توسعه‌دهندگان تحت فشارند تا سریع نسخه بدهند، ایرادها را رفع کنند و مدام بهبود بدهند — نه این‌که دنبال کمال بگردند.خیلی از قوانینی که مثل وحی منزل دنبالشان می‌کنیم، در واقع افسانه‌هایی‌اند که در زرورق «نمایش بهره‌وری» پیچیده شده‌اند.این یک غر زدن نیست. یک تلنگر به واقعیت است.در ادامه ۹ افسانه‌ای را می‌خوانید که ظاهراً منطقی‌اند، اما پنهانی وقتتان را می‌خورند.افسانه ۱ — برای مرتبط ماندن باید از جدیدترین تکنولوژی استفاده کنیدوسوسه‌انگیز است، نه؟ یک فریم‌ورک تازه در Hacker News ترند شده، یک یوتیوبر با تیتر «Next.js 15 دیوانه‌کننده است» ویدیو گذاشته و ناگهان استک شما حس و حال عهد بوق پیدا می‌کند.اما حقیقت این است: بیشتر اینترنت هنوز روی تکنولوژی‌های کسل‌کننده می‌چرخد.WordPress روی ۴۳٪ وب سوار است. PHP هنوز زنده و فعال است. Java همچنان سلطان اینترپرایز است. بک‌اند اپلیکیشن محبوبتان شاید روی Flask، Rails یا حتی... Drupal باشد.دنبال کردن تکنولوژی‌های براق و تازه می‌تواند سرگرم‌کننده باشد، اما دنبال کردن پایداری است که قبض‌هایتان را پرداخت می‌کند.مگر شغلتان ایجاب کند که با ابزارهای جدید کار کنید، استفاده از فناوری‌های «خسته‌کننده» کاملاً اشکالی ندارد.جدید به معنای بهتر نیست؛ فقط یعنی تازه‌تر.نکته:تکنولوژی جدید را زمانی به کار ببرید که واقعاً مشکلی را حل کند، نه فقط چون در شبکه X (توییتر سابق) ترند شده است.افسانه ۲ — کد تمیز همیشه بهتر استنوشتن کد تمیز و خوانا چیز خوبی است… تا وقتی که تبدیل به سرگرمی تمام‌وقتتان نشود.اگر جلسه «refactoring» شما به یک مراسم ۴ ساعته برای انتخاب نام متغیر تبدیل شود، در حالی که ویژگی اصلی هنوز کار نمی‌کند، شما در حال بهینه‌سازی نیستید — فقط دارید تعلل را شیک و حرفه‌ای جلوه می‌دهید.فرق هست بین شفافیت و کمال‌گرایی. کد تمیز کمک می‌کند تیم‌ها راحت‌تر مقیاس بگیرند و اعضای جدید سریع‌تر جا بیفتند. اما وقتی موعد تحویل نزدیک است و قابلیت‌ها نصفه‌نیمه‌اند، وسواس روی این‌که اسم را بگذاریم userHandler یا userService کمکی نمی‌کند.نکته:اول کاری کنید که جواب بدهد، بعد آن را زیبا کنید. کد تمیز باید حامی سرعت باشد، نه قاتل آن.افسانه ۳ — «خودت را تکرار نکن» یا داری اشتباه می‌کنی (DRY)توصیه «خودت را تکرار نکن» تا وقتی خوب است که به هزارتویی از هِلپرهای انتزاعی تبدیل نشده باشد که هیچ‌کس سر درنیاورد.اپلیکیشن‌های در مراحل ابتدایی معمولاً از کمی تکرار سود می‌برند. تکرار یک تابع سه‌خطی بسیار ساده‌تر از این است که آن را در یک ابزار کلی (generic util) بیندازید که شش تیم بعدی مجبور شوند با کامنت‌هایی مثل // به این دست نزنید، همه‌چیز را خراب می‌کند، آن را مهندسی معکوس کنند.افراط در انتزاع، تله بهره‌وری است. شما کد را «یک‌بار» می‌نویسید اما برای همیشه دیباگش می‌کنید.نکته:با آگاهی تکرار کنید. اگر امروز کپی‌پیست کار را شفاف‌تر می‌کند، انجامش دهید. refactor را زمانی انجام دهید که تکرار واقعاً دردسر ایجاد کند، نه قبل از آن.افسانه ۴ — پوشش تست یعنی کد شما امن استنشان «۱۰۰٪ پوشش تست» در README فوق‌العاده به نظر می‌رسد، اما این سپری در برابر باگ‌ها نیست. اغلب فقط یک حس امنیت کاذب ایجاد می‌کند.چرا؟ چون همه تست‌ها یکسان نیستند. شما می‌توانید با تست‌هایی که فقط مسیر اجرای کد را طی می‌کنند (نه رفتار واقعی را)، به پوشش صددرصد برسید، در حالی که سناریوهای واقعی بی‌خبر رها می‌شوند.نکته:تست‌هایی بنویسید که استفاده واقعی را شبیه‌سازی کنند، نه فقط آمار را پر کنند. به دنبال پوشش معنادار باشید، نه اعداد تزئینی.افسانه ۵ — باید یک پارادایم برنامه‌نویسی «واقعی» را انتخاب کنیدبعضی توسعه‌دهندگان به برنامه‌نویسی شی‌ءگرا (OOP) سوگند خورده‌اند. بعضی دیگر با برنامه‌نویسی تابعی (FP) نفس می‌کشند. انجمن‌ها این را به جنگ مذهبی تبدیل می‌کنند، انگار استفاده از هر دو باعث خطای segmentation fault می‌شود.واقعیت؟ بیشتر کدهای واقعی ترکیبی از پارادایم‌ها هستند و این اشکالی ندارد.نکته:وسواس «پاکی» را کنار بگذارید. طوری بنویسید که فهم، نگهداری و دیباگ کد آسان‌تر شود. عمل‌گرایی همیشه بر کمال‌گرایی برتری دارد.افسانه ۶ — همیشه باید از ابتدا برای عملکرد (Performance) بهینه کنیدافسانه این است: اپ شما باید از روز اول سرعت آتشین، کش لبه‌ای (edge caching)، یک شبکه CDN و مقیاس‌پذیری (serverless auto-scaling) داشته باشد، وگرنه کارتان اشتباه است.اما مگر این‌که تعداد کاربران شما از اعتیاد به قهوه‌تان بیشتر باشد، بهینه‌سازی زودهنگام فقط اتلاف وقت است.یک اپ to-do برای پنج کاربر به Redis، Kafka و سه Lambda نیاز ندارد. شما هنوز Netflix نیستید.نکته:ساده بسازید. استفاده واقعی را اندازه بگیرید. بعد بهینه‌سازی کنید. تنظیم عملکرد واکنشی به مقیاس است، نه پیش‌نیازی برای انتشار.افسانه ۷ — هرگز بیرون از ساعات کاری کدنویسی نکنید (فرهنگ کار بیش‌ازحد بد است)بعضی‌ها در اینترنت داد می‌زنند: «بعد از ساعات کاری کدنویسی نکن، این همون فرهنگ مسموم کار بیش‌ازحده!» درست است، فرسودگی شغلی واقعی است و مرزگذاری اهمیت دارد.اما خب، بیرون از ساعات کاری کدنویسی کردن همیشه به معنای «جان کندن» نیست.گاهی شبیه یک بازی است. گاهی هم زمین بازی شخصی خودت.پروژه‌های جانبی چیزهایی به شما یاد می‌دهند که هیچ شغل رسمی نمی‌تواند: مالکیت واقعی کار، کنجکاوی، باگ‌های عجیب و غریب، و آن حس لذت وقتی که اپلیکیشن‌تان ساعت ۲:۴۷ صبح بالاخره درست کار می‌کند.نکته:اگر لذت می‌برید، انجامش بدهید. نه برای کف‌زدن‌های LinkedIn. نه برای رؤیای استارتاپ. فقط چون ساختن چیزها سرگرم‌کننده است. اشتیاق، کار بیش‌ازحد نیست — بازی است.افسانه ۸ — ابزارها از اصول مهم‌ترندوسوسه‌انگیز است که فکر کنیم مسلط شدن به آخرین framework شما را به یک توسعه‌دهنده ۱۰برابری تبدیل می‌کند. اما حقیقت این است: ابزارها تغییر می‌کنند، اصول باقی می‌مانند.React تغییر خواهد کرد. Python ترفندهای تازه پیدا می‌کند. شاید کتابخانه محبوب شما هفته بعد کنار گذاشته شود.اما حل مسئله، ساختمان داده‌ها، الگوریتم‌ها و تفکر منطقی این‌ها همان قدرت‌های واقعی‌اند.نکته:ابزارها را یاد بگیرید تا محصول بسازید، اما اصول را بیاموزید تا رشد کنید. توسعه‌دهنده‌ای که بازگشت (recursion) را می‌فهمد، همیشه از کسی که فقط قطعات آماده را کپی‌پیست می‌کند جلوتر است.افسانه ۹ — هوش مصنوعی همه برنامه‌نویس‌ها را جایگزین خواهد کرداین یکی از پر سر و صداترین افسانه‌هاست. بله، هوش مصنوعی کد می‌نویسد. گاهی درست، گاهی هم کاملاً پرت.می‌تواند کدهای تکراری بسازد، کامپوننت طراحی کند، حتی تست بنویسد. اما در عین حال:متغیرهایی می‌سازد که وجود ندارند.توابعی می‌نویسد که اصلاً اجرا نمی‌شوند.مثل یک توسعه‌دهنده تازه‌کار در روز اول، نیاز به مراقبت دائمی دارد.هوش مصنوعی یک ابزار است، نه جایگزین شما. برای سرعت‌بخشیدن به کار، نمونه‌سازی سریع، یا سپردن کارهای تکراری عالی است. اما فاقد همان درک، قضاوت و غریزه حل مسئله واقعی است که شما دارید.نکته:اگر با هوش مصنوعی مثل یک هم‌تیمی در بازی رفتار کنید مفید است، اما شما همچنان بازیکن اصلی هستید. کارها را به او بسپارید، اما مسئولیت را واگذار نکنید.جمع‌بندی: بنویسید، تست کنید، منتشر کنید، تکرار کنیددر دنیایی پر از نظرهای تند، اصطلاحات پرزرق‌وبرق و میم‌های ترندی برنامه‌نویسی، خیلی راحت می‌توان احساس کرد که عقب افتاده‌اید اگر از آخرین چارچوب استفاده نمی‌کنید، پوشش تست ۱۰۰٪ ندارید، یا طبق یک قانون نانوشته بهره‌وری زندگی نمی‌کنید.اما حقیقت این است: بیشتر این افسانه‌ها فقط سروصدا هستند.تنها معیار واقعی که اهمیت دارد این‌ است که در حال یادگیری باشید. در حال ساختن. در حال حل مسائل واقعی.پس اگر کد شلخته مشکل را حل می‌کند، بنویسید. اصول را بیاموزید. منتشر کنید. بازسازی کنید. دوباره تکرار کنید.با افتخار ترجمه شده ازhttps://medium.com/@dev_tips/dev-myths-debunked-9-rules-you-were-told-to-follow-that-might-just-slow-you-down-a54872b9846b</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Sun, 10 Aug 2025 22:39:02 +0330</pubDate>
            </item>
                    <item>
                <title>نکته هایی درباره Git - قسمت اول</title>
                <link>https://virgool.io/@vakily/%D9%86%DA%A9%D8%AA%D9%87-%D9%87%D8%A7%DB%8C%DB%8C-%D8%AF%D8%B1%D8%A8%D8%A7%D8%B1%D9%87-git-%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84-qge6xj1bfaef</link>
                <description>سلام به همه!امروز می‌خواهم چند نکتهٔ کاربردی برای استفادهٔ مؤثرتر از Git با شما به اشتراک بگذارم. همان Git معروف که احتمالاً همین حالا هم با آن کار می‌کنید؛ همان یار همیشگی کدنویسی که همکاری در پروژه را برای ما مثل آب خوردن می‌کند.وقتی یک توسعه‌دهنده بعد از شش تا هشت ماه برمی‌گردد و به یک commit نگاه می‌کند، اغلب یادش نمی‌آید چرا اصلاً آن تغییر را ثبت کرده بود. علت؟ معمولاً پیام کامیت شفاف و گویا نبوده. رعایت استانداردهای نوشتن پیام کامیت، کلید حل این مشکل است. اگر این اصول را رعایت کنید، کامیت‌های شما برای خودتان و هر کسی که بعداً آن را بررسی کند، واضح و قابل‌فهم خواهد بود.یک پیام کامیت خوش‌ساخت، بهترین راه برای انتقال منظور تغییرات به دیگر توسعه‌دهندگان است. علاوه بر این، تیم باید روی یک الگوی مشخص برای پیام‌های کامیت توافق کند تا تاریخچهٔ کنترل نسخهٔ پروژه/محصول به‌روشنی مستند شود.من بخش‌های مربوط به «قواعد نام‌گذاری شاخه‌ها» و «قواعد نوشتن پیام کامیت» را در سه سطح پایه، متوسط و پیشرفته دسته‌بندی کرده‌ام.می‌توانید تا هر سطحی که نیاز دارید پیش بروید، اما توصیه می‌کنم دست‌کم سطح متوسط را رعایت کنید تا بهترین نتیجه را بگیرید.آیا پیش آمده بی‌هدف شاخه بسازید، یا وسط کار متوجه شوید خودتان هم معنی یک commit را نمی‌فهمید، یا برای فهم یک تغییر مجبور شوید بین فایل‌ها جست‌وجوی پرزحمت انجام دهید؟ اگر این تصویر برایتان آشناست، نگران نباشید؛ این نکته‌ها مسیر را برایتان روشن‌تر می‌کند.چرا باید استانداردها را رعایت کنیم؟وضوح و فهم بهتر: تا حالا شده به یک کامیت چند ماه قبل نگاه کنید و با خودتان بگویید «آن موقع چی توی سرم بود؟» پیام واضح باعث می‌شود حتی بعد از مدت‌ها هدف تغییر را بفهمید.همکاری و کار تیمی: پیام‌های دقیق باعث می‌شوند همهٔ اعضای تیم روی یک خط باشند و کار گروهی روان‌تر پیش برود.سهولت پیمایش و نگهداشت: رعایت استانداردها جابه‌جایی در کد و نگهداری پروژه را راحت‌تر و کم‌دردسرتر می‌کند.مستندسازی و انتقال دانش: یک پیام کامیت خوب مثل یک یادداشت کوچک است که تازه‌واردها را سریع با تاریخچهٔ پروژه آشنا می‌کند.کیفیت پروژه: شیوه‌های یکپارچه باعث می‌شود کیفیت و پایداری پروژه بالاتر برود.گزارش تغییرات خودکار: با رعایت الگوها، می‌توانید گزارش تغییرات (Changelog) را به‌صورت خودکار تولید کنید و کار مدیریت انتشار را ساده کنید.بهینه‌سازی CI/CD: پیام‌های روشن می‌توانند فرایندهای «یکپارچه‌سازی» و «استقرار مداوم» را بهبود دهند و زمینهٔ لازم برای ابزارهای خودکار را فراهم کنند.اشکال‌زدایی و حل مشکلات: وقتی مشکل پیش می‌آید، پیام‌های استاندارد کمک می‌کنند سریع علت پیدا شود و رفع اشکال آسان‌تر شود.مسئولیت‌پذیری: پیام شفاف مشخص می‌کند چه کسی چه تغییری داده و چرا، و این یک لایهٔ مسئولیت‌پذیری به پروژه اضافه می‌کند.یکپارچگی بین پروژه‌ها: رعایت الگوهای ثابت باعث می‌شود جابه‌جایی بین پروژه‌ها آسان باشد و تاریخچهٔ آنها سریع درک شود.قواعد نام‌گذاری شاخه‌ها (Branch Naming Conventions)نام‌های توصیفی: یک شاخه با نام درست و دقیق، فوراً هدف خود را به مخاطب منتقل می‌کند. به‌جای نام‌های کلی و مبهم، نامی انتخاب کنید که شفافیت داشته باشد.مثال:feature/login
bugfix/navbar-overflow
استفاده از خط تیره (Hyphen): برای جدا کردن کلمات در نام شاخه‌ها از خط تیره استفاده کنید (فرمت kebab-case). این کار خوانایی را افزایش می‌دهد.مثال:bugfix/fix-login-issue
این روش بسیار خواناتر از نمونه‌های زیر است:bugfix/fixLoginIssue
bugfix/fix_login_issue
حروف کوچک و کاراکترهای الفبایی-عددی: تنها از حروف کوچک انگلیسی (a-z)، اعداد (0-9) و خط تیره استفاده کنید. از نشانه‌گذاری‌ها، فاصله، آندرلاین یا کاراکترهای خاص تا حد امکان پرهیز کنید.پرهیز از خط تیرهٔ اضافی: خط تیره‌های پشت‌سرهم یا در ابتدا/انتهای نام شاخه، غیرضروری و نادرست‌اند.مثال بد:feat/new--login--
کوتاه و مؤثر: نام شاخه باید ساده و در عین حال گویا باشد؛ به‌گونه‌ای که هدف آن با یک نگاه مشخص شود.پیش‌وند یا نوع شاخه‌ها (Prefix or Type)استفاده از پیش‌وند برای شاخه‌ها کمک می‌کند تا بر اساس هدف و ماهیتشان دسته‌بندی شوند. این کار نه‌تنها وضوح را افزایش می‌دهد، بلکه در اتوماسیون فرایندها نیز مؤثر است.در ادامه، پیش‌وندهای رایج شاخه‌ها و کاربرد هر یک آمده است:feature/: برای توسعه قابلیت‌های جدید.مثال:feature/new-dashboard  
feature/user-profile-page  
feature/new-feature  
bugfix/: برای رفع اشکالات کد که معمولاً به یک issue مرتبط هستند.مثال:bugfix/login-error  
bugfix/incorrect-calculation  
hotfix/: برای رفع فوری و حیاتی اشکالات در محیط تولید (Production).مثال:hotfix/memory-leak  
hotfix/urgent-security-patch  
release/: برای آماده‌سازی نسخه‌های جدید، معمولاً برای اصلاحات نهایی و بازبینی‌ها.مثال:release/version-1.0.0  
release/2.1.0-final  
docs/: برای نوشتن، ویرایش یا اصلاح مستندات.مثال:docs/update-api-docs  
docs/installation-guide  
chore/: برای وظایف روزمره و نگهداری که عملکرد کد را تغییر نمی‌دهند، مانند به‌روزرسانی وابستگی‌ها.مثال:chore/dependency-update  
chore/refactor-build-scripts  
chore/update-dependencies  
test/: برای افزودن یا به‌روزرسانی تست‌ها.مثال:test/add-unit-tests  
test/fix-integration-tests  
style/: برای تغییراتی که عملکرد کد را تحت تأثیر قرار نمی‌دهند ولی قالب‌بندی و استایل کد را بهبود می‌بخشند، مثل اصلاح تورفتگی‌ها یا قواعد نگارشی.مثال:style/code-cleanup  
style/fix-indentation  
perf/: برای بهبودهای عملکردی.مثال:perf/optimize-loading-time  
perf/reduce-memory-usage  
revert/: برای بازگرداندن تغییرات قبلی.مثال:revert/feature-branch-name  
revert/hotfix-issue-123  
refactor/: برای بازسازی کد بدون تغییر عملکرد، با هدف بهبود ساختار یا خوانایی.مثال:refactor/optimize-helpers  
experiment/: برای قابلیت‌ها یا تغییرات آزمایشی که هنوز در مرحله تست هستند.مثال:experiment/new-algorithm-test  
build/: برای تغییرات در فرایند ساخت یا پیکربندی پروژه.مثال:build/update-webpack-config  
افزودن شماره تیکت‌هااگر پروژهٔ شما از سیستم‌های پیگیری مسائل مانند Jira، GitHub Issues یا ابزارهای مشابه استفاده می‌کند، بهتر است شماره تیکت مربوطه را در نام شاخه وارد کنید. این کار دنبال کردن و ارجاع به تسک‌های مرتبط را ساده‌تر می‌کند.مثال:feature/PROJ-123-footer-links
نتیجه گیریرعایت یک الگوی ثابت برای نام‌گذاری شاخه‌ها باعث می‌شود همه اعضای تیم به‌سرعت هدف هر شاخه را بفهمند و روند توسعه روان‌تر شود. همچنین، این کار یکپارچگی با فرایندهای CI/CD و ابزارهای خودکار را آسان‌تر کرده و به نگهداری یک مخزن مرتب و سازمان‌یافته کمک می‌کند.پایان قسمت اول ...با افتخار ترجمه شده ازhttps://substack.com/home/post/p-146876210?utm_campaign=post&amp;utm_medium=web</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Sat, 09 Aug 2025 23:48:50 +0330</pubDate>
            </item>
                    <item>
                <title>راهنمای ساده مفهوم Proxy ها</title>
                <link>https://virgool.io/@vakily/%D8%B1%D8%A7%D9%87%D9%86%D9%85%D8%A7%DB%8C-%D8%B3%D8%A7%D8%AF%D9%87-%D9%85%D9%81%D9%87%D9%88%D9%85-proxy-%D9%87%D8%A7-tl6rqtox6dyg</link>
                <description>این راهنما به زبان ساده توضیح می‌دهد که پروکسی سرور چیست، چطور به‌عنوان واسطه بین کاربر و اینترنت عمل می‌کند، چرا برای حفظ حریم خصوصی و افزایش سرعت کاربرد دارد و تفاوت پروکسی‌های Forward و Reverse در چیست.تا حالا به این فکر کرده‌اید که چطور می‌شود ناشناس در اینترنت گشت‌وگذار کرد؟پاسخ این معما اغلب در یک چیز نهفته است: پروکسی سرورها.پروکسی‌ها نقش واسطه را بین دستگاه شما و وب‌سایت‌هایی که بازدید می‌کنید ایفا می‌کنند و از حریم خصوصی گرفته تا بهبود سرعت اینترنت، کاربردهای متنوعی دارند.اما دقیقاً چطور کار می‌کنند؟در این مقاله، قرار است به زبان ساده اصول اولیه پروکسی‌ها را توضیح بدهیم، نحوه عملکرد آن‌ها را شرح دهیم و تفاوت پروکسی‌های Forward و Reverse را روشن کنیم.پروکسی سرور چیست؟پروکسی سرور، یک واسطه بین کلاینت (مثل کامپیوتر شما) و اینترنت است.به‌جای اینکه دستگاه شما مستقیماً به یک وب‌سایت متصل شود، پروکسی وسط ماجرا قرار می‌گیرد و ارتباط را به نیابت از شما برقرار می‌کند.مثل این است که شما به جای خودتان، یک دوست را بفرستید تا از کسی سؤالی بپرسد و او جواب را برایتان بیاورد.از نگاه وب‌سایت، این دوست (پروکسی) درخواست‌دهنده واقعی به نظر می‌رسد و شما پشت صحنه پنهان می‌مانید.به زبان فنی، پروکسی سرور یک IP مخصوص به خودش دارد و به‌جای IP شما، با وب‌سایت‌ها ارتباط برقرار می‌کند.وقتی از پروکسی استفاده می‌کنید، وب‌سایت‌ها IP پروکسی را می‌بینند، نه IP واقعی شما.این یعنی هویت شما محفوظ می‌ماند و می‌توانید ناشناس در اینترنت بچرخید.اما این تمام ماجرا نیست؛ پروکسی‌ها می‌توانند محتوای مزاحم را فیلتر کنند یا داده‌های پرکاربرد را در حافظه خود ذخیره کنند تا در مراجعه‌های بعدی سریع‌تر تحویل دهند.پروکسی سرور چطور کار می‌کند؟بیایید فرآیند کار پروکسی را قدم‌به‌قدم مرور کنیم:۱. ارسال درخواست: شما (کلاینت) می‌خواهید به یک وب‌سایت دسترسی پیدا کنید. به‌جای ارتباط مستقیم، این درخواست ابتدا به پروکسی ارسال می‌شود (براساس تنظیماتی که در مرورگر یا دستگاه‌تان انجام شده).۲. بررسی کش (Cache): پروکسی بررسی می‌کند که آیا قبلاً نسخه‌ای از صفحه یا داده در حافظه محلی خود ذخیره کرده یا خیر. اگر داشته باشد، همان را به شما تحویل می‌دهد و دیگر نیازی به مراجعه به سایت اصلی نیست.۳. ارسال درخواست به سایت مقصد: اگر داده در کش موجود نباشد، پروکسی درخواست را به سایت هدف ارسال می‌کند و از IP خودش برای دریافت داده استفاده می‌کند.۴. دریافت پاسخ از سایت: وب‌سایت فکر می‌کند این درخواست از سوی پروکسی آمده و پاسخ را برای او ارسال می‌کند.۵. ارسال پاسخ به شما: پروکسی داده دریافتی را به شما تحویل می‌دهد و ارتباط کامل می‌شود.تفاوت پروکسی Forward و Reverseهمه پروکسی‌ها یکسان نیستند.دو نوع پرکاربرد آن‌ها عبارتند از:پروکسی Forward (سمت کاربر)این نوع پروکسی در سمت کاربر قرار می‌گیرد.شرکت‌ها معمولاً از پروکسی‌های Forward استفاده می‌کنند تا تمام ترافیک اینترنتی کارکنانشان از یک مسیر مشخص عبور کند.کاربردهایش شامل:مسدود کردن سایت‌های خاصکش کردن محتوای پرتکرارپنهان کردن IP شبکه داخلی از دنیای بیروناگر تا به حال از یک وب‌سایت پروکسی برای دور زدن محدودیت‌ها استفاده کرده‌اید، در واقع با یک پروکسی Forward کار کرده‌اید.پروکسی Reverse (سمت سرور)این نوع پروکسی در سمت سرور قرار می‌گیرد و در جلوی یک یا چند وب‌سرور مستقر می‌شود.کاربردهایش شامل:توزیع درخواست‌ها بین چندین سرور (Load Balancing)ارائه سریع‌تر محتوا از طریق کشافزایش امنیت با پنهان کردن سرورهای واقعیبسیاری از شبکه‌های تحویل محتوا (CDNها) مثل Cloudflare در واقع Reverse Proxy هستند که محتوا را به شکل گسترده کش می‌کنند و سرورهای مبدا را از حملات محافظت می‌کنند.شناخت تفاوت این دو نوع پروکسی بسیار مهم است؛ چون یکی از مباحث پرکاربرد در مصاحبه‌های طراحی سیستم محسوب می‌شود!چرا باید از پروکسی استفاده کنیم؟شاید به نظر برسد استفاده از پروکسی فقط دردسر اضافه است، اما در واقع مزایای زیادی برای کاربران عادی و سازمان‌های بزرگ دارد:حریم خصوصی و ناشناس ماندن: پنهان کردن IP شما باعث می‌شود هویتتان محفوظ بماند.امنیت و فیلترینگ: پروکسی‌ها می‌توانند نقش فایروال یا فیلتر را ایفا کنند و دسترسی به سایت‌های مخرب یا نامطلوب را مسدود کنند. همچنین، چون بین شبکه شما و اینترنت قرار دارند، جلوی حملات مستقیم به سرورهای داخلی را می‌گیرند.کش و بهبود عملکرد: پروکسی‌ها محتوای پرتکرار را کش می‌کنند. این باعث کاهش مصرف پهنای باند و افزایش سرعت پاسخ‌دهی می‌شود.تعادل بار و مقیاس‌پذیری: در سیستم‌های بزرگ، Reverse Proxy کمک می‌کند تا بار ترافیک بین چندین سرور تقسیم شود و از فشار بیش‌ازحد روی یک سرور جلوگیری شود. اگر یکی از سرورها از کار بیفتد، ترافیک به سایر سرورها هدایت می‌شود.همین مزایا باعث شده‌اند پروکسی‌ها به بخشی جدایی‌ناپذیر از زیرساخت‌های شبکه‌های امروزی تبدیل شوند.جمع‌بندیشاید پروکسی‌ها پشت صحنه کار کنند، اما حالا می‌دانید که آن‌ها واسطه‌های باهوشی هستند که ارتباطات اینترنتی را امن‌تر، سریع‌تر و خصوصی‌تر می‌کنند.از پروکسی Forward که به شما اجازه می‌دهد ناشناس وب‌گردی کنید تا Reverse Proxy که سایت‌های بزرگ را قادر می‌سازد میلیون‌ها درخواست را پاسخ دهند، این ابزارها در قلب طراحی سیستم‌های مدرن جای دارند.با افتخار ازhttps://substack.com/@arslandg/p-170015267?utm_source=profile&amp;utm_medium=reader2</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Thu, 07 Aug 2025 00:30:25 +0330</pubDate>
            </item>
                    <item>
                <title>چگونه API ها را نسخه بندی کنیم؟</title>
                <link>https://virgool.io/@vakily/%DA%86%DA%AF%D9%88%D9%86%D9%87-api-%D9%87%D8%A7-%D8%B1%D8%A7-%D9%86%D8%B3%D8%AE%D9%87-%D8%A8%D9%86%D8%AF%DB%8C-%DA%A9%D9%86%DB%8C%D9%85-segib3sfzfyj</link>
                <description>این روزها APIها در همه‌جا حضور دارند و اگر بخواهید سیستمی بسازید، بی‌تردید به موفقیت شما گره خورده‌اند. اما وقتی API تغییر می‌کند یا یکی از مصرف‌کنندگان درخواست افزودن قابلیت جدیدی را مطرح می‌کند چه اتفاقی می‌افتد؟ اینجاست که موضوع نسخه‌بندی (Versioning) به میان می‌آید.سرفصل‌ها به این شرح‌اند:چرا و چه زمانی باید APIهایتان را نسخه‌بندی کنید؟استراتژی‌های نسخه‌بندیروش‌های پیاده‌سازینسخه‌بندی معنایی (Semantic Versioning)مدیریت چرخه عمر APIابزارهاچرا و چه زمانی باید APIهایتان را نسخه‌بندی کنید؟با رشد و تکامل یک نرم‌افزار، ناگزیر نیاز خواهید داشت تغییراتی در APIهای خود ایجاد کنید؛ افزودن قابلیت‌های جدید، رفع باگ‌ها، یا بهبود عملکرد. اما به‌محض اینکه توسعه‌دهندگان دیگر شروع به ساختن اپلیکیشن‌هایی کنند که به API شما وابسته است، هر تغییری ممکن است کدهای آن‌ها را مختل کند. اینجاست که نسخه‌بندی API اهمیت حیاتی پیدا می‌کند.تصور کنید API‌ای ساخته‌اید که بسیاری از وب‌سایت‌ها برای نمایش داده‌های مالی روی داشبوردهایشان از آن استفاده می‌کنند. فعلاً مقادیر را به دلار (USD) بازمی‌گرداند، اما تصمیم گرفته‌اید واحد یورو (EUR) را هم اضافه کنید. اگر بدون نسخه‌بندی، فرمت پاسخ را تغییر دهید، ممکن است اپلیکیشن‌هایی که به فرمت قبلی وابسته‌اند دچار مشکل شوند.البته، لازم نیست با هر تغییر کوچک، یک نسخه جدید از API ارائه دهید. اما برای تغییرات مخربی که می‌تواند اپلیکیشن‌های موجود را بشکند، حتماً باید نسخه جدیدی تعریف کنید. نمونه‌هایی از این تغییرات عبارت‌اند از: حذف یا تغییر نام فیلدهای پاسخ، اضافه کردن پارامترهای اجباری جدید، یا تغییر نحوه عملکرد اساسی یک endpoint.از سوی دیگر، تغییراتی که باعث شکستن API نمی‌شوند، نیازمند نسخه‌بندی نیستند؛ مثل اضافه کردن فیلدهای اختیاری به پاسخ یا بهینه‌سازی عملکرد API بدون تغییر در نحوه استفاده کلاینت‌ها.در مثال API مالی، اضافه کردن یک فیلد اختیاری برای یورو (EUR) آسیبی به اپلیکیشن‌های موجود که فقط از دلار استفاده می‌کنند نمی‌زند. اما اگر فیلد Dollars را به «currency» تغییر دهید، اپلیکیشن‌هایی که به نام قبلی وابسته‌اند دچار مشکل خواهند شد.البته نسخه‌بندی بی‌رویه هم دردسرساز است. نگهداری هر نسخه جدید هزینه‌های توسعه و تست را افزایش می‌دهد و تعدد نسخه‌ها ممکن است توسعه‌دهندگان را در انتخاب نسخه مناسب سردرگم کند.پس باید رویکرد نسخه‌بندی دقیقی داشته باشید؛ رویکردی که تعادل میان ثبات و قابلیت‌های جدید را برقرار کند. هدف این است که API خود را ارتقاء دهید بدون آنکه کاربران را در این مسیر به دردسر بیندازید.استراتژی‌های نسخه‌بندیبرای مدیریت تغییرات در APIها معمولاً دو رویکرد اصلی وجود دارد: استراتژی تغییرات افزایشی (Additive Change) و استراتژی نسخه‌بندی صریح (Explicit Versioning).استراتژی تغییرات افزایشی:در این روش، شما صرفاً ویژگی‌ها و فیلدهای جدیدی به API اضافه می‌کنید، بدون آنکه به ساختار فعلی آسیبی وارد شود. تغییراتی که باعث ناسازگاری با نسخه‌های قبلی می‌شود (مثل حذف یا تغییر نام فیلدها، تغییر نوع داده‌ها یا کدهای خطا، یا تغییر اساسی در رفتار endpointها) ممنوع است.کارهایی که مجاز هستند شامل موارد زیر می‌شود:افزودن فیلدهای جدید (مشروط به اینکه اختیاری باشند)اضافه کردن endpointهای جدیدافزودن پارامترهای opt-in برای فعال کردن قابلیت‌های جدیدبیایید با یک مثال ببینیم چطور این روش عمل می‌کند. فرض کنید API مالی شما چنین پاسخی برمی‌گرداند:{
  &quot;stock&quot;: &quot;AAPL&quot;,
  &quot;price&quot;: ۱۵۰.۲۵,
  &quot;currency&quot;: &quot;USD&quot;,
  &quot;market_cap&quot;: ۲۵۰۰۰۰۰۰۰۰
}
بعد از مدتی متوجه می‌شوید که برخی کاربران به اطلاعات ارزش بازار (market_cap) نیازی ندارند و این فیلد باعث بار اضافه روی شبکه آن‌ها می‌شود. طبق استراتژی افزایشی نمی‌توانید این فیلد را حذف کنید، چون برخی کلاینت‌ها به آن وابسته‌اند.اما می‌توانید یک پارامتر اختیاری مثل exclude_market_cap=true اضافه کنید. در این حالت، کلاینت‌هایی که می‌خواهند بار شبکه را کاهش دهند می‌توانند از این پارامتر استفاده کنند و دیگران لازم نیست تغییری بدهند.استراتژی افزایشی برای APIهای کوچک که تغییرات زیادی ندارند مناسب است. اما هرچه API بزرگ‌تر و پیچیده‌تر شود، حفظ سازگاری به این روش سخت‌تر خواهد شد.استراتژی نسخه‌بندی صریح:در این رویکرد، شما نسخه‌های مختلفی از API را به‌طور هم‌زمان نگهداری می‌کنید. هرگاه نیاز به ایجاد تغییرات مخرب داشتید، نسخه جدیدی منتشر می‌کنید. این روش آزادی عمل بیشتری برای توسعه API به شما می‌دهد.نسخه‌بندی صریح برای اپلیکیشن‌های سازمانی و محصولاتی که نیاز به تکامل گسترده در طول زمان دارند، بسیار مناسب است. شرکت‌هایی مانند Stripe و Slack از این رویکرد استفاده می‌کنند، چون انعطاف‌پذیری لازم برای بهبودهای اساسی را در اختیارشان می‌گذارد و در عین حال، کاربران نسخه‌های قبلی را نیز پشتیبانی می‌کنند.در بخش بعدی، به روش‌های پیاده‌سازی نسخه‌بندی صریح خواهیم پرداخت.روش‌های پیاده‌سازی نسخه‌بندیسه روش اصلی وجود دارد که کاربران می‌توانند از طریق آن‌ها مشخص کنند می‌خواهند از کدام نسخه API استفاده کنند.رایج‌ترین روش، نسخه‌بندی در مسیر URL (URL Path Versioning) است. در این روش، نسخه را به مسیر URL اضافه می‌کنید، مانند مثال‌های زیر:https://api.example.com/v1/stocks
https://api.example.com/v2/stocks
در اینجا شناسه نسخه (مثل v1 یا v2) قبل از نام منبع (resource name) قرار می‌گیرد. این کار باعث می‌شود نسخه مشخص‌شده به همه منابع و متدهای آن نسخه اعمال شود. مزیت این روش در سادگی و وضوح آن است. هنگام دیباگ کردن، بلافاصله نسخه API را در هر درخواست می‌بینید. همچنین با ابزارهای مستندسازی و تست API نیز به‌خوبی سازگار است.اما ایرادی که دارد این است که با هر تغییر نسخه، آدرس URL منبع تغییر می‌کند. این موضوع وقتی مشکل‌ساز می‌شود که بخواهید URLها به‌عنوان لینک‌های دائمی (permalinks) استفاده شوند. با وجود این، بسیاری از APIهای معروف مثل GitHub و Stripe همین روش را به‌کار می‌گیرند.روش دوم، استفاده از هدر سفارشی HTTP (Custom HTTP Header) برای مشخص کردن نسخه است. در این روش، به‌جای تغییر URL، نسخه را در هدر درخواست تعریف می‌کنید:GET /stocks HTTP/1.1
Host: api.example.com
Api-Version: 2
این رویکرد باعث می‌شود URLها تمیز و ثابت باقی بمانند و با این ایده هم‌راستا است که URL باید هویت منبع را مشخص کند، نه نحوه نمایش آن را. با این حال، استفاده از هدر سفارشی پیاده‌سازی پیچیده‌تری برای مصرف‌کنندگان API دارد و اگر به‌درستی مدیریت نشود، ممکن است مشکلاتی در کشینگ (Caching) ایجاد کند.سومین روش، استفاده از پارامترهای پرس‌وجو (Query Parameters) برای تعیین نسخه است. در این حالت نسخه به‌عنوان یک پارامتر در URL نوشته می‌شود. این روش راه‌اندازی ساده‌ای دارد و ساختار پایه URL را تغییر نمی‌دهد. اما مشکلش این است که پارامترهای پرس‌وجو معمولاً برای فیلتر کردن استفاده می‌شوند، نه نسخه‌بندی. همین موضوع ممکن است باعث شود که مستندات API به آن‌ها اشاره نکند یا با پارامترهای دیگر تداخل پیدا کند. این روش کمتر رایج است، اما برخی APIها (مثل بعضی از سرویس‌های Google) از آن استفاده می‌کنند.هر یک از این روش‌ها مزایا و معایب خود را دارند، اما مهم‌ترین نکته، یکدستی و ثبات در انتخاب روش است. بیشتر APIهای بزرگ از نسخه‌بندی در مسیر URL استفاده می‌کنند چون روشی شفاف و ساده است. با این وجود، برخی سرویس‌ها برای پوشش سناریوهای مختلف، چندین روش نسخه‌بندی را به کاربران پیشنهاد می‌دهند.نسخه‌بندی معنایی (Semantic Versioning)هنگام نسخه‌بندی APIها، نیاز به یک سیستم شفاف برای نام‌گذاری نسخه‌ها دارید. یکی از رویکردهای محبوب در این زمینه، نسخه‌بندی معنایی (Semantic Versioning یا SemVer) است که از یک فرمت عددی سه‌قسمتی استفاده می‌کند: نسخه اصلی (Major)، نسخه فرعی (Minor) و وصله (Patch).فرض کنید API شما در نسخه ۲.۰.۰ قرار دارد. معنای هر بخش به این صورت است:نسخه اصلی (Major Version) – عدد اول (۲): زمانی تغییر می‌کند که تغییراتی ناسازگار با نسخه‌های قبلی ایجاد کنید؛ مثل حذف یا تغییر نام فیلدها یا تغییر رفتار یک endpoint. وقتی یک توسعه‌دهنده می‌بیند API از ۲.۰.۰ به ۳.۰.۰ رسیده، می‌داند که باید در کد خود تغییراتی بدهد.نسخه فرعی (Minor Version) – عدد دوم (۰): زمانی افزایش پیدا می‌کند که قابلیت‌های جدیدی به API اضافه می‌کنید که همچنان با نسخه‌های قبلی سازگارند. مثلاً افزودن یک endpoint جدید یا یک فیلد اختیاری. حرکت از ۲.۰.۰ به ۲.۱.۰ به توسعه‌دهندگان اجازه می‌دهد از ویژگی‌های جدید بهره‌مند شوند بدون اینکه نیاز به تغییر کدهای قبلی داشته باشند.وصله (Patch Version) – عدد سوم (۰): برای رفع باگ‌ها و تغییرات جزئی که قابلیت جدیدی اضافه نمی‌کنند اما مشکلات موجود را برطرف می‌کنند. ارتقاء از ۲.۱.۰ به ۲.۱.۱ باید برای تمام کاربران بی‌خطر باشد و نیازی به تغییر در کدهای کلاینت نباشد.استفاده از نسخه‌بندی معنایی باعث می‌شود توسعه‌دهندگان دقیقاً بدانند چه نوع تغییراتی در API رخ داده است. افزایش نسخه اصلی نشانه نیاز به تغییرات در کد است، در حالی که نسخه‌های فرعی و وصله‌ها (Minor و Patch) باید بدون ایجاد مشکل قابل استفاده باشند.مدیریت چرخه عمر APIبا تغییرات مداوم در API و انتشار نسخه‌های جدید، در نهایت باید نسخه‌های قدیمی‌تر را کنار بگذارید. زمانی که یک نسخه اصلی (Major Version) جدید منتشر می‌کنید، باید برای پشتیبانی از نسخه‌های قبلی یک بازه زمانی مشخص تعریف کنید. مثلاً وقتی نسخه ۴ را ارائه می‌دهید، اعلام می‌کنید که نسخه ۱ به‌زودی از پشتیبانی خارج خواهد شد.به طور معمول، اگر به توسعه‌دهندگان ۶ تا ۱۲ ماه زمان برای مهاجرت به نسخه‌های جدید بدهید، فرصت کافی برای برنامه‌ریزی و پیاده‌سازی تغییرات را خواهند داشت، بدون آنکه در فشار و عجله قرار بگیرند.یکی از روش‌های عملی و مؤثر برای اطلاع‌رسانی توقف پشتیبانی (Deprecation) استفاده از هدر Sunset در پاسخ‌های API است. این هدر به توسعه‌دهندگان می‌گوید که یک نسخه یا endpoint خاص تا چه زمانی در دسترس خواهد بود:Sunset: Sat, 31 Dec 2025 23:59:59 GMT
به‌محض اینکه یک توسعه‌دهنده این هدر را در پاسخ API ببیند، متوجه می‌شود که باید رابط کاربری خود را به‌روزرسانی کند. پس از رسیدن به تاریخ sunset، درخواست‌هایی که به آن نسخه ارسال می‌شوند یا باید پیغام خطا دریافت کنند، یا به نسخه جدید ریدایرکت شوند.ابزارهامدیریت نسخه‌های API به صورت دستی، خیلی زود تبدیل به کاری پیچیده و پرخطا می‌شود. خوشبختانه ابزارها و کتابخانه‌هایی وجود دارند که دقیقاً برای همین منظور طراحی شده‌اند و به کمک شما می‌آیند.OpenAPI Specification که قبلاً با نام Swagger شناخته می‌شد، یکی از بهترین روش‌ها برای توصیف و طراحی APIهاست. این استاندارد مزایای بسیاری در زمینه نسخه‌بندی دارد:به‌راحتی می‌توانید تغییرات هر نسخه را در فایل‌های تعریف جداگانه مستندسازی و ردیابی کنید.مستندات تعاملی (Interactive Documentation) به توسعه‌دهندگان کمک می‌کند تا به‌سرعت تفاوت‌های هر نسخه را ببینند.ابزارهایی وجود دارند که می‌توانید با آن‌ها نسخه‌های مختلف API خود را با یکدیگر مقایسه کرده و تغییرات مخربی (Breaking Changes) که ممکن است باعث بروز خطا شوند را شناسایی کنید.برای مثال، ابزار openapi-diff به شما این امکان را می‌دهد که دو مشخصات API (Specification) را با هم مقایسه کنید و بفهمید کجاها ناسازگاری ایجاد شده است:openapi-diff original.json updated.json
خروجی ممکن است چیزی شبیه به این باشد:GET /stocks

Return Type:

- Changed 200 OK

Media types:

- Changed application/json

Schema: Broken compatibility

Missing property: price (number)
این گزارش به شما می‌گوید که حذف فیلد &quot;price&quot; یک تغییر ناسازگار است که نیازمند انتشار یک نسخه اصلی جدید می‌باشد.علاوه بر مقایسه مشخصات (Specification Comparison)، ابزارهای دیگری نیز وجود دارند که به مدیریت نسخه‌بندی کمک می‌کنند. مثلاً API Gatewayهایی مثل Amazon API Gateway، Azure API Management یا Kong می‌توانند نسخه‌بندی را به‌صورت خودکار برای شما مدیریت کنند. این ابزارها با توجه به اطلاعات نسخه در URL یا هدرها، درخواست‌ها را به backend مناسب هدایت می‌کنند.ممکن است نسخه‌بندی API در ابتدا کاری زمان‌بر و پرزحمت به نظر برسد، اما در واقع یک سرمایه‌گذاری بلندمدت برای موفقیت API و رضایت کاربران است. رویکردی دقیق و ثابت در طول زمان به توسعه‌دهندگان نشان می‌دهد که برای کار آن‌ها ارزش قائلید و این اعتماد را حفظ می‌کند؛ حتی زمانی که API شما تغییر می‌کند.با افتخار ازhttps://newsletter.francofernando.com/p/apis-versioning?utm_source=%2Fsearch%2FElasticsearch&amp;utm_medium=reader2&amp;hide_intro_popup=true</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Mon, 04 Aug 2025 18:35:48 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با شبکه none در Docker</title>
                <link>https://virgool.io/codenevis/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B4%D8%A8%DA%A9%D9%87-none-%D8%AF%D8%B1-docker-oltcpbmmbhaf</link>
                <description>در این مقاله کوتاه قصد دارم درباره شبکه none در داکر صحبت کنم. شبکه none یکی از انواع شبکه‌هایی است که داکر برای ایزوله‌سازی کانتینرها ارائه می‌دهد. این شبکه به‌طور خاص طراحی شده است تا کانتینر را از هرگونه دسترسی به اینترنت یا دیگر شبکه‌ها کاملاً ایزوله کند.زمانی که یک کانتینر با استفاده از شبکه none اجرا می‌شود:تنها یک رابط loopback داخلی (localhost) در کانتینر فعال است.کانتینر نمی‌تواند به هیچ منبع خارجی (مانند وب‌سرویس‌ها، دیتابیس‌ها، یا حتی دیگر کانتینرها) متصل شود.بنابراین این ویژگی باعث می‌شود شبکه none گزینه‌ای ایده‌آل برای سناریوهایی باشد که امنیت و ایزوله‌سازی کامل داده‌ها اهمیت بالایی دارند.بیایید با هم سناریو زیر را در نظر بگیرم:به عنوان مدیر تیم مهندسی داده، تصمیم گرفتم از محمد، که یک عضو تازه‌کار و مشتاق است، برای انجام بخش کوچکی از یک پروژه از جنس ETL استفاده کنم. هدف من این است که مهارت‌های محمد را در یک محیط کنترل‌شده محک بزنم و در عین حال نشان دهم که او می‌تواند در شرکت تأثیرگذار باشد. با این حال، به دلیل تازه‌کار بودن محمد و مسائل مربوط به امنیت داده‌ها، او اجازه دسترسی به داده‌های محرمانه را ندارد.شرح تسکی که برای محمد تعریف کردم به این صورت بود:محمد باید کدی بنویسد که مادامی که هر فایل ورودی CSV را از یک دایرکتوری قرار داده شد، پردازش خود را شروع کند. لذا من چند فایل CSV به‌عنوان نمونه طراحی کردم که شامل داده‌هایی مشابه داده‌های واقعی است اما هیچ‌گونه اطلاعات حساس ندارد. این فایل در اختیار محمد قرار دادم. محمد باید در این فایل، تغییراتی ایجاد کند که شامل تغییر نام و نوع ستون‌ها است و همچنین از ستون متنی، تمامی کد ملی ها به همراه نام و نام خانوادگی افراد استخراج شوند و در دو ستون جدید، با جداکننده کاما (,) ذخیره شوند. پس از اعمال این تغییرات، فایل پردازش‌شده باید در یک دایرکتوری مشخص به نام output ذخیره شود. حالا من می توانم خروجی‌های پردازش‌شده را به‌راحتی به یک دیتابیس منتقل کنم تا برای تحلیل‌های بیشتر، گزارش‌گیری، یا ذخیره بلندمدت مورد استفاده قرار گیرند یا آن ها را می‌توانم به‌عنوان ورودی در یک سیستم یا Pipeline دیگر قرار دهم. به‌این‌ترتیب، می‌توانم این داده‌ها را به مراحل بعدی پردازش یا تحلیل‌های پیچیده‌تر انتقال دهم.اما مشکل چیست؟مشکل اینجاست که من فرصت بررسی کد محمد را ندارم و فقط خروجی کار او برایم مهم است. بنابراین ممکن است او در کد خود عملیاتی خرابکارانه انجام دهد، مثلاً ارسال داده‌ها به یک وب‌سرویس خارجی یا ذخیره آن‌ها در محلی دیگر.برای جلوگیری از این موضوع:من از محمد خواستم که پس از تکمیل توسعه، کد خود را در گیت (Git) پوش کند تا بتوانم بعدا سر فرصت به تاریخچه تغییرات کد و جزئیات آن دسترسی داشته باشم.به محمد دسترسی به داده‌های اصلی و محرمانه داده نشده است، و تنها می‌تواند با فایل نمونه کار کند.من تصمیم گرفتم که برای اجرای کدهای محمد از شبکه none داکر استفاده کنم. این تصمیم به این دلیل گرفته شد که این نوع شبکه، کانتینر را به‌صورت کامل از هرگونه دسترسی به اینترنت یا شبکه داخلی ایزوله می‌کند. با این کار، مطمئن می‌شوم پس از دیپلوی کدهای محمد نمی‌توانند داده‌های اصلی را به هیچ وب‌سرویس یا مقصد خارجی ارسال کنند.با این روش، با خیال راحت هر تعداد دسته از داده‌های اصلی را که به‌صورت فایل‌های CSV هستند، به عنوان ورودی در مسیر پردازش ETL محمد قرار دهم. هر فایل ورودی توسط کد محمد پردازش می‌شود و خروجی آن، پس از طی مراحل ETL، در مسیر مشخص‌شده (دایرکتوری output) ذخیره می‌شود.از آنجا که شبکه none داکر جلوی هرگونه دسترسی غیرمجاز به شبکه را می‌گیرد، مطمئن هستم که داده‌های اصلی در این فرآیند کاملاً ایمن هستند.</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Fri, 17 Jan 2025 12:36:08 +0330</pubDate>
            </item>
                    <item>
                <title>بررسی سرعت مدل lang_ident_model_1</title>
                <link>https://virgool.io/@vakily/%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C-%D8%B3%D8%B1%D8%B9%D8%AA-%D9%85%D8%AF%D9%84-langidentmodel1-pxarm1mpoeky</link>
                <description>اگر بخواهیم شناسایی زبان را در داده‌های متنی بررسی کنیم، اولین سوالی که پیش می‌آید این است که چگونه می‌توانیم به راحتی زبان یک متن را شناسایی کنیم؟ برای این کار، ابزارها و تکنیک های متنوعی وجود دارد که یکی از آن‌ها استفاده از امکانات موجود دیتابیس Elasticsearch است. در این مقاله، قصد داریم با استفاده از مدل lang_ident_model_1 در Elasticsearch، سرعت شناسایی زبان بر روی یک دیتاست فارسی به صورت ساده و مقدماتی انجام دهیم.فرض کنید شما یک فروشگاه اینترنتی دارید که مشتریان به زبان‌های مختلف نظرات خود را می‌نویسند. شما می‌خواهید تمام این نظرات را به صورت خودکار شناسایی زبان کرده و سپس تحلیل‌های بیشتری بر اساس زبان انجام دهید.ما یک دیتاست فارسی داریم که شامل نظرات کاربران در زمینه هتل و تلفن همراه است. دیتاست دارای دو بخش اصلی است: نظرات و درصد درستی آن‌ها. درصد درستی، همان امتیازی است که خود کاربر هنگام نوشتن نظر داده است.گام اول: آماده‌سازی دیتاستابتدا فایل داده‌ها را از اینجا بارگذاری کرده و سپس نظرات را استخراج می‌کنیم:import pandas as pd 
df = pd.read_csv(&amp;quotHotel.csv&amp;quot, encoding=&#039;utf-16&#039;)
reviews = df[&amp;quotreview&amp;quot].values.tolist()در اینجا، نظرات به صورت لیستی از رشته‌ها استخراج می‌شوند. حالا که داده‌ها آماده شدند، وقت آن است که این نظرات را به Elasticsearch ارسال کنیم.گام دوم: ایجاد پایپ‌لاین شناسایی زباندر این قسمت باید پایپ‌لاین شناسایی زبان را در Elasticsearch ایجاد کنیم. این کار با استفاده از دستور PUT _ingest/pipeline/language_detection_pipeline انجام می‌شود. پایپ‌لاین شناسایی زبان به مدل lang_ident_model_1 برای شناسایی زبان نیاز دارد و متن‌های هر نظر را به این مدل ارسال می‌کند.PUT _ingest/pipeline/language_detection_pipeline
{
   &amp;quotprocessors&amp;quot: [
      {
         &amp;quotinference&amp;quot: {
            &amp;quotmodel_id&amp;quot: &amp;quotlang_ident_model_1&amp;quot,
            &amp;quotinference_config&amp;quot: {
               &amp;quotclassification&amp;quot: {
                  &amp;quotnum_top_classes&amp;quot: 1
               }
            },
            &amp;quotfield_map&amp;quot: {
               &amp;quotcontent&amp;quot: &amp;quottext&amp;quot
            }
         }
      }
   ]
}در اینجا، این پایپ‌لاین با استفاده از مدل lang_ident_model_1 زبان متن‌هایی که در فیلد content قرار دارند را شناسایی می‌کند. مدل به طور پیش‌فرض، عمل دسته‌بندی را انجام می‌دهد و به بالاترین دسته (که همان زبان شناسایی شده است) توجه می‌کند.گام سوم: ارسال داده‌ها به Elasticsearch با استفاده از پردازش موازیحالا که داده‌ها آماده‌اند، می‌خواهیم این داده‌ها را به Elasticsearch ارسال کنیم. از آنجایی که تعداد نظرات به 6432 رکورد است، ارسال آن‌ها به صورت یکجا می‌تواند زمان زیادی ببرد. برای حل این مشکل، از پردازش موازی استفاده می‌کنیم تا به صورت همزمان چندین بخش از داده‌ها را ارسال کنیم و عملکرد مدل را در بهترین حالت ممکن انجام دهیم. این کار با استفاده از ThreadPoolExecutor در پایتون انجام می‌شود. کد زیر نشان می‌دهد که چگونه می‌توانیم داده‌ها را به بخش‌های کوچک تقسیم کرده و به صورت موازی ارسال کنیم:from concurrent.futures import ThreadPoolExecutor
from elasticsearch import Elasticsearch, helpers

def send_chunk(chunk):
    _chunk = [
        {&amp;quot_index&amp;quot: &amp;quothotel&amp;quot, &amp;quot_source&amp;quot: {&amp;quotcontent&amp;quot: doc}, &amp;quotpipeline&amp;quot: &amp;quotlanguage_detection_pipeline&amp;quot}
        for doc in chunk
    ]
    helpers.bulk(es, _chunk)

es = Elasticsearch([{&#039;host&#039;: &#039;localhost&#039;, &#039;port&#039;: 9200}])

chunk_size = 500
def chunk_list(data, chunk_size):
    for i in range(0, len(data), chunk_size):
        yield data[i:i + chunk_size]

with ThreadPoolExecutor(max_workers=8) as executor:
    executor.map(send_chunk, chunk_list(reviews, chunk_size))

es.close()در این کد، داده‌ها به دسته‌های 500 تایی تقسیم می‌شوند و هر دسته به صورت موازی به Elasticsearch ارسال می‌شود. استفاده از 8 ترد در اینجا به این معنی است که 8 بخش از داده‌ها به صورت همزمان پردازش خواهند شد.گام چهارم: محاسبه زمان اجرادر نهایت، زمان اجرای این عملیات به صورت زیر است:CPU times: total: 156 ms
Wall time: 9.54 sاز آنجایی که تعداد رکورد های مجموعه داده ما 6432 است، هر ثانیه حدودا 674 داده را پردازش و به دیتابیس وارد کرده است.نمونه ای از یک دادهنتیجه گیریدر این مقاله سعی شد بررسی مقدماتی و ساده ای از میزان سرعت مدل تشخیص زبان دیتابیس Elasticsearch داشته باشیم. با استفاده از مدل lang_ident_model_1، می‌توانیم به راحتی زبان متن‌های مختلف را شناسایی کرده و بر اساس آن تحلیل‌های دقیق‌تری انجام دهیم. از طرفی، استفاده از پردازش موازی باعث شد که سرعت پردازش داده‌ها به شکل قابل توجهی افزایش یابد. با استفاده از پردازش موازی، این عملیات در کمتر از 10 ثانیه انجام شد که زمان مناسبی برای حجم داده‌های متوسط محسوب می‌شود.</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Thu, 02 Jan 2025 13:50:35 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با Best Practice های ElasticSearch</title>
                <link>https://virgool.io/@vakily/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-best-practices-%D9%87%D8%A7%DB%8C-elasticsearch-qnylj7ndthny</link>
                <description>در این نوشته قصد دارم در مورد best practice های استفاده از ElasticSearch بنویسم. این روش‌ها توصیه‌های عمومی هستند و می‌توانند در هر مورد کاربردی اعمال شوند. آشنایی با Bulk Requestsمفهوم API Bulk امکان انجام بسیاری از عملیات‌های index/delete را در یک فراخوانی API فراهم می‌کند. این می‌تواند سرعت index کردن را به طور قابل توجهی افزایش دهد. هر subrequest به صورت مستقل اجرا می‌شود، بنابراین failure یک subrequest تاثیری بر success دیگران نخواهد داشت. اگر هر یک از request ها faile شود، top-level error flag به true تنظیم می‌شود و جزئیات خطا گزارش خواهد شد.آشنایی با Multithread clients to Index Dataیک single thread که request های bulk را ارسال می‌کند، احتمالاً قادر به استفاده کامل از ظرفیت indexing ElasticSearch cluster نخواهد بود. برای استفاده از تمام منابع cluster، شما باید داده‌ها را از چندین thread یا processe ارسال کنید. علاوه بر استفاده بهتر از منابع cluster، این باید کمک کند تا هزینه هر fsync را کاهش دهد. هر دو داده index و transaction log به طور دوره‌ای به دیسک flush می‌شوند. اگر داده‌های بیشتری با multithread وجود داشته باشند، داده‌های بیشتری به دیسک sync می‌شود تا I/O را برای بهبود performance کاهش دهد.درباره index.refresh_intervalبه طور پیش فرض، ElasticSearch به طور دوره‌ای هر ثانیه index ها را refresh می‌کند، اما درصورتی که تنها بر روی index هایی که در 30 ثانیه گذشته حداقل یک request از نوع جستجو دریافت کرده باشند. اگر شما ترافیک جستجوی کم یا اصلاً ندارید (به عنوان مثال، کمتر از یک request جستجو در هر 5 دقیقه) و می‌خواهید برای سرعت indexing بهینه‌سازی کنید، این config بهینه است. این رفتار در پیکربندی پیش فرض هنگامی که جستجویی انجام نمی‌شود، به بهینه‌سازی خودکار bulk indexing کمک می‌کند. برای انصراف از این رفتار، می توانید interval refresh را به صورت صریح تنظیم کنید. از طرف دیگر، اگر index شما request های جستجوی منظمی را تجربه کند، این رفتار پیش فرض به این معنی است که ElasticSearch هر 1 ثانیه index شما را refresh خواهد کرد. اگر بین زمانی که یک document ایندکس می‌شود و زمانی که قابل مشاهده می‌شود را افزایش دهید، افزایش index.refresh_interval به یک مقدار بزرگتر، به عنوان مثال 30s، ممکن است به بهبود سرعت indexing کمک کند.آشنایی با Auto generated IDsهنگام index کردن یک document که دارای یک id مشخص است، ElasticSearch نیاز دارد تا بررسی کند که آیا document ای با همان id در همان shard وجود دارد یا خیر، که این یک عملیات هزینه‌بر است و همین هزینه با رشد index بیشتر می‌شود. با استفاده از id های خودکار، ElasticSearch می‌تواند این بررسی را از بین ببرد، که باعث می‌شود index کردن سریع‌تر انجام شود.آشنایی با index.translog.sync_intervalاین پارامتر تعیین می‌کند که بدون توجه به عملیات write، چه مقداری translog به دیسک fsync شده و commit می‌شود. به طور پیش فرض برابر با 5 ثانیه است. مقادیر کمتر از 100 میلی‌ثانیه مجاز نیستند.آشنایی با index.translog.flush_threshold_sizeمفهوم translog تمام عملیات‌هایی را که هنوز به طور safe در Lucene ذخیره نشده‌اند را ذخیره می‌کند. اگرچه این عملیات‌ها برای خواندن در دسترس هستند، اما اگر shard متوقف شد و نیاز به recovery داشت، باید دوباره replay شوند. این تنظیمات maximum اندازه کلی این عملیات‌ها را کنترل می‌کند، تا از اینکه recovery ها زمان زیادی بگیرند جلوگیری شود. هنگامی که به maximum رسیده باشد، یک flush اتفاق خواهد افتاد، که یک Lucene commit point جدید تولید می‌کند. به طور پیش فرض برابر با 512 مگابایت است.آشنایی با Large Documentsتمامی large document ها بر network، مموری و دیسک فشار و stress بیشتری می آورند. index کردن large document ها می تواند مقدار حافظه ای را استفاده کند که ضریبی از اندازه اصلی document است. همچنین Proximity search ها (به عنوان نمونه phrase query ها) و highlighting نیز گران تر می شود زیرا هزینه آنها به طور مستقیم به اندازه document اصلی بستگی دارد.تنظیم Index Mapping Explicitlyدیتابیس ElasticSearch می تواند mapping را به صورت dynamic ایجاد کند، اما ممکن است برای تمام سناریوها مناسب نباشد. به عنوان مثال، فیلد های string پیش فرض در ElasticSearch هر دو از انواع &quot;keyword&quot; و &quot;text&quot; هستند. در بسیاری از سناریوها غیر ضروری است.آشنایی با Index Mapping — Nested Typesهمانطور که می دانید query در فیلدهای nested نسبت به فیلدهای parent document کندتر است. بازیابی فیلدهای match شده nested سرعت را کاهش می دهد. هرگاه شما فیلدی از یک document حاوی فیلدهای nested را به روز کنید، بستگی به اینکه آیا یک فیلد nested را به روز کردید یا خیر، تمام داكيومنت های Lucene باید به عنوان &quot;حذف شده&quot; علامت گذاری شوند و دوباره نوشته شوند.علاوه بر کاهش سرعت به روزرسانی ها، چنین عملیاتی garbage ای ایجاد می کند که باید توسط segment merging بعداً پاک شود.آشنایی با Index Mappingبا استفاده از فیلد _all، مقادیر تمام فیلدها به یک string تبدیل می شوند. این نسبت به سایر فیلدها نیاز به فضای بیشتر CPU و دیسک دارد. بیشتر use case ها نیازی به فیلد _all ندارند. شما می توانید چندین فیلد را با استفاده از پارامتر copy_to عمل concatenate را انجام دهید. فیلد _all به طور پیش فرض در نسخه های 6.0 و بالاتر ElasticSearch غیرفعال است.آشنایی با Leverage Index Templatesبا Index template ها تنظیماتی مانند تعداد shard ها، replica ها و mappings ها را تعریف می کنند که می توانید به صورت خودکار هنگام ایجاد index های جدید اعمال کنید. الستیک template ها را بر اساس pattern ایندکسی که با نام ایندکس مطابقت دارد به ایندکس های جدید اعمال می کند.استفاده از replica ها به منظور مقیاس پذیری و انعطاف پذیریالستیک سرچ به صورت available و scalable با نیازهای شما ساخته شده است. شما می توانید node ها را به cluster اضافه کنید تا ظرفیت آن را افزایش دهید و ElasticSearch به طور خودکار load داده ها و query شما را بین تمام node های موجود توزیع می کند. برای اینکه ElasticSearch همیشه در دسترس باشد، index های آن باید fault tolerance داشته باشند. این می تواند با استفاده از replica shard ها انجام شود.یک replica shard کپی از یک primary shard است. replica ها نسخه های اضافی از داده های شما را برای محافظت در برابر خرابی سخت افزار و افزایش ظرفیت برای ارائه request های خواندن مانند جستجو یا بازیابی یک document فراهم می کنند.آشنایی با مفهوم Shard Sizingیک shard که در ایندکس Lucene است، از file handle ها، مموری و CPU cycle ها استفاده می کند. هدف از انتخاب تعداد shard ها توزیع یکنواخت index در سراسر تمام node های داده در cluster است. با این حال، این shard ها نباید خیلی بزرگ یا خیلی زیاد باشند. یک قاعده خوب این است که سعی کنید اندازه شارد را بین 10-50 گیگابایت نگه دارید. شاردهای بزرگ می توانند باعث سختی ElasticSearch در بازیابی از خرابی شوند، اما چون هر شارد مقداری از CPU و حافظه را استفاده می کند، داشتن shard های کوچک خیلی زیاد می تواند باعث خطا های performance و out of memory شود.آشنایی با Index State Managementمفهوم ISM به شما اجازه می دهد تا policy های custom management را برای خودکار کردن task های روتین تعریف کنید و آنها را روی index ها و index pattern ها اعمال کنید. دیگر نیازی به راه اندازی و مدیریت فرآیندهای خارجی برای اجرای عملیات index نیست. یک policy شامل یک state پیش فرض و یک لیست از state ها برای انتقال بین index ها است. در هر state ای، شما می توانید یک لیست از action ها و شرایطی که این trigger را فعال می کنند تعریف کنید. یک use case معمول این است که به طور دوره ای index های قدیمی را پس از یک دوره معین حذف کنید.باتشکر ازhttps://lazypro.medium.com/best-practices-of-using-elasticsearch-2a2485a289c7</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Sun, 12 May 2024 15:37:56 +0330</pubDate>
            </item>
                    <item>
                <title>ترکیب vector search و filtering در ElasticSearch</title>
                <link>https://virgool.io/@vakily/%D8%AA%D8%B1%DA%A9%DB%8C%D8%A8-vector-search-%D9%88-filtering-%D8%AF%D8%B1-elasticsearch-l7604aisu0tx</link>
                <description>مدل‌های زبانی بزرگ (LLM) هر روز در حال تکامل هستند و این وضعیت به گسترش جستجوی معنایی یا semantic search کمک می‌کند. LLM ها در تجزیه و تحلیل متون و آشکارسازی شباهت‌های معنایی برتری دارند. این وضعیت همچنین در موتورهای جستجو منعکس می‌شود زیرا موتورهای جستجوی معنایی می‌توانند نتایج بیشتری را برای کاربران ارائه دهند.با اینکه مدل‌های زبانی بزرگ می‌توانند نتایج نزدیک به معنا را دریافت کنند، پیاده‌سازی filter ها در نتایج جستجو برای بهبود تجربه کاربر ضروری است. به عنوان مثال، اضافه کردن filter های مبتنی بر تاریخ یا دسته‌بندی‌ها می‌تواند به تجربه جستجوی بیشتری کمک کند. بنابراین، چگونه می‌توانیم به طور موثر جستجوی معنایی را با filtering ترکیب کنیم؟بیایید ابتدا با اتصال ElasticSearch و query های اولیه جستجو شروع کنیم:from elasticsearch import Elasticsearch
import config as cfg
client = Elasticsearch(
&#039;https://localhost:9200&#039;,
ssl_assert_fingerprint=cfg.ES_FINGERPRINT,
basic_auth=(&#039;elastic&#039;, cfg.ES_PASSWORD)
)من اطلاعات لازم برای connection را از یک config file می‌خوانم، و این جزئیات به صورت خودکار زمانی که Elasticsearch برای اولین بار راه‌اندازی می‌شود، ارائه می‌شوند.[
 {
 &amp;quottitle&amp;quot: &amp;quotData Structures and Algorithms&amp;quot,
 &amp;quotdate&amp;quot: &amp;quot2023-08-02&amp;quot,
 &amp;quotauthor&amp;quot: &amp;quotEmily Johnson&amp;quot
 },
 {
 &amp;quottitle&amp;quot: &amp;quotArtificial Intelligence Trends&amp;quot,
 &amp;quotdate&amp;quot: &amp;quot2023-08-01&amp;quot,
 &amp;quotauthor&amp;quot: &amp;quotWilliam Smith&amp;quot
 },
    ...
 ]مجموعه داده‌ای که در این پست استفاده خواهم کرد توسط ChatGPT تولید شده و format ای را که در بالا توضیح داده شده است، رعایت می‌کند.بیایید داده‌هایمان را با استفاده از این فایل JSON بخوانیم و یک ایندکس Elasticsearch را بر اساس این format ایجاد کنیم، سپس داده‌ها را به آن اضافه کنیم. book_mappings = {
 &amp;quotmappings&amp;quot: {
 &amp;quotproperties&amp;quot: {
 &amp;quottitle&amp;quot: {&amp;quottype&amp;quot: &amp;quottext&amp;quot},
 &amp;quotauthor&amp;quot: {&amp;quottype&amp;quot: &amp;quottext&amp;quot},
 &amp;quotdate&amp;quot: {&amp;quottype&amp;quot: &amp;quotdate&amp;quot}
        }
    }
}

client.indices.create(index = &amp;quotbook_index&amp;quot, body=book_mappings)

import json
with open(&#039;data.json&#039;, &#039;r&#039;) as f:
    data = json.load(f)

for each in data:
    client.index(index=&#039;book_index&#039;, document=each)
client.indices.refresh()در مجموعه داده‌ای که ایجاد کرده‌ایم، سه فیلد وجود دارد، دو تای آنها به صورت متن و یکی به صورت تاریخ format شده‌اند. سپس، از این mapping برای ایجاد یک index استفاده می‌کنیم، که آن را “book_index” می‌نامیم. از آنجا که داده‌ها و index ما در یک format هستند، در این مرحله نیازی به پردازش اضافی نیست.بیایید با یک query شروع کنیم که تمام document های داخل index را بازیابی می‌کند:برای اعمال filtering به document های داخل index، باید پارامتر “query” را تغییر دهیم. برای جستجوی کلمات درون متن، از “match” استفاده خواهیم کرد:ما document هایی را در index لیست کردیم که کلمه “Data” در فیلد “title” آنها وجود دارد.اگر می‌خواهید filtering را بر روی چندین فیلد اعمال کنید، می‌توانید با استفاده از “bool” این کار را انجام دهید.حالا، بیایید همان index را با document vector ها ایجاد کنیم. برای این پست، من از کتابخانه Sentence-Transformers و مدل ‘all-mpnet-base-v2’ استفاده خواهم کرد. محدودیتی در استفاده از مدل وجود ندارد بنابراین می‌توانید هر مدلی که می‌خواهید را انتخاب کنید.vector_mapping = {
 &amp;quotmappings&amp;quot: {
 &amp;quotproperties&amp;quot: {
 &amp;quottitle&amp;quot: {&amp;quottype&amp;quot: &amp;quottext&amp;quot},
 &amp;quotauthor&amp;quot: {&amp;quottype&amp;quot: &amp;quottext&amp;quot},
 &amp;quotdate&amp;quot: {&amp;quottype&amp;quot: &amp;quotdate&amp;quot},
 &amp;quotvector&amp;quot: {
 &amp;quottype&amp;quot: &amp;quotdense_vector&amp;quot,
 &amp;quotdims&amp;quot: 768,
 &amp;quotindex&amp;quot: True,
 &amp;quotsimilarity&amp;quot: &amp;quotdot_product&amp;quot
            }
        }
    }
}

client.indices.create(index=&#039;vector_index&#039;, body= vector_mapping)در حالی که این بار “vector_index” را ایجاد می‌کنیم، یک فیلد اضافی از نوع “dense_vector” اضافه می‌کنیم و پارامترهای vector search را مشخص می‌کنیم:پارامتر “dims” بُعد بردار تولید شده به عنوان خروجی توسط مدل استفاده شده را نشان می‌دهد. پارامتر “Similarity” روش اندازه‌گیری vector similarity را تعیین می‌کند.from sentence_transformers import SentenceTransformer
model = SentenceTransformer(&#039;all-mpnet-base-v2&#039;)

for each in data:
    each[&#039;vector&#039;] = model.encode(each[&#039;title&#039;])
    client.index(index=&#039;vector_index&#039;, document=each)
client.indices.refresh()بیایید مدل را با استفاده از کتابخانه Sentence-Transformers بارگذاری کنیم و vector ها را از بخش‌های &quot;title&quot; مجموعه داده استخراج کنیم. سپس این vector ها را به هر ورودی داده اضافه کرده و ادامه می‌دهیم تا این داده‌ها را به ایندکس &quot;vector_index&quot; اضافه کنیم.برای انجام vector search در Elasticsearch، ابتدا به یک متن query و سپس نمایش برداری متناظر آن نیاز داریم.توجه مهم: مدلی که برای به دست آوردن بردار query استفاده می‌شود باید همان مدل باشد که هنگام index کردن document ها استفاده شده است.برای انجام vector search، تابع Elasticsearch.search() از پارامتر &quot;knn&quot; استفاده می‌کند. یک نمونه از query برای &quot;knn&quot; در تصویر زیر نشان داده شده است. مقدار &quot;k&quot; نشان می‌دهد که چه تعداد نتیجه می‌خواهید بازیابی کنید، در حالی که &quot;num_candidates&quot; مشخص می‌کند که چند document برای محاسبات در pool گرفته می‌شوند. &quot;query_vector&quot; نمایش برداری از متن query است (در مورد ما &quot;HTML and CSS programming&quot;). نتایج برای query نمونه در تصویر بالا قابل مشاهده است. با اینکه هیچ یک از نتایج بازگشتی دقیقاً همان کلمات را در بر ندارند، اما با موفقیت نتایج مشابه از نظر معنایی را جمع‌آوری کرده‌اند.پس، اگر ما هم می‌خواهیم از این نتایج جستجوی معنایی به همراه filtering استفاده کنیم، چگونه باید کوئری “knn” را آماده کنیم؟ هر filter ای که اعمال می‌کنیم به عنوان یک “filter” درون پارامتر “knn” ارائه می‌شود. شما می‌توانید در اینجا هر تعداد filter ای که می‌خواهید اضافه کنید و نتایج را بر اساس این filter ها ترکیب کنید.توجه مهم: Elasticsearch پس از فرآیند vector search، عمل filtering را انجام می‌دهد، بنابراین ممکن است مواردی وجود داشته باشد که نتواند دقیقاً تعداد “k” نتایج را برگرداند. در تصویر بالا، با اینکه مقدار “k” به 5 تنظیم شده است، query تعداد 3 سند یا document را به عنوان نتیجه برگردانده است. این بخاطر آن است که در مجموعه داده‌ای که به عنوان مثال آماده شده است، فقط 3 سند معیارهای مشخص شده را برآورده می‌کنند.باتشکر ازhttps://medium.com/@fatihsati/how-to-combine-vector-search-with-filtering-in-elasticsearch-b938ec78d179</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Sun, 12 May 2024 00:33:55 +0330</pubDate>
            </item>
                    <item>
                <title>10 پروژه برتر NLP که باید در سال 2024 بدانید</title>
                <link>https://virgool.io/@vakily/10-%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D8%A8%D8%B1%D8%AA%D8%B1-nlp-%DA%A9%D9%87-%D8%A8%D8%A7%DB%8C%D8%AF-%D8%AF%D8%B1-%D8%B3%D8%A7%D9%84-2024-%D8%A8%D8%AF%D8%A7%D9%86%DB%8C%D8%AF-fzkqwgrkodhm</link>
                <description>پردازش زبان طبیعی (NLP) بخشی از هوش مصنوعی پیشرفته است که به کامپیوترها یاد می دهد زبان انسان را درک کنند. در این مقاله، ما برترین ایده های پروژه های NLP را برای تمام سطوح به اشتراک خواهیم گذاشت که افراد مبتدی و متخصصان با تجربه داده می توانند از آنها برای درک بهتر و کار با زبان استفاده کنند. این پروژه ها طیف گسترده ای از تشخیص موجودیت های نامگذاری شده (NER) تا ایجاد نقل قول‌های الهام‌بخش (inspiring quotes) را پوشش می دهند. با کار بر روی این پروژه ها، می توانید از NLP برای تأثیرگذاری بر تجزیه و تحلیل و پردازش داده استفاده کنید.10 ایده برتر پروژه NLPاین پروژه‌ها طیف گسترده‌ای از برنامه‌های NLP را پوشش می‌دهند و می‌توانند به شما کمک کنند تا مهارت‌های خود را در درک و پردازش زبان انسانی با استفاده از تکنیک‌های یادگیری ماشین افزایش دهید.شماره یک: Named Entity Recognition (NER)تشخیص موجودیت نام‌گذاری‌شده (NER) یک تسک در سطح elementary در پردازش زبان طبیعی است که در آن هدف، شناسایی و طبقه‌بندی آیتم‌هایی مانند نام افراد، سازمان‌ها، مکان‌ها و تاریخ‌ها از یک متن مشخص است.هدف یا Objectiveهدف این تحقیق ایجاد یک سیستم NER است که می تواند به طور خودکار موارد نامگذاری شده را در متن شناسایی و دسته بندی کند و امکان استخراج اطلاعات مهم از داده های بدون ساختار (unstructured data) را فراهم کند.مروری بر مجموعه داده ها و پیش پردازش داده هابرای این پروژه به مجموعه داده برچسب‌گذاری شده‌ای نیاز است که حاوی متن و موجودیت‌های حاشیه‌نویسی شده (annotated entities) باشد. مجموعه داده‌های رایج برای NER شامل CoNLL-2003، OntoNotes و Open Multilingual Wordnet هستند.پیش پردازش داده شامل Tokenizingتقسیم بندی یا Tokenizing متن: متن به واحدهای کوچک‌تر و معنی‌دار مانند کلمات یا عبارات تقسیم می‌شود.تبدیل به نمایش عددی (numerical representation): token ها به اعداد تبدیل می‌شوند تا رایانه بتواند آن‌ها را پردازش کند.مدیریت نویز یا ناسازگاری در حاشیه‌نویسی‌هادستاوردهای کلیدی و یافته‌ها:سیستم تشخیص موجودیت نام‌گذاری‌شده (NER) قادر خواهد بود تا موجودیت‌های نام‌گذاری‌شده را در متن ارائه‌شده شناسایی و طبقه‌بندی کند. این سیستم می‌تواند در استخراج اطلاعات، تحلیل احساسات و سایر کاربردهای پردازش زبان طبیعی (NLP) برای کسب بینش از داده‌های بدون ساختار استفاده شود.شماره دو: Machine Translationترجمه ماشینی یکی از تسک های ضروری NLP است که به طور خودکار متن را از یک زبان به زبان دیگر ترجمه می کند و ارتباط بین زبانی (cross-lingual communication) و دسترسی (accessibility) را تسهیل می کند.هدف یا Objectiveترجمه ماشینی با هدف ترجمه یکپارچه متن از یک زبان به زبان دیگر، امکان ارتباط بین زبانی (cross-lingual communication) و دسترسی آسان را فراهم می کند.مروری بر مجموعه داده ها و پیش پردازش داده هااین پروژه به پیکره های موازی (parallel corpora) نیاز دارد که مجموعه‌ای از متون به زبان‌های مختلف با ترجمه‌های مربوطه هستند. مجموعه داده های محبوب شامل WMT، IWSLT و Multi30k است. پیش پردازش داده‌ها شامل توکن‌سازی، مدیریت تفاوت‌های خاص زبان (language-specific nuances)، و تولید جفت های ورودی-هدف (input-target pairs) برای آموزش است.دستاوردهای کلیدی و یافته‌ها:سیستم ترجمه ماشینی می‌تواند ترجمه‌های معتبری را بین چند زبان ایجاد کند، که امکان تماس بین فرهنگی (cross-cultural contact) را فراهم می‌کند و اطلاعات را برای مخاطبان در سراسر جهان در دسترس‌تر می‌سازد.شماره سه: Text Summarizationخلاصه کردن متن یک تسک مهم پردازش زبان طبیعی است که شامل ایجاد خلاصه‌های مختصر و منسجم از بخش های طولانی‌تر متن است. این امکان بازیابی و درک سریع اطلاعات را فراهم می کند و آن را برای حجم زیادی از داده های متنی ارزشمند می کند.هدف یا Objectiveهدف این پروژه توسعه یک مدل خلاصه سازی متن است که قادر به ایجاد خلاصه های آموزنده و مختصر از document های متنی طولانی است.مروری بر مجموعه داده ها و پیش پردازش داده هااین پروژه به مجموعه داده‌ای نیاز دارد که شامل مقالات یا اسنادی با خلاصه‌های تولید شده توسط انسان است. پیش‌پردازش داده‌ها شامل توکن‌سازی متن، مدیریت punctuation ها، و ایجاد جفت‌های ورودی-هدف (input-target pairs) برای آموزش است.دستاوردهای کلیدی و یافته‌ها:مدل خلاصه‌سازی متن با موفقیت خلاصه‌های مختصر و متناسب تولید خواهد کرد، که باعث بهبود کارایی بازیابی اطلاعات و بهبود تجربه کاربر هنگام مواجهه با محتوای متنی گسترده می‌شود.شماره چهار: Text Correction and Spell Checkingپروژه‌های اصلاح متن و بررسی املایی به دنبال توسعه الگوریتم‌هایی هستند که به صورت خودکار اشتباهات املایی و دستور زبانی در داده‌های متنی را اصلاح می‌کنند. این کار دقت و خوانایی محتوای نوشته شده را بهبود می‌بخشد. هدف یا Objectiveاین پروژه به دنبال ساخت یک مدل بررسی املایی و اصلاح متن است تا کیفیت محتوای نوشته شده را ارتقا دهد و ارتباط موثر را تضمین کند.مروری بر مجموعه داده ها و پیش پردازش داده هااین پروژه به مجموعه داده‌ای نیاز دارد که شامل متن با کلمات اشتباه املایی و نسخه‌های اصلاح شده متناظر است. پیش‌پردازش داده‌ها شامل رسیدگی به حروف بزرگ، نشانه‌گذاری يا punctuation ها و کاراکترهای خاص است.دستاوردهای کلیدی و یافته‌ها:مدل اصلاح متن با دقت اشتباهات املایی و دستور زبانی را شناسایی و اصلاح خواهد کرد، کیفیت محتوای نوشته شده را به طور قابل توجهی بهبود می‌بخشد.شماره پنجم: Sentiment Analysisتحلیل احساسات یکی از مهمترین تسک های NLP است که احساس بیان شده در یک متن را تعیین می‌کند، مانند اینکه آیا مثبت، منفی یا خنثی است. این مدل برای تحلیل بازخورد مشتری، نگرش‌های بازار و نظارت بر رسانه‌های اجتماعی بسیار حیاتی است.هدف یا Objectiveاین پروژه به دنبال توسعه یک مدل تحلیل احساسات است که قادر به طبقه‌بندی متن به دسته‌بندی‌های احساسی و کسب بینش از داده‌های متنی است.مروری بر مجموعه داده ها و پیش پردازش داده هابرای آموزش مدل تحلیل احساسات، نیاز به یک مجموعه داده برچسب‌دار از داده‌های متنی با برچسب‌های احساسی متناظر است. پیش‌پردازش داده‌ها شامل پاکسازی متن، توکن‌سازی و رمزگذاری (encoding) است.دستاوردهای کلیدی و یافته‌ها:مدل تحلیل احساسات به شرکت‌ها امکان می‌دهد تا نظرات و احساسات مشتریان را به طور موثر سنجیده و ارزیابی کنند، که این امر به تصمیم‌گیری مبتنی بر داده‌ها کمک می‌کند و رضایت مشتریان را افزایش می‌دهد.شماره ششم: Text Annotation and Data Labelingتفسیر متن و برچسب‌زنی داده‌ها تسک های اساسی در پروژه‌های برتر NLP هستند، زیرا شامل برچسب‌زنی داده‌های متنی برای آموزش مدل‌های یادگیری ماشینی با نظارت است. این یک گام حیاتی است تا دقت و کیفیت مدل‌های NLP را تضمین کند.هدف یا Objectiveاین پروژه به دنبال توسعه یک ابزار یا برنامه تفسیری است که به طور موثر به مفسران اجازه می‌دهد تا داده‌های متنی را برای وظایف NLP برچسب‌زنی و تفسیر کنند.مروری بر مجموعه داده ها و پیش پردازش داده هااین پروژه به مجموعه داده‌ای از داده‌های متنی که نیاز به تفسیر دارد، نیازمند است. پیش‌پردازش داده‌ها شامل ایجاد یک رابط کاربری دوستانه برای تفسیرگر و تضمین همسانی و کنترل کیفیت است.دستاوردهای کلیدی و یافته‌ها:ابزار تفسیر فرآیند برچسب‌زنی داده‌ها را ساده‌تر خواهد کرد، توسعه سریع‌تر مدل NLP را تسهیل می‌کند و دقت داده‌های برچسب‌زده شده را برای بهبود عملکرد مدل تضمین می‌کند.شماره هفت: ایجاد Chatbotsایجاد چت‌بات‌ها یک پروژه چالش‌برانگیز NLP است که شامل ساخت عوامل مکالمه‌ای بسیار پیچیده قادر به مدیریت مکالمات کاربری تعاملی و جذاب است. چت‌بات‌ها به طور انحصاری در خدمات مشتری، دستیاران مجازی و برنامه‌های مختلف دیگر استفاده می‌شوند.هدف یا Objectiveهدف از ایجاد چت‌بات‌ها ساخت عامل های هوش مصنوعی مکالمه‌ای موثر است که قادر به داشتن مکالمات تعاملی و مناسب با کاربران در چندین حوزه است.مروری بر مجموعه داده ها و پیش پردازش داده هاآموزش چت‌بات نیازمند یک مجموعه داده مکالمه‌ای است که شامل تعاملات user-bot و پاسخ‌های متناظر است. پیش‌پردازش داده‌ها شامل توکن‌سازی، رسیدگی به تاریخچه مکالمه برای پاسخ‌های آگاه از متن و پیش پردازش جفت‌های ورودی-هدف (input-target pairs) است.دستاوردهای کلیدی و یافته‌ها:چت‌بات هوش مصنوعی قصد دارد تجربه کاربر و خدمات پشتیبانی مشتری را با ساده‌سازی جریان‌های کاری و ارائه تعاملات شخصی‌سازی شده بهبود بخشد، افزایش تعامل و رضایت کاربر را افزایش می‌دهد.شماره هشت: Text-to-Speech (TTS) and Speech-to-Text (STT)متن به گفتار (TTS) و گفتار به متن (STT) اجزای مهم پردازش زبان طبیعی هستند که ارتباط بی دردسر بین انسان ها و ماشین ها را تسهیل می کنند. TTS متن نوشته شده را به صدای انسان تبدیل می کند. در مقابل، STT کلمات گفته شده را به متن نوشته شده تبدیل می کند.هدف یا Objectiveهدف از متن به گفتار (TTS) و گفتار به متن (STT) این است که یک سیستم NLP دو طرفه را طراحی کنند که بتواند متن نوشته شده را به صدای شبیه به انسان ترجمه کند و کلمات گفته شده را به متن نوشته شده تبدیل کند.مروری بر مجموعه داده ها و پیش پردازش داده هابرای TTS، مجموعه داده ای شامل متن و داده های صوتی جفت شده برای آموزش مدل لازم است. پیش پردازش داده ها شامل تبدیل متن به صدا ها و آماده سازی ویژگی های صوتی است. برای STT، مجموعه داده صوتی با ترجمه ها لازم است. پیش پردازش داده ها شامل استخراج ویژگی های مربوطه از داده های صوتی است.دستاوردهای کلیدی و یافته‌ها:سیستم NLP دو طرفه (bidirectional NLP system) امکان تعامل بین انسان ها و ماشین ها را فراهم می کند. TTS صدایی شبیه به انسان خواهد ساخت، که رابط کاربری را جذاب تر و قابل دسترس تر می کند. STT اجازه خواهد داد تا ترجمه خودکار گفتار انجام شود، که امکان پردازش و تجزیه و تحلیل کارآمد اطلاعات گفته شده را فراهم می کند. دقت و عملکرد سیستم تجربه کاربر را بهبود بخشیده و استفاده از برنامه های مبتنی بر صدا را گسترش خواهد داد.شماره نه: Emotion Detectionتشخیص احساسات یک تسک ارزشمند NLP است که شامل شناخت و درک احساسات منتقل شده از طریق متن است. کاربردهای آن شامل تحلیل احساسات، خدمات مشتری و تعامل باز انسان-کامپیوتر (open human-computer interaction) است.هدف یا Objectiveاین پروژه به دنبال ایجاد یک سیستم NLP است که قادر به درک احساساتی مانند خوشحالی، غم و خشم، از جمله دیگران از کلمات گفته شده یا نوشته شده است.مروری بر مجموعه داده ها و پیش پردازش داده هابرای آموزش مدل تشخیص احساسات، مجموعه داده متن یا گفتار مشخص شده با احساسات برچسب زده شده لازم است. پیش پردازش داده ها شامل استخراج ویژگی ها و آماده سازی داده ها برای طبقه بندی احساسات است.مدل تشخیص احساسات به درک احساسات کاربر کمک خواهد کرد، امکان پاسخ های متناسب با حالات عاطفی کاربران را فراهم می کند و بهبود برنامه های مختلف NLP را امکان پذیر می سازد.شماره ده: Inspiring Quote Generatorتولید کننده نقل قول الهام بخش یا همان Inspiring Quote Generator یک پروژه خلاقانه NLP است که مدلی را می سازد که بر اساس کلمات کلیدی یا موضوعات ورودی، نقل قول های انگیزشی و بلند کننده تولید می کند.هدف یا Objectiveاین پروژه به دنبال توسعه یک مدل NLP برای تولید نقل قول های الهام بخش برای بالابردن انگیزه کاربران است.مروری بر مجموعه داده ها و پیش پردازش داده هاآموزش مدل تولید کننده نقل قول نیازمند یک مجموعه داده شامل نقل قول ها با کلمات کلیدی یا موضوعات مرتبط است. پیش پردازش داده ها شامل tokenization و آماده سازی داده ها برای آموزش مدل تولید زبان است.دستاوردهای کلیدی و یافته‌ها:این مدل به کاربران نقل قول های انگیزشی شخصی می دهد، مثبت بودن را ترویج می کند و می تواند در برنامه ها و پلتفرم های مختلف گنجانده شود.باتشکر ازhttps://www.analyticsvidhya.com/blog/2023/08/nlp-projects/</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Mon, 06 May 2024 16:33:18 +0330</pubDate>
            </item>
                    <item>
                <title>بررسی LDAP با Django</title>
                <link>https://virgool.io/@vakily/%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C-ldap-%D8%A8%D8%A7-django-oecjr1gh1crl</link>
                <description>در این مقاله، نحوه اتصال و authenticate یک برنامه Django با یک سرور LDAP یا Lightweight Directory Access Protocol را بررسی خواهیم کرد. فریم ورک Django با یک بک‌اند authentication پیش‌فرض برای authenticate کردن اطلاعات کاربری با database ارائه شده همراه است. بنابراین به جای آن، Django App خود را به سرور LDAP وصل می‌کنیم تا کاربر با Active Directory خودش authenticate شود.پیاده سازی LDAPما از django-auth-ldap استفاده خواهیم کرد، یک کتابخانه open-source عالی برای Django است. این کتابخانه با یک  LDAP Authentication Backend  داخلی عرضه می‌شود که authenticate کردن کاربران با سرور LDAP را بسیار آسان می‌کند.سپس، یک login/logout REST API  در django-rest-framework با استفاده از SessionAuthentication  فریمورک rest برای authenticate کاربران با سرور LDAP ایجاد خواهیم کرد.در فایل settings.py تنظیمات را اضافه نمایید.مسیر uri سرور LDAP را اضافه کنید.AUTH_LDAP_SERVER_URI = &amp;quotldap://test.example.com:389&amp;quotاکنون admin سرور LDAP را اضافه کنید تا بتوانید عملیات جستجوی مختلف کاربر را انجام دهید.AUTH_LDAP_BIND_DN = &amp;quotcn=admin,dc=example,dc=com&amp;quot
AUTH_LDAP_BIND_PASSWORD = &amp;quottest@1234&amp;quotاکنون مسیر جستجوی کاربران در دایرکتوری LDAP را اضافه کنید، یعنی در کدام پوشه باید LDAP برای کاربران جستجو کند. آرگومان ldap.SCOPE_SUBTREE به LDAP می گوید که در همه زیرپوشه های directory کاربران جستجو کند.import ldap
from django_auth_ldap.config import LDAPSearch
AUTH_LDAP_USER_SEARCH = LDAPSearch(&amp;quotOU=users,DC=example,DC=com&amp;quot,
                                   ldap.SCOPE_SUBTREE,
                                   &amp;quot(uid=%  (user)s)&amp;quot)اکنون mapping را اضافه کنید تا ویژگی‌های مدل User جنگو را از LDAP directory پر کنید. پس از authentication موفقیت‌آمیز از سرور LDAP، مدل User جنگو با ویژگی‌های زیر پر می‌شود.AUTH_LDAP_USER_ATTR_MAP = {
&amp;quotfirst_name&amp;quot: &amp;quotgivenName&amp;quot,
    &amp;quotlast_name&amp;quot: &amp;quotsn&amp;quot,
    &amp;quotemail&amp;quot:&amp;quotmail&amp;quot
}   حالا LDAP authentication backend را قبل از ModelBackend اضافه کنید تا ابتدا از طریق LDAP عمل authentication را به جای django Model Backend پیش فرض انجام دهد.AUTHENTICATION_BACKENDS = (
    &amp;quotdjango_auth_ldap.backend.LDAPBackend&amp;quot,
    &amp;quotdjango.contrib.auth.backends.ModelBackend&amp;quot,
)در نهایت، SessionAuthentication را به DEFAULT_AUTHENTICATION_CLASSES اضافه کنید.REST_FRAMEWORK = {
    &#039;DEFAULT_AUTHENTICATION_CLASSES&#039;: (
        &#039;rest_framework.authentication.SessionAuthentication&#039;,
    ),
}درباره Login APIدر این قسمت، ابتدا authentication_classes را روی empty تنظیم می کنیم زیرا برای login api به pre-authentication نیاز نداریم. ما از توابع پیش فرض django یعنی authenticate() و login() استفاده خواهیم کرد.هنگامی که تابع authenticate() اجرا می شود، django به طور خودکار ابتدا LDAPBackend را برای authenticate کاربران انتخاب می کند و در صورت عدم موفقیت، به سراغ backend بعدی یعنی ModelBackend می رود.from django.contrib.auth import authenticate, login, logout
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
class LDAPLogin(APIView):
    &amp;quot&amp;quot&amp;quot
    Class to authenticate a user via LDAP and
    then creating a login session
    &amp;quot&amp;quot&amp;quot
    authentication_classes = ()
    def post(self, request):
        &amp;quot&amp;quot&amp;quot
        Api to login a user
        :param request:
        :return:
        &amp;quot&amp;quot&amp;quot
        user_obj = authenticate(username=request.data[&#039;username&#039;],
                                password=request.data[&#039;password&#039;])
        login(request, user_obj)
        data={&#039;detail&#039;: &#039;User logged in successfully&#039;}
        return Response(data, status=200)نحوه Logout APIدر اینجا، ما permission_classes را روی IsAuthenticated تنظیم می‌کنیم تا فقط فردی که وارد سیستم شده است بتواند درخواست logout را ارسال کند.class LDAPLogout(APIView):
    &amp;quot&amp;quot&amp;quot
    Class for logging out a user by clearing his/her session
    &amp;quot&amp;quot&amp;quot
    permission_classes = (IsAuthenticated,)

    def post(self, request):
        &amp;quot&amp;quot&amp;quot
        Api to logout a user
        :param request:
        :return:
        &amp;quot&amp;quot&amp;quot
        logout(request)
        data={&#039;detail&#039;: &#039;User logged out successfully&#039;}
        return Response(data, status=200)نتیجه گیریتکنیک LDAP authentication مشکل بزرگی را در ایجاد حساب های جدید هنگام ورود به یک وب سایت جدید و به خاطر سپردن چندین مجموعه از login credential ها را حل می کند.امیدوارم این مقاله نکاتی را در مورد authentication از طریق LDAP و مزایای مربوط به آن ارائه کرده باشد.باتشکر ازhttps://medium.com/@itsayushbansal/ldap-authentication-with-django-a2b4f00c9a04</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Fri, 03 May 2024 22:55:41 +0330</pubDate>
            </item>
                    <item>
                <title>بررسی Kafka با KRaft mode - قسمت اول</title>
                <link>https://virgool.io/@vakily/%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C-kafka-%D8%A8%D8%A7-kraft-mode-%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84-zoziit5bvqjv</link>
                <description>آپاچی کافکا یک پلتفرم event streaming به صورت توزیع شده است که توسط هزاران شرکت برای pipelines های داده با عملکرد بالا، تجزیه و تحلیل به صورت streaming، یکپارچه سازی داده ها و برنامه های کاربردی حیاتی یا mission-critical applications استفاده می شود.مفهوم KRaft یا Kafka Raft، پروتکل اجماعی یا consensus protocol است که در Kafka برای حذف وابستگی به ZooKeeper برای مدیریت metadata معرفی شده است. این تغییر باعث ساده‌سازی معماری Kafka شده و مسئولیت مدیریت metadata را به خود Kafka می‌سپارد.در این مقاله قصد دارم به نحوه استقرار و اجرا آن با استفاده از Docker بپردازم.جهت بررسی آن به دنبال فایلی برای Docker Compose می‌گشتم که به من امکان اجرای Kafka در حالت Kraft را بدهد. اما متاسفانه، تمام دستورالعمل‌هایی که پیدا کردم شامل انجام چندین مرحله بودند، از جمله ایجاد یک cluster ID، فرمت کردن log ها، و در نهایت راه‌اندازی container ها.آیا امکان اجرای Kafka در حالت Kraft با تنها یکبار اجرای Docker Compose وجود دارد؟زمانی که Kafka را بدون Zookeeper اجرا می‌کنیم، باید موارد زیر را مشخص کنیم:ویژگیprocess.roles - می‌تواند broker يا controller یا هر دو باشد.ویژگیcontroller.quorum.voters - آدرس‌هایی به فرمت nodeid@servername:portاست  که جهت اجماع (consensus) رأی می‌دهند. این تنظیم جایگزین تنظیم قدیمیzookeeper.connect می‌شود.ویژگیnode.id - همان node ID مرتبط با role هایی است که process ایفا می‌کند.قبل از شروع، clusterIdباید تولید شود و storage باید با یک ابزار خاص فرمت شود.برای تولید uuid می توانیم از اسکریپت زیر استفاده کنیم:kafka-storage.sh random-uuidو command جهت format کردن به صورت زیر است:kafka-storage.sh formatشناسه خوشه یا cluster ID باید فقط یک بار تولید شود و بین همه container ها به اشتراک گذاشته شود. علاوه بر این، از همان cluster ID باید برای format کردن log ها استفاده شود.لذا  Docker Compose ما شامل چهار container خواهد بود که سه container اول به عنوان broker های Kafka عمل می کنند. هر یک از این broker ها دو نقش broker و controller را به طور همزمان بر عهده خواهند گرفت. container چهارم، cluster ID را در یک فایل تولید می کند و سپس خارج می شود.این container برای broker به شکل زیر است:kafka1: image: confluentinc/cp-kafka:7.3.3 hostname: kafka1 container_name: kafka1 ports: - &quot;39092:39092&quot; environment: KAFKA_LISTENERS: BROKER://kafka1:19092,EXTERNAL://kafka1:39092,CONTROLLER://kafka1:9093 KAFKA_ADVERTISED_LISTENERS: BROKER://kafka1:19092,EXTERNAL://kafka1:39092 KAFKA_INTER_BROKER_LISTENER_NAME: BROKER KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,BROKER:PLAINTEXT,EXTERNAL:PLAINTEXT KAFKA_PROCESS_ROLES: &#x27;controller,broker&#x27; KAFKA_NODE_ID: 1 KAFKA_CONTROLLER_QUORUM_VOTERS: &#x27;1@kafka1:9093,2@kafka2:9093,3@kafka3:9093&#x27; KAFKA_LOG_DIRS: &#x27;/tmp/kraft-combined-logs&#x27; volumes: - ./scripts/update_run.sh:/tmp/update_run.sh - ./clusterID:/tmp/clusterID command: &quot;bash -c &#x27;/tmp/update_run.sh &amp;&amp; /etc/confluent/docker/run&#x27;&quot;این container دارای دو volume است:اول: clusterID - این همان دایرکتوری است که clusterID در آن تولید می شود.دوم: update_run.sh - اسکریپتی است که منتظر می ماند تا clusterID در دسترس باشد و سپس فرآیند format کردن را اجرا می کند.در قسمت زير conainer برای تولید id مشخص شده است:kafka-gen: image: confluentinc/cp-kafka:7.3.3 hostname: kafka-gen container_name: kafka-gen volumes: - ./scripts/create_cluster_id.sh:/tmp/create_cluster_id.sh - ./clusterID:/tmp/clusterID command: &quot;bash -c &#x27;/tmp/create_cluster_id.sh&#x27;&quot;این conainer به سادگی بررسی می کند که آیا cluster ID از قبل موجود است یا خیر. اگر موجود نباشد، یک مورد جدید ایجاد می کند.فایل compose نهایی را می توانید از اینجا ببینید.دور زدن تحریم های Dockerیکی از ساده ترین راه های آن استفاده از docker.arvancloud.ir است. می توانید آن را پشت هر آدرس image قرار دهید تا با سرعت بالا image ها را دریافت نمایید.یعنی:image: docker.arvancloud.ir/confluentinc/cp-kafka:7.3.3اتصال به kafka از طریق Offset Explorerبرای اتصال تنها کافی است در تنظيمات kafka برای EXTERNAL در KAFKA_ADVERTISED_LISTENERS مقدار localhost را قرار دهید.به عنوان مثال برای container کافکا اولی:KAFKA_ADVERTISED_LISTENERS: BROKER://kafka1:19092,EXTERNAL://localhost:39092باتشکر ازhttps://kafka.apache.org/https://docs.confluent.io/platform/current/kafka-metadata/kraft.htmlhttps://github.com/katyagorshkova/kafka-krafthttps://medium.com/@katyagorshkova/docker-compose-for-running-kafka-in-kraft-mode-20c535c48b1ahttps://www.arvancloud.ir/fa/dev/dockerhttps://www.kafkatool.com/index.html</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Mon, 22 Apr 2024 14:26:28 +0330</pubDate>
            </item>
                    <item>
                <title>شناسایی 5 گروه برتر تبلیغاتی یک مجموعه داده</title>
                <link>https://virgool.io/@vakily/%D8%B4%D9%86%D8%A7%D8%B3%D8%A7%DB%8C%DB%8C-5-%DA%AF%D8%B1%D9%88%D9%87-%D8%A8%D8%B1%D8%AA%D8%B1-%D8%AA%D8%A8%D9%84%DB%8C%D8%BA%D8%A7%D8%AA%DB%8C-%DB%8C%DA%A9-%D9%85%D8%AC%D9%85%D9%88%D8%B9%D9%87-%D8%AF%D8%A7%D8%AF%D9%87-vkjd2dvirpwt</link>
                <description>در این نوشته قصد داریم با بررسی یک دیتاست، 5 گروه برتر تبلیغاتی آن را بدست بیاوریم.برای این منظور در محیط توسعه، ابتدا دیتاست را می خوانیم.import warnings
warnings.simplefilter(&#039;ignore&#039;)

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from pandas.plotting import parallel_coordinates

%matplotlib inline

data = pd.read_csv(&#039;./data/ad_table.csv&#039;, parse_dates=[&#039;date&#039;])
data.tail(20)حال می بایست درآمد را از هزینه کم کنیم تا سود بدست آید.data[&#039;profit&#039;] = data[&#039;total_revenue&#039;] - data[&#039;avg_cost_per_click&#039;] * data[&#039;clicked&#039;]
data.head()برای شناسایی 5 گروه برتر تبلیغاتی، معیارهای مختلفی مانند میانگین نرخ کلیک یا میانگین نرخ تبدیل وجود دارد. در اینجا، از آنجایی که اطلاعات درآمد و هزینه داده شده است، ما به سادگی از سود خالص به ازای هر تبلیغ داده شده برای یافتن 5 گروه برتر تبلیغاتی استفاده می کنیم.def unit_profit(df):
    &amp;quot&amp;quot&amp;quot function to calculate the unit profit &amp;quot&amp;quot&amp;quot
    profit = df[&#039;profit&#039;].sum()
    shown = df[&#039;shown&#039;].sum()
    val = profit / shown
    return val
grouped = data.groupby(&#039;ad&#039;).apply(unit_profit).reset_index()
grouped = grouped.rename(columns={0: &#039;unit_profit&#039;})
grouped = grouped.sort_values(by=&#039;unit_profit&#039;, ascending=False)
grouped.head(10)بر اساس محاسبات بالا، می‌توانیم آن ها را مشاهده کنیم: ad_group_16، ad_group_2، ad_group_14، ad_group_31، ad_group_27.همچنین می توانیم از طریق نمودار زیر وضعیت نقاط داده را با توجه به ابعاد مختلف مشاهده نماییم.classes=[&#039;ad_group_16&#039;, &#039;ad_group_2&#039;, &#039;ad_group_14&#039;, &#039;ad_group_31&#039;, &#039;ad_group_27&#039;]
features=[&#039;shown&#039;, &#039;clicked&#039;, &#039;converted&#039;, &#039;avg_cost_per_click&#039;,  &#039;ad&#039;]

plt.figure(figsize=(15,8))
visualizer = pd.plotting.radviz(dd[features], &#039;ad&#039;, colormap=plt.get_cmap(&amp;quotSet2&amp;quot))
plt.legend(bbox_to_anchor=(1.0, 1.0))</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Sun, 27 Mar 2022 19:25:36 +0430</pubDate>
            </item>
                    <item>
                <title>تجزیه و تحلیل داده های کیفی</title>
                <link>https://virgool.io/@vakily/%D8%AA%D8%AC%D8%B2%DB%8C%D9%87-%D9%88-%D8%AA%D8%AD%D9%84%DB%8C%D9%84-%D8%AF%D8%A7%D8%AF%D9%87-%D9%87%D8%A7%DB%8C-%DA%A9%DB%8C%D9%81%DB%8C-vripb0wgperj</link>
                <description>بیایید با آنچه که نمودار های affinity به ما کمک می کنند شروع کنیم:1. آنها به درک انواع داده ها (نظر کاربران/بازخورد ها، حقایق، مسائل و ... ) کمک می کنند.2. اطلاعات را به گونه ای گروه بندی می کنند که بتوانید تصمیمات تجاری را بر اساس آنها اتخاذ کنید.طراحان تجربه کاربری برای درک چندین چیز مانند نقاط درد کاربر (user’s pain points)، نیازها و ترجیحات آنها استفاده می کنند و به آنها کمک می کند فرصت ها را نیز شناسایی کنند. این یک تمرین است که با استفاده از sticky note ها، marker ها و تخته انجام می شود.در این مقاله بر روی نمودار Affinity از دیدگاه یک مدیر کسب و کار تمرکز می کنیم و اینکه چگونه مدیر می تواند از داده های کیفی بینش کسب کند.بیایید یک مورد فرضی کوچک اما کامل را برای درک اهمیت و کاربرد تکنیک دیاگرام Affinity در نظر بگیریم.مثال: شما مالک هتل هند بیزینس (Hind Business Hotel) هستید و از 20 سال گذشته این هتل را با موفقیت اداره می کنید. معمولاً ضریب اشغال (occupancy rate) هتل شما در حدود 90٪ باقی می ماند اما اخیراً این میزان در یک سال گذشته به 75٪ کاهش یافته است. مهمانان شما عمدتاً مهمانان تکراری هستند که در فواصل زمانی معین به هتل شما سفر می کنند و اقامت می کنند. شما می خواهید بفهمید که دلایل این افت چیست. شما به عنوان مالک هتل می خواهید مشکلات اساسی را که میهمانان در طول اقامت با آن مواجه هستند پیدا کنید.شما از کارمند خود می خواهید فهرستی از نظرات مهمانان در 60 روز گذشته را تهیه کند. او به شما کمک می کند تا همه نظرات منفی را فیلتر کنید و به اشتراک بگذارید.اکنون، بررسی ها را تحت عناوین یا گروه های مختلف دسته بندی کنید. این گروه ها اساسا مجموعه ای از دامنه وسیع تری از بررسی هستند. در حالت ایده آل نباید بیش از 8 تا 10 گروه ایجاد شود.به اسکرین شات بالا توجه کنید. همه شکایات را در این 8 دسته طبقه بندی کرده ایم. مجموع هر دسته، یعنی تعداد 1 ها در هر دسته را محاسبه کنید.در مرحله بعد، جدولی را مطابق جدول زیر ایجاد کنید که تعداد (count) و مقدار cumulative را از نظر دسته نشان می دهد.بینش ها یا Insight های بدست آمده از تجزیه و تحلیلحدود 80 درصد از مسائل را می توان تنها با تمرکز بر 4 چیز حل کرد. اتاق ها و امکانات آن (Rooms and its facilities) بیشترین سهم را در این رقم 80 درصدی دارند. حتی اگر فقط اتاق ها و امکانات آن را تعمیر کنیم، می توانیم نظرات منفی را به میزان قابل توجهی کاهش دهیم.به عنوان مالک می خواهیم بفهمیم که چه مشکلی در اتاق و امکانات آن رخ داده است و آیا مشکلی رایج در اتاق ها وجود دارد که به دلیل آن افراد زیادی درباره آنها نظر منفی می دهند؟ همچنین ممکن است بخواهیم نظرات مثبت را به طور مشابه تجزیه و تحلیل کنیم تا ببینم آیا نتایجی که می‌گیرم درست هستند یا خیر.برای دسترسی به نمونه فایل اکسل اینجا را کلیک کنید.منبع</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Sat, 26 Mar 2022 14:48:26 +0430</pubDate>
            </item>
                    <item>
                <title>SQL Window Functions: The Intuitive Guide</title>
                <link>https://virgool.io/@vakily/sql-window-functions-the-intuitive-guide-afxw8fqpju6d</link>
                <description>در این نوشته هدف اصلی، درک مفاهیم اساسی window function ها و اعمال آنها در گردش کار SQL است. window function ها چیزی بیش از FOPO (Function Over PartitionBy OrderBy) نیستند. در اینجا یک طرح کلی از آنچه در این مقاله پوشش داده خواهد شد، آمده است.The GROUP BYThe Window Function — 4 Major Components (The FOPO)The func() OVER ()The PARTITION BYThe ORDER BYThe PARTITION BY &amp; ORDER BYSummaryAppendixThe GROUP BYاگر درک خوبی از GROUP BY دارید، می توانید مفهوم window function ها به راحتی درک کنید. به طور خلاصه، GROUP BY یک جدول را به ردیف های کمتری متراکم می کند یا ردیف های منحصر به فرد را خروجی می گیرد. هنگام گروه بندی بر اساس یک ستون، کوئری SQL یک سطر را برای هر مقدار متمایز یافت شده تحت آن ستون خروجی می دهد. در گروه بندی چندین ستونه، خروجی از ترکیبات منحصر به فرد ستون های مشخص شده (با / بدون) برخی aggregate function ها تشکیل می شود. در اینجا مثالی آورده شده است.در این جدول product_orders، هر order_id به تمام آیتم های محصول (product_name) خریداری شده توسط مشتری پیوست می شود.ابتدا order_id به عنوان ستون GROUP BY تعیین می شود.دوم، مقادیر مربوط به order_id با استفاده از تابع تجمعی SUM در یک مقدار (total_amount) جمع می‌شوند.اکنون، بیایید نگاهی عمیق‌تر به مکانیزم window function ها بیندازیم.4 کامپونت اصلی window function ها - The FOPOابتدا، کامپوننت تابع یا function، رفتار داده ها را تعیین می کند. برای مثال، می‌توانیم بر اساس یک ستون (به عنوان مثال، DENSE_RANK) رتبه‌بندی کنیم یا سطل‌هایی (bin هایی) با اندازه مساوی ایجاد کنیم (مانند NTILE). window function های موجود در Postgres را اینجا بررسی کنید. aggregate function ها (به عنوان مثال، SUM، COUNT، AVG، و غیره) را می توان به عنوان window function ها نیز استفاده کرد - در اینجا فهرست شده است.دوم، کاربرد OVER این است که می تواند همه چیز را کنار هم نگه دارد. توابع بالا با استفاده از عبارت OVER برای ایجاد window function ها فراخوانی یا فعال می شوند.سوم، مشابه GROUP BY، عبارت PARTITION BY شبیه یک subgroup-by است. به جای جمع کردن (collapsing) مجموعه داده، PARTITION BY در واقع subgroups/blocks/partitions ها را بر اساس ستون یا ستون های مشخص شده ایجاد می کند.در نهایت، عبارت ORDER BY داده ها را دوباره بر اساس ستون یا ستون های مشخص شده مرتب می کند.بر اساس لول رفتار مورد نیاز برای transform دیتا، نیازی به استفاده از همه کامپوننت ها نیست، به جز OVER. (به یاد داشته باشید: عبارت OVER باعث فراخوانی window function ها می شود و همچنین aggregate function ها را قادر می سازد تا به window function ها تبدیل شوند.) در اینجا موارد استفاده وجود دارد.func() OVER ()func(&lt;column, integer value&gt;) OVER ()func() OVER (PARTITION BY &lt;column(s)&gt;)func(&lt;column, integer value&gt;) OVER (PARTITION BY &lt;column(s)&gt;)func() OVER (PARTITION BY &lt;column(s)&gt; ORDER BY &lt;column(s)&gt;)func(&lt;column, integer value&gt;) OVER (PARTITION BY &lt;column(s)&gt; ORDER BY &lt;column(s)&gt;)The func() OVER ()روش OVER () بدون تعریف PARTITION BY (و/یا) ORDER BY ، تابع را در کل مجموعه داده اعمال می کند. این رویکرد به خوبی با aggregate function ها جفت می شود. یکپارچگی جدول یا مجموعه داده حفظ می شود در حالی که یک تابع برای محاسبه یک مقدار با استفاده از تمام ردیف ها اعمال می شود.در این مثال، سه aggregate function با عبارت OVER جفت می‌شوند تا سه window function ایجاد کنند که با total_amount، total_count و total_mean نمایش داده می‌شوند. برای مثال total_amount تمام مقادیر زیر ستون amount را جمع می‌کند و مجموع جدید در هر ردیف ظاهر می‌شود. همین منطق برای total_count و total_mean صدق می کند. این setup به محاسبه درصد کل و ایجاد نسبت‌هایی در برابر مقدار کل یا آماری مانند میانگین کمک می‌کند.SELECT 
  t1.*,
  SUM(t1.amount) OVER () AS total_amount,
  COUNT(*) OVER () AS total_count,
  AVG(t1.amount) OVER () AS total_mean
FROM orders t1;در نتیجه، مقادیر window function ها در ایجاد معیارهای استاندارد برای مقایسه آسان در میان مجموعه داده مفید هستند. اولین بلوک خاکستری برجسته، مقادیر کل را در مثال ارائه شده در زیر نشان می دهد، در حالی که بلوک دوم حاوی معیارهایی است که داده ها را توصیف می کند.SELECT 
  t1.order_id,
  t1.order_date,
  -- aggregate functions + OVER clause = window functions
  SUM(t1.amount) OVER () AS total_amount,
  ROUND(AVG(t1.amount) OVER (), 2) AS avg_order_size,
  SUM(t1.num_product_items) OVER () AS total_product_items,
  COUNT(*) OVER () AS total_count,
  -- create ratios and % of total using values from window functions
  ROUND(1.0 * t1.amount / SUM(t1.amount) OVER (), 4) AS percent_amount,
  ROUND(1.0 * t1.num_product_items / SUM(t1.num_product_items) OVER (), 4) AS 
ercent_product_items
FROM orders t1;The PARTITION BYهمانطور که قبلاً اشاره کردم، PARTITION BY مشابه GROUP BY است. مانند GROUP BY، با تعریف ستون یا ستون ها PARTITION BY شروع کنید. هنگامی که زیرگروه ها تعریف شدند، عبارت OVER تابع را فراخوانی یا فعال می کند تا منطق خود را در هر زیرگروه اجرا کند. برخلاف GROUP BY، بند PARTITION BY جدول را فشرده نمی کند. در عوض، یکپارچگی جدول را حفظ می کند در حالی که خروجی را به عنوان یک ستون اضافه می کند.SELECT
  user_id,
  order_id,
  product_name,
  amount,
  NTILE(3) OVER (PARTITION BY order_id) AS ntile_by_order_id,
  FIRST_VALUE(amount) OVER (PARTITION BY order_id) AS first_amount_value_by_order_id,
  COUNT(*) OVER (PARTITION BY order_id) AS count_by_order_id,
  SUM(amount) OVER (PARTITION BY order_id) AS sum_by_order_id,
  ROUND(AVG(amount) OVER (PARTITION BY order_id), 4) AS avg_amount_by_order_id
FROM product_orders;برای مثال، با استفاده از جدول product_orders، عبارت PARTITION BY روی ستون order_id است. علاوه بر این، تعداد زیر گروه ها با تعداد منحصر به فرد order_id تعریف می شود. در این مورد، آن عدد، سه است.در NTILE : NTILE(3) برابر با تعداد bin ها است و PARTITION BY زیر گروه ها (یا پارتیشن ها) را تعیین می کند که در آن هر زیر گروه به سه bin تقسیم می شود.در FIRST_VALUE: تابع اولین مقدار یا ردیف را در زیرگروه تعریف شده را خروجی می دهد.در COUNT: تعداد ردیف های هر زیر گروه تعریف شده را می شمارد.در SUM: مقادیر (مثلاً amount) را در هر زیرگروه جمع می کند.در AVG: میانگین هر زیرگروه تعریف شده را محاسبه می کند.در خروجی، بلوک های خاکستری مشخص شده زیر زیرگروه های تعریف شده را با عبارت PARTITION BY و ایجاد ستون های جدید توسط window function ها را نشان می دهند.The ORDER BYعبارت ORDER BY هنگام رتبه بندی یا مرتب سازی داده ها استفاده می شود. این می تواند یک عبارت مستقل در window function ها باشد یا با عبارت PARTITION BY جفت شود. گاهی اوقات، فقط استفاده از عبارت ORDER BY مناسب تر خواهد بود، که امکان رتبه بندی یا ترتیب کل مجموعه داده را فراهم می کند. به عنوان مثال:SELECT
  order_id,
  amount,
  num_product_items,
  -- ranking by num_product_items
  ROW_NUMBER() OVER (ORDER BY num_product_items) AS row_num_by_items,
  RANK() OVER (ORDER BY num_product_items) AS rank_by_items,
  DENSE_RANK() OVER (ORDER BY num_product_items) AS dense_rank_by_items,
  -- ranking by amount
  ROW_NUMBER() OVER (ORDER BY amount) AS row_num_by_amount,
  RANK() OVER (ORDER BY amount) AS rank_by_amount,
  DENSE_RANK() OVER (ORDER BY amount) AS dense_rank_by_amount
FROM orders;استفاده از عبارت ORDER BY در توابع رتبه بندی، view مرتبی را بر اساس مقادیر یافت شده در ستون num_product_items و amount ایجاد می کند. تفاوت بین توابع رتبه بندی در ناحیه پررنگ نارنجی زیر نشان داده شده است. یادآوری: عبارت ORDER BY به ترتیب صعودی (ASC) تنظیم شده است. برای نزولی، باید با DESC نشان داده شود (به عنوان مثال، ORDER BY amount DESC).در ROW_NUMBER(): این تابع بدون توجه به مقادیر تکراری در ستون، به ترتیب با صعود یا نزول رتبه بندی می کند.در RANK(): تابع به صورت متوالی با افزایش یا نزول رتبه بندی می کند، اما زمانی که مقادیر تکراری وجود داشته باشد، گپ هایی وجود خواهند داشت. به عنوان مثال، در num_product_items، دو مورد از شماره 1 وجود دارد. بنابراین، تابع هر دو را در رتبه 1 قرار می دهد (زیر rank_by_items). در مرحله بعد، دو مورد از 2 در زیر num_product_items وجود دارد، و تابع اینها را به عنوان 3 رتبه بندی می کند.در ()DENSE_RANK: این تابع مانند تابع RANK() است اما رد نمی شود و شکاف یا گپی را ایجاد نمی کند. برخلاف ROW_NUMBER()، که در آن هر ردیف بدون توجه به مقادیر تکراری با یک رتبه منحصر به فرد مشخص می‌شود، DENSE_RANK() همان رتبه را برای مقادیر تکراری بدون شکاف اعمال می‌کند.The PARTITION BY &amp; ORDER BYپس از بررسی مکانیزم  PARTITION BY و ORDER BY به طور جداگانه، جفت کردن این دو کامپوننت مرحله بعدی است. PARTITION BY بر اساس ستون یا مجموعه ای از ستون های انتخابی، زیر گروه ها (یا پارتیشن ها) را ایجاد می کند. ORDER BY داده ها را به ترتیب صعودی یا نزولی سازماندهی می کند. من جفت شدن این مؤلفه ها را با استفاده از جدول product_orders نشان خواهم داد.در این مثال، من از 9 window function برای نشان دادن جفت شدن PARTITION BY و ORDER BY استفاده می کنم. در این مرحله، اگر درک کاملی از هر کامپوننت دارید، این باید ساده باشد. شرح هر window function ای برای Postgres در اینجا موجود است.در این کوئری SQL، تمام window function ها از order_id در عبارت PARTITION BY استفاده می کنند. تعداد order_id های یکتا برابر با تعداد زیر گروه ها است و ستون ORDER BY داده های هر زیرگروه را مرتب می کند.SELECT
  user_id,
  order_id,
  product_name,
  amount,
  -- rank items within the order by amount
  ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY amount DESC) AS row_num,
  -- rank items within the order by amount and highlight same values with same rank
  DENSE_RANK() OVER (PARTITION BY order_id ORDER BY amount DESC) AS dense_rnk,
  -- understand the percentile ranking of items in terms of amount within the order
  PERCENT_RANK() OVER (PARTITION BY order_id ORDER BY amount) AS percent_rnk,
  -- what is the first product_name within the order based on items being ordered by price ascending?
  FIRST_VALUE(product_name) OVER (PARTITION BY order_id ORDER BY amount RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_val,
  -- what is the last product_name within the order based on items being ordered by price ascending?
  LAST_VALUE(product_name) OVER (PARTITION BY order_id ORDER BY amount RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_val,
  -- create three bins within the order by bucketing items based on amount ascending
  NTILE(3) OVER (PARTITION BY order_id ORDER BY amount) AS ntile_bin,
  -- what is the second product_name within the order ordered by amount?
  NTH_VALUE(product_name, 2) OVER (PARTITION BY order_id RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS nth_val,
  -- grab the amount of an item that immediately precedes the current item within the order ordered by amount
  LAG(amount) OVER (PARTITION BY order_id ORDER BY amount) AS lag_val,
  -- grab the amount of an item that immediately following the current item within the order ordered by amount
  LEAD(amount) OVER (PARTITION BY order_id ORDER BY amount) AS lead_val
FROM product_orders;یکی از مواردی که قبلاً مورد بحث قرار نگرفت، استفاده از عبارت «RANGE BETWEEN UNBOUNDED PRECEDING UNBUNDED AND UNBOUNDED FOLLOWING» در توابع FIRST_VALUE()، LAST_VALUE() و NTH_VALUE() است. این عبارت برای تعریف ردیف اول و آخر زیرگروه مورد نیاز است. هیچ چیز خاصی در مورد این عبارت وجود ندارد، به جز اینکه باید برای تنظیم frame توابع پنجره ای یا window function ها شامل شود.خلاصهنکته کلیدی این است که توابع پنجره تلفیقی از مفاهیم SQL موجود هستند که با هم ترکیب شده اند تا روشی متفاوت برای برش داده ها ایجاد کنند. استفاده از توابع پنجره ای مزایای مشخصی دارد و به شما امکان می دهد تا به سرعت داده های transform شده را در مقابل صرف کردن زمان برای ایجاد توابع سفارشی خود، خروجی بگیرید.ضمیمهاگر قبلاً Postgres را روی رایانه خود نصب کرده اید، لطفاً این دستورات CREATE TABLE و INSERT را اجرا کنید و پرس و جوهای SQL را که قبلاً به اشتراک گذاشته ام را اجرا کنید.DROP TABLE IF EXISTS orders;

CREATE TABLE orders (
  order_id serial primary key,
  order_date timestamp,
  user_id integer,
  amount numeric,
  num_product_items integer
);

INSERT INTO orders VALUES (134,&#039;2017-12-03 14:18:12&#039;,1,19.99,1);
INSERT INTO orders VALUES (145,&#039;2018-01-05 12:33:00&#039;,1,54.56,2);
INSERT INTO orders VALUES (156,&#039;2018-01-18 21:34:59&#039;,1,36.78,3);
INSERT INTO orders VALUES (167,&#039;2018-03-07 09:35:34&#039;,1,24.56,2);
INSERT INTO orders VALUES (234,&#039;2018-03-12 09:45:56&#039;,2,63.96,4);
INSERT INTO orders VALUES (245,&#039;2018-04-01 10:45:56&#039;,2,456.87,6);
INSERT INTO orders VALUES (256,&#039;2018-05-04 18:23:14&#039;,2,122.45,3);
INSERT INTO orders VALUES (267,&#039;2018-08-11 21:59:59&#039;,2,34.56,1);
INSERT INTO orders VALUES (345,&#039;2016-06-12 18:45:01&#039;,3,136.08,5);
INSERT INTO orders VALUES (356,&#039;2017-06-10 09:51:14&#039;,3,165.67,4);
INSERT INTO orders VALUES (367,&#039;2018-06-07 22:54:04&#039;,3,156.76,3);

DROP TABLE IF EXISTS product_orders;

CREATE TABLE product_orders (
  user_id integer,
  order_date timestamp,
  order_id integer,
  product_name varchar,
  amount numeric
);

INSERT INTO product_orders VALUES (1,&#039;2017-11-12 00:11:45&#039;,123,&#039;dvd_movie&#039;,19.99);
INSERT INTO product_orders VALUES (1,&#039;2017-11-12 00:11:45&#039;,123,&#039;tennis_balls&#039;,12.99);
INSERT INTO product_orders VALUES (1,&#039;2017-11-12 00:11:45&#039;,123,&#039;bestseller_book&#039;,28.56);
INSERT INTO product_orders VALUES (1,&#039;2017-11-12 00:11:45&#039;,123,&#039;jacket_winter&#039;,112.99);
INSERT INTO product_orders VALUES (1,&#039;2017-11-12 00:11:45&#039;,123,&#039;sweater_winter&#039;,49.99);
INSERT INTO product_orders VALUES (2,&#039;2018-03-12 09:45:56&#039;,234,&#039;socks_spring&#039;,9.99);
INSERT INTO product_orders VALUES (2,&#039;2018-03-12 09:45:56&#039;,234,&#039;hoodie_jacket&#039;,16.99);
INSERT INTO product_orders VALUES (2,&#039;2018-03-12 09:45:56&#039;,234,&#039;blue_jeans&#039;,24.99);
INSERT INTO product_orders VALUES (2,&#039;2018-03-12 09:45:56&#039;,234,&#039;baseball_hat&#039;,11.99);
INSERT INTO product_orders VALUES (3,&#039;2016-06-12 18:45:01&#039;,345,&#039;pc_game_2&#039;,24.99);
INSERT INTO product_orders VALUES (3,&#039;2016-06-12 18:45:01&#039;,345,&#039;pc_game_3&#039;,45.99);
INSERT INTO product_orders VALUES (3,&#039;2016-06-12 18:45:01&#039;,345,&#039;console_controller&#039;,35.12);
INSERT INTO product_orders VALUES (3,&#039;2016-06-12 18:45:01&#039;,345,&#039;surge_protector&#039;,12.99);
INSERT INTO product_orders VALUES (3,&#039;2016-06-12 18:45:01&#039;,345,&#039;desk_lamp&#039;,16.99);منبع</description>
                <category>ابوالفضل وکیلی</category>
                <author>ابوالفضل وکیلی</author>
                <pubDate>Fri, 25 Mar 2022 01:03:10 +0430</pubDate>
            </item>
            </channel>
</rss>