<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های احمد گنج‌تابش</title>
        <link>https://virgool.io/feed/@agtabesh</link>
        <description>یه برنامه نویس!</description>
        <language>fa</language>
        <pubDate>2026-06-19 01:14:03</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/3503/avatar/GS1ApU.png?height=120&amp;width=120</url>
            <title>احمد گنج‌تابش</title>
            <link>https://virgool.io/@agtabesh</link>
        </image>

                    <item>
                <title>در اعماق نگاره - نمایه‌سازی</title>
                <link>https://virgool.io/Negare/%D8%AF%D8%B1-%D8%A7%D8%B9%D9%85%D8%A7%D9%82-%D9%86%DA%AF%D8%A7%D8%B1%D9%87-%D9%86%D9%85%D8%A7%DB%8C%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-vlrvrf785kow</link>
                <description>در اعماق نگاره - بخش اول - نمایه‌سازیسلام مجدد خدمت همه همراهان نگاره. امیدوارم حالتون خیلی خیلی خوب باشه.طبق برنامه ریزی که کردیم قرار هست جزییات فنی اکثر کارایی که تو نگاره انجام میدیم رو توی چند تا پست آموزشی منتشر کنیم.بدون مقدمه میرم سر اصل مطلب. همه می‌دونیم که یه روش بدیهی برای جستجو بین اسناد، نگاه کردن به تک تک اون اسناد هست تا زمانی که سند مورد نظرمون رو پیدا کنیم. این روش به ظاهر روش خوبیه ولی اصلا بهینه نیست و با افزایش تعداد اسناد، زمان صرف شده برای پیدا کردن سند مورد نظر هم افزایش پیدا میکنه.یه بحثی توی علوم کامپیوتر وجود داره به اسم پیچیدگی زمانی که میگه:چه مقدار زمان نیاز هست تا یه الگوریتمی برای ورودی به اندازه n اجرا شود. یعنی اگر بخوایم یه الگوریتمی رو روی یه مجموعه به طول n اجرا کنیم، چقدر طول می‌کشه تا به جواب برسیم. این زمان واحد خاصی نداره و تابعی بر حسب n (ورودی) است.مثلا برای پیدا کردن یک عدد در لیستی از اعداد به تعداد n، نیاز هست که عدد مورد نظر با تک تک اعداد موجود در لیست مقایسه بشه. حالا ۳ تا حالت پیش میاد:عدد مورد نظر دقیقا اولین عدد در لیست باشه. پس الگوریتم ما فقط یکبار عمل مقایسه را انجام می‌ده.عدد مورد نظر دقیقا آخرین عدد در لیست باشه. پس الگوریتم ما به تعداد n بار عمل مقایسه را انجام میده تا به عدد مورد نظر برسه یا مشخص بشه که عدد در لیست موجود نیست.عدد مورد نظر نه در خانه اول و نه در خانه دوم، بلکه در بقیه خانه‌های لیست باشه که دراین صورت با توجه به موقعیت عدد در لیست، تعداد مقایسه ها می‌تونه بین ۲ تا n-۲ متغیر باشه.حالت اول به عنوان بهترین حالت، حالت دوم به عنوان بدترین حالت، و میانگین تمام حالت‌های سوم به عنوان حالت میانگین در نظر گرفته می‌شه. معمولا بدترین حالت به عنوان معیار برای مقایسه الگوریتم‌ها استفاده میشه و با حرف انگلیسی O بزرگ نشون داده میشه. مثلا الگوریم جستجوی بالا از مرتبه (O(n است یعنی اگر اندازه ورودی n باشه، در بدترین حالت، باید n تا کار انجام بدیم تا عدد مورد نظر رو پیدا کنیم.حالا چرا این بحثو مطرح کردیم؟ به خاطر اینکه دقیقا همین مشکل بالا رو توی مباحث جستجو داریم. یعنی اگه بخوایم عبارتی خاصی رو توی اسناد جستجو کنیم باید همه اسناد رو دونه دونه بررسی کنیم که کار بسیار هزینه‌بری هست (از نظر زمان و منابع سیستمی). پس باید دنبال یه راه حل بهتر باشیم یعنی باید اسناد رو به شکلی ذخیره کنیم که فرایند جستجو توی آونها خیلی خیلی آسونتر و سریعتر باشه.مقدمه‌ای بر نمایه‌سازیقبل از اینکه خیلی جزیی تر وارد قضیه بشیم اینو بگم که هدف اصلی نمایه سازی، ذخیره اطلاعات بصورتیه که برای جستجو بهینه باشه. بدون نمایه سازی برای پیدا کردن عبارت مورد نظرمون احتمالا مجبوریم همه اسناد رو بگردیم که اصلا بهینه نیست، منابع زیادی مصرف می‌کنه و زمان خیلی زیادی طول می‌کشه. همه اینها نهایتا روی تجربه کاربری تاثیر بسیار بدی می‌ذاره و نارضایتیه کاربرا رو بالا می‌‌بره. پس نمایه سازی درست یکی از اصلی‌ترین مباحث تو موتورهای جستجو هست.اصلی‌ترین قسمت نمایه سازی ایجاد یک ساختار داده ای است که هر کلمه را به لیستی از اسناد شامل آن کلمه نگاشت می‌کنه (یعنی یه کلمه به عنوان ورودی میگیره و یه لیستی از اسنادی که شامل اون کلمه هست رو برمی‌گردونه). اصطلاحا به این کار نمایه معکوس (Inverted Index) می‌‌گن. یعنی بجای اینکه اسنادی داشته باشیم که شامل کلمات هستن، کلماتی داریم که شامل اسناد هستن. حالا می‌خوایم. این اسناد رو نمایه سازی کنیم. برای نمایه سازی باید یه مرحله پیش‌پردازش روی اسناد انجام بدیم تا آماده نمایه‌سازی بشن. این مراحل عبارتند از:اسناد رو به حالت نرمال دربیاریم، مثلا حروف بزرگ رو به حروف کوچیک تبدیل کنیم، حروف عربی رو به معادل فارسیشون تبدیل کنیم (مثلا ئ به ی)، و کارهایی از. این قبیل.کلمات ایست (stopwords) رو از اسناد حذف کنیم (مثل از، با، را، به، و ...)کلماتی که باید فیلتر بشن رو از متن حذف کنیم.کلماتی که در اسناد هست رو ریشه یابی کنیم (مثلا کتابها به کتاب تبدیل میشه).کاراکترهای خاص مثل !,@،#، $، %، ^، &amp;، *، (، )، و ... رو از اسناد حذف کنیم.بعد از اینکه پیش‌پردازش انجام شد، اسناد آماده نمایه‌سازی هستن. مراحلی که برای نمایه‌سازی باید طی بشه بصورت زیر هست:لیستی از همه کلماتی که در همه اسناد تکرار شده رو تهیه کنیم.اسناد رو به هر کلمه تخصیص بدیم.مثلا فرض کنید ۳ تا سند داریم که محتوای هرکدوم بصورت زیر هست:اسناد داده شده برای نمایه سازیبعد از اعمال مراحل پیش‌پردازش بر روی این اسناد خروجی بصورت زیر خواهد بود:اسناد پس از اعمال پیش‌پردازشو پس از نمایه‌سازی یه جدول بصورت زیر خواهیم داشت که نشون میده هر کلمه توچه سندی وجود داره:تخصیص اسناد به کلماتبرای مثال کلمه نگاره تو اسند شماره ۱ و ۳ وجود داره. نکته مهم و قابل توجه اینه که برای پیدا کردن عبارت موردنظر کافیه تعداد خیلی کمی از اسناد رو مورد بررسی قرار بدم مثلا برای پیدا کردن کلمه نگاره فقط کافیه ۲ تا سند رو بررسی کنم (الان اختلاف. زیادی نداره ولی در عمل واقعا باعث میشه اسناد خیلی کمی رو بررسی کنم?). با این کار پیچیدگی زمانی به مقدار خیلی زیادی کاهش پیدا میکنه و مستقل از تعداد اسناد میشه. این. باعث میشه مصرف منابع به مقدار چشمگیری کاهش پیدا کنه و مقیاس پذیری سیستم هم افزایش چیمگیری داشته باشه.الگوریتم‌های زیادی برای ذخیره این نوع نمایه های معکوس بصورت بهینه وجود دارد. اکثر این روشها بصورت کامل در کتاب Managing Gigabytes توضیح داده شده.معمولا از جدول درهم‌سازی‌شده (Hash Table) برای ذخیره این نمایه‌های معکوس استفاده می‌‌شود.تا اینجا با روش ساخت و ذخیره‌سازی نمایه معکوس آشنا شدیم. در ادامه با نحوه پیاده سازی چند روش نمایه‌سازی آشنا می‌شیم.۱) تکمیل کننده خودکار (Autocomplete):این روش یکی از پرکاربردترین روشها برای نمایه‌‌سازی است که با استفاده از Tire (نوعی درخت که در آن نود هایی که پدر یکسان دارن قسمتی از متن آندو نیز مشترک است) پیاده سازی می‌شن.مزیت‌های این روش:پاسخگویی بسیار سریع (معمولا در حد میلی ثانیه)مقیاس پذیری خوب (به آسانی می‌تواند هزاران درخواست در ثانیه را روی یک ماشین پاسخ دهد)عیب‌های این روش:درواقع این یه موتور جستجو نیست. یعنی ما به دنبال قسمتی از متن روی یه لیست از قبل تهیه شده می‌گردیم. این روش به خاطر محدود بودن لیست، یا نتایجی در بر نداره یا مرتبط نیست. از نظر تجربه کاربری نیز می‌تواند نتایج بدی دربر داشته باشه.همچنین به دلیل محدود بودن لیست، مرتبط بودن نتایج نیز به اندازه موتورهای جستجو نیست. این روش اگرچه سرعت و مقیاس پذیری بالایی داره، به دلیل محدودیت‌هاش تاثیر بسیار بدی توی تجربه کاربری خواهد داشت.۲) نمایه سازی پیشرو (Index Prefixes):این روش برای ساخت نمایه معکوس علاوه بر کلمات، از ساختار پیشرو کلمات نیز استفاده می‌کنه (مثلا علاوه بر کلمه &quot;کتاب&quot; از عبارات &quot;ک&quot;، &quot;کت&quot;، &quot;کتا&quot; نیز استفاده می‌کنه). معمولا از دو نمایه معکوس یکی برای کلمات و دیگری برای پیشرو کلمات استفاده ‌می‌شود که اولویت با نمایه معکوس کلمات است.مزیت‌های این روش:پاسخگویی بسیار سریع (به دلیل اینکه نمایه معکوس از قبل ساخته شده)عیب‌های این روش:ساخت نمایه معکوس زمان بیشتری طول می‌‌کشه.فضای مصرفی افزایش پیدا می‌کنه (چون نمایه‌های معکوس در حافظه اصلی (RAM) سرور نگهداری میشه)امکان تشخصی غلط املایی بسیار پیچیده و زمانبر میشه.این روش هم با توجه به اینکه سرعت پاسخگویی بالایی داره، فضای ذخیره سازی زیادی نیاز داره که مقیاس پذیری سیستم رو بشدت تحت تاثیر قرار می‌ده. بصورت مشابه نمایه سازی پسرو هم به همین شکل کار میکنه ولی از آخر عبارات رو می‌سازه.۲) نمایه سازی N-Gram:این روش خیلی شبیه به روش نمایه سازی پیشرو است با این تفاوت که طول کلمات پیشرو نمی‌تواند از یه حداقل و حداکثری تجاوز کنه. بزرگترین مزیت این روش کاهش هزینه زمانی و حافظه مصرفی است. مثلا کلمه &quot;پیراهن&quot; بصورت عبارات &quot;پیر&quot;، &quot;یرا&quot;، &quot;راه&quot;، &quot;اهن&quot;، نمایه‌سازی ‌می‌شود (که در آن حداقل و حداکثر طول  عبارات ۳ است).مزایا و معایب این روش نیز همانند نمایه‌سازی پیشرو است و تنها یک بهبود جزئی در هزینه زمانی و فضای مصرفی داره.۲) جستجوی عبارات پیشرو در زمان جستجو:این روش فرایند نمایه‌سازی را تنها با ذخیره لیست درهم‌سازی شده برای کلمات و اسناد بسیار ساده می‌کنه. محاسبه عبارات پیشرو به زمان درخواست جستجو موکول میشه. یعنی هروقت جستجویی انجام شد، عبارات پیشرو محاسبه میشه و جستجو بر اساس اونها انجام میشه.مزیت‌های این روش:عملیات نمایه سازی بسیار ساده انجام می‌شود.هیچگونه افتی در مرتبط بودن نتایج مشاهده نمی‌شه.عیب‌های این روش:جستجوها بسیار پیچیده و کند میشه.مقیاس‌‌پذیری بسیار بسیار پایین (مناسب برای زمانی که تعداد اسناد کم است).امیدوارم تا اینجای مطلب مفید بوده باشه براتون. در قسمت های بعد درمورد جزییات بیشتر اتفاقاتی که توی نگاره میوفته صحبت می‌کنیم.شاد و پیروز باشید...</description>
                <category>احمد گنج‌تابش</category>
                <author>احمد گنج‌تابش</author>
                <pubDate>Mon, 10 Feb 2020 20:34:48 +0330</pubDate>
            </item>
                    <item>
                <title>داستان تولد یک استارت‌آپ! مسیری که با نگاره شروع کرده ‌ایم...</title>
                <link>https://virgool.io/Negare/%D8%AF%D8%A7%D8%B3%D8%AA%D8%A7%D9%86-%D8%AA%D9%88%D9%84%D8%AF-%DB%8C%DA%A9-%D8%A7%D8%B3%D8%AA%D8%A7%D8%B1%D8%AA%D8%A2%D9%BE-%D9%85%D8%B3%DB%8C%D8%B1%DB%8C-%DA%A9%D9%87-%D8%A8%D8%A7-%D9%86%DA%AF%D8%A7%D8%B1%D9%87-%D8%B4%D8%B1%D9%88%D8%B9-%DA%A9%D8%B1%D8%AF%D9%87-%D8%A7%DB%8C%D9%85-ah7mxaghd1p4</link>
                <description>سرویس جستجوی نگارهحدودا ۶ ماه پیش بود که کاملا اتفاقی با مدیر وبسایت گلدتگ، آقای علی سفیداری، در مورد مشکلات جستجوی سایتشون صحبت کردم. سرویس جستجوی پیشفرضی که روی سایتشون بود نتایج کاملا بی‌ربطی رو برمی‌گردوند. بعضی وقتا هم عین عبارت رو تایپ می‌کردیم ولی هیچ نتیجه‌ای برگردونده نمی‌شد. در واقع قسمت جستجوی سایتشون عملا هیچ کمکی به کاربران سایت نمی‌کرد.با توجه به تجربه اندکی که توی هوش مصنوعی و مباحث Information Retrieval داشتم، پیشنهاد یه موتور جستجوی بهتر رو بهشون دادم و قرار شد تو ۲ هفته یه نسخه اولیه به عنوان MVP بسازیم و تستش کنیم. بعد از ۲ هفته نسخه اولیه آماده شد.تو نسخه اولیه یه مفهومی داشتیم به اسم مجموعه داده که می‌شد اسناد رو دسته‌بندی کرد. ایده این بود که بشه اسناد و محصولات مختلف مجموعه داده‌های مختلفی ساخت. مثلا مطالب وبلاگ و محصولات سایت می‌بایست از هم جدا می‌شد. تنها کاری که این نسخه انجام می‌داد ذخیره و ویرایش محصولات و جستجو بین اونها بود.آماده برای پرتاپ! وقتی همه چیز آماده شد، یه سرور مجازی گرفتم که ۸ هسته CPU و ۸ گیگ رم داشت! سرویس رو روی این سرور راه اندازی کردیم و به عنوان یه شروع نتیجه خوبی گرفته بودیم.تا ۵ ماه این سرویس روی گلدتگ فعال بود و به کاربرا سرویس می‌داد. تو این مدت کلی فیدبک خوب از آقای سفیداری گرفتم که توی ادامه راه خیلی کمکم کرد. همین فیدبک های مثبت و کارایی سرویس تو این مدت باعث شد نیاز به همچین سرویسی رو برای بقیه کسب و کارها هم حس کنم.یه جلسه با محسن گذاشتم. قضیه آشنایی من با محسن برمی‌گرده به ۳ سال پیش که برای یه پروژه دنبال هم‌تیمی می‌گشتم که با محسن آشنا شدم. با اینکه در نهایت اون ایده موفق نشد، اما تو این سه سال باهم رو پروژه‌های مختلف کار کردیم و به دوستای خوبی برای هم تبدیل شدیم. قرار شد سرویس رو مجدد بازنویسی کنیم و اشکالاتی که در نسخه اولیه سرویس بود رو رفع کنیم. الگوریتم های خطایابی خیلی کاملتر شد. روش ذخیره سازی بسیار بهینه تر شد بطوری که تونستیم از ذخیره اطلاعات تکراری برای وبسایت‌های مختلف جلوگیری کنیم که همین کار باعث شد فضای مصرفی تا ۷۵ درصد کاهش پیدا کنه! امکان تعریف روابط معنایی هم به سرویس اضافه شد تا نتایج دقیقتر بشن. همه چیز آماده بود تا نسخه اولیه محصول رو آپلود و تست کنیم.راه‌اندازی سرویس و روبرو شدن با اولین چالشما توی بخشای مختلفی از سرویسمون از دیتابیس ردیس برای اهداف مختلفی استفاده می‌کنیم. طبق بررسی هایی که انجام دادیم قرار شد ردیس رو بصورت کلاستر نصب و کانفیگ کنیم تا بتونیم مقیاس پذیرتر باشیم و کارایی سرویس رو بالا ببریم. بعضی از توابع ردیس تو حالت کلاستر کار نمیکنن، یعنی اونهایی که چند تا کلید رو به عنوان ورودی میگیرن یا اصطلاحا multi-key هستند. عملیات سورت کردن، محاسبه اشتراک و اجتماع روی مجموعه های مرتب شده و ... جزء اون دستورات بود.روش‌های مختلفی رو تست کردیم ولی کارایی سرویس با افت شدید مواجه شد بطوری که به این نتیجه رسیدیم که نمی‌تونیم سرویس مقیاس‌پذیری داشته باشیم مگر اینکه همه الگوریتم‌ها و ساختارهای داده ای رو از پایه کدنویسی کنیم. بعد از ۲ روز تلاش شبانه روزی تونستیم بعضی از الگوریتم هارو با توجه به انواع داده های قابل پشتیبانی توسط ردیس دوباره نویسی کنیم. پشتیبانی ردیس از زبان LUA هم باعث شد تا خیلی از کارها رو بصورت سفارشی شده و کاملا بهینه انجام بدیم. همین بازنویسی مجدد باعث شد میانگین زمان پاسخ دهی سرویس با ۲۰ درصد بهبود به ۸.۷ میلی ثانیه برسه که تجربه خیلی خوبی رو به کاربر میده.بعد از اینکه همه چیز تموم شد سایت رو بالا آوردیم و همه چیز طبق انتظار خیلی خوب کار می‌کرد. بعد از برطرف کردن این چالش، که باعث شده بود تا مرز ناامیدی پیش بریم، مصمم تر از قبل سرویس رو توسعه می‌دیم.تکمیل کننده جستجوبعد از یه مدت کوتاهی متوجه شدیم که در کنار سرویس جستجوی اصلی نیاز به یه سرویس مکمل داریم که هنگام تایپ، عبارات مناسب را به کاربر پیشنهاد دهد. یکی از اصلی‌ترین چالش های این سرویس، در‌نظر گرفتن کلمات قبلی در پیشنهادات آتی بود. مثلا وقتی عبارت پیراهن مر تایپ می‌شود می‌بایست عبارت پیراهن مردانه در لیست گزینه‌های پیشنهادی می‌بود. از طرفی وقتی عبارت تخم مر تایپ می‌شود می‌بایست عبارات تخم مرغ در لیست گزینه‌های پیشنهادی می‌بود. با این کار می‌توان نتایج مرتبط‌تری را به کاربر نمایش داد.پس از حل این چالش، امکان تکمیل کننده جستجو نیز به سرویس جستجوی نگاره اضافه شد.بعد از اینکه مطمئن شدیم سرویس به خوبی داره کار می‌کنه، یه سری کارای جانبی داشیم که باید انجام می‌دادیم. اول از همه باید یه صفحه فرود طراحی می‌کردیم که کاربرامون بتونن با سرویسمون آشنا شن. چیزی که برامون مهم به نظر می‌اومد طراحی یه دمو خیلی خوب بود که هر کسی مستقل از دانش فنی و ... بتونه سرویس رو تست کنه. یه دمو که نشون بده سرویس ما چیه، به چه دردی میخوره، و چقد خوبه.طبق صحبت‌هایی که با آقای سفیداری انجام شد، قرار شد از اطلاعات و محصولات وبسایت گلدتگ برای ساخت این دمو استفاده کنیم. (برای دیدن دمو می‌تونید اینجا کلیک کنید)بعد از اینکه دمو آماده شده باید مستندات رو تکمیل می‌کردیم تا کاربرا به راحتی بتونن از سرویس استفاده کنن. یه کتابخونه برای زبان PHP هم نوشتیم که در بخش مستندات قرار داره.مسیر همچنان ادامه دارد...هنوز مثل خیلی از استارت‌آپای دیگه مسیر طولانی و دشواری رو در پیش داریم؛ موانع و چالش هایی هستن که باید بهشون غلبه کنیم. با انگیزه و پرانرژی به حرکت کردن ادامه میدیم چون کاری رو که انجام می‌دیم رو دوست داریم.در حال حاضر داریم روی پنل کاربری کار می‌کنیم که بشه مجموعه داده هارو تعریف کرد و یه سری تحلیل ها رو اونجا دید. در کنارش داریم یه سری کتابخونه هم واسه سیستم های مدیریت محتوای مختلف می‌نویسیم که کاربرا براحتی بتونن وبسایت یا اپلیکیشن موبایل خودشون رو به سرویس نگاره وصل کنن.اگه علاقه دارید که توی این مسیر بهمون کمک کنید، حتما بهمون پیام بدید. خوشحال می‌شیم که شما رو توی تیممون داشته باشیم.</description>
                <category>احمد گنج‌تابش</category>
                <author>احمد گنج‌تابش</author>
                <pubDate>Thu, 30 Jan 2020 00:54:47 +0330</pubDate>
            </item>
            </channel>
</rss>