<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های دیوار</title>
        <link>https://virgool.io/feed/@divar</link>
        <description>تنها اکانت رسمی دیوار، پلتفرم خرید و فروش بی‌واسطه آنلاین، در ویرگول. اینجا بچه‌های دیوار درباره محیط کاری، دغدغه‌ها، چالش‌های حرفه‌ای و زندگی در دیوار حرف می‌زنند.</description>
        <language>fa</language>
        <pubDate>2026-06-10 06:26:12</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/249648/avatar/Iy1mDC.png?height=120&amp;width=120</url>
            <title>دیوار</title>
            <link>https://virgool.io/@divar</link>
        </image>

                    <item>
                <title>از دستیار کدنویس تا همکار هوشمند؛ گام دوم: اتصال کدبیس دیوار به مدل‌های زبانی</title>
                <link>https://virgool.io/@divar/%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%DB%8C%D8%A7%D8%B1-%DA%A9%D8%AF%D9%86%D9%88%DB%8C%D8%B3-%D8%AA%D8%A7-%D9%87%D9%85%DA%A9%D8%A7%D8%B1-%D9%87%D9%88%D8%B4%D9%85%D9%86%D8%AF-%DA%AF%D8%A7%D9%85-%D8%AF%D9%88%D9%85-%D8%A7%D8%AA%D8%B5%D8%A7%D9%84-%DA%A9%D8%AF%D8%A8%DB%8C%D8%B3-%D8%AF%DB%8C%D9%88%D8%A7%D8%B1-%D8%A8%D9%87-%D9%85%D8%AF%D9%84-%D9%87%D8%A7%DB%8C-%D8%B2%D8%A8%D8%A7%D9%86%DB%8C-siy72zeedr8l</link>
                <description>در قسمت قبلی «از دستیار کدنویس تا همکار هوشمند»، با مسیر توسعه ابزار تولید مستندات توسط AI آشنا شدیم. حالا توی این قسمت، می‌خوایم ببینیم که چطور می‌تونیم دانش و داده‌های داخلی سازمان (کانتکست) رو در اختیار LLM‌ها قرار بدیم.وقتی این بُعد تازه به قابلیت مدل‌ها اضافه بشه، می‌تونیم کارهای خیلی پیچیده‌تری رو به کمکشون انجام بدیم.کار با ابزار‌های هوش‌مصنوعی در کدنویسی: از هیجان تا عادتبعد از معرفی ابزار GitHub Copilot، استفاده از LLMها به‌عنوان دستیارهای برنامه‌نویسی به شکل جدی مطرح شد؛ به‌طوری که برنامه‌نویسی، تبدیل به یکی از اهداف اصلی توسعه‌دهندگان این مدل‌ها شد. برای مثال، یکی از بنچمارک‌های اصلی برای ارزیابی همین مدل‌ها، SWE-BENCH است که شامل تسک‌های برنامه‌نویسی روی issueهای پروژه‌هاست. همینطور شرکت Anthropic، که مدل‌های Claudeش خیلی معروف هستند، تمرکز اصلی‌اش رو بر روی این بازار مشتریان قرار داد و با وجود اینکه قیمت مدل‌هایش بسیار بالاتر هست، چون عملکرد بهتری در زمینه تولید کد داشتند، همیشه جزو اولین مدل‌های این زمینه بودن.ما هم در دیوار این هدف رو برای خودمون گذاشتیم که با استفاده از هوش مصنوعی، بهره‌وری مهندسی رو افزایش بدیم. در شروع سرویس‌های مکالمه‌محور مثل ChatGPT رو آوردیم و باهاشون کار کردیم. به مرور سرویس‌هایی مثل Copilot و Cursor هم امتحان کردیم. تجربه‌مون تا مدتی به این صورت بود که هر ابزار جدیدی که می‌اومد تعدادی از مشکلات و اذیت‌هایی که با ورژن‌های قدیمی‌تر داشتیم برطرف می‌کرد. برای مثال در کار با ChatGPT باید توضیحات خیلی مفصلی از مسئله ارائه می‌دادیم و تمام کدهای مورد نیازشو کپی پیست می‌کردیم و کد خروجیش رو داخل محیط توسعه‌مون می‌آوردیم و مشکلات سینتکسی که داشت رو برطرف می‌کردیم. برای دیباگ هم لاگ‌های خروجیش رو باز به GPT می‌دادیم. این تجربه کاربری رفت و برگشتی تا حد خوبی در محصولاتی مثل Cursor برطرف شد اما همچنان مشکلات بزرگ دیگری داشتیم.چرا این ابزار‌ها در مقیاس بزرگ می‌لنگند؟Cursor برای پروژه‌های کوچک و self-contained خیلی خوب عمل می‌کرد. اما برای پروژه‌های داخل یک سازمان به مشکل می‌خورد. مشکل این بود که همه اطلاعات مورد نیاز داخل پروژه در دسترس نیست و یا پیدا کردنش برای کسی که دانش قبلی از سازمان و کانونشن‌های پروژه نداره کار ساده‌ای نیست. خیلی از جاها هم زمان و هزینه‌ای که ایجنت‌ها برای پیدا کردن داده مورد نظر می‌ذاشتن خیلی بالا بود و حتی ممکن بود Context Window مدل به طور کامل پر بشه و به نتیجه نرسه. تمام محصولات دیگری که امتحانشون کردیم، هر چقدر هم پیشرفته بودن و از مدل‌های بهتر و توکن بیشتری استفاده می‌کردن، باز هم مشکل اصلی پابرجا بود. اینکه کانتکست دیواری و دانش کتابخانه‌های داخل سازمانی رو نداشتن و عملکردشون به همین علت، بهینه نبود. در خیلی از موارد هم مستندات معتبری داشتیم و یا ساخته بودیم که به خوبی ازشون استفاده نمی‌شد.مکانیزم پیشنهادی برای حل کردن این مسائل در مدل‌های زبانی قابلیت استفاده از ابزار (tool calling) در عامل‌های (agents) هوش‌مصنوعی بود. اینطور که خود مدل بسیاری از داده‌هایی که نیاز داره رو به دست بیاره، و خودش اکشن‌هایی که پیشنهاد می‌ده رو انجام بده و خروجی‌شون رو بررسی کنه. این یعنی مسئولیت از دوش کاربر استفاده کننده برداشته بشه.برای همین تصمیم گرفتیم اول سعی کنیم منابع داده مختلفی رو که داریم رو با استفاده از ابزارهایی که امکانش هست، به LLMها وصل کنیم. اما باید برای هر سرویسی، به طور جداگانه، داخل Agent Libraryها و با استفاده از SDK خود شرکت‌ها ابزار رو به عنوان یک تابع یا اندپوینتی که صدا زده می‌شه، اضافه کنیم. کار قابل انجامی بود اما یکپارچه نبود و خیلی از سرویس‌های انحصاری هم قابلیت تغییر و اضافه کردن ابزار به این شکل رو به ما نمی‌دادن.اینجا بود که با MCP آشنا شدیم. MCP یک پروتکل باز بر پایه JSON-RPC v2 هست که توسط Anthropic معرفی شده برای اینکه تعامل LLMها با بقیه APIهای موجود رو استاندارد کنه و از وقتی عرضه شده، استقبال زیادی داشته. در حال حاضر تقریبا هر LLM Application پراستفاده‌ای ازش پشتیبانی می‌کنه (لیست محصولاتی که از MCP پشتیبانی می‌کنند). برای همین ما هم تصمیم گرفتیم تعدادی سرور MCP توسعه بدیم و ببینیم که به مدل‌ها در انجام تسکشون کمک می‌کنه یا نه.جستجوی کد در تمام پروژه‌هایک مسئله بزرگ وجود داره که اصلا محدود به LLMها نیست و شاید خود شما هم در شرکتتون الان این مسئله رو داشته باشید، مسئله محدودیت دسترسی به دانش داخلی هست. برای مثال در دیوار هم اوایل از سرچ گیت‌لب و یا ابزارهایی مثل grep یا rg داخل پروژه‌ها استفاده می‌کردیم. این روش زمان زیادی می‌برد و در اکثر مواقع چیزی رو که دنبالش بودیم پیدا نمی‌کردیم و مجبور بودیم از افراد مختلف پرس و جو کنیم و دانش سینه به سینه بین افراد و تیم‌ها منتقل می‌شد. چند باری هم که خواستیم این مسئله رو با روش‌هایی مثل semantic search یا Source Code Embedding و RAG حل کنیم ناموفق بودیم.در مراحل بعدی بیشتر تمرکزمون رو روی این گذاشتیم که ببینیم خودمون زمانی که دنبال قطعه کد خاصی می‌گردیم چطور عمل می‌کنیم و به راه‌هایی از جنس exact text search رسیدیم. دنبال ابزاری می‌گشتیم که همون کاری که grep و rg برای ما می‌کرد در سطح کل کدبیس به صورت static و با قابلیت فیلتر دقیق‌تر روی پارامترهای مدنظر برنامه‌نویسی ارائه بده. توی این مسیر به سرویس Zoekt رسیدیم که دقیقا همین قابلیت‌ها رو روی کدبیس به ما ارائه میده. این ابزار با زبان کوئری ساده‌ای که ارائه میده، می‌تونه روی نام فایل، پروژه و زبان برنامه‌نویسی فیلتر کنه و با استفاده از regexهای نسبتا ساده جست‌و‌جوی دقیقی انجام بده. و ما دیدیم که نیاز نیست چرخ رو از اول اختراع کنیم.سرویس Code Search از شرکت Sourcegraph هم از Zoekt به عنوان هسته اصلی سرچش استفاده می‌کنه. و البته UI خیلی بهتری هم داره و فیلترهای دقیق‌تر و کوئری‌بیلدر راحت‌تر ی هم ارائه می‌ده. همچنین قابلیت‌هایی که در ابزارهایی مثل محصولات JetBrains هست مثل LSP و Finding Usage &amp; Definition رو روی تمام زبان‌های برنامه‌نویسی در سطح کل کدبیس ارائه میده و این قابلیت‌ها رو در زبان کوئریش هم اضافه می‌کنه (مثلا میشه روی symbolها ی برنامه نویسی و موجود در AST سرچ کرد). با این ابزارها به راحتی می‌شه فهمید چه کدی کجا تعریف شده و API مد نظرمون در کجا داره صدا زده می‌شه.در گام بعدی، می‌خواستیم به مدل‌ها استفاده از این ابزار و این نحوه کد سرچ کردن رو یاد بدیم. اگه شما هم دیده باشید ابزارهای برنامه نویسی، برای اینکه اطلاعاتی که دنبالش هستن رو پیدا کنن، بیشترشون داخل پوشه پروژه shell باز می‌کنن و دستورهایی مثل cat, grep, tail استفاده می‌کنن. ما طبق بررسی‌ها و آزمون و خطایی که داشتیم به این نتیجه رسیدیم که سه ابزار باید آماده کنیم که مدل‌ها برای سرچ کردن ازش استفاده کنن.‏search_prompt_guide: ابزاریه که یک توضیح مفصل از سینتکس کوئری Code Search به همراه مثال می‌ده و سرور MCP و استفاده‌اش رو به مدل معرفی می‌کنه. علاوه بر اون یه بخش داخل پرامپت برای دانش داخل سازمانی هم در نظر گرفتیم که نکاتی قبیل اینکه پروژه‌ها و کتابخانه‌های اصلی کجا قرار دارن و معماری سیستم و پروژه‌ها چی هست رو داخل خودش داره. مدل همیشه از این ابزار، به عنوان اولین ابزار، قبل از جستجو استفاده می‌کنه.‏search: مشابه همینه که مدل به نوار جستجو در Code Search دسترسی داره و هر کوئری‌ای که نیاز داره رو می‌تونه بزنه و ما هم همون رو مستقیم به کدسرچ می‌دیم. البته خروجی‌ای که می‌ده رو ساده سازی می‌کنیم و چند خط بالا و پایین خطی از کد که match شده هم بر می‌گردونیم و یا جواب‌ها رو زمانی که تعداد نتایج بالا باشه فیلتر می‌کنیم.‏fetch_content: این رو در پی توسعه سرور MCP و مدتی بعد از ورژن اول بهش رسیدیم. دیدیم خیلی از مواقع جواب مدل کامل داخل یک فایل وجود داره و اگر این قابلیت رو بهش بدیم که تمام محتوای یک فایل رو بگیره بهش کمک می‌کنه. در بسیاری از موارد هم اگر فایل‌های یک آدرس از پروژه رو بدونه می‌تونه سرچ بعدی و یا فایل بعدی‌ای که می‌خواد محتواش رو بخونه بهتر پیدا کنه. به خصوص اگر پروژه README یا ai doc مناسب داشته باشه ( اشاره به مستندسازی برای پروژه‌ها به کمک هوش‌مصنوعی)، با خوندن اون‌ها خیلی دید بهتری نسبت به سوالی که داره و جایی که جواب سوالش هست پیدا می‌کنه.جزئیات دقیق‌تر از پرامپت این ابزارها هم اینجا در دسترسه: https://github.com/divar-ir/code-context-provider/blob/master/src/prompts/prompts.yamlسه رکن مهم محصول LLMی خوب؟ ارزیابی ارزیابی ارزیابی!یعنی تموم شد؟ همینقدر راحت همه چیز کار کرد؟ نه راستش! پرامپت و توضیحاتی که ما برای این ابزار می‌گذاشتیم، خیلی روی خروجی و کیفیت کار تاثیرگذار بود. مسئله این بود که خیلی مطمئن نبودیم که چه تعداد از جواب‌هایی که داره می‌ده خوب و کمک کننده هست و چقدر هم جواب اشتباه داره میده. پس سراغ این رفتیم ساختار قابل اطمینانی برای ارزیابی داشته باشیم.برای ارزیابی عملکرد سرور MCP، یک دیتاست از سوال و جواب روی کدبیس دیوار درست کردیم. جواب سوال‌ها رو به صورت سرچ دستی و یا از مصاحبه با تیم‌هایی که روی سرویس آنبورد بودن پر کردیم. بعدش یک ساختار نوشتیم که ارزیابی کارکرد سرور رو به این شکل انجام بدیم:یک ایجنت بالا میاریم و بهش MCP کد سرچ رو به عنوان ابزار می‌دیم.بخش سوال آیتم دیتاست رو بهش می‌دیم و ازش می‌خوایم که جوابش رو پیدا کنه و توضیحاتش رو در قالب مشخصی بهمون برگردونهسپس جواب ایجنتمون رو با بخش جواب توی دیتاست (با استفاده از داوری LLM) مقایسه می‌کنیم و بهش نمره قبول/رد می‌دیم. برای اینکه بتونیم مانیتورینگ راحت‌تر داشته باشیم از سرویس Langfuse استفاده کردیم که مخصوص LLM Application Observability هست و trace تمام tool callهایی که داخل یک نوبت روی سرور ما انجام می‌شه رو بهمون نشون می‌ده. ما از طریق این می‌تونیم به راحتی مسیری رو که مدل برای جست‌و‌جو انتخاب کرده رو تحلیل کنیم و ببینیم مسیر مناسبی رو انتخاب کرده و در آخر به جواب رسیده یا نه. بعد از این هر تغییری که روی پرامپت‌ها یا پیاده سازی داشتیم این فرایند ارزیابی رو اجرا می‌کردیم و درصد موفقیتش رو به عنوان متریک در نظر می‌گرفتیم.برای درصد موفقیت بالا باید جلوی شانس رو گرفت!در خیلی از موارد، سرویس‌هایی که با کدسرچ تعامل می‌کنن مدل قوی‌ای پشتشون نیست و یا محدودیت tool call دارند. در شرایطی هم، خروجی‌هایی که از codesearch می‌گیرن، کانتکستشون رو با دیتای نامفهوم پر می‌کنه و حتی اگر به جواب سوالی که دارن برسن، نمیتونن تسکی که با اون جواب می‌خوان انجام بدن رو تکمیل کنن. برای حل این موضوع از معماری MCP in MCP استفاده کردیم و یک سرور MCP ارائه دادیم که پشتش در واقع یک ایجنت برنامه نویسی هست که به MCP کدسرچ ما دسترسی داره. در ورژن فعلی این ایجنت همون ایجنت فرایند ارزیابی‌مون هست که محدودیت روی فرمت خروجیش رو کمتر کردیم و به عنوان MCP کانتکست ارائه‌اش دادیم. به نوعی پیاده سازی ما پیرو مفهوم و ابزار Deep Search بود که خیلی از محصولات اضافه کرده بودن. این MCP سرور شامل ابزارهای زیر بود:‏query_reformatter: یک فاکتور خیلی تاثیرگذار در کیفیت جواب سرور ما، درستی اولین سوالی بود که مدل از MCP می‌پرسید که تاثیر زیادی روی ادامه مسیر جستجو روی اون موضوع داره. مواردی مثل زبان برنامه‌نویسی‌ای که مدل دنبالشه یا اسم پروژه‌ای که داخلش دنبال کد می‌گرده، اگر اشتباه یا نامفهوم گفته بشه، میتونه سرچ رو خیلی تحت تاثیر بگذاره. از طرف دیگه هم مدل خیلی اطلاعات محدودی از معماری و stack تکنولوژی‌ای که ما استفاده می‌کنیم داره که اگر بدونه می‌تونه سوال دقیق‌تری رو بپرسه. کار این ابزار اینه که سوال اولیه مدل رو می‌گیره و با استفاده از یک ایجنت با دسترسی به کدسرچ سعی می‌کنه حدس بزنه منظور دقیق درخواست کننده چی بوده و تعدادی گزینه، که هر کدوم از یک ورژن دقیق شده سوال اولیه بوده، رو به عنوان خروجی بر می‌گردونه تا مدل از بین این گزینه‌ها سوالی رو که به هدفی که داره نزدیک‌تره در کوئری بعدی بپرسه.‏agentic_search: ورودی این ابزار سوالیه که از کدبیس داریم برای مثال: چه سرویسی وظیفه احراز هویت رو داره؟ چه کسی RPC X رو صدا می‌زنه؟ چطور از فیچرفلگ داخل کد Golang استفاده کنم؟ سوال‌هایی از این قبیل که بعد از دقیق شدن توسط query_reformatter از سرور کانتکست پرسیده می‌شن و این ابزار یک گزارش کامل به همراه قطعه کد و فایل‌ها و پروژه‌هایی که به عنوان منبع ازشون جواب رو استخراج کرده بر می‌گردونه.نتایج واقعیکمتر از دو سه هفته می‌شه که ما این سرویس رو داخل شرکت ارائه دادیم و بازخورد مثبتی که تا الان گرفتیم خیلی بالا بوده. بهترین رابط کاربری‌مون دستیار جدا شده‌ای هست که وظیفه‌اش پاسخ دادن به سوال‌های فنی از کدبیس دیواره و مسئله آنبوردینگ و رفت و برگشت سوال بین چند تیم یا دانش داخلی که سینه به سینه منتقل می‌شده رو تا حد خوبی بر طرف کرده. یک ایجنت بررسی تغییرات (code review) هم اضافه کردیم که روی اکثر پروژه‌ها روشن شده و هر تغییری که روی کد انجام می‌شه، قبل از اضافه شدن به پروژه و ریلیزش به طور دقیق بررسی می‌کنه و بازخورد می‌ده.در زمینه ایجنت‌های برنامه‌نویسی اما هنوز به نتیجه مدنظرمون نرسیدیم که محصولاتی مثل Cursor همراه ابزارهای داخلی خودشون به کمک ابزار ما هم تسک‌ها رو انجام بدن. اگر سرورهای MCP کدسرچ رو بهشون بدیم در استفاده از ابزار سرچ داخلی خودشون و ابزار سرچ ما گمراه می‌شن و اگر سرور کانتکست رو بهشون بدیم خیلی خوب عمل می‌کنن اما به دلیل زمانی که می‌بره (حدود ۲ دقیقه به ازای هر agentic_search) چرخه توسعه رو خیلی کند می‌کنه. و فعلا بهترین استفاده از این ابزار همین پرسیدن از دستیار کد زمانی که سوال پیچیده‌تری از کدبیس داریم هست.مسیر آیندهدر چند ماه اخیر مفهوم ایجنت‌های برنامه‌نویسی داخل CLI مثل Claude Code، Amp Code و Gemini CLI خیلی جدی‌تر بهشون پرداخته شده. این ایجنت‌ها می‌تونن در پس‌زمینه یا داخل محیط ترمینال وظایف برنامه‌نویسی رو انجام بدن. اینها ایجنت‌های بهینه‌سازی شده‌ای هستن که قابلیت‌هایی نظیر Planning، Context Summarization و Intelligent Model Choosing بهشون اضافه شده. طبق تجربه‌ای که باهاشون داشتیم، از سرور کدسرچ خیلی خوب استفاده می‌کنند و احتمال بالایی وجود داره که بتونن جایگزین بخش سرور کانتکست ما بشن. همچنین ایجنت‌هایی که تسک‌های برنامه‌نویسی انجام می‌دن مثل ایجنت تست نویس می‌تونن از این ابزارها به عنوان قالب شروع استفاده کنن.بهتره که ابزار مشابه سرچ کد رو روی مخازن دیگر اطلاعات سازمان از جمله مستندات داخلی، پروپوزال‌ها، Post Mortemها و منابع دیتایی داشته باشیم. که باعث می‌شه این اطلاعات هم در دسترس‌تر و قابل استفاده‌تر باشه و بهره‌وری افراد سازمان که در وظیفه‌شون به داشتن دانش از این منابع نیاز دارند افزایش پیدا بکنه.کارکردهای مشابه Code Review که با این ابزارها ممکن می‌شه مثل تست نرم‌افزار، دیباگ، افزایش مشاهده‌پذیری و CI/CD بررسی و پیاده سازی کنیم.در بسیاری از موارد سرویس‌های منسوخ شده و یا نام‌گذاری بد پروژه‌ها به همراه مستندات غیر معتبر و منقضی شده تاثیر منفی روی عملکرد ابزارهای ما داشتن. این مسیر AI Enabled شدن یک سازمان موضوع Deprecation رو برامون جدی‌تر کرده که به همراه مستندسازی پروژه‌ها برای دسترسی بهتر مدل‌ها نیاز به پاک کردن پروژه‌های استفاده نشده و نام‌گذاری بهتر دیده می‌شه.اگر کارهایی که اینجا گفته شد براتون جالب بود و می‌خواستید خودتون کارهای مشابهی انجام بدید ما پیاده‌سازی‌مون از سرورهای MCP رو اوپن سورس کردیم:Zoekt MCP: https://github.com/divar-ir/zoekt-mcpSourcegraph MCP: https://github.com/divar-ir/sourcegraph-mcpهمچنین اگر دوست دارید پیاده‌سازی مشابهی برای ارزیابی سرورهای کدسرچ و سرور کانتکست داشته باشید می‌تونید از این پروژه الهام بگیرید و استفاده کنید:Code Context Provider: https://github.com/divar-ir/code-context-provider</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Thu, 21 Aug 2025 16:13:11 +0330</pubDate>
            </item>
                    <item>
                <title>از دستیار کدنویس تا همکار هوشمند؛ گام اول: کابوس مستندسازی</title>
                <link>https://tech.divar.ir/از-دستیار-کدنویس-تا-همکار-هوشمند-گام-اول-کابوس-مستندسازی-jx7vhznchc9w</link>
                <description>بیایید واقع‌بین باشیم: نگه‌داری مستندات واقعاً اعصاب‌خُرده‌کن ـه!احتمالا همه‌امون با پروژه‌ای رو به رو شدیم که تو README فقط این نوشته بود: &quot;TODO: Add documentation&quot;. یا حتی بدتر... داک‌هایی که آنقدر قدیمی‌ان که فقط باعث گمراهی می‌شن. بعدشم اینطوری بودیم که: کلی وقت برای فهمیدن پروژه گذاشتیم، به خودمون قول دادیم که این‌بار داکش می‌کنیم. ولی نـــــه... deadline‌ها و باگ‌های پروداکشن می‌رسن و مستند‌سازی می‌ره ته لیست کارها.چرخه‌ی مرگ مستند‌هاماجرا معمولاً این‌طوری شروع می‌شه:شروع قوی: این بار دیگه داک رو همیشه آپدیت نگه می‌داریم!واقعیت می‌خوره تو صورتمون: آخرهای اسپرینته، باگ‌های پروداکشن، فیچر جدید و داکی که عقب میافته.جمع شدن بدهی فنی: کد تغییر می‌کنه، dependencyها آپدیت می‌شن، تصمیمات معماری هم عوض می‌شن.داک‌ بو می‌گیرن: همون داک نصفه‌نیمه هم، یه روز می‌بینیم کاملاً غلط و قدیمی شده و دیگه به‌روز نیست.تازه‌واردها عذاب می‌کشن: onboarding تبدیل می‌شه به حفاری معدن؛ باید کدها رو خط‌به‌خط خوند تا فهمید سرویس چیکار می‌کنه.و این چرخه‌ی مریض ادامه داره: همه مدام دنبال حل مشکل فوری‌ان و کسی حوصله رسیدن به ریشه ماجرا رو نداره.ورود به عصر هوش‌مصنوعیوقتی ChatGPT و Claude و بقیه مدل‌های هوش‌مصنوعی وارد میدون شدن و در فهم کد پیشرفت کردن، به این فکر افتادیم: واقعاً نمی‌شه این کارهای عذاب‌آور رو خودکار کرد؟ منظور صرفا تولید یه قالب و متن کلی از پروژه نیست؛ واقعا مثل یک برنامه‌نویس باتجربه کد رو تحلیل و مستند کنن. نکته اینجاست که مدل‌های هوش‌مصنوعی در تشخیص الگوها واقعاً خوبن؛ فقط باید درخواست و context رو براشون درست آماده کنید. اما LLMها و هوش مصنوعی امروزی، یک چالش خیلی بزرگ دارن، که اونم محدودیت «حافظه» یا همون «پنجره کانتکست» (Context Window) اون‌هاس. خیلی ساده یعنی نمی‌تونیم کل دانش و داده یک پروژه رو، مثلاً تمام کدها (Codebase)، یک‌باره جلوی مدل بذاریم و انتظار یک تحلیل عمیق و درست و حسابی داشته باشیم.اما خب شاید بگید مدل‌های مثل Gemini که یک میلیون توکن ورودی می‌گیرن چطور؟ مشکل اینه وقتی مدل با حجم عظیمی از داده روبرو می‌شه، عملاً در اطلاعات غرق می‌شه. این اتفاق باعث می‌شه که از یک طرف، فرآیند تحلیل به شدت کند و گران تموم بشه و از طرف دیگه، کیفیت جواب‌ها افت کنه. مدل یا مسئله رو خیلی کلی و سطحی حل می‌کنه که به دردمون نمی‌خورد، یا کاملاً گیج می‌شه و شروع می‌کنه به «هذیان‌گویی» (Hallucination) و بافتن کلمات بی‌ربط به هم.راه حل ما دقیقاً برای رفع همین مشکل بزرگ بودن ابعاد پروژه‌ها طراحی شد. به جای اینکه هر بار مدل رو در این فرآیند ناقص غرق کنیم، با یک بار تحلیل جامع و عمیق، اکثریت کانتکست مورد نیازش رو استخراج کنیم و در یک «حافظه پایدار» براش نگهداری کنیم. به این ترتیب، هوش مصنوعی همیشه پیش‌زمینه لازم برای ارائه پاسخ‌های دقیق، سریع و به مراتب کم‌هزینه‌تر رو در اختیار داره.از طرفی هم این مسئله، مسئله‌ی بزرگ و سختیه! پرسیدن &quot;کل این کدبیس رو توضیح بده&quot; از هوش‌مصنوعی، مثل اینه که از تازه‌وارد تیم بخواید تو پنج دقیقه ته این سرویس رو دربیاره! خب در نمیاد! منطقا باید پروژه رو به چند تیکه مشخص و قابل مدیریت خرد کرد. اینکه توی یه حرکت بشه کل پروژه رو نگاه کرد و همچی یادت بمونه، نشدنیه.پس رفتیم سراغ اینکه سعی کنیم مسئله رو بشکونیم، و هر مسئله روی بخشی از سوال متمرکز باشه. اینطوری Agentهای مختلفی می‌سازیم که روی بخشی از حل مسئله متمرکزن.رویکرد Multi-Agentبرای حل مسئله، اول با این شروع کردیم که اگر جای LLM واقعا یک انسان داشتیم چطور این مسئله‌ رو حل می‌کرد؟ براساس همین طرز فکر به این پنج تا ایجنت رسیدیم:۱.Structure Agent: اولین قدم برای هر توسعه‌دهنده شناخت معماری پروژه‌اس. از ساختار ماژول‌ها و اینترفیس‌ها بگیر تا متودهای مهم و پترن‌های پروژه. این Agent، الگوهای معماری رو پیدا می‌کنه، روابط اجزای مختلف رو شرح می‌ده و ساختار کلی پروژه رو مستندسازی می‌کنه — همون چیزی که معمولاً روزها طول می‌کشه تا مستند کاملی ازش درست کنیم.۲. Data Flow Agent: مرحله بعدش، دنبال کردن جریان داده تو پروژه‌‌اس. معمولا توی هر پروژه، کلی داده داریم که از یه جایی تولید می‌شن و توی سیستم می‌چرخن. یه تغییری می‌کنن و تهش سر از یجای دیگه درمیارن. این Agent رد پای دیتا رو از مدل‌ها، Transformationها، دیتابیس‌ها و غیره می‌گیره و چرخه تغییر داده رو، سعی می‌کنه توضیح بده.۳. Request Flow Agent: حالا باید بفهمیم وقتی درخواستی به سیستم می‌رسه، مثلا وقتی یک اندپوینت HTTP یا RPC صدا زده میشه، چطوری به سیستم می‌رسه، چه اعتبارسنجی‌هایی روش انجام می‌شه و چطوری توی سیستم مسیریابی میشه تا به جای خاصی برسه و … . این Agent کل مسیر درخواست رو از سر تا ته قضیه مستند می‌کنه.۴. Dependency Agent: تهشم، باید Dependencyها رو بسنجیم. اینکه سیستم ما چه وابستگی‌های داخلی و خارجی‌ای داره، به چه سرویسی ریکوئست میزنه، چه پکیج‌هایی استفاده کرده و … .این Agent نه‌تنها وابستگی‌ها رو لیست می‌کنه، بلکه مشکلاتشون، Circular Dependency، و ... رو هم می‌سنجه — تفاوت بین یه pip freeze ساده با شناخت بهتر از وابستگی‌هات.۵. API Agent: این Agent از دل دستیارهای داخلی‌امون درومد. موقعی که دیدم خیلی از توسعه‌دهنده‌ها، سوال‌هایی مثل &quot;چطور این endpoint رو دستی کال کنم؟&quot;یا &quot;ریسپانس خروجی این endpoint چیه؟&quot; رو می‌پرسند. کارش هم ساده‌اس. پیدا کن چه APIهایی رو سرویس serve می‌کنه یا کجاها رو کال میکنه. اینا رو مستند کن.نکته طلایی: LLMها و AIرو مثل برنامه‌نویس‌ها و آدم‌ها نگاه کن. مشکل رو همونطوری حل کن که توسعه‌دهنده‌ی حرفه‌ای حل می‌کنه. هر Agent یک دیدگاهی داره، و ترکیب‌شون همون روالی رو بازسازی می‌کنه که ما به‌شکل انسانی انجام می‌دیمخروجی واقعی: context بهتر برای همهتو خونه‌ی اول این داک‌ها رو برای دستیارهای هوشمند داخلی خودمون آماده‌سازی کردیم. این دستیارها برای فهم پروژه دیگه کافی بود Readme و AI Docها رو بخونن و درجا سراغ تحلیل مستقیم کد نرن. ساختار داک رو جوری طراحی کردیم که هم خواندنش برای آدم راحت باشه، هم برای AI به شکل ساختارمند و مناسب استفاده بشه.مثلاً وقتی دستیار کدمون باید جواب بده &quot;کدوم سرویس مسئول احراز هویت کاربره؟&quot;، اول سراغ مستندهای apiامون می‌ره، بعد اگر نشد سراغ کدها و ... . عملا این داک‌ها نقش مکانیزم کشف (discovery) برای AI رو همزمان بازی می‌کنه.ولی اونجا جالب‌تر شد که ابزارهایی مثل Copilot، Claude و ChatGPT هم جواب‌های دقیق‌تر، مرتبط‌تر و کاربردی‌تر تولید کردن. چون context (پیش زمینه‌) رو از داک‌ها می‌خوندن و می‌تونستن براساس واقعیت پروژه، پیشنهاد بدن.در اصل این بخشی از همون چیزیه که بهش میگن Context Engineering. یه سیستم که میتونه دیتای مورد نیاز AI Agentها رو در زمان مناسب بهشون برسونه.واقعیت فنیساختن این سیستم فقط چند خط پرامپت نبوده، معماری باید هم ساده و هم مطمئن طراحی می‌شد.تصمیم گرفتیم که فریم‌ورک‌های موجود رو بررسی کنیم و ببینیم چیا ترند هستن. منطقا دوس نداشتیم دوباره از اول خیلی چیزا رو اختراع کنیم و تا جای ممکن می‌خواستیم زمانمون رو روی پرامپت‌نویسی و سیم‌کشی بین Agentها بذاریم تا پیاده‌سازی‌های پایه‌ای.طبق ستاره‌های گیت‌هاب، CrewAI جزو فریم‌ورک‌های برتر AI بود. بعد خوندن داک و مثال‌هایی که داشت، بنظر می‌اومد که می‌تونه کار ما رو خوب راه بندازه. اینکه از ابتدا با ذهنیت MultiAgent (Crew) ساخته شده، برای ایجنت‌ات یه سری کانسپت ساده مثل Role, Backstory و Goal تعریف میکنه تا راحت‌تر پرامپت رو بنویسی، و از همون اول مجموعه‌ای از ابزارهای از پیش آماده داره، باعث می‌شد که آپشن خوبی بنظر بیاد.ماجرای CrewAIاول همه‌چیز رو با CrewAI پیاده کردیم. در ظاهر می‌توانی role و crew agentهای مختلف بسازی، بقیه orchestration رو خودش انجام می‌ده. ولی در عمل این مشکلات رو داشت:تفت‌دادن پرامپت‌ها: CrewAI پرامپت‌ها رو با قالب خودش قاطی می‌کرد، همه دقت و ظرافت پرامپت‌نویسی رو از بین می‌برد.مشکلات Parse کردن ریسپانس: کلی ارور ‍‍‍‍Invalid response from LLM call - None or empty، مخصوصاً روی مدل‌هایی غیر از OpenAI.کال‌های ناقص: taskها نصفه‌کاره می‌پریدن بیرون، بعدشم باید دستی ادامه می‌دادی.کنترل ناقص: نمی‌تونستی کنترل کنی که یه تسک کی تموم بشه، یا بعضا انقدر ادامه پیدا می‌کرد تا به لیمیت برسه.مشاهده‌پذیری پایین: به خودی خود، خیلی چیزی لاگ نمی‌کرد و مجبور بودی کلی Middleware براش توسعه بدی.پس هم کنترل پرامپت رو از دست می‌دادی و هم Parse کردن ریسپانس غیرقابل پیش‌بینی بود. کلی پرامپت رو تنظیم می‌کردی و آخرش، خروجی خراب می‌شد! خلاصتا بعد از چندماه دست و پا زدن و نتیجه قابل اتکا نگرفتن، تصمیم گرفتیم که بازنویسی بکنیم سیستم رو. این دفعه، با توجه به تجربه‌ی یکی دیگه از تیم‌ها و توضیحات آدم‌ها توی ردیت و بلاگ‌پست‌ها، به Pydantic-AI رسیدیم.چرا Pydantic-AI برنده شد؟(چپ به راست شو) Pydantic-AI، برعکس CrewAI اصلاً کنترل داشتن روی رفتار و دیباگش رو پیچیده‌ نمی‌کنه؛ همچی رو شفاف و ساده و بدون افراط نگه‌ می‌داره. اینطور می‌شه فهمید هر مشکلی از کجاست، نه اینکه شاید Crew AI پرامپت‌هاش با خواسته‌ی ما تناقض داره. همچنین تعریف Agent جدید و پرامپتشون ساده‌ است و پرامپت‌ها دستکاری نمی‌شن. و درسته که ابزارهای از پیش آماده نداره، اما پیاده‌سازی ابزار توش ساده‌اس و tool callهای بهتری داره. و مهم‌تر اینکه کانتکست تسک‌هات باهم قاطی نمی‌شن و مستقل از هم کار می‌کنن.همینطور ما خیلی بیشتر می‌تونستیم بهش اعتماد کنیم. parsing errorها حذف شد و اعتبارسنجی‌هایی که انجام می‌داد باعث می‌شد خروجی ریسپانس LLM همیشه مطابق اون ساختاری که ازش خواستیم باشه و اگر نبود، agent خودش اتومات دوباره امتحان می‌کرد و کل تحلیل دود نمی‌شد. همچنین روی ایجنت‌ها و کارهات تسلطی که داشتی هم خیلی بیشتر بود. لیمیت‌های مختلف، ریترای‌های دقیق‌تر به ازای هر چیزی، محدود کردن توکن‌های مورد استفاده و مشاهده‌پذیری بهتر.Prompt Engineering به سبک مهندسییکی دیگه از کارهای مهم‌امون این بود که با پرامپت‌ مثل کد برخورد کردیم! به‌جای هاردکد کردن پرامپت‌ها وسط کد، با قالب‌سازی و توی یه فایل yaml نگهداریشون کردیم. (اینجا از Jijna2 استفاده کردیم). این باعث شد:همه می‌تونستن مشارکت کنن: لازم نبود حتماً توسعه‌دهنده باشی تا پرامپت رو پیدا کنی و تغییر بدی. ساختارش ساده بود و تغییرش هم ساده.ورژن کنترل: تمام تاریخچه تغییرات پرامپت‌ها قابل‌دیدن بودن. از طرفی بررسی یه نفر دیگه هم برای انتشار نهایی حتما لازم بود.تغییرپذیری: قالب و متن هر پرامپت براساس ورودی و context منعطف بود و می‌تونست تغییر کنه.نگهداری: پرامپت‌هامون اینور اونور پروژه ریشه نزده و یک‌جا میشه خوند و فهمید چی‌ان.تجربه نشون داد تو پروژه‌های AI، اهمیت پرامپت معمولا از خود کد بیشتره! و باید با همون فرهنگ مهندسی مدیریت بشه.مسئله ارزیابیکلاً تولید هرچیزی با AI یک سوال اساسی داره: از کجا بفهمیم خروجی قابل‌قبوله؟اولش مسئول هر پروژه، داک‌های تولیدی‌امون رو برای پروژش رو چک می‌کرد و بازخورد می‌داد. خوب بود، ولی scale نمی‌شد و با زیاد شدن تعداد پروژه‌ها، باید با آدم‌های بیشتری تعامل می‌کردیم و کار فرسایشی، طولانی و سخت می‌شد. باید روال ساده‌تری پیدا می‌کردیم.برای اینکه ارزیابی راحت‌تری داشته باشیم، گفتیم با این داک‌ها، بیایم Readmeهای بامعنا و جامعی برای هر پروژه درست کنیم. این چندتا فایده داشت برامون، یکی اینکه خیلی از پروژه‌ها Readme درست و درمون نداشتن و لازم بود اپدیت بشن و هم اینکه خوندن یه Readme و ارزیابی‌اش، خیلی ساده‌تر از خوندن کلی داک بود. از طرفی، کلی پروژه هم داشتیم که Readmeهای خوبی داشتن (چه پروژه متن‌باز چه پروژه داخلی) و می‌تونستیم با همونا هم چک کنیم که چقدر خروجی‌هامون درسته. پس اینطوری همون اول کار، یه سری معیار آماده هم برای ارزیابی سیستمون داشتیم. از طرفی دیگه، می‌تونستیم Readmeهای دقیق‌تر و مفیدتری هم از چیزهای جنرال برای خودمون بنویسیم. از اینکه یه توضیح کلی از پروژه بده شروع می‌شد تا جایی که Request Flow و C4 Model و … رو توی Readme می‌ذاشت و رودمپ پروژه رو بهمون توضیح می‌داد.پس عملا نوشتن README برامون یه متر خوب شد: اگر درست و شفاف کار پروژه و معماری و راه استفاده رو توضیح می‌داد، می‌فهمیدیم تحلیل درست بوده.نتایج واقعیتوی چند ماه استفاده روی پروژه‌های داخل شرکت:فرایند Onboarding سریع‌تر شد: توسعه‌دهنده‌های تازه‌ای که چند هفته‌ی اول رو درگیر آشنایی با پروژه‌های مختلف و ... بودن، خیلی سریع‌تر و توی یه روز، ساختار و معماری پروژه‌ها رو فهمیدن.زیرخاکی‌ها پیدا شدن: مثلاً یک سرویس هنوز از API منسوخ استفاده می‌کرد که همه یادشون رفته بود. از طرفی هم یه سری پترن‌های پروژه‌ها هم بالاخره مکتوب شد.اتصال GitLab: یه کرون‌جاب که هرهفته اجرا می‌شه، هر ریپویی که تغییر جدید داره، آنالیز میشه و داکش آپدیت میشه. هر هفته ۵۰+ پروژه‌ داریم که داک‌هاشون آپدیت میشن ــ بدون هیچ زحمت مستندسازی دستی‌ای!AIها بهتر شدند: Copilot و Claude براساس context واقعی تیم و پروژه، کد و خروجی می‌دادند.آیا واقعاً می‌ارزید؟برای شروع روی چند سرویس قدیمی و حتی متروکه تست کردیم. پروژه‌هایی که توسعه‌دهنده اصلی رفته، README قدیمیه و داک وجود نداره. هر کی بخواد تغییری بده باید کلی وقت بذاره تا بفهمه چی به چیه، و نتیجه خیلی برامون جذاب بود! داک‌های جدید، این سرویس‌ها از &quot;جعبه سیاه&quot; تبدیل شدن به سیستم‌های شناخته‌تر شده. کار توسعه جدید رو این سرویس‌ها کلی جلو افتاد و راحت تر شد!یه اتفاق خوب دیگه‌ای که افتاد این بود وقتی سیستمی نوشتیم که کل پروژه‌های شرکت رو دوره‌ای تحلیل کنه و توی یک پوشه توی خود پروژه بریزه، دیگه حتی ابزار‌های تولید کد با AI، مثل Cursor و Aider، خیلی بهتر پروژه رو می فهمید و می تونست کد‌های درست، با کیفیت بالاتر، و مطابق استاندارد‌ها بزنه، اونم با هزینه‌ی کمتر! چون نیاز به کل پروژه برای فهم پروژه نیست.خبر خوب اینکه دیوار تصمیم گرفته این پروژه رو اوپن سورس کنه و اگه کد پروژه رو می‌خواید ببینید یا اجراش کنید، اینجا کلیک کنید.</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Sat, 26 Jul 2025 19:20:17 +0330</pubDate>
            </item>
                    <item>
                <title>دیوار در محاصره محدودیت اینترنت: تحلیلی از پیامدهای قطعی‌ و ناپایداری اینترنت</title>
                <link>https://virgool.io/@divar/%D8%AF%DB%8C%D9%88%D8%A7%D8%B1-%D8%AF%D8%B1-%D9%85%D8%AD%D8%A7%D8%B5%D8%B1%D9%87-%D9%85%D8%AD%D8%AF%D9%88%D8%AF%DB%8C%D8%AA-%D8%A7%DB%8C%D9%86%D8%AA%D8%B1%D9%86%D8%AA-%D8%AA%D8%AD%D9%84%DB%8C%D9%84%DB%8C-%D8%A7%D8%B2-%D9%BE%DB%8C%D8%A7%D9%85%D8%AF%D9%87%D8%A7%DB%8C-%D9%82%D8%B7%D8%B9%DB%8C-%D9%88-%D9%86%D8%A7%D9%BE%D8%A7%DB%8C%D8%AF%D8%A7%D8%B1%DB%8C-%D8%A7%DB%8C%D9%86%D8%AA%D8%B1%D9%86%D8%AA-mtglzelxe09l</link>
                <description>اختلالات و قطعی‌های پی‌درپی اینترنت جهانی، دیگر یک مشکل فنی ساده نیست؛ بلکه به نظر می‌رسد نتیجه‌ سیاست‌گذاری‌های سیستماتیکی است که در حال تخریب زیرساخت‌های اقتصادی و اجتماعی کشور است. در این گزارش، ما به تحلیل پیامدهای عمیق و کمتر دیده شده‌ این فروپاشی می‌پردازیم. این رویکرد نه تنها کسب‌وکارهایی مانند دیوار را به‌شدت متأثر می‌کند، بلکه یادگیری، آموزش و پایه‌های رشد سرمایه انسانی کشور را نیز مختل می‌سازد؛ همان‌هایی که ستون‌های اصلی توسعه شرکت‌هایی چون دیوار در سال‌های آتی هستند.چرا قطعی اینترنت به قلب اقتصاد دیجیتال حمله می‌کند؟اولین و ملموس‌ترین قربانی، اقتصاد دیجیتال است. بر اساس برآوردهای نهاد ناظر بین‌المللی «نت‌بلاکس»، هر ساعت قطعی کامل اینترنت در ایران، خسارتی بالغ بر ۱.۵ میلیون دلار به اقتصاد کشور تحمیل می‌کند. اما این آمار، تنها نوک کوه یخ است. این عدد، زیان انباشته ناشی از بی‌اعتمادی مشتریان، نابودی کمپین‌های بازاریابی دیجیتال که با هزینه‌های گزاف طراحی شده‌اند و توقف چرخه ارتباط با مشتری را محاسبه نمی‌کند.کسب‌وکارهای مبتنی بر شبکه‌های اجتماعی که معیشت صدها هزار خانوار را تامین می‌کردند، در خط مقدم این آسیب قرار دارند. اما بحران به مراتب بزرگ‌تر از چند فروشگاه آنلاین است. شرکت‌های بزرگ فناوری کشور نیز که سال‌ها برای ایجاد زیرساخت‌های فروش آنلاین، لجستیک و خدمات دیجیتال سرمایه‌گذاری کرده‌اند، با کاهش ترافیک ورودی و ناتوانی در ارائه خدمات پایدار، با فرسایش سرمایه و ریزش نیروی انسانی متخصص مواجه شده‌اند. این وضعیت، به معنای مرگ تدریجی محصولات دیجیتالی است که خود حاصل توسعه اینترنت در دهه گذشته بود.تهدیدات سایبری و از دست رفتن اعتماد عمومیدر لایه‌ای پنهان‌تر و به مراتب خطرناک‌تر، محدودیت‌های اینترنتی کشور را در برابر تهدیدات سایبری جهانی، بی‌دفاع کرده است. زیرساخت‌های دیجیتال یک کشور، از سرورهای یک بانک گرفته تا پلتفرم‌های خدماتی و دستگاه‌های کاربران برای حفظ امنیت خود نیازمند دریافت مداوم «به‌روزرسانی‌های امنیتی» (Security Patches) از شرکت‌های توسعه‌دهنده در سراسر جهان هستند. این به‌روزرسانی‌ها، حفره‌های امنیتی جدیدی را که توسط هکرها کشف می‌شوند، ترمیم می‌کنند.با قطع ارتباط با سرورهای بین‌المللی، این فرایند حیاتی متوقف می‌شود. این یعنی سرورها یا رایانه‌های شخصی‌ ایرانی، با نرم‌افزارهایی که حفره‌های امنیتی شناخته‌شده دارند، به فعالیت خود ادامه می‌دهند و به سیبل‌های ثابت برای حملات باج‌افزاری، سرقت یا نشت داده‌ها (Data Breach) و عملیات خرابکارانه بدل می‌شوند. در حقیقت، ما با پدیده‌ای به نام «خودتحریمی امنیتی» مواجه هستیم؛ وضعیتی که در آن، یک کشور با دست خود، سپرهای دفاعی‌اش را پایین می‌آورد و اطلاعات شهروندان و پایداری خدماتش را در معرض ریسکی غیرقابل محاسبه قرار می‌دهد. این آسیب، برخلاف زیان اقتصادی، در کوتاه‌مدت قابل اندازه‌گیری نیست، اما می‌تواند در بلندمدت خساراتی جبران‌ناپذیر به اعتماد عمومی و حاکمیت دیجیتال کشور وارد کند.مرگ مغزی هوش مصنوعی و توقف نوآوریبسیاری از سرویس‌های هوشمندی که امروزه ستون فقرات پلتفرم‌های بزرگ ایرانی را تشکیل می‌دهند، برای پردازش حجم عظیم داده‌ها و اجرای الگوریتم‌های پیچیده، به سرویس‌های ابری بین‌المللی وابسته‌اند.برای مثال، سیستم‌های پیشرفته «تشخیص تقلب و کلاهبرداری» در پلتفرم‌های آگهی‌محور مانند دیوار، برای تحلیل الگوهای مشکوک و محافظت از کاربران، از مدل‌های هوش مصنوعی بهره می‌برند که نیازمند ارتباط دائم با این زیرساخت‌های جهانی هستند. با مسدود شدن پروتکل‌های ارتباطی، این سیستم‌ها دچار «مرگ مغزی» می‌شوند؛ اپلیکیشن کار می‌کند، اما مغز متفکر و تحلیلگر آن از کار افتاده است. این امر نه تنها بهره‌وری را به‌شدت کاهش می‌دهد و کیفیت خدمات را پایین می‌آورد، بلکه راه را برای افزایش کلاهبرداری و مزاحمت‌های دیجیتال هموار می‌سازد و به سوءاستفاده‌های غیرقانونی از پلتفرم‌ها دامن می‌زند، در نتیجه ارزش افزوده آن‌ها را کاهش می‌دهد. این محدودیت‌ها به مرور باعث عقب‌ماندگی فزاینده محصولات ایرانی نسبت به معادل‌های خارجی شده و به رنج مردم و کاربران می‌انجامد.بن‌بست دوگانه؛ میان چکش تحریم و سندان فیلترینگطنز تلخ ماجرا در این است که جامعه فناوری ایران سال‌هاست که با «تحریم‌های بین‌المللی» دست و پنجه نرم می‌کند. بسیاری از کتابخانه‌های برنامه‌نویسی، ابزارهای توسعه نرم‌افزار و پلتفرم‌های حیاتی، دسترسی کاربران با IP ایران را مسدود کرده‌اند. تنها راه بقا و تنفس متخصصان ایرانی در این فضای تحریمی، استفاده از ابزارهای دور زدن محدودیت‌ها، مانند شبکه‌های خصوصی مجازی (VPN) و تانل‌های ارتباطی، برای دسترسی به دانش و ابزار روز دنیا بوده است.اکنون، سیاست‌های محدودساز داخلی، با مسدودسازی گسترده‌ پروتکل‌های ارتباطی رایج، همان روزنه‌های باریک را نیز مسدود کرده است. شرکت‌ها و متخصصان ایرانی در یک «بن‌بست دوگانه» گرفتار شده‌اند: از یک سو، توسط جهان خارج تحریم هستند و از سوی دیگر، ابزارهای مقابله با آن تحریم‌ها توسط سیاست‌گذاری داخلی از آن‌ها گرفته شده است. این وضعیت، عملاً به معنای قطع کامل ارتباط جامعه علمی و فنی کشور با اکوسیستم جهانی و تسریع فرآیند فرار مغزها و سرمایه‌هاست.فرسایش سرمایه انسانی و آینده‌ سترونشاید راهبردی‌ترین آسیب این اتفاقات، نه در «حال»، که در «آینده» نمایان شود: فرسایش سرمایه انسانی. اینترنت برای نسل جوان ایران، یک دانشگاه موازی و خودآموز بود؛ پلی که شکاف ناشی از تحریم‌ها را با اتصال مستقیم به منابع دانش جهانی، از مقالات علمی گرفته تا دوره‌های آموزشی و پروژه‌های متن‌باز، پر می‌کرد.سیاست انسداد، این شریان حیاتی یادگیری را قطع کرده و فرآیند «تولید و به‌روزرسانی دانش» را در کشور متوقف می‌کند. این امر مستقیماً حیات شرکت‌های نوآور مانند دیوار را تهدید می‌کند که سوخت اصلی‌شان نه منابع دولتی، بلکه «سرمایه انسانی متخصص» است. وقتی مسیر تربیت و به‌روزرسانی چنین نیرویی مسدود شود، موتور نوآوری کشور از حرکت باز می‌ایستد و این شرکت‌ها در میان‌مدت با بحران نیروی کارِ همگام با فناوری روز دنیا مواجه خواهند شد.در واقع، این سیاست بیش از آنکه به کسب‌وکار امروز لطمه بزند، با عقیم‌سازی فکری نسلی که باید آینده را بسازد، زمینِ نوآوریِ فردا را شخم می‌زند.انتخاب میان انزوا و اتصالآنچه امروز در ایران رخ می‌دهد، یک اختلال موقت در اینترنت نیست؛ بلکه یک دگرگونی در نگرش به جهان دیجیتال است. این سیاست‌ها اینترنت را از یک «ابزار توسعه» به یک «مظنون امنیتی» همیشگی بدل کرده است. کالبدشکافی این پدیده نشان می‌دهد که زخم‌های آن بسیار عمیق‌تر از آن چیزی است که در سطح جامعه احساس می‌شود و تمام ابعاد اقتصادی، امنیتی، علمی و اجتماعی کشور را تحت تأثیر قرار داده است. ادامه این مسیر، نه تنها به انزوای دیجیتال، بلکه به یک عقب‌گرد تاریخی در توسعه‌یافتگی ایران منجر خواهد شد. اکنون کشور بر سر یک دوراهی تاریخی ایستاده است: انتخاب میان بازگشت به جهان متصل به اینترنت یا فرورفتن در یک جزیره دیجیتالِ ایزوله، آسیب‌پذیر و رو به زوال. تصمیم امروز، سرنوشت فردای ایران را رقم خواهد زد.</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Tue, 08 Jul 2025 16:06:12 +0330</pubDate>
            </item>
                    <item>
                <title>سفر تکامل نقشه‌ی دیوار: داستان مهندسی پشت نمایش هوشمند میلیون‌ها آگهی</title>
                <link>https://tech.divar.ir/سفر-تکامل-نقشه-ی-دیوار-داستان-مهندسی-پشت-نمایش-هوشمند-میلیون-ها-آگهی-bhwoaodprld6</link>
                <description>وقتی به دنبال خانه یا ملک می‌گردید، «کجا بودن» آن شاید اولین و مهم‌ترین سؤالی باشد که به ذهنتان می‌رسد. در پلتفرمی مثل دیوار که روزانه هزاران آگهی املاک در آن ثبت می‌شود، نمایش این حجم از اطلاعات مکانی به شکلی کارآمد و قابل فهم، یک چالش بزرگ است. ما در دیوار مسیری پر فراز و نشیب را برای بهبود نمایش آگهی‌ها روی نقشه طی کرده‌ایم؛ از نمایش ساده‌ی نقطه‌ای تا سیستم‌های هوشمند کلاستربندی داینامیک. این مقاله داستان این تکامل فنی و تصمیم‌هایی است که در این راه گرفته‌ایم. هدف ما نه تنها ارائه‌ی یک تجربه‌ی کاربری روان، بلکه ساخت زیرساختی پایدار و مقیاس‌پذیر برای آینده‌ی نقشه‌ی دیوار بوده است.چرا نقشه؟ نیاز به درک بصری موقعیتدر ابتدا، آگهی‌های املاک در دیوار، مانند سایر دسته‌بندی‌ها، به صورت لیستی نمایش داده می‌شدند. اما ماهیت جستجوی ملک با جستجوی کالاهای دیگر متفاوت است. کاربران نیاز دارند به سرعت موقعیت چندین آگهی را نسبت به هم و نسبت به نقاط مهم شهری بسنجند. نمایش لیستی، هرچقدر هم که با فیلترهای دقیق همراه باشد، نمی‌تواند این درک بصری و مقایسه‌ای را به خوبی یک نقشه ارائه دهد. همین نیاز بود که ما را به سمت استفاده از نقشه برای نمایش آگهی‌های املاک سوق داد. می‌خواستیم به کاربران کمک کنیم تا با یک نگاه، پراکندگی آگهی‌ها را در مناطق مختلف ببینند، گزینه‌های نزدیک به محل کار یا زندگی خود را پیدا کنند و در نهایت، تصمیم آگاهانه‌تری بگیرند.اولین قدم برای ساخت نقشه!برای پیاده‌سازی نقشه، ما از کتابخانه‌ی Mapbox استفاده کردیم. Mapbox یک کتابخانه‌ی قدرتمند برای ساخت و نمایش نقشه‌های تعاملی است که ابزارهای متنوعی را در اختیار توسعه‌دهندگان قرار می‌دهد. در ابتدا، مهندسین بلد که تازگی به دیوار اضافه شده بودند، در یک محصول کاملاً جداگانه و خارج از لیست اصلی دیوار، نمونه‌ی اولیه‌ای از نقشه را با استفاده از Mapbox پیاده‌سازی کرد.یکی از اولین چالش‌های ما، نحوه‌ی نمایش و ایندکس کردن آگهی‌ها بود. تا آن زمان، بیشتر سیستم‌های ما بر اساس «زمان» آگهی‌ها کار می‌کردند؛ یعنی آگهی‌های جدیدتر در اولویت نمایش قرار می‌گرفتند. اما برای نقشه، «مکان» اهمیت اصلی را دارد، و بعد از آن زمان انتشار آگهی. بنابراین، باید به سمت «ایندکس جغرافیایی» (Geographical Indexing) حرکت می‌کردیم. خوشبختانه، داده‌های مکانی آگهی‌ها (طول و عرض جغرافیایی) در Elasticsearch ذخیره می‌شدند و Elasticsearch ابزارهای بسیار خوبی برای جستجو و فیلتر کردن داده‌های مکانی ارائه می‌دهد. با تعریف یک فیلتر ساده، توانستیم آگهی‌های موجود در یک محدوده‌ی جغرافیایی مشخص را استخراج کنیم.از «تایل»های استاتیک تا «ویوپورت» داینامیکدر نسخه‌های اولیه‌ی نقشه، ما از مفهومی به نام «تایل» (Tile) در Mapbox استفاده می‌کردیم. تایل‌ها در واقع قطعات مربعی کوچکی از نقشه هستند. Mapbox به این صورت کار می‌کند که شما یک URL پایه به آن می‌دهید و Mapbox با توجه به موقعیت فعلی نقشه و سطح بزرگنمایی (Zoom Level)، مقادیر x، y (مختصات تایل) و z (سطح زوم) را در آن URL قرار می‌دهد و درخواست را به سرور ارسال می‌کند. سرور باید آگهی‌های مربوط به آن تایل خاص را برگرداند و Mapbox آن‌ها را روی نقشه نمایش می‌دهد. Mapbox همچنین این تایل‌ها را در سمت کلاینت نگه می‌دارد تا در اگر کاربر مجدد دوربین را روی ان تایل‌ها برد، مقدار قدیمی را نشان دهد و هم‌زمان درخواست برای دریافت مقدار جدید بزند.این روش مزایایی مانند سادگی پیاده‌سازی و سرعت اولیه دارد. اما یک مشکل اساسی هم ایجاد می‌کرد: کنترل ما بر روی نمایش آگهی‌ها محدود بود. وقتی کاربر کمی نقشه را جابجا می‌کرد یا زوم می‌کرد، اگر محدوده‌ی جدید همچنان در تایل‌های کش‌شده قرار داشت، تایل‌های جدیدی از سرور درخواست نمی‌شد. یعنی در صورت تغییر خیلی کم در مکان دوربین یا تغییر کم زوم دوربین، با اینکه تعداد آگهی‌های نمایشی در گوشی کاربر عوض می‌شد، اما ریکوئست جدیدی به بک‌اند ارسال نمی‌شد و این باعث می‌شد تعداد آگهی‌هایی که ما به عنوان شمارش کلی در یک منطقه نشان می‌دادیم با تعداد پین‌های واقعی روی نقشه همخوانی نداشته باشد. چون تعدادی از پین‌ها خارج از دید نقشه بودند. به عبارت دیگر، داده‌ها «استاتیک» (Static) بودند و به صورت لحظه‌ای با تغییرات کوچک کاربر آپدیت نمی‌شدند.برای حل این مشکل و داشتن کنترل کامل بر نمایش داده‌ها، به سراغ پیاده‌سازی «ویوپورت» (Viewport) رفتیم. بسیاری از پلتفرم‌های مشابه نیز از این روش استفاده می‌کنند. در روش ویوپورت، به جای تکیه بر تایل‌های مجزا، ما کل محدوده‌ی قابل مشاهده‌ی نقشه در نمایشگر کاربر را در نظر می‌گیریم. هر بار که کاربر نقشه را جابجا می‌کند یا سطح زوم را تغییر می‌دهد، یک درخواست جدید به سرور ارسال می‌شود که حاوی مختصات دقیق ویوپورت فعلی است. سرور نیز دقیقاً آگهی‌هایی را که در آن محدوده قرار دارند، برمی‌گرداند. با این روش، داده‌ها همیشه «داینامیک» (Dynamic) و دقیق هستند و ما کنترل کاملی بر نحوه‌ی نمایش و تعداد آگهی‌ها داریم.چالش حجم زیاد آگهی‌ها: راه حل «کلاسترینگ»پس از پیاده‌سازی ویوپورت، با چالش جدیدی روبرو شدیم: حجم زیاد آگهی‌ها. تصور کنید کاربر در حال مشاهده‌ی نقشه‌ی شهری بزرگ مانند تهران از فاصله‌ی دور است. در این حالت، هزاران آگهی در ویوپورت کاربر قرار می‌گیرند. اگر بخواهیم همه‌ی این آگهی‌ها را به صورت پین‌های مجزا نمایش دهیم، نقشه به سرعت با انبوهی از نقاط قرمز پوشیده می‌شود و عملاً غیرقابل استفاده خواهد بود. از طرفی، اگر تعداد پین‌ها را به یک عدد ثابت (مثلاً ۱۰۰ یا ۲۰۰) محدود کنیم، بسیاری از آگهی‌ها نمایش داده نمی‌شوند و کاربر دید درستی از تراکم آگهی‌ها در مناطق مختلف پیدا نمی‌کند.راه حل این مشکل، استفاده از تکنیکی به نام «کلاسترینگ» (Clustering) یا خوشه‌بندی بود. ایده‌ی اصلی کلاسترینگ این است که به جای نمایش تعداد زیادی پین نزدیک به هم، آن‌ها را در یک «کلاستر» یا خوشه گروه‌بندی کنیم و به جای چندین پین، یک نشانگر واحد (معمولاً همراه با تعداد آگهی‌های آن خوشه) نمایش دهیم. وقتی کاربر روی یک کلاستر زوم می‌کند، آن کلاستر باز شده و پین‌های داخل آن یا کلاسترهای کوچکتر نمایان می‌شوند.آشنایی با دنیای کلاسترینگ: مفاهیم و روش‌هابرای پیاده‌سازی کلاسترینگ، باید چندین مرحله را طی می‌کردیم و در هر مرحله، تصمیم‌های فنی مهمی می‌گرفتیم. ابتدا برخی مفاهیم کلیدی را مرور می‌کنیم:تایل (Tile): در نقشه‌های دیجیتال، تایل‌ها بخش‌های مربعی کوچکی از نقشه هستند که با کنار هم قرار گرفتن، نمای کلی نقشه را تشکیل می‌دهند. این تقسیم‌بندی به بارگذاری سریع‌تر و کارآمدتر نقشه‌ها کمک می‌کند.پالیگان (Polygon): یک محدوده‌ی جغرافیایی بسته روی نقشه (مانند یک شهر یا محله).اچ۳ (H3): یک سیستم شبکه‌بندی جغرافیایی که سطح زمین را به شش‌ضلعی‌های منظم تقسیم می‌کند. این سیستم توسط اوبر توسعه داده شده و برای تحلیل داده‌های مکانی بسیار مفید است.کلاسترینگ استاتیک (Static Clustering): کلاستر‌ها و مراکز‌ آنها از پیش تعیین شده و ثابت هستند (مثلاً بر اساس محله‌ها).کلاسترینگ داینامیک (Dynamic Clustering): مراکز کلاسترها بر اساس توزیع لحظه‌ای آگهی‌ها در ویوپورت کاربر محاسبه می‌شوند.مراحل اصلی پیاده‌سازی کلاسترینگ عبارت بودند از:۱.  تهیه‌ی پالیگان‌های مبنا: باید تصمیم می‌گرفتیم که کلاسترها بر اساس چه واحدهای جغرافیایی شکل بگیرند. گزینه‌ها شامل استفاده از سیستم‌های گریدبندی منظم مانند تایل‌های خود نقشه یا سلول‌های H3، یا استفاده از پالیگان‌های نامنظم بر اساس توزیع واقعی آگهی‌ها یا تقسیمات جغرافیایی موجود (مانند شهرها و محله‌ها) بود. هر کدام مزایا و معایب خود را داشتند؛ مثلاً گریدهای منظم پوشش کاملی ارائه می‌دهند اما ممکن است مرکزشان با تراکم واقعی آگهی‌ها همخوانی نداشته باشد.۲.  شمارش آگهی‌ها در هر پالیگان: پس از مشخص شدن پالیگان‌ها، باید تعداد آگهی‌های (فیلتر شده) موجود در هرکدام را از Elasticsearch استخراج می‌کردیم. اینجا هم دو رویکرد اصلی وجود داشت: ۱.مالتی‌سرچ (Multi-Search): برای هر پالیگان یک درخواست شمارش جداگانه به Elasticsearch ارسال کنیم و نتایج را تجمیع کنیم.  ۲.اگریگیشن (Aggregation): از قابلیت‌های تجمیع خود Elasticsearch استفاده کنیم تا در یک درخواست، تعداد آگهی‌ها را برای چندین پالیگان به صورت گروه‌بندی شده دریافت کنیم. طبق بررسی‌ها و بنچ‌مارک‌هایی که گرفتیم، استفاده از اگریگیشن‌های مبتنی بر گرید (مانند geotile_grid یا geohash_grid) عملکرد بهتری از نظر زمان پاسخ‌دهی داشت.۳.  تجمیع نتایج و نمایش کلاسترها: پس از دریافت تعداد آگهی‌ها در پالیگان‌های پایه، باید تصمیم می‌گرفتیم که چگونه این نتایج را به کلاسترهای نهایی تبدیل کنیم.  ۱.روش استاتیک: نتایج را مستقیماً در مرکز همان پالیگان‌های پایه نمایش دهیم. این روش ساده‌تر بود اما ممکن بود مراکز کلاسترها با تراکم واقعی آگهی‌ها همخوانی نداشته باشد. ما یک «اکسپریمنت کلاسترینگ استاتیک» اولیه را پیاده‌سازی کردیم که در آن تعداد آگهی‌ها برای هر استان، شهر و محله (بر اساس دسته‌بندی‌های املاک) به صورت روزانه محاسبه و در Redis ذخیره می‌شد. این داده‌ها سپس برای نمایش کلاسترها در زوم‌های پایین استفاده می‌شدند. ۲.روش داینامیک: نتایج پالیگان‌های پایه (که معمولاً ریزتر و پرتعدادتر هستند) را با الگوریتم‌های خاصی تجمیع کرده و کلاسترهای جدید و بهینه‌تری ایجاد کنیم که مرکزشان به تراکم واقعی آگهی‌ها نزدیک‌تر باشد. این روش پیچیده‌تر بود اما نتیجه‌ی بهتری ارائه می‌داد.ترکیب نهایی که ما برای پیاده‌سازی کلاسترینگ داینامیک انتخاب کردیم، استفاده از «گرید سیستم مبتنی بر تایل‌های جغرافیایی (Geotile)»، «اگریگیشن Elasticsearch» برای شمارش آگهی‌ها در این تایل‌ها (با استفاده از داده‌های ایندکس شده برای سرعت بیشتر) و سپس «تجمیع داینامیک» نتایج برای ساخت کلاسترهای نهایی بود.مدیریت «State» در دنیای «Stateless» دیوار: راه حل «هش»یکی دیگر از چالش‌های مهم ما، مدیریت State نقشه در زیرساخت عمدتاً Stateless دیوار بود. در سیستم‌های Stateless، هر درخواست به سرور به صورت مستقل و بدون وابستگی به درخواست‌های قبلی پردازش می‌شود. سرور اطلاعاتی از وضعیت قبلی کاربر (مثلاً اینکه قبلاً روی چه چیزی کلیک کرده یا چه فیلترهایی را انتخاب کرده) نگه نمی‌دارد و تمام اطلاعات مورد نیاز با هر درخواست ارسال می‌شود.اما نقشه ذاتاً یک کامپوننت «با وضعیت» (Stateful) است. وضعیت دوربین نقشه (موقعیت، سطح زوم)، فیلترهای اعمال‌شده، پین‌های انتخاب‌شده و ... همگی بخشی از وضعیت فعلی نقشه هستند که با تعاملات کاربر تغییر می‌کنند. برای مثال، وقتی کاربر شهر یا محله‌ی خود را در فیلترها تغییر می‌دهد، انتظار دارد دوربین نقشه به صورت خودکار به آن موقعیت جدید منتقل شود. این یعنی بک‌اند باید از وضعیت قبلی (شهر قبلی) و وضعیت جدید (شهر جدید) مطلع باشد تا بتواند این انتقال دوربین را به درستی مدیریت کند.در نسخه‌های قدیمی‌تر از روش‌های ساده‌تری مانند ارسال همزمان وضعیت قدیم و جدید به بک‌اند استفاده می‌شد. اما این روش‌ها در زیرساخت اصلی و استاندارد دیوار که برای مقیاس‌پذیری و پایداری بالا طراحی شده، قابل قبول نبودند و باعث پیچیدگی و انتقال داده‌های اضافی می‌شدند.راه حلی که ما برای این مشکل پیدا کردیم، استفاده از «هش» (Hash) بود. ایده به این صورت است که فیلترها و پارامترهای مهمی که بر وضعیت دوربین و نمایش نقشه تأثیرگذار هستند (مانند شهر، محله، دسته‌بندی و ...) در هر درخواست، در بک‌اند، به یک رشته‌ی هش تبدیل می‌شوند. این هش به همراه هر درخواست، توسط کلاینت، به بک‌اند ارسال می‌شود. بک‌اند مقدار دقیق این هش برایش مهم نیست؛ فقط کافی است هش دریافتی از کلاینت را با هشی که خودش بر اساس state فعلی محاسبه می‌کند، مقایسه کند. اگر این دو هش متفاوت بودند، بک‌اند متوجه می‌شود که یکی از پارامترهای کلیدی تغییر کرده و در نتیجه، باید وضعیت دوربین (مثلاً مختصات و سطح زوم) را مجدداً محاسبه و برای کلاینت ارسال کند. در غیر این صورت، دوربین در همان وضعیت قبلی باقی می‌ماند. این رویکرد به ما کمک کرد تا بدون نیاز به ذخیره‌سازی وضعیت کامل کاربر در بک‌اند، تغییرات مهم را تشخیص داده و تجربه‌ی کاربری روانی را فراهم کنیم.جمع‌بندی: نقشه‌ای برای آیندهتلاش ما همواره بر این بوده که با نگاهی عمیق به مسائل فنی و با استفاده از بهترین راهکارهای موجود، زیرساختی قوی و انعطاف‌پذیر برای نقشه‌ی دیوار بسازیم؛ زیرساختی که نه تنها پاسخگوی نیازهای امروز کاربران باشد، بلکه بتواند در آینده نیز با رشد دیوار و پیچیده‌تر شدن نیازها، به تکامل خود ادامه دهد. مسیر ساخت نقشه‌ی دیوار را هیچ وقت تمام‌شده نمی‌دانیم؛ چون هر بار با چشم کاربران به این نقشه نگاه می‌کنیم، نیازهای تازه و چالش‌های جدیدی جلوی رویمان ظاهر می‌شود. هنوز هم کارهای زیادی پیش رو است، اما مطمئنیم هر قدم رو به جلو، تجربه‌ی کاربران‌مان را معنادارتر می‌کند.برای مشاهده‌ی موقعیت‌های شغلی باز دیوار اینجا کلیک کنید.</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Thu, 22 May 2025 13:43:38 +0330</pubDate>
            </item>
                    <item>
                <title>آینده مهندسی در دیوار: تکامل مهندسی با هوش مصنوعی!</title>
                <link>https://virgool.io/@divar/%D8%A2%DB%8C%D9%86%D8%AF%D9%87-%D9%85%D9%87%D9%86%D8%AF%D8%B3%DB%8C-%D8%AF%D8%B1-%D8%AF%DB%8C%D9%88%D8%A7%D8%B1-%D8%AA%DA%A9%D8%A7%D9%85%D9%84-%D9%85%D9%87%D9%86%D8%AF%D8%B3%DB%8C-%D8%A8%D8%A7-%D9%87%D9%88%D8%B4-%D9%85%D8%B5%D9%86%D9%88%D8%B9%DB%8C-s9n6sz43ltn7-s9n6sz43ltn7</link>
                <description>پیشرفت‌های هوش مصنوعی، مخصوصاً مدل‌های زبانی بزرگ (LLM)، دارن با یه سرعت باورنکردنی دنیای فناوری و ذات مهندسی نرم‌افزار رو دگرگون می‌کنن. ما تو دیوار، این تحول رو نه فقط ظهور AI Software Engineer، بلکه تکامل تمام نقش‌های مهندسی می‌دونیم. باور داریم که هوش مصنوعی داره به یه مهارت و ابزار اصلی برای همه مهندس‌ها تبدیل میشه و مرزهای سنتی بین تخصص‌ها کم‌کم محو میشن، هرچند عمق تخصصی تو حوزه‌های مهم همچنان حیاتی هستند. این نگاه ما به مهندسی و آینده تیم‌های فنی‌مونه.آینده مهندسی، ذاتاً با هوش مصنوعی گره خورده و ما در دیوار نه تنها این آینده رو پذیرفته‌ایم، بلکه فعالانه در حال ساختن اون هستیم. ما مهندسی با هوش مصنوعی رو عامل بازتعریف تجربه کاربری و خلق ارزش‌های جدید برای کاربرها می‌بینیم. این نقش تو دیوار در تقاطع مهندسی نرم‌افزار، درک عمیق از قابلیت‌ها و محدودیت‌های هوش مصنوعی و تفکر محصولی ایستاده.مهندس نرم‌افزار هوش مصنوعی در دیوار:مهندس هوش مصنوعی در دیوار، پیش از هر چیز یک مهندس نرم‌افزار هست. هوش مصنوعی و LLMها براش نه فقط یه ابزار، بلکه بخش جدایی‌ناپذیر تفکر روزمره برای حل مسئله هستند. این فرد ترکیبی از یک مهندس نرم‌افزار، متخصص کاربرد مدل‌های زبانی و فردی با درک عمیق از محصول و نیاز کاربره. اینجا خبری از کار صرفاً آکادمیک با مدل‌ها توی نوت‌بوک نیست! کارمون کاربردی‌تر، محصول‌محورتر و عمیقاً با مهندسی نرم‌افزار آمیخته است. مسئولیت اصلی، راهبری کامل چرخه سیستم‌های هوشمند از ایده تا اجراست:از فهم عمیق یک نیاز مبهم محصولی یا یک چالش فنی و شناسایی فرصت‌های کاربرد AI با ذهنیتی کنجکاو و آزمایش‌محور.تا طراحی راه‌حل با در نظر گرفتن توازن میان دقت و مقیاس‌پذیری با تکنولوژی امروز یا چند ماه آیندهسپس، توسعه و طراحی تجربه کاربری، تعریف معیارهای ارزیابی دقیق و تأثیر بر کاربر، تحلیل خطا و بهبود مستمر سیستم.در نهایت، او مسئول استقرار و پایش مداوم این سیستم‌ها در محیط عملیاتی است؛این فرآیند ذاتاً تکرارشونده (iterative) و با توجه به ماهیت نوپا و پرابهام کار با LLMها، نیازمند چابکی بالاست.کار در عمل: فراتر از تست یه پرامپت تو محیط‌های چتوقتی LLM کار می‌کنیم، با سیستم‌هایی سروکار داریم که ذاتاً غیرقطعی هستن. برخلاف سیستم‌های سنتی، یهو ممکنه جوابی کاملاً بی‌ربط یا نادرست تولید کنه. اینجاست که کار واقعی شروع میشه: ریشه‌یابی دقیق مشکل. آیا پرامپت‌ها ایراد داره؟ داده‌های ورودی مشکل داره؟ ابزارها (Tools) و توضیحاتشون دقیق نیست؟ یا شاید خود مدل محدودیت داره؟ شاید کل معماری سیستم نیاز به بازنگری داره و باید مسئله رو باید مدل دیگه طرح کنیم.این یعنی ساعت‌ها کلنجار رفتن با پرامپت‌ها، کاویدن تریس‌های سیستم واسه فهمیدن دلیل یه رفتار، تحلیل مثال‌های خطا واسه دسته‌بندی مشکلات و پیدا کردن ایده‌های جدید. یه بخش مهم دیگه از کار، طراحی و پیاده‌سازی سیستم‌های ارزیابی مقیاس‌پذیره که کمکمون می‌کنه سریع‌تر محصول رو بهتر کنیم، مثلاً &quot;LLM as Judge&quot;هایی که با خروجی مطلوب ما تو محصول نهایی هماهنگ باشن.علاوه بر اینا، مهارت‌های کلیدی مهندسی نرم‌افزار مثل طراحی ماژولار، کد مقایس پذیر و قابل تست، الگوهای طراحی مناسب ، دیپلوی و مانیتورینگ مستمر سرویس ها هم خیلی مهمه. همچنین مدیریت وابستگی‌های پیچیده در سیستم‌های و طراحی API های انعطاف‌پذیر و قابل توسعه، بخش جدایی‌ناپذیر کار است.جعبه‌ابزار حل مسئله با هوش مصنوعی: ذهنیت و مهارت‌برای موفقیت تو نقش جدید مهندسی، یه ترکیب خاص از مهارت‌های نرم، طرز فکر و توانایی‌های فنی لازمه:۱. مهارت‌های نرم و طرز فکر کلیدی:هنر حل مسئله و مدیریت ابهام: باید بتونی مسائل پیچیده و مبهم رو به تیکه‌های کوچک‌تر بشکنی و راه‌حل‌های خلاقانه پیدا کنی. این یعنی بتونی با ابهام کنار بیای، آزمایش‌های هوشمندانه طراحی کنی و راه‌حل‌هایی بسازی که نه‌تنها امروز کار کنن، بلکه با پیشرفت سریع مدل‌های زبانی، تو آینده هم تکامل پیدا کنن.مالکیت کامل (End-to-End): انتظار میره که نه فقط یک جزء کوچک، بلکه کل چرخه حیات یک محصول رو از ایده تا اجرا و بهبود مستمر، متعلق به خودت بدونی. با نگاهی جامع به تمام اجزای سیستم، وابستگی‌ها و تاثیرات متقابلشون روی کاربرنگاه کاربر-محور: تمرکزت باید روی ساختن چیزی باشه که واقعاً به درد کاربر بخوره و تجربه‌ش رو بهتر کنه. این یعنی باید رفتار کاربر رو با دقت بررسی کنی، نیازهاش رو عمیق بفهمی و بتونی تجربه کاربری خوبی با سیستم‌های هوشمند براش بسازی.کنجکاوی و یادگیری مداوم: آدمی باشی که دائم دنبال یادگیریه و از آزمون و خطا و شکست‌های تو مسیر (Fail Fast) استقبال می‌کنه.تصمیم گیری هوشمندانه: باید بین دقت، سرعت، هزینه‌ها و مقیاس‌پذیری تعادل ایجاد کنی. این نیازمند چابکی تو تصمیم‌گیری و تطبیق سریع با شرایط جدیده.۲. مهارت‌های فنی و مهندسی ضروری:پایه‌های مهندسی نرم‌افزار: تسلط رو زبان‌های برنامه‌نویسی مثل پایتون یا Go، توانایی نوشتن کد تمیز و قابل تست، و درک عمیق از اصول طراحی سیستم و معماری سرویس‌ها، ستون اصلی موفقیتته.تجربه با LLMها و چرخه توسعه: با مدل‌های زبانی و چرخه کامل توسعه AI آشنا باشی. این شامل آماده‌سازی داده‌ها، طراحی آزمایش‌ها، تحلیل دقیق برای فهمیدن نقاط ضعف، و ساختن سیستم‌های ارزیابی مقیاس‌پذیر برای سنجش کیفیت محصوله.استقرار، پایش و بهبود مستمر: کار یه مهندس AI با انتشار اولیه محصول تازه شروع میشه! تو استقرار سیستم‌ها، پایش مداوم عملکردشون، و بهبود مستمر بر اساس داده‌ها و بازخوردها مهارت داشته باشی.چالش‌های مسیر و آینده‌ی پیش روکار در لبه هوش مصنوعی با چالش‌های خاصی همراهه. این حوزه خیلی سریع در حال تغییره و باید همیشه در حال یادگیری باشیم. یکی از واقعیت‌های کار با LLMها اینه که ساختن یه نمونه اولیه که ۷۰ درصد مواقع کار کنه، زیاد سخت نیست. چالش اصلی از جایی شروع میشه که بخوایم اونو به یه محصول واقعی، قابل اتکا و باکیفیت تبدیل کنیم. اینجاست که نیاز به فرایندهای ارزیابی دقیق، بررسی و تولید داده‌ واقعی، تحلیل خطاها و تکرارهای متعدد این چرخه برای بهبود خودش رو نشون می‌دهد. هدف ما ارائه راه‌حل‌هایی که با پیشرفت مدل‌های هوشمندتر، سیستم‌های ما هم هوشمندتر و مفیدتر بشند.با تمام این چالش‌ها، آینده‌ای که پیش رو داریم واقعاً هیجان‌انگیزه. ما تو دیوار دنبال اینیم که ایجنت‌های هوشمند تخصصی و عمومی‌تری بسازیم تا هوش مصنوعی رو خیلی عمیق‌تر با محصولات و خدماتمون یکپارچه کنیم. می‌خوایم از این تکنولوژی جدید برای کمک به بخش‌های مختلف فرآیند توسعه و عملیاتمون هم حسابی استفاده کنیم.چرا کار کردن به عنوان مهندس در دیوار جذابه؟کار در دیوار یعنی فرصت حل مسائل واقعی با مقیاس چند میلیون کاربر و دیدن تأثیر مستقیم کارت روی زندگی آدم‌ها. اینجا هوش مصنوعی یه موضوع فانتزی و آزمایشی نیست؛ یه سرمایه‌گذاری جدیه و همه بهش باور داریم. اینجا همه به ابزارهای به‌روزه دسترسی داریم. حاضریم برای ایده های خوب کلی ریسورس خرج کنیم و مهم‌تر از همه، فرهنگیه که تشویقت می‌کنه کار رو درست، اصولی و مهندسی‌شده انجام بدی. اینجا فرصت داری خطاکنی، آزمایش کنی و یادبگیری، اما در نهایت iterative یه محصول پایدار و باکیفیت تحویل بدی.سخن پایانی: مهندسی آینده، امروز در دیوارباور ما اینه که به‌زودی، مرزهای سنتی بین تخصص‌های مهندسی کم‌رنگ‌تر میشه و هوش مصنوعی به جزء جدایی‌ناپذیر تفکر و ابزار همه اعضای تیم تبدیل خواهد شد. این نقش، در واقع تصویری از آینده تمام مهندس های دیوار است؛ مسیری که همه با هم در حال طی کردن اون هستیم. هدفمون ساختن تیمی از مهندس هاست که با AI و بر پایه اون، محصولات و سیستم‌های نوآورانه و تأثیرگذار می‌سازن. اگه خودت رو مشتاق همراهی با این تحول و ساختن آینده مهندسی می‌بینی و اگر فکر می‌کنی مهارت‌ها و انگیزه لازم برای رشد در این مسیر رو داری، از تو دعوت می‌کنیم نگاهی به فرصت‌ همکاری با ما به عنوان AI Software Engineer بندازی.</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Wed, 14 May 2025 18:45:51 +0330</pubDate>
            </item>
                    <item>
                <title>از زیرساخت آزمایش‌ها تا هوش مصنوعی: سفر چهار ساله تیم بهره‌وری مهندسی دیوار</title>
                <link>https://tech.divar.ir/از-زیرساخت-آزمایش-ها-تا-هوش-مصنوعی-سفر-چهار-ساله-تیم-بهره-وری-مهندسی-دیوار-zgjrwxevgvm6</link>
                <description>تو دنیای پرسرعت فناوری، بهبود مداوم فرآیندها و ابزارهای توسعه نرم‌افزار یه ضرورته که نمیشه انکارش کرد. تیم بهره‌وری مهندسی دیوار حدود چهار سال پیش، برای بهبود این مسئله با یک ایده شکل گرفت: بهره‌ورتر کردن فرآیند توسعه و کم کردن بار ذهنی توسعه دهنده‌ها. این هدف ما رو به سمت ساخت یه سری ابزار و فرآیند برد که الان دیگه جزء جدایی‌ناپذیر زیرساخت فنی دیوار شدن.تو این پست می‌خوایم از موفقیت‌ها، شکست‌ها و درس‌هایی که تو این چهار سال گرفتیم بگیم. از توسعه‌ی سیستم‌های پیچیده مثل زیرساخت آزمایش و سندباکسمون گرفته تا تمرکز روی هوش مصنوعی در فرآیند توسعه. اگه می‌خواید بدونید پشت پرده یه تیم بهره‌وری مهندسی چه خبره، با ما همراه باشید!کلود سندباکسینگدیوار با گذر زمان، بزرگ و پیچیده شده و کلی میکروسرویس داره. این یعنی تست کردن حتی یه سرویس کوچک، نیاز به کلی وابستگی (dependency) داره. به خاطر همین توسعه‌دهنده‌ها عموما نمی‌تونن راحت یک سرویس رو روی ماشین شخصی خودشون (local) بالا بیارن و تست کنن.برای حل این مشکل، سرویس کلود سندباکسینگ رو توسعه دادیم تا مهندسا بتونن سریع و راحت یه محیط تست بسازن. قبل از اون نیاز بود تا بتونیم ترافیک دیوار رو به سادگی و خودکار مدیریت کنیم، پس سرویس «کنترل‌پلین» رو ساختیم که سرویس مرکزی مدیریت ترافیک دیوار به کمک فریم ورک آر‌پی‌سی خودمون یعنی divar-rpc بود و به کلود سندباکسینگ api می‌داد.دیوار‌آرپی‌سی فریم‌ورک داخلی rpc دیواره که یک رپر دور gRPC حساب می‌شه و چیزهایی مثل متریک انداختن، تریسینگ، روتینگ رو در دیوار استاندارد کرده.ساختار کلود سندباکسینگ اینطوریه که ما یه سری «پروفایل» داریم از پروژه‌ها و سرویس‌های مختلف (که در واقع Helm chart‌هایی هستن با کانفیگ‌های لازم). توسعه‌دهنده با انتخاب یکی از این پروفایل‌ها، یه دیپلویمنت جدید توی محیط ایزوله می‌سازه و به کنترل‌پلین می‌گه ترافیک کلاینتِ تو رو، به این سندباکس بفرسته. کلاینت‌ها با هدر‌های خاصی که می‌فرستند از هم متمایز می‌شن. «جعبه ابزار دیوار» که توی همه کلاینت‌هامون پیاده شده، استفاده از این هدرها رو خیلی ساده می‌کنه.در حال حاضر  روزانه بیش از 80 تا سندباکس با این سیستم ساخته میشه که نشون میده چقدر مورد استقبال قرار گرفته. این زیرساخت به بچه‌های QA هم کمک زیادی کرده که تغییرات رو قبل از انتشار راحت‌تر و کامل‌تر بررسی کنن. این پروژه یکی از تأثیرگذارترین کارهایی بوده که انجام دادیم. زمان توسعه رو کاهش داده و به مهندس‌ها اعتماد به نفس بیشتری داده تا ایده‌های جدید رو امتحان کنن. البته بدی‌هایی هم داشته، مثل این که آدم‌ها عادت می‌کنن کمتر برای کدهای خودشون تست بنویسن. صحبت‌های دقیق‌تر از این جنس رو ایشالا می‌ذاریم تو بلاگ پست‌های بعدی.زیرساخت آزمایش (experiment) و فیچر فلگThe only way to win is to learn faster than anyone else.حالا چطوری سریع‌تر از بقیه یاد بگیریم؟ با آزمایش کردن!بعد از کلود سندباکسینگ، نوبت به یکی از مهم‌ترین زیرساخت‌های ما رسید: سیستم آزمایش‌های دیوار. این سیستم در کنار فیچر فلگ‌ها، قلب تپنده نوآوری در دیواره. با این زیرساخت تو دیوار ما می‌تونیم سریع‌تر و با ریسک کمتر، آزمایش‌های بیشتری کنیم تا خلق ارزش بیشتری رو برای کاربر رقم بزنیم.اول لازمه یه توضیح کوچیک بدیم درباره فیچر فلگ‌ها. تو divar-rpc هر جزئی از کانفیگ‌های ما، در واقع یک فیچر فلگه.فیچر فلگ در حالت ساده یک متغیر با یک تایپ و یک مقداره. این مقدار می‌تونه بسته به شرایط مختلف، مثل نوع کلاینت یا نسخه‌ی کاربر تغییر کنه. برای مثال مقدارش در صورتی که از کلاینت وب بود، با کلاینت اندروید متفاوت باشه.حالا اکسپریمنت چطور با این فلگ‌ها کار می‌کنه؟ اگه کاربر توی یه آزمایش خاص قرار گرفته باشه، سیستم اکسپریمنت میاد و مقادیر فلگ‌های مرتبط با اون آزمایش رو تغییر میده. این شکلی ما حالت‌های مختلفی از بخش‌های متفاوت دیوار می‌تونیم به کاربر نشون بدیم و تصمیم‌هامون رو سبک سنگین کنیم. (چه محصولی و چه فنی!)اما چرا خودمون همچین سیستمی ساختیم و نرفتیم سراغ راه‌حل‌های آماده مثل پروژه‌های اوپن سورس A/B تست یا پلتفرم‌هایی مثل Unleash؟ دلیلش اینه که این پلتفرم‌ها خیلی ابتدایی هستن و یه محدودیت بزرگ دارن: از آزمایش‌های عمود بر هم رو پشتیبانی نمی‌کنن. (حداقل تو زمانی که ما داشتیم این زیرساخت توسعه می‌دادیم).منظور از آزمایش‌های عمود بر هم چیه؟ فرض کنید دو تا آزمایش داریم: یکی رنگ پس‌زمینه رو قرمز می‌کنه، یکی دیگه رنگ متن رو. اگه یه کاربر همزمان توی هر دو آزمایش بیفته، ممکنه نتیجه اصلاً قابل خوندن نباشه! حالا همین رو بیایم بسط بدیم رو کلی از متغیرهای محصولیمون. مثلا اگه پاشیم بیایم توی سرچ دیوار یک جور دیگه‌ای آگهی به کاربرها پیشنهاد بدیم، باعث می‌شه زنگ خور اون آگهی بیشتر بشه یا نه و آیا چنین آزمایشی، رو آزمایش دیگه‌ای که قراره مدل نردبان کردن آگهی تو دیوار رو تغییر بده تاثیر می‌ذاره؟ مشخصا اگه تاثیر بذاره این دوتا آزمایش باید مستقل از هم انجام بشن.برای حل این مشکل، ما از یه مقاله گوگل الهام گرفتیم: &quot;Overlapping Experiment Infrastructure: More, Better, Faster Experimentation&quot;. این مقاله یه مدل لایه‌ای رو معرفی می‌کنه که آزمایش‌های عمود بر هم رو ممکن می‌کنه.مزیت دیگه این روش اینه که می‌تونیم تعداد خیلی زیادی آزمایش همزمان داشته باشیم. اگه هر آزمایش ۵٪ ترافیک رو می‌گرفت، نهایتاً می‌تونستیم ۲۰ تا آزمایش داشته باشیم. ولی با این روش لایه‌ای، تعداد آزمایش‌ها عملاً نامحدوده، به شرطی که لایه‌ها رو درست طراحی کنیم. برای پیاده‌سازی این سیستم، یه سری کد توی Divar RPC زدیم، یه سری کد دیگه توی گیت‌وی‌هامون، و یه پنل ساختیم که بچه‌ها بتونن راحت آزمایش تعریف کنن. جالبه بدونید آزمایش‌های ما زیر ۱ دقیقه توی کل سیستم اعمال میشن و حتی توی کلاینت‌ها هم کار می‌کنن.توی یک سال گذشته در دیوار، ما بیش از ۴۰۰ آزمایش به واسطه‌ی همین زیرساخت انجام دادیم که بیشترشون روی جنبه‌های محصولی تمرکز داشتن. جالبه بگم همین الان که دارم این بلاگ رو می‌نویسم، ۷۵ آزمایش توی دیوار روشنن!به گفته‌ی بچه‌هاییمون که از این زیرساخت استفاده می‌کنن، یه سری از کارهایی که توی یک سال اخیر روی سرچ دیوار انجام دادیم، بدون این زیرساخت ممکن بود ۴-۵ سال طول بکشه و احتمالا خیلی‌هاشون هیچوقت محقق نمی‌شدن. از اون طرف فلگ‌ها هم توی تیم‌های کلاینتیمون به شدت دارن استفاده می‌شن و تقریبا هر فیچری، پشت یک فیچر فلگیه.دشواری‌هایی هم با زیرساخت فعلیمون داریم، مثلا بحث‌های تحلیلیش جزئیات زیادی دارن، مثلا وقتی ما روی یک گروه آماری، آزمایشی انجام می‌دیم، احتمال خوبی وجود داره که اون گروه نسبت به آزمایش‌های بعدیمون سوگیری پیدا کرده باشن. فرضا اگه من فروردین یک آزمایش خاص ببینم و اردیبهشت یک آزمایش دیگه، خیلی امکان داره که رفتار تاثیر‌پذیرفته‌ای در آزمایشی که خردادماه روم انجام می‌شه داشته باشم و پیدا کردن چنین مسائلی دردسرهایین که هنوز نتونستیم حلشون کنیم.دستیار، دوستی با هوش مصنوعی مولداین روزا همه جا پر شده از خبرهای هوش مصنوعی. از chatGPT گرفته تا کلی ابزار دیگه که هر روز دارن معرفی می‌شن. اواخر ۱۴۰۲ بود که نشستیم فکر کردیم خب حالا با این همه هیاهو و ابزارهای جدید چیکار کنیم؟ چطوری می‌تونیم از این فناوری تو کارهای روزمره‌مون استفاده کنیم؟ مشخص هم نبود کدوماشون واقعا اثر مثبت دارن تو کار روزمره و کدوما نه.اینجا بود که تصمیم گرفتیم دو تا کار انجام بدیم تا هم بچه‌ها با Generative AI آشنا بشن هم یاد بگیرن چطوری ازش تو کارهاشون استفاده کنن و یه جورایی اون مرز و موضع‌گیری بین بچه‌ها و AI رو از بین ببریم:یه تجربه شبیه ChatGPT روی مدل‌های مختلف هوش مصنوعی به بچه‌های شرکت بدیمبه توسعه‌دهنده‌ها اجازه بدیم APIهای هوش مصنوعی رو استفاده کنند و ایده‌های جدید رو امتحان کنننتیجه؟ فراتر از انتظارمون بود. دستیار شد یه ابزار محبوب برای حل مسائل روزمره. توسعه‌دهنده‌ها شروع کردن به استفاده از AI تو کارها و پروژه‌هاشون و کارهای خیلی باحالی انجام دادن. مثلا بچه‌های فروشمون سعی کردن یک بار با چت کردن با دستیار و استفاده از مدل‌هایی که توانایی بیناییِ ماشین دارن، ببینن می‌تونن بنرهای تبلیغاتی دیوار رو تایید یا رد بکنن؟ و دیدن آره با دقیق کردن promptها این کار شدنیه. بعد به کمک نیروهای فنی براش یک سرویس نوشتن که همه‌ی بنرهای تبلیغاتی‌مون رو مورد بررسی قرار می‌ده!از دستیار جالب‌تر، دسترسی راحت بچه‌های دیوار به APIهای مدل‌های مختلف بود. خیلی زود آزمایش‌های کوچیک کوچیک تو شرکت شروع شد و ناگهان به محصول نهایی دیوار نفوذ کرد و کار به جایی رسید که تیم زیرساختمون یکی از تمرکزهاش، فراهم کردن دسترسی به مدل‌های مختلف هوش مصنوعی به صورت پایدار شد.در خصوص دستیار برنامه‌نویسی هم، اوایل ۱۴۰۳ شروع کردیم Github Copilot سازمانی دادن به همه‌ی بچه‌ها، کم کم که جلو اومدیم تو تابستون ۱۴۰۳ دیدیم Cursor به نظر ابزار قدرتمندیه و به بهره‌وری بیشتر خیلی کمک می‌کنه. اول چند ماهی با بچه‌های توسعه‌دهنده‌ی وب تستش کردیم  و بعد هم دسترسیش رو به تمام بچه‌های شرکت دادیم.از اواسط ۱۴۰۳ و با اومدن مدل claude-3-5-sonnet-20241022 تصمیم گرفتیم تمرکز بیشتری بذاریم روی هوش مصنوعی مولد توی بهره‌وری مهندسی و اولش یک پروژه‌ی کوچیک و تقریبا سخت رو انتخاب کردیم: تلاش برای بازنویسی یک سرویس پایتونی به گولنگ، به صورت خودکار توسط AI، با human in the loop برای فاز اعتبار‌سنجی (validation).انسان در چرخه (Human in the loop): «رویکردی در سیستم‌های هوش مصنوعیه که انسان در نقاط کلیدی فرآیند تصمیم‌گیری یا اعتبارسنجی دخالت می‌کنه تا دقت و کیفیت خروجی‌ها را تضمین یا بهبود ببخشه.»هدفمون بیشتر این بود که پتانسیل‌های AI رو توی توسعه بیشتر درک کنیم و  از شکستن خوردن ترسی نداشتیم. با یک سرویس آسون شروع کردیم و خروجی‌های جالبی گرفتیم، بعدش رفتیم سراغ سرویس احراز هویت دیوار و اونجا با دشواری‌های دیگه‌ای مواجه شدیم. در نهایت هر دو سرویس رو تو حدود ۳ ماه توسط AI بازنویسی کردیم، ولی خب انجام مجدد این کارو فعلا، با مدل‌ها و ابزارهای فعلی به کسی پیشنهاد نمی‌کنیم.با تجربه‌ی بازنویسیمون، درک نسبتا خوبی پیدا کردیم از توانمندی‌های AI تو توسعه و اونجا تیم رو چرخوندیم به سمت توسعه‌ی ابزارهای مبتنی بر هوش مصنوعی مولد و تلاشمون اینه تا آخر ۱۴۰۴، بتونیم بخش خوبی از آزمایش‌هامون در دیوار رو به صورت خودگردان (Autonomous) به‌وسیله‌ی هوش مصنوعی مولد انجام بدیم تا تیم‌هامون چابک‌تر شن و ظرفیت آدم‌هامون بیشتر بشه.با دستیار، ما فقط یه ابزار نساختیم، بلکه داریم یه فرهنگ جدید رو تو کار کردن در دیوار شکل می‌دیم. فرهنگی که توش هوش مصنوعی نه یه چیز عجیب و غریب، بلکه یه همکار روزمره‌ست. و این، شاید مهم‌ترین دستاورد ما تا الان بوده. چون وقتی همه بتونن از این فناوری استفاده کنن و باهاش راحت باشن، اون وقته که واقعاً می‌تونیم بگیم آماده‌ایم برای آینده‌ای که هوش مصنوعی توش نقش پررنگ‌تری داره.شکست‌ها و کارهایی که هنوز ثمره‌ای ندادنیکی از کارهایی که همیشه دوست داشتیم انجام بدیم محاسبه‌ی کارایی تیم‌ها بود. خیلی اینور اونور چرخیدیم که ببینیم چیکار می‌تونیم براش بکنیم و به کمک کتاب زیبای Accelerate و ریسرچ‌هایی که DORA در اختیارمون گذاشته بود، ۴ متریک دورا برای محاسبه کردن در سطح پروژه‌هامون انتخاب کردیم. چند بار تاحالا تلاش کردیم تا این متریک‌ها رو برای پروژه‌هامون محاسبه کنیم و یک بار هم با اقتباس از Test Certified Program گوگل سعی کردیم یک «مدل بلوغ» برای دیوار بسازیم و جا بندازیمش، اما فعلا هنوز هیچکدوم راه به جایی نبردن. اخیرا امیدواریم با یکپارچه کردن تجربه‌ی توسعه دهنده‌هامون با ابزار backstage، راهی برای ورود و بهبود این متریک‌ها پیدا کنیم و ببینیم نتیجه‌ی کارهای مختلفی که روی فرآیند‌های توسعه‌مون تو دیوار می‌کنیم و فرهنگی که می‌سازیم، به چه شکله.چهار متریک DORA ( یعنی deployment frequency, lead time, change failure rate, mean time to recovery ) توسط DevOps Research and Assessment برای سنجش کارایی سازمان استفاده می‌شن.کارهایی هم بودن که تو هفته‌ها و ماه‌های اول خوب ثمر می‌دادن، ولی بعد از یه مدت رها می‌شدن. از اونجایی که هر کدوم از این ابزارها، به همراه خودشون یک فرآیندی هم میارن، بعد یه مدت استفاده‌شون کم می‌شد و ما هم خیلی روش هزینه نمی‌کردیم و کم کم از فرآیند توسعه‌ خارج شدن. کلا این جنس مساله توی کارهایی که تیممون می‌کنه زیاد پیش میاد.تلاش‌های دیگه‌ای هم برای بحث اشتراک دانش تو شرکت و جمع کردن مستنداتمون کردیم، ولی خب ظاهرا مثل خیلی جاهای دیگه، اصلا وضعیت خوبی تو این بخشا هم نداریم و یکی از چشم امیدهامون به هوش مصنوعی مولد تو این زمینه‌س تا یه مقداری وضعیت مستند‌سازی، خصوصا فنی‌هاش رو برامون بهتر کنه. تا الآن خروجی‌های جالبی هم روش گرفتیم که توضیحاتش می‌مونه برای بعد.تست نویسی در دیوار هم از اون چیزایی بود که باید خیلی روش سرمایه‌گزاری می‌کردیم. شاید اگه زیرساخت اکسپریمنتمون به بالا بردن «سرعت توسعه» کمک کرده باشه، تست‌های بیشتر و حرفه‌ای‌تر تو لایه‌های مختلف رو هم نیاز داریم تا «پایداری توسعه»مون رو بالا ببره و خب کلا تست نوشتن کار سختیه! تو تیممون سعی کردیم با یادگرفتن از پست‌ها و کتاب‌های مختلف، خصوصا آموزه‌های بخش test کتاب Software Engineering at Google ( فصل‌های ۱۶ تا ۱۹ ) کارهایی بکنیم، مثلا راه انداختن یک زیرساخت تست end to end API ولی عملا می‌تونیم روی این تلاش هم، برچسب «شکست خورده» رو بزنیم.کار روی زیرساخت ci/cdمون هم به بخش مهم پایپلاین توسعه همیشه باهامون بوده و تجربه‌های شکست و موفقیت زیادی ازش داریم. از تلاش برای بردن زیرساخت ciمون روی سرورهای خارجی گرفته تا کارهای دیگه که اونارو هم جداگونه باید توضیح بدیم.ادامه‌ی راهمون چه شکلیه؟بده‌بستان (trade-off) وقت و انرژی گذاشتن روی هر کدوم از این کارها، سخت و قشنگه! مثلا این که الان بشینی پایپلاین‌هات رو ۱۰ ثانیه سریع‌تر کنی، یا زیرساخت اکسپریمنتت رو غنی‌تر کنی؟ یا تمام بچه‌هارو بندازی روی ابزارهای AIای؟ از اونور هم خراب کردن هر کدومشون تاثیر عجیبی روی سیستم داره. مثلا یه باگ بزنی و اکسپریمنت‌ها جابجا بشن و داده‌ها اشتباه تگ بخورن، یا فرضا ciهات رو ببری رو یه تکنولوژی دیگه و کل شرکت رو بدبخت کنی.هوش مصنوعی مولد هم داره به شکل خوبی سیستم رو عوض می‌کنه و یه سری از کارهایی که شاید در گذشته برای ما پر هزینه، چالشی و نیازمند نگه‌داری بالا بود رو قابل انجام‌تر می‌کنه. از اون طرف بهره‌وری بقیه‌ی فرآیندهای مهندسی و توسعه‌مون هم به قابل استفاده‌تر شدن هوش مصنوعی توی بخش‌های مختلفمون کمک می‌کنه.کلا این «بهره‌وری مهندسی» مفهوم خیلی قشنگ، پر ابهام، سخت و چالشی‌ایه و هر چیزی رو می‌شه بهش پیوند داد. این که بتونی کار به درد بخور و اثرگذار هم توش بکنی خیلی سخته، با وجود این که مشتریت داره کنارت می‌شینه! این شکلی نیست که فرضا برداری یک apiت رو ۸۰ درصد سریع‌تر کنی و ته هفته خوشحال باشی، این شکلیه که ۳ ماه وقت می‌ذاری رو یک چیزی و تهشم نمی‌فهمی به درد خورد یا نخورد! یا صدای ملت واقعا در اومد یا چون رفیقاتن و کنارت توی همون شرکت می‌شینن، خیلی بهت گیر نمی‌دن و اذیتت نمی‌کنن. ولی خب با همه‌ی این قصه‌ها، ما خیلی دوستش داریم!آدم‌های زیادی بهمون کمک کردن تا این اتفاق‌ها تو دیوار بیافته و ازشون کلی یاد گرفتیم. وقتی یکی از بچه‌های قدیمی دیوار میومد تو تیم، می‌دیدیم چقدر دانش بومی‌ای که از سیستم‌های شرکت داره بهمون کمک می‌کنه، یا وقتی یه نفر از یک شرکت دیگه، تازه وارد تیممون می‌شد می‌دیدیم چقدر ایده‌های جدید و قشنگی می‌ده و دیوار و فرآیند‌هاش رو از یک زاویه دیگه می‌بنیه، یا وقتی نیروهای تازه کار و با استعداد می‌گرفتیم، می‌دیدیم چقدر کار سختی توی آنبورد کردنشون روی تیم داریم، تا بتونیم وضعیت مهندسای دیگه تو دیوار رو بهتر کنیم.من، سید مصطفی مشکاتی، ۳ سال و نیمی هست افتخار حضور در این تیم رو دارم و برای همین لازمه اینجا از همه‌ی بچه‌هایی که تو این تیم بودن و برامون خلق ارزش کردن تشکر کنم. پویای رضایی و محمد حسین خوشرفتار عزیز که آجرهای اول تیم رو گذاشتن و به ماموریت تیم اعتماد داشتن. از علی محیط و روزبه صیادی و محمد وطن‌دوست و مریم یونسی، از عمران باتمان‌قلیچ و امین عارف زاده، از امیرحسام ادیبی‌نیا و مرتضی رستگار راد و زهرا دارابی، کیهان اسدی و ساسان یساری که هر کدوم بخشی از این تیم رو ساختن و بالا کشیدن و با کیفیت‌ترش کردن. الآن هم که با سجاد ایوبی، حسام زمان‌پور، مصطفی کاظمی، عرفان میرشمس و میلاد نوروزی که با اشتیاق بالا روی بخش‌های هوش مصنوعی‌ هستیم و تلاش می‌کنیم تجربه‌ی توسعه‌ی بهتری برای بچه‌هامون و در نهایت کاربرها بسازیم.[1] https://martinfowler.com/articles/feature-toggles.html[2] https://research.google/pubs/overlapping-experiment-infrastructure-more-better-faster-experimentation/[3] https://github.com/danny-avila/LibreChat[4] https://itrevolution.com/product/accelerate/[5] https://dora.dev/guides/dora-metrics-four-keys/[6] https://mike-bland.com/2011/10/18/test-certified.html[7] https://backstage.io/</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Sat, 03 May 2025 09:40:16 +0330</pubDate>
            </item>
                    <item>
                <title>چند ثانیه سریع‌تر، یک تجربه متفاوت: افزایش سرعت سرویس ثبت آگهی، رضایت کاربران و درآمد!</title>
                <link>https://tech.divar.ir/چند-ثانیه-سریع-تر-یک-تجربه-متفاوت-افزایش-سرعت-سرویس-ثبت-آگهی-رضایت-کاربران-و-درآمد-za0a4boguyzr</link>
                <description>سال ۱۴۰۱، سرویس ثبت آگهی دیوار، یکی از حیاتی‌ترین بخش‌های پلتفرم، با چالش‌های فزاینده‌ای روبرو بود. با رشد دیوار و افزایش روزانه‌ی تعداد آگهی‌ها، زیرساخت قدیمی که با پایتون نوشته شده بود، دیگر پاسخگوی نیازهای ما نبود. کاربران هنگام ثبت آگهی با کندی و خطا مواجه می‌شدند و این موضوع مستقیماً بر تجربه‌ی آن‌ها و در نتیجه بر موفقیت دیوار تأثیر می‌گذاشت. تیم فنی تصمیم گرفت برای حل ریشه‌ای این مشکلات، سرویس ثبت آگهی را بازنویسی کند. هدف اصلی بهبود پایداری (Reliability) و سرعت سرویس بود، اما نتیجه‌ی کار، یک غافلگیری خوشایند برای همه ما به همراه داشت: بدون اینکه هیچ تغییری در ظاهر یا فرآیند محصولی ثبت آگهی ایجاد کنیم، شاهد بهبود قابل توجه در متریک‌های محصولی و حتی افزایش محسوس درآمد دیوار بودیم!ماجرا چه بود؟ چالش‌های سرویس قدیمی ثبت آگهیسرویس قدیمی ثبت آگهی که با زبان پایتون توسعه داده شده بود، در گذر زمان و با افزایش بار ترافیکی، دچار مشکلاتی شده بود که هم کاربران و هم تیم‌های فنی دیوار را آزار می‌داد:کندی و خطاهای مکرر: طراحی قدیمی سرویس دیگر نمی‌توانست حجم بالای درخواست‌ها را به خوبی مدیریت کند. کاربران اغلب با کندی در بارگذاری صفحات فرم ثبت آگهی و حتی خطاهای غیرمنتظره در لحظه‌ی نهایی فشردن دکمه «ثبت آگهی» مواجه می‌شدند. طبق گزارش‌ها، نزدیک به ۱۰ درصد تماس‌های پشتیبانی دیوار ناشی از همین مشکلات در فرآیند ثبت یا ویرایش آگهی بود و حدود ۰.۷۵ درصد درخواست‌های ثبت/ویرایش آگهی با خطای غیرمنتظره مواجه می‌شدند.وابستگی‌های زیاد و شکنندگی: سرویس ثبت آگهی به سرویس‌های داخلی متعددی وابسته بود. بروز مشکل در هر یک از این سرویس‌ها می‌توانست کل فرآیند ثبت آگهی را مختل کند.تجربه‌ی کاربری نامطلوب: کندی و خطاها باعث می‌شد کاربران از ثبت آگهی منصرف شوند یا فرآیند را نیمه‌کاره رها کنند. این تجربه‌ی ناخوشایند، به خصوص برای کاربرانی که برای اولین بار قصد ثبت آگهی داشتند، می‌توانست دلسردکننده باشد.بهره‌وری پایین توسعه‌دهندگان: سرویس قدیمی از کتابخانه‌ای به نام ui schema برای ساخت فرم‌ها استفاده می‌کرد که قدیمی، فاقد type safety و مستندات کافی بود. این موضوع باعث بروز خطاهای زیاد در زمان توسعه، کندی فرآیند توسعه (تا ۲۰٪ کندتر طبق گفته‌ی تیم‌ها) و سختی در افزودن قابلیت‌های جدید می‌شد. مذاکرات مداوم بین تیم‌های بک‌اند و کلاینت برای اطمینان از هماهنگی، زمان زیادی را تلف می‌کرد.با توجه به این چالش‌ها، در اردیبهشت ۱۴۰۲ تیمی اختصاصی برای بازنویسی کامل سرویس ثبت آگهی تشکیل شد. هدف، ساخت سرویسی به‌روز، پایدار، سریع و توسعه‌پذیر بود.تغییرات فنی‌ای که دادیم: بازنویسی با نگاهی نوتیم بازنویسی با هدف رفع مشکلات بنیادی سرویس قدیمی، مجموعه‌ای از تغییرات کلیدی را در معماری و تکنولوژی‌های مورد استفاده اعمال کرد:مهاجرت به Go: زبان Go به دلیل مدیریت بهتر هم‌روندی (Concurrency) و کارایی بالا، به عنوان زبان اصلی سرویس جدید انتخاب شد. این انتخاب به ما کمک کرد تا درخواست‌های همزمان به سرویس‌های وابسته را بهینه‌تر مدیریت کنیم و زمان پاسخ‌دهی کلی را کاهش دهیم.استفاده از Type Safety با Protobuf: برای تعریف ساختار داده‌های آگهی و همچنین کامپوننت‌های فرم، از Protobuf استفاده کردیم. این کار باعث شد کل فرآیند، از بک‌اند تا کلاینت‌ها (اندروید، iOS، وب)، کاملاً Type Safe شود. این یعنی خطاهای ناشی از ناهماهنگی داده‌ها یا اشتباهات تایپی به شدت کاهش یافت و فرآیند توسعه بسیار ساده‌تر و مطمئن‌تر شد. این زیرساخت جدید (که FormPage نام گرفت) جایگزین ui schema قدیمی شد و امکان استفاده از ویجت‌های استاندارد دیوار در فرم‌ها را فراهم کرد.اجرای درخواست‌ها در پس‌زمینه (Online Request): برخی از مراحل ثبت آگهی نیازمند استعلام از سرویس‌های دیگر بودند (مانند استعلام کد ملی از سامانه شاهکار). در سیستم قدیمی، این استعلام‌ها در لحظه‌ی نهایی ثبت انجام می‌شد و کاربر باید منتظر پاسخ می‌ماند. در سرویس جدید، این درخواست‌های زمان‌بر به محض وارد کردن اطلاعات توسط کاربر، در پس‌زمینه ارسال می‌شوند. به این ترتیب، تا کاربر به مراحل پایانی برسد، پاسخ این استعلام‌ها آماده است و کاربر هیچ تأخیری را حس نمی‌کند.مدیریت وابستگی‌های UI در کلاینت (Offline Dependency): در سیستم قبلی، تغییر برخی فیلدها (مثلاً انتخاب نوع کنسول بازی) نیازمند ارسال درخواست به سرور و بارگذاری مجدد بخشی از فرم برای نمایش فیلدهای وابسته (مثلاً مدل کنسول) بود. در سیستم جدید، این وابستگی‌ها به صورت هوشمند در خود کلاینت مدیریت می‌شوند و نیازی به رفت و برگشت اضافه به سرور نیست.کاهش وابستگی‌های خارجی: در طراحی جدید تلاش شد تا حد امکان وابستگی‌های خارجی سرویس ثبت آگهی کاهش یابد تا پایداری کلی سیستم افزایش پیدا کند.یک اتفاق جالب: وقتی بهبود سرعت و پایداری، محصول را متحول می‌کند!همانطور که گفتیم، هدف اصلی بازنویسی، بهبود پایداری و سرعت بود. اما پس از انتشار تدریجی سرویس جدید، با نتایج شگفت‌انگیزی در متریک‌های محصولی مواجه شدیم:افزایش محسوس درآمد دیوار: این مهم‌ترین و غیرمنتظره‌ترین نتیجه بود. با اینکه هیچ تغییری در مدل کسب‌وکار یا قیمت‌گذاری‌ها نداده بودیم، صرفاً با بهبود تجربه‌ی فنی ثبت آگهی، درآمد دیوار به طور محسوسی افزایش یافت.افزایش تعداد آگهی‌های موفق: کاربران بیشتری موفق به تکمیل فرآیند ثبت آگهی شدند. نرخ ثبت آگهی موفق نسبت به ورود به فرآیند ثبت، ۴.۱۷٪ افزایش یافت. همچنین نرخ موفقیت کاربرانی که دکمه نهایی «ثبت آگهی» را می‌زدند، ۳۲٪ بهبود پیدا کرد.صرفه‌جویی عظیم در زمان کاربران: به طور میانگین، کاربران ۱۶ ثانیه زودتر فرآیند ثبت آگهی را به پایان می‌رساندند. با توجه به اینکه روزانه حدود یک میلیون آگهی در دیوار ثبت می‌شود، این بهبود به معنای صرفه‌جویی مجموعاً بیش از ۴۴۰۰ ساعت از زمان کاربران دیوار در هر روز است!کاهش چشمگیر تماس‌های پشتیبانی: مشکلات فنی کمتر به معنای نیاز کمتر کاربران به تماس با پشتیبانی بود. سهم مشکلات فنی ثبت آگهی از کل تماس‌های پشتیبانی دیوار از ۰.۲۱٪ به ۰.۰۳٪ کاهش یافت (یعنی تقریباً یک هفتم شد). همچنین درصد تماس‌های مربوط به خطای ثبت آگهی نسبت به کل تماس‌های با موضوع ثبت آگهی، از ۱.۷۱٪ به ۰.۵۴٪ رسید.این نتایج به وضوح نشان داد که بهبود زیرساخت‌های فنی، حتی اگر برای کاربر نهایی نامرئی باشد، می‌تواند تأثیر مستقیم و قابل توجهی بر رفتار کاربر، موفقیت محصول و در نهایت درآمد شرکت داشته باشد.این موضوع منحصر به دیوار نیست و پیش‌تر شرکت‌های دیگر نتایج همانندی را گزارش کرده بودند. آمازون به عنوان یک شرکت تجارت الکترونیک، همواره روی سرعت بارگذاری وب‌سایت و سرویس‌های خود حساس بوده است. یک مطالعه‌ی معروف در آمازون نشان داد که حتی تاخیرهای بسیار کوچک نیز مستقیماً بر رضایت و رفتار خرید کاربران اثر می‌گذارد. هر ۱۰۰ میلی‌ثانیه تأخیر اضافی = ۱٪ کاهش فروش!​ در آزمون‌های A/B، حتی اختلاف‌های چند دهم ثانیه‌ای در سرعت صفحه، افت قابل توجهی در درآمد به همراه داشت​.نتیجه‌ی تغییرات فنی: اعداد سخن می‌گویندعلاوه بر بهبودهای محصولی، سرویس جدید به اهداف فنی اولیه‌ی خود نیز با موفقیت دست یافت:کاهش چشمگیر زمان پاسخ‌دهی (Response Time):میانگین زمان پاسخ‌دهی (Upper 50) از ۵۶ میلی‌ثانیه به ۲۵ میلی‌ثانیه کاهش یافت (۵۵٪ بهبود).زمان پاسخ‌دهی برای ۹۰٪ درخواست‌ها (Upper 90) از ۳۷۸ میلی‌ثانیه به ۹۷ میلی‌ثانیه کاهش یافت (۷۴٪ بهبود).زمان پاسخ‌دهی برای ۹۹٪ درخواست‌ها (Upper 99) از ۱۴۰۱ میلی‌ثانیه به ۲۵۰ میلی‌ثانیه کاهش یافت (۸۲٪ بهبود).افزایش آپتایم (Uptime): آپتایم سرویس از ۹۹.۸۰۰٪ به ۹۹.۹۶۲٪ افزایش یافت.کاهش مصرف منابع: مصرف CPU حدود ۸۹٪ و مصرف RAM حدود ۹۳٪ کاهش یافته است.بهبود فنی فقط یک کار فنی نیست!بازنویسی سرویس ثبت آگهی دیوار داستانی از اهمیت سرمایه‌گذاری بر زیرساخت‌های فنی است. پروژه‌ای که با هدف حل مشکلات پایداری و سرعت آغاز شد، نه تنها به اهداف فنی خود رسید، بلکه به طور غیرمنتظره‌ای منجر به بهبود متریک‌های کلیدی محصول و افزایش درآمد شد. این تجربه، در کنار تجربه‌ی مشابه قبلی ما در بهینه‌سازی سرویس تصاویر آگهی‌ها، این باور را در دیوار تقویت کرد که سلامت و کارایی فنی سیستم‌ها، بخشی جدایی‌ناپذیر از موفقیت محصول است. گاهی بهترین راه برای بهبود تجربه‌ی کاربری و رشد محصول، نه افزودن ویژگی‌های جدید، بلکه تقویت پایه‌های فنی سیستم است.با تشکر از تیم ثبت آگهی - مهدی مصطفوی، مهدی عباسی، مسیح جزایری، همایون علی محمدی، کامیار میرزاوزیری، ایمان نامداری، امین موسوی، محراب صاف دل، متین عبداللهی و دیگر همکاران - که با تلاش و تعهد خود این بازنویسی موفق را به سرانجام رساندند.</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Sat, 12 Apr 2025 15:04:52 +0330</pubDate>
            </item>
                    <item>
                <title>از نظارت انسانی تا هوش مصنوعی: داستان تحول بررسی آگهی‌های دیوار</title>
                <link>https://tech.divar.ir/از-نظارت-انسانی-تا-هوش-مصنوعی-داستان-تحول-بررسی-آگهی-های-دیوار-kjqz4ivxtwoz</link>
                <description>روزانه بیش از یک میلیون آگهی جدید در دیوار منتشر می‌شود که هر کدام نیازمند بررسی دقیق هستند تا کیفیت آگهی‌ها حفظ شود. آگهی‌ها قلب تپنده دیوار هستند و کیفیت آنها مستقیماً بر تجربه کاربران تأثیر می‌گذارد. تا همین چند ماه پیش، بررسی این آگهی‌ها ترکیبی از سیستم‌های نیمه‌خودکار و ناظران انسانی بود که هزینه‌بر، زمان‌بر و گاهی با خطا همراه بود. اما امروز، با استفاده از مدل‌های زبانی بزرگ (LLM)، دیوار توانسته فرآیند بررسی آگهی‌ها را متحول کند و سرعت، دقت و کیفیت را به طور چشمگیری بهبود بخشد.ساختار قبلی بررسی آگهی در دیوارقبل از تغییرات اخیر، دیوار از یک سیستم ترکیبی برای بررسی آگهی‌ها استفاده می‌کرد. این سیستم شامل چندین بات مبتنی بر مدل‌های زبانی خیلی کوچک و ساده بود که آگهی‌ها را به صورت اولیه بررسی می‌کردند. این بات‌ها عمدتاً بر اساس تشخیص کلمات کلیدی عمل می‌کردند و فاقد درک عمیق از محتوا و بافت آگهی بودند.مکانیزم کار به این صورت بود که به طور پیش‌فرض، آگهی‌ها تأیید می‌شدند مگر اینکه یکی از بات‌ها آن را به عنوان &quot;مشکوک&quot; شناسایی می‌کرد. در این صورت، آگهی برای بررسی به ناظران انسانی ارجاع داده می‌شد تا تصمیم نهایی را اتخاذ کنند.این ساختار با مشکلات متعددی همراه بود:محدودیت در تشخیص: بات‌ها تنها حدود ۶۵٪ از آگهی‌های نامناسب را شناسایی می‌کردند و قادر به تشخیص موارد پیچیده‌تر نبودند.زمان انتظار طولانی: برخی کاربران مجبور بودند بیش از نیم ساعت برای بررسی آگهی خود منتظر بمانند.هزینه بالا: استخدام و آموزش ناظران انسانی هزینه‌های قابل توجهی را به همراه داشت.عدم یکپارچگی در بررسی: ناظران انسانی مختلف ممکن بود برداشت‌های متفاوتی از قوانین داشته باشند که منجر به عدم یکسان بودن فرآیند بررسی می‌شد.بازخورد ضعیف به کاربران: دلایل رد آگهی‌ها اغلب کلی و غیردقیق بود و کاربران نمی‌دانستند دقیقاً چه مشکلی در آگهی‌شان وجود دارد.دشواری در تغییر قوانین: هر تغییر در قوانین نیازمند آموزش مجدد تمام ناظران بود که هفته‌ها زمان می‌برد.علاوه بر این، سیستم قبلی در برخورد با موارد خاص مانند تشخیص تصاویر نامناسب، آگهی‌های تکراری یا آگهی‌های با دسته‌بندی اشتباه،  بخاطر محدودیت‌های مدل زبانی ساده،خیلی جا برای بهتر شدن داشت. همچنین کاربران می‌توانستند با روش‌های ساده (مثال: نوشتن کلمات خلاف قوانین در عکس آگهی) قوانین را دور بزنند.تصمیم به تغییر و مراحل پیاده‌سازیبا توجه به پیشرفت های چشمگیر در حوزه هوش مصنوعی و به ویژه مدل های زبانی بزرگ (LLM)، تصمیم گرفتیم از این فناوری برای بهبود فرآیند بررسی آگهی استفاده کنیم. ایده اولیه تیم، توسعه و fine-tune کردن مدل های زبانی اختصاصی بود، اما پس از بررسی های دقیق تر، متوجه شدیم که استفاده از API های موجود نه تنها مقرون به صرفه تر است، بلکه با توجه به روند نزولی قیمت ها و افزایش کیفیت این سرویس ها، انتخاب هوشمندانه تری خواهد بود.استراتژی ما ابتدا تمرکز بر کیفیت و نه قیمت بود. از مدل‌های قوی‌تر استفاده کردیم و پرامپت‌ها و طراحی سیستم را به گونه‌ای &quot;LLM Friendly&quot; پیاده‌سازی کردیم که به مدل خاصی وابسته نباشد. این رویکرد باعث شد بعد از دستیابی به دقت مورد نظر، بتوانیم بدون تغییرات زیرساختی به مدل‌های جدیدتر مانند Gemini مهاجرت کنیم و همزمان با کاهش هزینه‌ها، شاهد افزایش دقت نیز باشیم.استراتژی توسعه و پیاده‌سازیبرای پیاده‌سازی این سیستم جدید، یک استراتژی چند مرحله‌ای را دنبال کردیم:۱. رهانش تدریجی با تمرکز بر دقت: تغییر اساسی ما در سیستم جدید این بود که برخلاف بات‌های قبلی که فقط آگهی‌ها را &quot;مشکوک&quot; می‌کردند و تصمیم نهایی با ناظران انسانی بود، LLM‌ها می‌توانستند مستقیماً تصمیم بگیرند و آگهی را تأیید یا رد کنند. این قابلیت یک شمشیر دولبه بود؛ می‌توانست اتوماسیون را به ۱۰۰٪ برساند اما ریسک اشتباه هم داشت. استراتژی ما برای مدیریت این ریسک، رهانش تدریجی بود. ابتدا سیستم را طوری تنظیم کردیم که دقت (Precision) بسیار بالایی داشته باشد (بالای ۹۵٪)، حتی اگر به قیمت پایین آمدن نرخ تشخیص (Recall) باشد. به بیان ساده‌تر، ترجیح دادیم فقط آگهی‌هایی را رد کنیم که کاملاً مطمئن بودیم مشکل دارند. با بهبود پرامپت‌ها و افزایش تجربه، به تدریج نرخ تشخیص را افزایش دادیم، اما همواره دقت را بالا نگه داشتیم. برای هر قانون، چندین نسخه را به صورت مرحله‌ای منتشر کردیم و هر بار سیستم را بهبود بخشیدیم، مثل آگهی تکراری که پنج مرحله دیپلوی داشت. این فرآیند تکراری به ما اجازه داد بدون آسیب به تجربه کاربران، سیستم را گام به گام تکامل دهیم.۲. تلفیق سیستم قدیم و جدید: برای کاهش ریسک و بهینه‌سازی هزینه، بات‌های قبلی را کاملاً کنار نگذاشتیم بلکه فرآیند بررسی را دو مرحله‌ای کردیم. تنظیمات بات‌های قبلی را طوری تغییر دادیم که حساسیت بیشتری داشته باشند (افزایش ریکال) حتی به قیمت کاهش دقت. به این ترتیب، این بات‌ها به عنوان فیلتر اولیه عمل می‌کردند و آگهی‌های بیشتری را مشکوک تشخیص می‌دادند. این باعث شد به جای بررسی تمام آگهی‌ها با LLM (که هزینه‌بر است)، تنها حدود ۲۰-۳۰ درصد آگهی‌ها که توسط بات‌های قبلی مشکوک شناخته می‌شدند، به مرحله بررسی با LLM برسند. این استراتژی دو مرحله‌ای تأثیر چشمگیری در کاهش هزینه‌های کلی داشت.۳. بهبود تدریجی پرامپت‌ها و معیارها: با هر بار دیپلوی، پرامپت‌ها و معیارهای تصمیم‌گیری را بهبود می‌دادیم تا دقت حفظ شود و نرخ تشخیص افزایش یابد. برای مثال، برای تشخیص آگهی‌های تکراری پنج بار دیپلوی داشتیم و در هر مرحله دقت را بالای ۹۵٪ نگه داشتیم.یهینه‌سازی هزینهیکی از بزرگترین چالش‌ها در استفاده از LLM‌ها، مدیریت هزینه‌هاست. ما با استفاده از استراتژی‌های زیر توانستیم هزینه‌ها را به طور چشمگیری کاهش دهیم:فیلترینگ هوشمند: با استفاده از بات‌های سبک‌تر به عنوان فیلتر اولیه، تعداد درخواست‌های ارسالی به LLM را کاهش دادیم. به این ترتیب، به جای بررسی تمامی آگهی‌ها با LLM، تنها آگهی‌های مشکوک به این مرحله می‌رسیدند.انتخاب هوشمند مدل‌ها: برای هر نوع قانون، از مدل مناسب با آن استفاده کردیم. برای قوانین ساده‌تر از مدل‌های ارزان‌تر و برای قوانین پیچیده‌تر و حساس‌تر از مدل‌های قوی‌تر بهره بردیم.کش کردن نتایج مشابه: الگوریتم‌هایی را پیاده‌سازی کردیم که می‌توانست نتایج بررسی‌های مشابه را به خاطر بسپارد و از درخواست‌های تکراری به LLM جلوگیری کند.بهینه‌سازی پرامپت‌ها: با طراحی دقیق پرامپت‌ها، توانستیم حجم ورودی به مدل را کاهش دهیم که به نوبه خود باعث کاهش هزینه‌ها شد.حفظ حریم خصوصی کاربراننکته مهم در استفاده از سرویس‌های خارجی LLM، حفظ حریم خصوصی کاربران است. ما تنها اطلاعاتی را به LLM ارسال می‌کنیم که کاربر از ابتدا با هدف انتشار عمومی ثبت کرده است (مانند عنوان، توضیحات و تصاویر آگهی). اطلاعات شخصی کاربران مانند شماره تلفن، آدرس یا سایر اطلاعات شناسایی شخصی (PII) هرگز به LLM ارسال نمی‌شوند.داستان یک موفقیت: تشخیص هوشمندانه‌تر از انسانیکی از جذاب‌ترین موارد موفقیت سیستم جدید، توانایی آن در تشخیص دقیق‌تر آگهی‌های تکراری بود. در سیستم قبلی، ناظران انسانی به دلیل محدودیت زمانی، تنها می‌توانستند عنوان و بخشی از توضیحات را بررسی کنند و غالباً قادر به تشخیص آگهی‌های تکراری که با تغییرات جزئی مجدد ثبت می‌شدند، نبودند.مدل زبانی توانست با تحلیل عمیق تمام فیلدهای آگهی، الگوهایی را شناسایی کند که از چشم ناظران انسانی پنهان می‌ماند. جالب اینجاست که آمار نشان داد نرخ اعتراض به رد آگهی‌های تکراری که توسط LLM شناسایی شده بودند، به طور معناداری کمتر از آگهی‌هایی بود که توسط ناظران انسانی رد می‌شدند. این نشان می‌داد که تصمیمات LLM نه تنها سریع‌تر، بلکه در بسیاری موارد دقیق‌تر از انسان‌ها بود.مورد دیگر، تشخیص تصاویر نامناسب بود. LLM توانست سطح جدیدی از دقت در تشخیص مواردی مانند برهنگی، راه‌های ارتباطی پنهان شده در تصاویر، و نوشته‌های غیرمرتبط در عکس‌ها را ارائه دهد. این بهبود باعث شد تا کیفیت تصاویر در لیست دیوار به طور چشمگیری افزایش یابد.یک چالش جالب دیگر مربوط به قوانین منسوخ شده بود. در مواردی، قوانینی مانند &quot;ذکر قیمت در توضیحات&quot; از دستورالعمل‌های رسمی حذف شده بود، اما ناظران انسانی به دلیل عادت یا فراموشی، همچنان آگهی‌ها را بر اساس این قوانین قدیمی رد می‌کردند. با پیاده‌سازی سیستم جدید، این ناهماهنگی‌ها از بین رفت و تصمیم‌گیری یکپارچه‌تری ایجاد شد.تأثیر بر تجربه کاربرانسیستم جدید بررسی آگهی تأثیر عمیقی بر تجربه کاربران دیوار، هم در سمت عرضه (آگهی‌دهندگان) و هم در سمت تقاضا (خریداران و جستجوکنندگان) داشته است.برای آگهی‌دهندگان، مهم‌ترین بهبود، بازخورد دقیق و شخصی‌سازی شده بوده است. در سیستم قبلی، وقتی آگهی رد می‌شد، کاربر تنها پیام کلی دریافت می‌کرد: &quot;آگهی شما به دلیل مغایرت با قوانین دیوار رد شد.&quot; اما در سیستم جدید، کاربر دقیقاً متوجه می‌شود کدام بخش از آگهی‌اش مشکل داشته و چرا.برای مثال، اگر عکسی از آگهی حذف شود، کاربر پیامی دقیق مانند این دریافت می‌کند: &quot;عکس شماره [X] شما به دلیل [دلیل دقیق مانند وجود شماره تلفن یا نوشته تبلیغاتی] حذف شد.&quot; این بازخورد دقیق به کاربران کمک می‌کند تا سریع‌تر آگهی خود را اصلاح کنند و از سردرگمی‌های رایج جلوگیری شود.همچنین سرعت بررسی آگهی‌ها به طور چشمگیری افزایش یافته است. در حال حاضر، ۹۷٪ از آگهی‌ها در کمتر از یک دقیقه بررسی می‌شوند و حدود ۹۰٪ در کمتر از ۱۵ ثانیه نتیجه بررسی را دریافت می‌کنند. این در مقایسه با زمان انتظار نیم ساعته یا بیشتر در سیستم قبلی، تحول بزرگی به شمار می‌آید.برای کاربران سمت تقاضا، بهبود کیفیت لیست آگهی‌ها محسوس‌ترین تغییر بوده است. با افزایش دقت در شناسایی آگهی‌های نامناسب، تکراری و با دسته‌بندی اشتباه، کاربران با لیستی باکیفیت‌تر و مرتبط‌تر روبرو می‌شوند که تجربه جستجو و خرید آنها را بهبود می‌بخشد.یکی از بازخوردهای جالب کاربران این بوده که حس می‌کنند قوانین دیوار &quot;منصفانه‌تر&quot; اجرا می‌شود. در سیستم قبلی، گاهی قوانین سخت‌گیرانه‌تر برای کاربران عادی و آسان‌گیرانه‌تر برای &quot;دیواربازها&quot; (کاربرانی که راه‌های دور زدن قوانین را می‌دانستند) اعمال می‌شد. قبلاً کاربرانی با واحد پشتیبانی تماس می‌گرفتند و می‌گفتند: &quot;چطور فروشنده‌ای که جنس قاچاق می‌فروشد آگهی‌اش تأیید می‌شود، اما آگهی من فقط به خاطر یک شماره تلفن مسدود شده؟&quot; این ناهماهنگی بین توانایی تشخیص و شدت تخلف کاربران باعث نارضایتی زیادی می‌شد. اکنون با هوشمندتر شدن سیستم بررسی، دور زدن قوانین بسیار سخت‌تر شده، تشخیص تخلفات با میزان اهمیت آنها متوازن‌تر است و عدالت بیشتری در اعمال قوانین احساس می‌شود.نتایج نهاییپس از پیاده‌سازی کامل سیستم جدید بررسی آگهی مبتنی بر LLM، دستاوردهای چشمگیری حاصل شده است:افزایش اتوماسیون: از ۸۰٪ به ۹۷٪ رسیده است. این یعنی اکنون تنها ۳٪ از آگهی‌ها نیاز به بررسی انسانی دارند.کاهش هزینه‌ها: علی‌رغم افزایش قیمت دلار (از ۶۰ هزار تومان به بیش از ۹۰ هزار تومان)، توانستیم هزینه‌های بررسی آگهی را به نصف کاهش دهیم.بهبود دقت: دقت تشخیص در بسیاری از قوانین مهم بیش از دو برابر افزایش یافته است، به ویژه در حوزه‌های حساس مانند مصادیق مجرمانه و امنیت اخلاقی.افزایش سرعت: ۹۷٪ آگهی‌ها در کمتر از یک دقیقه و ۹۰٪ در کمتر از ۱۵ ثانیه بررسی می‌شوند.انعطاف‌پذیری در تغییر قوانین: زمان مورد نیاز برای اعمال یک قانون جدید از دو هفته به کمتر از یک ساعت کاهش یافته است.بهبود تجربه کاربری: کاربران بازخورد دقیق‌تر و شفاف‌تری دریافت می‌کنند و می‌توانند سریع‌تر آگهی‌های خود را اصلاح کنند.کیفیت بالاتر لیست آگهی‌ها: با تشخیص بهتر آگهی‌های نامناسب، کیفیت کلی آگهی‌های منتشر شده در دیوار افزایش یافته است.علاوه بر این، ما توانستیم یک زیرساخت قدرتمند برای توسعه محصولات مبتنی بر هوش مصنوعی در دیوار ایجاد کنیم که می‌تواند برای بهبود سایر جنبه‌های پلتفرم نیز مورد استفاده قرار گیرد.جمع‌بندیبا نگاهی متفاوت به فرآیند بررسی آگهی، توانستیم با استفاده از مدل‌های زبانی بزرگ، سیستمی را بازطراحی کنیم که با منابع کمتر، زمان پاسخ‌دهی بهتر و کیفیت بالاتری ارائه می‌دهد. اتوماسیون از ۸۰٪ به ۹۷٪ افزایش یافت و هزینه‌های بررسی علی‌رغم افزایش نرخ دلار، به نصف کاهش پیدا کرد. سرعت بررسی آگهی‌ها به کمتر از یک دقیقه رسید و کاربران اکنون بازخوردهای دقیق و شفافی دریافت می‌کنند.مهم‌تر از همه، با تمرکز بر طراحی &quot;LLM Friendly&quot;، توانستیم سیستمی ایجاد کنیم که همگام با پیشرفت‌های هوش مصنوعی، خودکار بهبود می‌یابد. زمان تغییر قوانین از دو هفته به کمتر از یک ساعت کاهش یافته و قوانین برای همه کاربران به طور یکسان و منصفانه اعمال می‌شود.این تغییرات نه تنها کیفیت لیست آگهی‌های دیوار را افزایش داده، بلکه مسیر را برای نوآوری‌های بیشتر هموار کرده است. با ادامه بهبود قوانین و طراحی آنها مخصوص LLM‌ها، و افزودن قابلیت‌های جدید مانند بررسی یکپارچگی فیلدهای آگهی، تجربه کاربری در دیوار روز به روز بهتر خواهد شد.با تشکر ویژه از تیم بررسی آگهی شامل محمود چوپانی، غزل صیادفر و سجاد ایوبی که بازطراحی و توسعه این سیستم هوشمند را بر عهده گرفتند و با تلاش و نوآوری خود، تجربه کاربری در دیوار را به سطح جدیدی ارتقا دادند.</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Tue, 18 Mar 2025 19:29:59 +0330</pubDate>
            </item>
                    <item>
                <title>از الگوهای دسترسی تا معماری: بهینه‌سازی سرویس تصاویر آگهی‌ها</title>
                <link>https://tech.divar.ir/از-الگوهای-دسترسی-تا-معماری-بهینه-سازی-سرویس-تصاویر-آگهی-ها-z7gie7y7mgif</link>
                <description>تصاویر آگهی‌ها یکی از مهم‌ترین بخش‌های دیوار هستند. کاربران هم زمان ثبت آگهی جدید و هم گشت و گذار در دیوار با سرویس مدیریت تصاویر در ارتباط هستند. اگر این سرویس کیفیت خوبی نداشته باشد هم آگهی‌های کمتری ثبت می‌شود و هم برروی تجربه کاربر زمان گشت و گذار در دیوار تاثیر منفی می‌گذارد.در یکی از مقاله‌های قدیمی توضیح دادیم سرویس‌ تصاویر دیوار را چطور طراحی کردیم و چه تصمیم‌هایی گرفتیم که پیشنهاد میکنیم قبل از مطالعه‌ی این مقاله، «دیوار چگونه از میلیون‌ها عکس نگهداری می‌کند؟» را بخوانید.الگوهای دسترسی تصاویر آگهی‌های دیوارمنظور از الگوهای دسترسی داده (Data Access Patterns) الگو‌هایی هستند که کاربر می‌تواند یک داده‌ ، در این مثال یک تصویر، را ذخیره، به‌روز یا دریافت کند. این الگوها تحت تأثیر میزان و نحوه‌ی درخواست تصاویر به‌وسیله‌ی کاربران قرار دارند. به عنوان مثال، دریافت تصاویر پروفایل یک کاربر در یک شبکه‌ی اجتماعی رابطه مستقیم با دنبال‌کنندگان و فعالیت کاربر دارد. در یک سرویس لیستینگ مشابه دیوار نیز الگوی دسترسی کاربران براساس تازگی (Recency) آگهی می‌باشد، به طوری که تصاویر مربوط به آگهی‌های جدیدتر بیشتر از تصاویر پست‌های قدیمی‌تر مشاهده می‌شوند.در دیوار، مفهوم «تازگی» (ًRecency) نقش مهمی در نحوه تعامل کاربران با آگهی‌ها دارد. معمولاً آگهی‌هایی که بیشتر مشاهده می‌شوند، آگهی‌های جدیدتر هستند، چرا که آگهی‌های جدید در بالای لیست می‌آیند و در معرض دید بیشتری هستند. این به این معناست که یک زیرمجموعه کوچک از تصاویر، که مربوط به آگهی‌های جدیدتر هستند، به صورت مکرر دیده می‌شوند در حالی که بیشتر تصاویر ذخیره شده، که مربوط به آگهی‌های قدیمی‌تر هستند، کمتر دیده می‌شوند. درک این الگو به ما این امکان را می‌دهد که استراتژی ذخیره‌سازی خود را بهینه کنیم؛ به این صورت که تصاویر پست‌های جدید را در یک انبار داده سریع‌تر نیز نگه داریم تا دسترسی سریع‌تری داشته باشیم و تجربه کاربری بهتری فراهم شود. به این ترتیب، تصاویر کمتر استفاده شده را می‌توان در یک انبار داده کندتر اما مقرون به صرفه‌تر ذخیره کرد تا بین عملکرد و هزینه تعادل برقرار شود.تغییر و طراحی جدید سرویس تصویرهادر طراحی قبلی، پیش از ثبت آگهی، عکس‌های آپلود شده را در باکتی با نام temp نگهداری می‌کردیم. پس از ثبت آگهی، از این عکس سه کپی گرفته می‌شد و عکس فعلی از باکت temp پاک و در باکت اصلی عکس‌های آگهی نگهداری می‌شد.عکس‌های ‌Thumbnail: عکس‌های بند انگشتی با سایز حدوداً ۲۰۰ در ۲۰۰ پیکسل، در صفحهٔ اول دیوار نمایش داده می‌شود.عکس‌های Post: عکس‌های پست در صفحهٔ آگهی نمایش داده می‌شود. این عکس‌ها با‌نسبتِ ابعاد عکس اصلی، تا ۱۵۰۰ پیکسل کوچک می‌شوند. همچنین، بر روی این عکس‌ها واترمارک قرار می‌گیرد و کیفیت آن‌ها برای کاهش حجم، ۱۰ درصد کم می‌شود.عکس‌های Manage: عکس‌هایی که فقط آگهی‌گذار می‌تواند آن‌ها را در صفحه مدیریت آگهی خود ببیند. این عکس‌ها با نسبت ابعاد عکس اصلی، تا ۳۰۰۰ پیکسل ذخیره می‌شود. این عکس‌ها بدون واترمارک و با کیفیت اصلی نگهداری می‌شود.اما این طراحی برای ما مشکلاتی می‌ساخت.وابستگی ثبت آگهی به فرآیند پردازش عکس‌ها: این وابستگی یک‌طرفه باعث می‌شد زمانی که سرویس عکس کند بود و یا پاسخ‌گو نبود، سرویس ثبت آگهی نیز دچار مشکل شود. همچنین پردازش‌آگهی‌هایی که عکس‌های زیادی داشتند، باعث کند شدن ثبت آن آگهی‌ها می‌شد.حجم زیاد عکس‌ها به‌خاطر چند کیفیت بودن: از هر عکس سه نسخه نگهداری می‌شد که حجم زیادی از فضای ذخیره‌سازی را مصرف می‌کرد.با تحقیق درباره‌ی ابزارهای موجود و بر اساس بنچ‌مارک‌ها تصمیم گرفتیم از ایمیج پروکسی استفاده کنیم. ایمیج پروکسی ابزاری‌ست که پردازش‌های تصویر را به صورت برخط انجام می‌دهد و عکسی را در حافظه نگه‌ نمی‌دارد. از مهم‌ترین ویژگی‌های ایمیج پروکسی این است که عکس‌ها را در لحظه می‌خواند و پردازش‌های تصویر (مثل کاهش کیفیت تصویر، کاهش سایز تصویر، اضافه کردن واترمارک و…) را انجام می‌دهد.با استفاده از ایمیج پروکسی دیگر نیاز به نگهداری سه نسخه از تصویرها نیست، بلکه یک نسخه از آن‌ها نگهداری می‌شود و پردازش تصویرها به کمک ایمیج پروکسی صورت می‌گیرد. با تنظیم سه حالت Thumbnail، Post و Manage عکس‌های مورد نظر توسط ایمیج پروکسی پردازش می‌شود. با این ابزار، به جای نگهداری سه نسخه از عکس‌ها، عکس‌ها را در موقع درخواست پردازش کرده و آن‌ها را نمایش می‌دهیم.پس با این تغییر، دو اتفاق مهم می‌افتد:دیگر فرآیند پردازش تصاویر بر تجربهٔ کاربر در زمان ثبت آگهی تاثیر منفی نمی‌گذارد.به‌جای پیش‌پردازش تصویرها و نگهداری نسخه‌های مختلف از هر عکس، فقط نسخهٔ اصلی را نگهداری می‌کنیم؛ اما هربار، براساس نیاز، زمان درخواست هر تصویر باید پردازش متناسب را داشته باشیم.حال این سوال پیش می‌آید که با استفاده از ایمیج پروکسی حجم بسیار زیادی از فضای ذخیره‌سازی خودمان را کاهش دادیم و این بار را بر دوش  پردازنده‌ها انداختیم. چطور فشار را بر روی پردازنده‌ها کمتر کنیم؟کش کردن خروجی Image Proxyجواب سوال طرح‌شده در سطر آخر بخش قبل، استفاده از CDN و کش پروکسی است. به طور کلی ما ذخیره شدن عکس‌های دیوار را بر روی فضای دیسک حذف نکردیم، بلکه با استفاده از CDN و کش پروکسی از نگهداری همه‌ی نسخه‌های پردازش‌شده‌ی عکس‌ها در آبجکت استوریج، دوری کردیم. یکی از دلایل این تصمیم ماهیت محصولی تصویرها در دیوار است.همیشه عکس‌ها یا آگهی‌های جدید بیشتر از آگهی‌های قدیمی دیده می‌شود. از این رو با استفاده از CDN می‌توانیم عکس‌های اخیر را کش کنیم و عکس‌های پیشین را نیز به خودی خود از نود‌های CDN پاک کنیم. با این کار، با استفاده از یک سیستم خودکار کش، با فضای کمتر و مدیریت راحت‌تر، می‌توان عکس‌ها را بدون پردازش نمایش داد؛ بدون آنکه نیاز باشد از همه‌ٔ عکس‌ها برای مدت طولانی سه نسخه نگهداری کنیم.همچنین یک الگوی دست‌رسی دیگر به داده‌ها در دیوار براساس موقعیت‌ جغرافیایی آگهی‌هاست. یعنی اگر شخصی در شهر مشهد آگهی‌ای ثبت می‌کند، اکثر بازدید‌های آن آگهی نیز از کابران مشهد خواهد بود. استفاده از CDN که لبه‌های آن در موقعیت‌های جغرافیایی مختلف هم توزیع شده است باعث می‌شود تصاویر آگهی‌های هر شهر، بیشتر در لبه‌ی آن شهر (یا نزدیک ترین لبه به آن) درخواست شوند و این روند باعث بهینه‌سازی کش‌ تصاویر آگهی‌ها می‌شود.لبه‌های CDN هرکدام ممکن است برای بارگیری عکس‌ها یک درخواست به ایمیج پروکسی بزنند. پس برای سه نسخهٔ عکس و به تعداد لبه‌های CDN، درخواست‌های زیادی به سوی ایمیج پروکسی روانه می‌شود. برای جلوگیری از بار اضافه بر پردازنده‌ها، از کش پروکسی استفاده کردیم. به این ترتیب، فقط برای اولین درخواست از CDN، درخواست به ایمیج پروکسی می‌رسد و باقی درخواست‌ها به‌وسیله‌ی کش پروکسی پاسخ داده می‌شود. از NginX به عنوان کش پروکسی استفاده کردیم و کش‌ها را با Policy پاک کردن عکس‌های قدیمی تنظیم کردیم.به طور کلی دیاگرام زیر معماری جدید سرویس‌ عکس دیوار را نشان می‌دهد.این راهکار کمک می‌کند تا هر عکس فقط یک‌بار به ایمیج پروکسی و در نهایت یک بار نیز به آبجکت استوریج درخواست بفرستند. دلیل وجود کش پروکسی دقیقاً همین است: که هر لبه‌ی CDN یک درخواست به ایمیج پروکسی ارسال نکند، بلکه فقط همان درخواست اول ارسال شود و باقی درخواست‌ها را کش پروکسی جواب دهد. نتیجهٔ این تمهید باعث شد تا عکس‌های پر بازدید اخیر در کش‌ها بمانند و درخواست‌ها یا از لبهٔ CDN و یا به‌وسیله‌ی کش پروکسی پاسخ داده شود. در نهایت نیز فقط یک نسخه از عکس نگهداری می‌شود.نتایج این طراحی چه بود؟با نگاهی متفاوت این سیستم را بازطراحی کردیم و با استفاده از منابع کمتر، توانستیم زمان پاسخ‌دهی بهتر و کیفیت خدمات بالاتری را به دست آوریم. در نتیجه، بیش از ۵۸ درصد از فضای آبجکت استوریج کاهش داشتیم. همچنین در سرویس جدید با بهینه‌سازی ۴۶ درصد از منابع پردازشی (cpu) و ۳۴ درصد از منابع حافظه‌ (memory) صرفه‌جویی کردیم. این صرفه‌جویی‌ها روی هم رفته حدود ۶ درصد ماهانه در آن زمان از هزینه‌ی زیرساخت ما کم کرد.با معماری جدید، پردازش‌های تصاویر دیگر در زمان ثبت آگهی انجام نمی‌شدند و تأثیر منفی بر تجربه کاربری ثبت آگهی نداشتند. این تغییر باعث افزایش تعداد آگهی‌های عکس‌دار در دیوار شد و در نهایت، بر کیفیت آگهی‌ها نیز تأثیر مثبت گذاشت.با تشکر ویژه از سیاوش گنجی، مهندس نرم‌افزار پیشین در دیوار که وظیفه این بازطراحی را بر عهده گرفته بود و تجربیات خودش را برای نوشتن این مقاله به اشتراک گذاشت.</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Thu, 19 Sep 2024 10:09:51 +0330</pubDate>
            </item>
                    <item>
                <title>پشت پردهٔ تیم زیرساخت دیتای دیوار!</title>
                <link>https://tech.divar.ir/پشت-پرده-تیم-زیرساخت-دیتای-دیوار-nnuklui8qclg</link>
                <description>جمله معروفی درباره شرکت‌های نرم‌افزاری وجود دارد: «اگر آن شرکت پروژه‌هایش را  میکرو سرویس نکند، نمی‌تواند رشد و توسعه پیدا کند». اما به جز این مورد، توصیه مهم دیگری هم وجود دارد: «اگر شرکتی تصمیم‌های محصولی مبتنی بر دیتا را مد نظر قرار ندهد، نمی‌تواند رشد کند.» برای همین نقش data engineer برای شرکت‌های بزرگ با دیتاهای بزرگ و متنوع به شدت اهمیت پیدا می‌کند.دیوار هم از این قاعده مستثنی نیست و با داشتن بیشتر از ۳۵ میلیون کاربر فعال، این موضوع برایش اهمیت ویژه‌ای پیدا می‌کند. متخصصین data engineer‌، تیم زیرساخت دیتای دیوار رو شکل می‌دهند و هدفشان این است که تصمیم‌گیری‌های محصولی مبتنی بر دیتا را دقیق‌تر، سریع‌تر  و  راحت‌تر کنند.اصلی‌ترین استفاده کننده‌های دیتا در دیوار data scientist ها، data analyst ها، business intelligence‌ها هستند که به طور مستقیم خروجی کارها و تحلیل‌های آنها، در تصمیم‌گیری‌های محصولی تاثیر می‌گذارد. هر چه‌قدر این تحلیل‌ها دقیق‌تر باشند  و سریع‌تر انجام شوند، تصمیم‌های بهتری در سطح محصول گرفته شده و به رشد شرکت کمک خواهد کرد.متخصصین data engineer معمولاً چه کارهایی انجام می‌دهند و چه مسئولیت‌هایی دارند؟وظیفه اصلی یک data engineer طراحی و پیاده‌سازی پایپلاین‌های بیگ دیتاست؛ تا تمرکز استفاده کننده‌های دیتا تا حد ممکن فقط روی خود دیتا باشد و وقت و تمرکزشان را برای جمع‌آوری نگهداری، تمیزسازی و کارهایی از این دست روی دیتا صرف نکنند.از طرفی هم با حجیم و متنوع شدن دیتا، کارهای مربوط به جمع آوری و نگهداری و در کل آماده‌سازی داده خام به شکل مناسب، پیچیده و تخصصی می‌شود.پایپلاین دیتا هم به طور خلاصه به تمام مراحل از تولید دیتا تا ذخیره‌سازی و خواندن نهایی آن گفته می‌شود. در شکل زیر یک شِمای کلی و بدون جزئیات از پایپلاین‌های دیتا را مشاهده می‌کنید.از وقتی که دیتا تولید می‌شود تا وقتی که به دست استفاده‌کننده برسد، تغییرات زیادی بر روی آن انجام می‌شود که همه این تغییرات، جزئی از پایپلاین دیتای مورد نظر به حساب می‌آید.شاید اسم بیگ دیتا را زیاد شنیده باشیم، اما به چه چیزی بیگ دیتا گفته می‌شود؟به دیتایی که یکی از سه ویژگی زیر را داشته باشد، بیگ دیتا می‌گوییم:حجم بسیار زیادی داشته باشد.تنوع بسیار زیادی داشته باشد.با rate خیلی زیادی دریافت شود.اگر دیتا در هر کدام از زمینه‌های بالا پیچیدگی داشته باشد، با روش‌های معمول نمی‌توان با آن کار کرد و به ابزار و دانش خاصی برای کار کردن با آن نیاز داریم؛ دانشی که گاهی اوقات به آن «دانش بیگ دیتا » می‌گوییم.در ادامه یکی از پایپلاین‌های مهم و پر چالش دیتای دیوار را بررسی می‌کنیم.یکی از مهم‌ترین دیتاها در دیوار اکشن‌لاگ کاربرهای دیوار است. این دیتا شامل تمام رفتار کاربرها روی اپلیکیشن (و سایت) دیوار از وقتی است که برنامه را باز می‌کنند. قسمت‌هایی که کاربران به آن سر می‌زنند و بخش‌هایی که بر روی آن کلیک می‌کنند. در کل با هر حرکت کاربر در برنامه دیوار یک request اکشن لاگ برای ما ارسال می‌شود که به آن یک اکشن می‌گوییم. این اکشن‌ها به صورت بسته‌های ۵ تایی برای ما ارسال می‌شوند. فایده این کار این است که باعث می‌شود تعداد request های اکشن لاگ خیلی پایین‌تر بیاید. بنابراین هم دریافت آن برای ما ساده‌تر است و هم باتری‌ گوشی‌های کاربرهای دیوار دیرتر تمام می‌شوند :)برای اینکه یک دید کلی از میزان بزرگی این دیتا بدست بیاورید، به نمودار زیر دقت کنید:همان‌طور که می‌بینید در ساعات اوج مصرف تعداد request های اکشن لاگی که سمت ما می‌آید نزدیک 6k بر ثانیه‌ست . یعنی 30 هزار تا اکشن در هر ثانیه.چه‌طور  این دیتا با این وسعت را جمع‌آوری و ذخیره می‌کنیم؟اولین و مهم‌ترین چالش این دیتا، rate و حجم بسیار بالای آن است. در گام اول ما سرویسی طراحی کردیم که request های اکشن لاگ کاربرها را دریافت می‌کند، batch ها را باز می‌کند (جدا کردن ۵ اکشن) و برای سرویس دیگری می‌فرستد (که در ادامه درباره آن صحبت می‌کنیم). به سرویسی که اکشن‌لاگ‌ها را دریافت می‌کند actionlogger می‌گوییم. ویژگی مهم این سرویس stateless بودن آن است. بنابراین ما می‌توانیم به راحتی instance های مختلف آن را بالا بیاوریم که در کنار هم به طور موازی این کار را انجام دهند و فشار بین آنها تقسیم شود. actionlogger  را بر روی کلاستر kubernetes بالا آوردیم که بالا نگه داشتن تعداد instance مورد نظر را انجام داده و اگه یکی از دست رفت، instance دیگری جایگزین کند. بعد از آن actionlogger این اکشن‌ها را برای سرویس دیگری به نام  fluentd می‌فرستد که مثل یه صف عمل خواهد کرد. fluentd  یک ابزار log collector و opensource هست که ما برای جمع‌آوری و ارسال  اکشن‌ها از آن استفاده می‌کنیم. اگر تمایل به آشنایی بیشتر با آن دارید می‌توانید اینجا را ببینید. علت اینکه  fluentd را به پایپلاین اضافه کردیم این بود که دیتا را بر روی هارد و مموری بافر کند و اگر مقصد مشکلی برای دریافت دیتا داشت به actionlogger فشار نیاید و دیتا هم از دست نرود. fluentd هم مثل actionlogger چون stateless هست تعدادی instance آوردیم بالا و یه کلاستر تشکیل دادیم. تعداد ریکوئست‌های سمت fluentd در ساعت اوج که بر اساس اکشن جدا شده اند  به 30k بر ثانیه می‌رسد.مسئله‌ای که در این مرحله مطرح می‌شود، شیوه و محل ذخیره سازی دیتاست. حجم این دیتا در روز به حدود ۳ الی ۴ ترابایت می‌رسد. پیش از هرچیز به فشرده‌سازی دیتا فکر کردیم. fluentd چنین  قابلیتی را در اختیارمان می‌گذارد که دیتای خروجی را به صورت فشرده‌شده تحویل دهد. دیتای اکشن لاگ به صورت فشرده‌شده از ۳ الی ۴ ترابایت در روز به ۳۰۰ الی ۴۰۰ گیگ کاهش پیدا می‌کند و شرایط را بهبود می‌دهد؛ ولی همچنان اگر روزی ۴۰۰ گیگ دیتا (دقت کنید فقط دیتای خام) را ذخیره کنیم در یک سال  حدود ۱۴۰ ترابایت فضا لازم داریم. این موجود ایجاب می‌کند تا برای ذخیره این حجم داده روش‌های دیگری را امتحان کنیم. در دانش بیگ دیتا سیستمی رایج و مشهور برای ذخیره سازی دیتا وجود دارد به نام Hadoop Distributed File System یا HDFS.همان‌طور که از نام آن مشخص است، hdfs یک فایل سیستم توزیع شده‌ است که به جای ذخیره‌سازی دیتا بر روی یک سرور، می‌تواند دیتا را به صورت توزیع‌شده روی مجموعه‌ای از سرورها ذخیره کند. برای آشنایی بیشتر با هدوپ می‌توانید به این لینک سر بزنید.با توجه به نکاتی که گفته شد، تا این مرحله پایپلاین اکشن لاگ دیوار به این شکل رسیده است:این دیتا را چطور برای استفاده تحلیل‌گرها آماده کنیم؟تا این مرحله دیتا را به صورت خام ذخیره کردیم. ولی این دیتا هنوز قابل استفاده نیست. دیتا باید تغییر کند، تمیز شود و فرمت آن هم متناسب با نیازها باشد. حجم این دیتا زیاد است و کوئری اجرا کردن روی این دیتا  کار آسانی نیست.برای تمیز کردن دیتا نیاز به یک ابزار محاسباتی قوی داریم که بتواند این حجم دیتا را بخواند، محاسبات لازم را بر روی آن انجام دهد و تمیزش کند. یک ابزار رایج و مشهور در دانش بیگ دیتا Apache Spark است. Spark یک موتور محاسباتی توزیع شده‌ مبتنی بر map reduce است. (مفهوم map reduce از ظرفیت این مقاله خارج است اما اگر علاقه‌مند  بودید می‌توانید این لینک را ببینید).حالا که ابزار مناسب برای خواندن دیتا و محاسبه بر روی آن را در اختیار داریم، این دیتا را می‌خوانیم، با spark تمیزش  می‌کنیم و خروجی را با فرمت apache parquet که روی روز / ساعت / اکشن پارتیشن شده و به صورت snappy فشرده شده‌ است ذخیره می‌کنیم. شاید این بخش از مطلب به توضیح بیشتری نیاز داشته باشد؛ فرمت parqeut یک فرمت ذخیره سازی ستونی است ( Column-oriented_DBMS ) که به جای ذخیره سطر به سطر، دیتا را ستون به ستون ذخیره می‌کند. به زبان ساده، این قابلیت کمک می‌کند تا وقتی یک نفر به ستون‌های خاصی از دیتا نیاز دارد (که معمولا دیتاساینتیست‌ها به همین شکل از دیتا استفاده می‌کنند)  فقط هزینه‌ی خواندن ستون‌های مورد نیازش را بپردازد و هزینه‌ای برای بقیه ستون‌ها پرداخت نکند. مساله بعدی پارتیشن کردن دیتا با توجه به روز و ساعت و اکشن است. با پارتیشن کردن به این شکل، هزینه فیلتر کردن‌های متداول کمتر شده  و در کل میزان خواندن دیتا برای رسیدن به دیتای مورد نظر  کاهش پیدا می‌کند.مطلب بعدی ذخیره سازی با فرمت snappy است. تمرکز فشرده‌سازی snappy بر مصرف کم cpu و سرعت است و هدف آن این است که با مصرف کم cpu بتوان فشرده‌سازی یا خارج کردن از حالت فشرده را  سریع انجام داد. این موضوع به ما کمک میکند تا بتوانیم دیتا را با سرعت بیشتری بخوانیم، علاوه بر آن  spark هم با این فرمت به خوبی سازگار است. در کل نسبت به gzip فشرده سازی کمتری ارائه میدهد، اما از آن جایی که برای ما سرعت و سی پی یو اهمیت بیشتری داشت، snappy را انتخاب کردیم.در تیم دیتا جاب‌های تمیز‌سازی اکشن لاگ را به صورت ساعتی اجرا می‌کنیم. برای زمان‌بندی کردن این جاب‌ها از ابزاری به اسم Apache Airflow استفاده می‌کنیم که امکانات خوبی برای ما فراهم می‌کند.  Airflow تسک‌ها رو به ترتیب و با زمان‌بندی مشخص بر روی spark اجرا می‌کند، مانیتورینگ راحتی ارائه می‌دهد تا اگر تسک‌هایمان به مشکل  برخوردند سریعا متوجه شویم.این گراف تسک‌های تمیز‌سازی اکشن لاگمان  را نشان می‌دهد که به صورت ساعتی اجرا می‌شوند. ابتدا fluentd‌ها flush می‌شوند که دیتای باقی مانده در  بافرها خالی شده و بعد از آن تمیز‌سازی آغاز می‌شود.تحلیل‌گرها چطور با این دیتا کار می‌کنند؟تا اینجا دیتا آماده شده و قابل استفاده است. در این مرحله تنها باید ابزارهای مناسب را در اختیار بچه‌ها قرار دهیم تا کار تحلیل را شروع کنند. ما ابزار Apache zeppelin  را برای بچه ها فراهم کردیم. مهم‌ترین ویژگی‌ زپلین این است که راحت به spark وصل می‌شود و می‌تواند از موتور spark برای انجام محاسبات استفاده کند.علاوه بر ابزار زپلین، تابع‌هایی برای خواندن و کار کردن با دیتا که اصطلاحا ETL نامیده می‌شوند توسط تیم ما به بچه‌ها ارائه می‌شود تا بتوانند راحت‌تر با دیتاها کار کنند.پس در نهایت پایپلاین دیتای اکشن لاگ دیوار به این شکل است:پایپلاین‌های دیگری هم وجود دارد که طراحی‌، پیاده‌سازی و نگهداری آنها در تیم زیرساخت داده انجام می‌شود تا تحلیل‌کننده‌هایدیتا بتوانند راحت‌تر با آن کار کنند.این  مقاله، خلاصه‌ای از فعالیت‌های تیم زیرساخت داده دیوار بود. این تیم تلاش می‌کند تا با استفاده از به‌روزترین ابزارها، راه حل‌های اثربخشی برای چالش‌ها ارائه دهد و با بررسی مستمر فرآیندها، روش‌های انجام کار را بهبود دهد.در نتیجه بهبود عملکرد تیم زیرساخت داده، استفاده کننده‌های دیتا سریع‌تر و راحت‌تر به خروجی‌های مورد نظر خود دست پیدا می‌کنند و این موضوع، به افزایش کیفیت تصمیماتی که در سطح محصول و بیزنس گرفته می‌شود، کمک زیادی می‌کند.</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Tue, 26 Jan 2021 19:50:48 +0330</pubDate>
            </item>
                    <item>
                <title>تشخیص پلاک در آگهی‌های خودرو با استفاده از بینایی ماشین-بخش دوم</title>
                <link>https://tech.divar.ir/تشخیص-پلاک-در-آگهیهای-خودرو-با-استفاده-از-بینایی-ماشین-قسمت-دوم-vl8fq1fcga9w</link>
                <description>مقدمهاین نوشته، قسمت دوم از مقاله مربوط به سرویس محو پلاک خودرو در دیوار است. در نوشته اول به تعیین مسئله و بیان اهداف‌مان پرداختیم و راه‌حل‌های موجود را بررسی کردیم. هدف ما از نگارش نوشته اول این بود که پیش‌زمینه لازم را درباره کاری که انجام داده‌ایم داشته‌باشید. در این نوشته، به بررسی راهکارهایی که امتحان کرده‌ایم می‌پردازیم و روند پیاده‌سازی سرویس را توضیح می‌دهیم.چه راهکارهایی را در نظر گرفتیم؟سرویس محو پلاک دارای دو مولفه مهم است:۱. یافتن موقعیت پلاک در تصویر۲. محو پلاک (مات کردن یا اعمال واترمارک)عمل محو پلاک به تنهایی پیچیده نیست. چالش اصلی مشخص کردن محل پلاک در تصویر است. در نوشته اول، سه روش کلی را برای آن مشخص کردیم:۱. الگوریتم‌های پردازش تصویر۲. مدل‌های شبکه عصبی تشخیص شئ۳. مدل‌های شبکه عصبی بخش‌بندیدر گام نخست الگوریتم‌های پردازش تصویر برای ما جذابیت بیشتری داشتند. استفاده از آن‌ها ساده است، کارکرد واضحی دارند، نیازی به فراهم آوردن دیتاست به منظور یادگیری نیست و همچنین سرعت اجرای به مراتب بالا‌تری نسبت به شبکه‌های عصبی دارند. این دلایل باعث شد در ابتدا به سراغ این روش‌ها برویم؛ به امید اینکه خروجی کار دقت مطلوبی داشته باشد.در صورت موفق نبودن راهکار اول، به عنوان یک راهکار جایگزین می‌بایست بین مدل‌های تشخیص شئ و مدل‌های بخش‌بندی یک راه حل را انتخاب می‌کردیم. چرا که متاسفانه امکان تست کردن و مقایسه کردن هر دو روش به دلیل هزینه بالای آن‌ها وجود نداشت. توسعه یک مدل شبکه‌ عصبی شامل مراحل مطالعه و تحقیق، آماده‌سازی دیتا، انتخاب معماری، پیاده‌سازی، آموزش مدل و ارزیابی آن بر روی دیتای تستی است که همه‌‌ی حالت‌های ممکن را در بر‌ داشته‌باشد. در نتیجه لازم بود که به انتخاب یک راهکار بسنده کنیم. در انتها با استناد به بررسی‌ها و تجربه‌های گذشته، مدل‌های تشخیص شئ را به دلایل زیر انتخاب کردیم:مدل تشخیص شئ برای هر پلاک یک BBox تولید می‌کند و این دقیقا همان چیزی بود که برای محو پلاک نیاز داشتیم. به صورت شهودی، یافتن BBox عمل ساده‌تری نسبت به مشخص کردن تمام پیکسل‌های یک شئ است. بنابراین انتظار داریم که خطای این کار کمتر باشد.تقریبا تمام مدل‌های بخش‌بندیِ قدرت‌مندی که وجود دارند، از نوع سنگین هستند. بعضی‌‌ از آن‌ها حتی بر روی GPU به کندی (کمتر از 3 FPS) اجرا می‌شوند، در نتیجه عملکرد آن‌ها بر روی CPU کاملا نامطلوب خواهد بود. بنابراین نیاز بود یکی از این دو راه را پیش بگیریم: بک‌بن این مدل‌ها را با شبکه‌های سبک‌تری جایگزین کنیم یا به طور کلی به سراغ معماری‌های سبک‌تر و ساده‌تر برویم. در هر صورت باید این پیامد را می‌پذیرفتیم که مدل‌ میزان قابل‌توجهی خطا خواهد داشت. هر‌چند امکان خطا در یک مدل هوش‌مصنوعی، امری طبیعی‌ست و ما هیچ‌گاه انتظار خروجی ۱۰۰درصد را نداشته‌ایم، اما این خطاها در مدل‌های بخش‌بندی به میزان بیش‌تری نسبت به مدل‌های تشخیص شئ خودنمایی کرده و کار را سخت‌تر می‌کنند. به عنوان مثال این مدل‌ها معمولا برای پیکسل‌های کرانه (Boundary) اشیا، خطای بیشتری دارند و تعدادی قابل توجهی پیکسل ممکن است False Positive و False Negative شوند. از آن‌جایی که می‌خواهیم چهارضلعی پلاک را به طور دقیق مشخص کنیم، باید الگوریتمی پس‌پردازشی طراحی کنیم که نسبت به این خطاها مقاوم باشد و بتواند چهارضلعی پلاک را با توجه به خروجی مدل تشخیص دهد. ممکن است بتوانیم این مشکل را با اعمال تعدادی تبدیل مورفولوژیک حل کنیم، اما در نهایت دقیقا معلوم نیست این کار چه میزان از مشکل را حل می‌کند.در بخش‌بندی معنایی، متمایز کردن نمونه‌های یک کلاس از یکدیگر اهمیتی ندارد. به عنوان مثال، اگر چند پلاک خودرو در تصویر داشته باشیم، تمایزی بین پیکسل‌های مربوط به هر پلاک‌ تشخیص داده نمی‌شود. این مشکل،  در ادامه کار ما را پیچیده می‌کند چون‌که به داشتن این تمایز نیاز داریم. از‌ آن‌جایی‌که مسئله‌ مورد نظر ما یک کلاس بیشتر ندارد، شاید بتوان این مشکل را در پس‌پردازش حل کرد. یک راه‌حل احتمالا این است که پیکسل‌های پلاک‌ها را کلاستر کنیم تا مشخص شود هر پیکسل متعلق به کدام پلاک است. اما اندازه کلاستر رو چند در نظر بگیریم؟ راه‌حل دیگر این است که مولفه‌های هم‌بند را به کمک Connected Component Analysis پیدا کنیم. اما این‌ کار برای چند درصد موارد پاسخگوست؟ممکن است این سوال برای شما پیش‌آمده باشد که برای حل مشکل متمایز کردن نمونه‌ها، چرا به سراغ بخش‌بندی نمونه‌ای نرویم؟ نکته‌ی مهم در اینجا این است که اکثر این شبکه‌ها بر پایه‌ مدل‌های تشخیص شئ هستند. بنابراین مسئله بیشتر وابسته به این است که مولفه تشخیص شئ چقدر خوب کار می‌کند. در نتیجه به‌جای بخش‌بندی نمونه‌ای، بهتر نیست در ابتدا سراغ شبکه‌های تشخیص شئ برویم و در صورت نیاز، معماری مربوط به بخش‌بندی را به آن‌ها اضافه کنیم؟دلایلی که به آن‌ها اشاره کردیم، الزاما به این معنی نیستند که مدل‌های بخش‌بندی انتخاب بدی هستند. اما اگر بخواهیم در کنار مدل‌های تشخیص شئ به آن‌ها نگاه کنیم و مقایسه کنیم کدام یک چالش‌های کمتری برای ما دارد، در این صورت مدل‌های تشخیص شئ انتخاب بهتری خواهند بود.بخش اول - مشخص کردن محل پلاکقدم اول - استفاده از روش‌های پردازش تصویربرای این قسمت، ما تقریبا تمام الگوریتم‌هایی که در نوشته اول نام بردیم، امتحان کردیم.در ابتدا برای انجام Edge Detection از Canny استفاده کردیم. بر روی آرگومان‌های کران بالا و پایین رنگ‌ Canny  یک عمل بهینه‌سازی را پیش بردیم به این صورت که این کران را با استفاده از توزیع رنگ‌ها، در هر چنل رنگ تصویر ورودی محاسبه می‌کردیم. کار دیگری که برای بهبود آن انجام دادیم این بود که متوجه شدیم اگر قبل از اعمال Canny، یک Gaussian Blur پیاده‌سازی کنیم، نتایج بهتری خواهیم داشت. در نهایت چند تبدیل مورفولوژیک (Morphological Transformations) را برای حذف نویز‌ها انجام دادیم.از میان الگوریتم‌هایی که امتحان کردیم، Hough Transform و یافتنِ کانتورِ مربوط به پلاک، بهترین نتایج را داشتند. اما هر یک، دچار نقص‌های مختلفی بودند.در تبدیل Hough، این هدف را دنبال می‌کردیم که پاره‌خط نسبتا موازی‌ای که تشکیل یک چهارضلعی می‌دهند را پیدا کنیم. از آن‌جایی که رزولوشن تصویر ورودی خیلی بالا نبود، در مواردی که پلاک در تصویر نسبتا کوچک بود، تبدیل Hough به درستی نمی‌توانست پاره‌خط‌های چهارضلعی پلاک را پیدا کند زیرا این پاره‌خط چند تکه و شکسته بود. تلاش کردیم که تبدیل Hough را با پارامتر‌های مختلف اجرا کنیم اما برای هر نمونه متفاوت بود و از یک قانون کلی پیروی نمی‌کرد.در تلاشی که برای یافتن کانتور پلاک داشتیم، به نتایج بهتری رسیدیم اما همچنان کاستی‌هایی وجود داشت. نکته‌ای که باید در نظر داشت این بود که تمام الگوریتم‌هایی که امتحان کردیم، وابسته به انجام بهینه Edge Detection هستند. در صورتی‌که در این بخش خطایی وجود داشته باشد، این خطا به الگوریتم‌های پس از آن نیز نشر داده می‌شود. هنگامی که روشنایی تصویر یا زاویه آن غیرطبیعی بود، این خطا در جداسازی کرانه‌ها خودش را بیشتر نشان می‌داد و این به تنهایی موجب می‌شد کانتور پلاک با اشکال اطراف آن ترکیب شود و یا اینکه کانتور آن به صورت ناقص بدست آید.در نهایت بهترین نتیجه‌ای که به‌دست آوردیم، پیدا کردن ۶۰درصد پلاک‌ها به صورت کاملا صحیح بود. این میزان با هدف ۹۵٪ ای که تعیین کرده بودیم فاصله زیادی داشت! یک راه‌حلی که برای بهبود نتیجه در نظر داشتیم این بود که تمام این روش‌ها را با هم ترکیب کنیم و به کمک یکدیگر، نقص‌های آن‌ها را پوشش دهیم. اما در واقعیت امیدوار نبودیم که به آن دقتی که مدنظر داریم می‌توانیم برسیم و در عین حال باید حواس‌مان به زمان محدودی که در اختیار داشتیم می‌بود. بنابراین تصمیم گرفتیم که به سراغ شبکه‌های عصبی برویم و در صورت نیاز، از روش‌های پردازش تصویر نیز استفاده کنیم.قدم دوم - آماده‌سازی دیتاست پلاکاز آن‌جایی که تصمیم گرفته بودیم از مدل‌های شبکه عصبی استفاده کنیم، لازم بود که دیتاستی از تصاویر پلاک به همراه Annotation آن‌ها (همان Ground truth) داشته باشیم. برای این کار حدود ۲۰۰۰۰ تصویر از خودرو آماده کردیم و تیمی دیگر مسئول آن شد که با استفاده از ابزار VGG Annotator، گوشه‌های تمام پلاک‌های موجود در تصاویر را مشخص کنند. مزیت مشخص کردن نقاط گوشه این است که BBox هر پلاک را می‌توانیم با استفاده از نقاط گوشه محاسبه کنیم و در مدل‌های تشخیص شئ از آن‌ها استفاده کنیم. هم‌چنین اگر لازم بود که اسکلت اصلی پلاک را داشته باشیم، می‌توانیم مستقیما از نقاط استفاده کنیم.در نگاه اول ممکن است این‌گونه به نظر نرسد اما زمان قابل توجهی را صرف آماده سازی دیتاست کردیم. با توجه به نیازهای‌مان، دیتاست را در چند مرحله آماده کردیم و در هر مرحله می‌بایست Annotation دیتای جدید را با Annotation قدیمی ترکیب می‌کردیم. در هر گام نیاز بود که فایل‌های JSON بدست آمده از VGG Annotator را از لحاظ صحت و کیفیت بررسی کرده و Annotation ها را به فرمت استاندارد COCO تبدیل می‌کردیم. مزیت استفاده از این فرمت این بود که می‌توانستیم از پکیج pycocotools به منظور Visualization دیتا و همچنین از معیارهای آن برای ارزیابی دقت مدل استفاده کنیم.به طور کلی آماده سازی دیتا همواره برای ما عذاب آور بود و تخمین‌هایی که از زمان انجام شدن کار داشتیم، غالبا اشتباه از آب در می‌آمد.قدم سوم - ارائه یک مدل تشخیص شئ (YOLO)خوشبختانه طی چند سال اخیر شبکه‌های عصبی تشخیص شئ پیشرفت بسیار چشمگیری از نظر دقت داشتند که لیستی از بهترین‌ها را اینجا می‌توانید ببینید. در کنار دقت، نکته‌ مهم دیگری که وجود دارد این است که شبکه‌، سرعت اجرای کمتر از ۴۰۰میلی‌ثانیه بر روی CPU داشته باشد. واژه CPU اینجا کلیدی است چرا که سرعت اجرا بر روی CPU نسبت به GPU چندین برابر کم‌تر است و اکثر شبکه‌های قدرتمندی که امروزه وجود دارد بیشتر از۲ ثانیه زمان برای اجرا لازم دارند. بنابراین لازم بود بین سرعت و دقت شبکه، سبک سنگین کنیم و به سراغ شبکه‌های کمی ضعیف‌تر برویم.در نهایت به سه مدل زیر رسیدیم:YOLO3Detectron2SSDبرای آموزش YOLO3 از این پیاده‌سازی استفاده کردیم (در آن زمان هنوز YOLO4 منتشر نشده بود). این پیاده‌سازی متکی بر فریم‌ورک Darknet است. صادقانه بگوییم این فریم‌ورک مناسبی برای توسعه دادن نیست. اما سه علت مهمی وجود داشت که باعث شد آن را انتخاب کنیم:۱. مدلی که روی ‌دارک‌نت آموزش داده شده را می‌توان با استفاده بک‌اند OpenCV نیز اجرا کرد و جالب‌ اینکه در این مورد خاص، به میزان ۲۰ درصد اجرا سریع‌تر نسبت به  پیاده‌سازی‌های TensorFlow و PyTorch خواهد بود.۲. این پیاده‌سازی multi-scale training انجام می‌دهد، به این معنی که هنگام آموزش مدل، تصاویر ورودی را با سایز‌های مختلف به شبکه می‌دهد. این در حالی‌ست که در پیاده‌سازی‌های دیگر این قاعده رعایت نشده یا اینکه لاجیک پیاده‌سازی آن با مقاله اصلی متفاوت بوده است.۳. آموزش مدل خیلی راحت انجام شد. کافی بود Annotation ها را به فرمتی که دارک‌نت می‌خواهد تبدیل می‌کردیم.نتیجه آموزش این شد دقت مدل بر روی دیتای تست به 97% Precision و 94% Recall با آستانه IoU 0.5 رسید و همچنین به Average IoU 0.78 برای BBoxهای پیش‌بینی شده رسیدیم که برای ما خیلی مطلوب بود. سرعت اجرا چیزی حدود ۳۰۰میلی‌ثانیه بر روی CPU با ۸ هسته بود. بعد از آن، محو پلاک با استفاده از Gaussian Blur را اضافه کردیم که چیزی حدود ۲۵میلی‌ثانیه بر این زمان اجرایی اضافه کرد.مورد دیگری که امتحان کردیم Detectron2 بود؛ کتاب‌خانه‌ای از Facebook AI Research که به منظور تشخیص شئ و بخش‌بندی به کار می‌رود. معماری شبکه‌ای که Detectron از آن پشتیبانی می‌کند، شبکه‌های Faster R-CNN بهینه شده با بک‌بن‌های متفاوت است. ما برای آموزش، یک نسخه سبک‌ از آن را انتخاب کردیم و در کمال تعجب آموزش مدل، کمتر از۱۰ دقیقه طول کشید! نتایجی که به آن رسیدیم تا حد زیادی مشابه YOLO بود (حدود یک درصد بهتر بود) و روند آموزش نیز ساده بود. اما نکته قابل توجهی که وجود داشت این بود که زمان اجرای آن کمی بیشتر از ۱‌ثانیه بود در حالی که زمان اجرای YOLO یک سوم این مقدار بود.برای شبکه SSD در نظر داشتیم که آن را با یک بک‌بن سبک مثل MnasNet امتحان کنیم اما در نهایت منصرف شدیم  چون قدیمی شده بود و اینکه طبق آمار رسمی، دقت آن نسبت به YOLO بر روی دیتاست COCO کم‌تر بود. از طرفی از نتایجی که با استفاده از YOLO گرفته بودیم راضی بودیم و برای همین با این مدل پیش رفتیم.تا اینجای کار ما به ۳ معیار اصلی‌ که برای محو پلاک تعیین کرده بودیم، دست پیدا کرده بودیم. از این لحظه به بعد تمرکز‌مان را روی توسعه سرویس به منظور چسباندن واترمارک بر پلاک گذاشتیم.قدم چهارم - طراحی مدلی برای مشخص نمودن گوشه‌های پلاکتا اینجای کار ما توانستیم Bounding Box (یا به طور خلاصه‌تر BBox) مربوط به هر پلاک را مشخص کنیم. ولی آیا این برای چسباندن واترمارک کافی‌ست؟ در حالت‌هایی که پلاک کمی چرخش به علت زاویه تصویر گرفته شده دارد، باعث می‌شود BBox با پلاک فیت نشده و مساحت بیشتری را پوشش دهد. مثال‌های زیر نشان می‌دهد که برای اعمال واترمارک در این حالت‌ها نیاز داریم چهارضلعی پلاک را به طور دقیق به دست بیاوریم تا بتون که برای اعمال واترمارک در این حالت‌ها نیاز داریم چهارضلعی پلاک را به طور دقیق به دست بیاوریم تا بتونیم واترمارکی با کیفیت مناسب داشته باشیم. اما این‌کار را چطور می‌توان با محدودیت‌های مدل YOLO مورد نظر مان انجام دهیم؟روندی را که پیش گرفتیم این بود که در ابتدا با استفاده از مدل YOLO، تمام نمونه پلاک‌های موجود در تصویر را پیدا کنیم و سپس برای هر نمونه، به طور محلی مشخص کنیم که چهارضلعی پلاک دقیقا به چه صورت است. پس مسئله جدید این خواهد بود که با داشتن یک تصویر محلی از پلاک، به طور دقیق‌تر چهارضلعی آن را مشخص کنیم.برای این کار یک‌بار دیگر سراغ روش‌های پردازش تصویر رفتیم و به طور خاص Hough Transform و Largest Contour را امتحان کردیم. اما متاسفانه نتایج‌ با آن‌که نسبت به حالت اول بهبود زیادی داشتند، در حالت‌هایی که تصویر از زوایای خیلی کج ثبت می‌شد، خطا بالا می‌رفت و در مواردی که روشنایی تصویر غیرعادی بود (خیلی تاریک یا خیلی روشن)، الگوریتم Edge Detection خطای زیادی در جداسازی کرانه‌ها داشت و این خطا در گام‌های بعدی نیز نشر داده می‌شد. تلاش‌هایی برای میزان کردن Edge Detection روی این موارد داشتیم اما نتایج خیلی دلچسب نبود.اینجا بود که تصمیم گرفتیم از یک مدل CNN سبک برای این‌کار استفاده کنیم. انتظار داشتیم پس از اینکه  تصویر پلاک را به مدل دادیم، چهار راس گوشه مربوط به پلاک را پیش‌بینی کند. اگر چهار راس پلاک را داشته باشیم، در این صورت می‌توانیم واترمارک را به درستی بر آن اعمال کنیم.اگر به یاد داشته باشید Annotation‌های مربوط به چهار گوشه پلاک را در دیتاست‌ داشتیم. بنابراین از جهت دیتا محدودیتی برای این کار وجود نداشت. برای شبکه از معماری Resnet-18 استفاده کردیم که کوچک‌ترین شبکه از خانواده ResNet است. برای ورودی مدل، تصویر پلاک را به یک سایز مشخص در می آوریم و برای خروجی مدل، مختصات گوشه‌های پلاک را با توجه به طول و عرض تصویر، به گونه‌ای نرمال می‌کنیم تا در بازه‌ی ۱- و ۱ قرار گیرد. یعنی اگر مختصات X یک راس در وسط تصویر باشد، به ۰ تبدیل می‌شود و اگر به ۱- تبدیل شود، به این معنی است که در ابتدای تصویر قرار داشته‌است. تصویر زیر یک مثال از این نرمال‌سازی است:با توجه به تبدیل فوق، تابع خطا را Smooth L1 در نظر گرفتیم که برای این ‌گونه پیش‌بینی‌ها رایج است. کل روند آموزش مدل را با استفاده کتاب‌خانه fastai انجام دادیم. fastai یک کتاب‌خانه متکی بر PyTorch است که خیلی کارها مثل Data Generation ،Augmentation ،Transfer Learning ،Visualization و Training را راحت کرده است. همچنین یک کورس آنلاین برای این کتاب‌خانه وجود دارد که علاوه بر اینکه آموزش استفاده از آن را بیان می‌کند، محتوای مناسبی برای یادگیری Deep Learning می‌باشد. مزیت مهمی که این کتاب‌خانه برای کار ما داشت، اعمال  Geometric Augmentation بر روی Annotation‌های مربوط به راس‌های گوشه پلاک بود. از مزیت‌های دیگر می‌تونیم به Learning Rate Finder و Super-Convergence اشاره کنیم که زمان آموزش مدل را خیلی کم می‌کند و برای آزمایش‌های متعدد مناسب است.نتیجه کار، دقت قابل توجه در پیش‌بینی گوشه‌ها بود به صورتی که با تقریب خوبی، این نقاط مشخص می‌شدند. در تصاویر زیر می‌توانید چند نمونه از خروجی‌های کار را مشاهده کنید.متاسفانه مشکلی که وجود داشت، زمان اجرای این مدل بود که بر خلاف اینکه مدل سبکی بود، حدود ۲۵۰میلی‌ثانیه طول می‌کشید. همچنین لحظه‌ای که زمان اجرای YOLO و پردازش‌های مربوط به اعمال واترمارک را اضافه کردیم، این زمان تا ۷۰۰میلی‌ثانیه پیش رفت و این عدد بیش‌تر از حد مجاز ۴۰۰میلی‌ثانیه که در نظر داشتیم، بود. با بررسی‌هایی که برای امکان سبک‌تر کردن مدل داشتیم، به این نتیجه رسیدیم که حتی اگر زمان اجرای مدل جدید تا ۱۰۰ میلی‌ثانیه پایین بیاید، با اینکه کاهش نسبتا محسوسی در دقت پیش‌بینی نقاط خواهیم داشت، همچنان در این شرایط زمان اجرای نهایی برای ما، مناسب نخواهد بود. از آن‌جایی که هزینه‌ زمانی‌ مدل تشخیص شئ  YOLO  (۳۰۰ میلی ثانیه) به تنهایی زیاد است، تصمیم گرفتیم به دنبال راه‌حلی بگردیم که دو مرحله‌ای نباشد. اگر بتوانیم این دو مدل را به نحوی ترکیب کنیم، شاید بتوانیم به سرعتی که مدنظر ما بوده، برسیم.قدم پنجم - بازطراحی شبکه عصبی EfficientDetبه این نقطه رسیدیم که چطور می‌توان مدل تشخیص شئ را با مدل یافتن نقاط گوشه ترکیب کنیم چرا که پایپ‌لاین قبلی از نظر سرعت، بهینگی لازم را نداشت. برای ترکیب این دو مدل، یکی از بزرگ‌ترین چالش‌ها این است که ورودی مدل نقاط گوشه، یک تصویر پلاک و خروجی آن ۸ عدد بوده که مختصات X, Y نسبی چهار نقطه گوشه را مشخص می‌کرد. اگر بخواهیم مدل تشخیص شئ را با مدل نقاط گوشه ترکیب کنیم، تعداد خروجی‌ها وابسته به تعداد پلاک‌های موجود در تصویر خواهد بود. بنابراین پیش‌بینی مختصات نقاط گوشه جوابگو نخواهد بود و شیوه‌‌ی انکود کردن نقاط را می‌بایست تغییر دهیم.راه‌حلی که به آن رسیدیم، مشابه مدل‌های شبکه‌ عصبی تخمین ژست (Top-Down Pose Estimation) است. ما برای هر پلاک چهار نقطه گوشه داریم. می‌خواهیم بدانیم این‌ها در چه پیکسل‌هایی از تصویر حضور دارند. فرض کنیم هر نقطه گوشه، یک کلاس خاص است. به طور مثال نقطه گوشه بالای چپ هر پلاکی کلاس ۱،  نقطه گوشه بالای راست کلاس ۲، و برای دو نقطه دیگر نیز به همین‌ شکل نام‌گذاری کنیم. مسئله این است که هر پیکسل در تصویر متعلق به کدام یک از این چهار کلاس است. از آن‌جایی که می‌خواهیم Multi-Label Classification انجام دهیم، یک کلاس دیگر به اسم Background باید در نظر بگیریم تا عدم وجود نقطه گوشه در پیکسل را نشان دهد. بنابراین در این حالت تعداد خروجی‌ها برابر تعداد پیکسل‌های تصویر *۵ خواهد بود. حال اگر بتوانیم به مدل تشخیص شئ، یک شاخه دیگر به منظور پیش‌بینی محل حضور نقاط گوشه اضافه کنیم، این مسئله حل خواهد شد.اما مشکل به این‌جا ختم نمی‌شود. فرض کنیم که تصویر ورودی ما دارای ۳ پلاک خودرو باشد. بنابراین سه نقطه از هر کلاس در تصویر حضور دارند. این سه نقطه را چطور برای هر کلاس پیدا کنیم؟ اگر تنها یک پلاک در تصویر وجود داشت، به طور مثال برای کلاس ۱، در جایی از تصویر که احتمال حضورِ ماکزیمم داشت را به عنوان نقطه گوشه انتخاب می‌کردیم. حال که سه پلاک داریم، آیا با انتخاب ۳ نقطه‌ای که احتمال‌شان بیشینه است، این مشکل حل می‌شود؟ خیر!چرا؟گفتیم که برای هر پیکسل در تصویر پیش‌بینی می‌کنیم که هر کلاس، با چه احتمالی در آن پیکسل حضور دارد. بنابراین اگر سایز تصویر ورودی ۵۱۲ * ۵۱۲ باشد، برای هر کلاس، خروجی‌ به اندازه  ۵۱۲ * ۵۱۲ خواهیم داشت. به این خروجی‌ها، اصطلاحا نقشه‌ حرارت (Heatmap) آن کلاس گفته می‌شود که احتمال حضور آن کلاس در قسمت‌های مختلف تصویر را نشون می‌دهد. در ابتدا برای یافتن نقاط گوشه هر پلاک، BBox این‌ها را که مدل، پیش‌بینی کرده بدست می‌آوریم. سپس به ازای هر پلاک، BBox متناظرش را بر روی نقشه‌ حرارت تمام کلاس‌ها قرار می‌دهیم و داخل آن قسمت خاص از نقشه، برای هر کلاس (نقطه گوشه)، به دنبال پیکسلی که در آن احتمال حضور ماکزیمم است، می‌گردیم. این تا حدی مشابه کاری است که برخی مدل‌های تخمین ژست برای پیدا کردن اسکلت بدن انجام می‌دهند.به طور خلاصه‌ برای ترکیب دو مدل تشخیص شئ و مدل یافتن نقاط گوشه، تغییرات زیر را باید انجام دهیم:۱. شیوه کد کردن نقاط را از مختصات، به نقشه‌ حرارتی که کل عکس در بر می‌گیرد تغییر دهیم.۲. پس‌پردازشی بر روی نقشه حرارت به منظور یافتن نقاط گوشه هر پلاک داشته باشیم.۳. یک مدل تشخیص شئ پیدا کنیم که بتوان شاخه جدید به آن اضافه کرد تا نقشه‌های حرارت را پیش‌بینی کند.چه مدل تشخیص شئ ای را انتخاب کنیم؟ خوشبختانه در زمانی که ما دنبال یک معماری جایگزین برای YOLOمی‌گشتیم، مقاله‌ی شبکه EfficientDet منتشر شد (دسامبر ۲۰۱۹). درباره‌ی معماری این شبکه، توضیحی کلی در نوشته اول ارائه کردیم. شبکه مذکور علاوه بر این‌که از YOLOسبک‌تر است، دقت تشخیص بیشتری دارد.حال برای پیش‌بینی نقشه حرارت نقاط گوشه، یک شاخه جدید پس از لایه‌های BiFPN اضافه کردیم. در ابتدا ویژگی‌ها در مقیاس‌های مختلف را ترکیب می‌کنیم و سپس با اضافه کردن تعدادی Convolution Transpose Block، نقشه‌ حرارتی با مقیاس برابر با تصویر ورودی تولید می‌کنیم.پس از این تغییرات، چند بار مدل را آموزش دادیم اما نتایج به هیچ وجه قانع کننده نبود! نقشه‌های حرارت مربوط به کلاس در بسیاری از موارد با یکدیگر اشتراک داشتند که این اتفاق خوبی نبود و پس‌پردازش ها را خراب می کردند. بنابراین دو تغییر اساسی دیگر نیز برای بهبود پیش‌بینی نقشه‌حرارت اعمال کردیم:۱. سراغ انکودینگ گاوسی (به جای انکودینگ ۰ و ۱) برای ساخت ground truth رفتیم که در این مقاله   توضیحات لازم آن داده شده.۲. تابع خطای Focal Loss که برای Binary Classification پیاده‌سازی شده را به گونه‌ای تغییر دادیم که با Softmax سازگار شود و همچنین از انکودینگ گاوسی پشتیبانی کند (به جای ۰ و ۱، با توزیع احتمال بتواند کار کند).اضافه کردن این موارد موجب شد مدلی به اصطلاح Multi-task داشته باشیم که علاوه بر این‌که پلاک‌های موجود در تصویر را پیدا کرده، موقعیت نقاط گوشه را نیز مشخص می‌کند.بخش دوم - اعمال واترمارک بر روی تصویرپس از اینکه BBox و نقاط گوشه هر پلاک را بدست آوردیم، نوبت به اعمال واترمارک می‌رسد.ارزیابی نقاط گوشهانتظار داریم چهار نقطه ‌گوشه‌ای که بدست آوردیم، تشکیل چهارضلعی‌ای تا حد زیادی شبیه به متوازی الاضلاع بدهند اما همیشه خروجی به این شکل نیست. ممکن است که زاویه تصویر گرفته شده بد بوده یا اینکه مدل ما همراه با خطا پیش‌بینی کرده باشد.در وهله اول می‌بایست مطمئن شویم نقاط را به ترتیب ساعت‌گرد داریم. برای این منظور، از Radial Sweep استفاده می‌کنیم. سپس بررسی‌های زیر را به‌جهت اطمینان از کیفیت واترمارک انجام می‌دهیم:۱. چهارضلعی حتما محدب باشد.۲. نسبت اضلاع مقابل به یک‌دیگر معقولانه باشد.۳. اندازه زوایای مقابل نزدیک هم باشند.در صورتی که تمام شرایط فوق برقرار نباشند، به جای اعمال واترمارک، تنها پلاک را مات می‌کنیم.اعمال واترمارکاین یکی ازبخش‌هایی بود که حین انجام آن، با چالش‌هایی مواجه شدیم که اصلا انتظارش را نداشتیم. برای اعمال واترمارک دیوار بر روی پلاک، لازم بود که تبدیل پرسپکتیو (Perspective Transformation) انجام دهیم که برای این کار به کتاب‌خانه OpenCV نیاز داشتیم. مشکلی که وجود داشت، کیفیت بسیار پایین واترمارک بود به گونه‌ای که محتوای آن شطرنجی دیده می‌شد. یکی از علت‌های این اتفاق، رزولوشن متوسط تصویر بوده و از آن‌جایی که پلاک بخش کوچکی از این تصویر است، نمی‌توانیم انتظار وضوح بالایی داشته باشیم. برای حل این مشکل، چندین راه‌حل مختلف از جمله تبدیل از اندازه‌های متفاوت، تغییر سایز به‌علاوه‌ی تبدیل و روش‌های درون‌یابی مختلف مثل Cubic و Linear را امتحان کردیم که هیچ‌کدام نتیجه جالبی نداشت.اما زمانی‌که این تبدیل را با کتابخانه Pillow انجام دادیم، کیفیت تصویر به صورت محسوسی بهتر شد که این عجیب بود. بهینه‌سازی دیگری که در بهبود کیفیت کمک کرد این بود که، ابتدا واترمارک دیوار را به چند برابر بزرگ‌تر از اندازه واترمارکی که نهایتا می‌خواهیم روی پلاک بزنیم تبدیل کرده و سپس با تغییر سایز، واترمارک تبدیل شده را به اندازه نهایی‌‌اش تغییر دهیم. استفاده از درون‌یابی‌های BICUBIC و BILINEAR در تبدیل‌های فوق نیز کمک کننده بود. پس از تحقیقات بیشتر به کتاب‌خانه Pillow-SIMD برخوردیم که یک نسخه بهینه شده از Pillow است و عملکرد آن نیز بهتر است. ما در نهایت از همین کتاب‌خانه استفاده کردیم.تنظیم روشناییروشنایی تصویر در آگهی‌ها می‌تواند متفاوت باشد و این مولفه‌ی مهمی است که ما باید در واترمارک لحاظ می‌کردیم. به منظور نزدیک کردن روشنایی واترمارک به تصویر ورودی، مقادیر پیکسل واترمارک را با توجه به اختلاف مقداری که میانگین پیکسل‌های آن در هر کانال رنگ با میانگین پیکسل‌ها در تصویر ورودی دارند، با اعمال ضریب مناسبی انتقال می‌دهیم. در نهایت پس از این تغییرات، واترمارک روی تصویر ورودی قرار داده می‌شود.ارزیابیبه‌ منظور ارزیابی عملکرد مدل واترمارک‌ هنگام آموزش مدل، از ابزار پکیج pycocotools استفاده کردیم. در این پکیج متریک‌های متنوعی مطابق با استانداردهای دیتاست COCO برای سنجش دقت مدل‌های تشخیص شئ، تخمین نقطه و … پیاده‌سازی شده است.برای دقت تشخیص، با محاسبه برای ۱۰۱ نقطه بازیابی و ۱۰ IoU مختلف، به 61.2 mAP رسیدیم. برای کیفیت پیش‌بینی محل واترمارک متاسفانه نتوانستیم از معیار OKS استفاده کنیم و به ارزیابی بر روی ۱۰۰۰ تصویر از آگهی‌های دیوار بسنده کردیم.طی ارزیابی‌ای که از آگهی‌ها داشتیم، حدود ۹۷٪ از پلاک‌های اصلی را محو کردیم و تقریبا به اندازه ۰٪ پلاک اشتباه تشخیص دادیم. کیفیت واترمارک از نظر ما، رضایت‌بخش بود. برخی از آن‌ها را در زیر می‌توانید مشاهده کنید:برخی از بهینه‌سازی‌هایی که برای اجرای مدل شبکه عصبی و تبدیل‌های پردازش تصویر داشتیم باعث شدند سرعت اجرای نهایی سرویس را به ۲۲۰ میلی‌ثانیه کاهش دهیم که خوشبختانه بهبود قابل توجه‌ای  نسبت به  سرویس ۷۰۰میلی‌ثانیه‌ای پیشین ما بود.جمع‌بندیاین پروژه فرصت خوبی را برای ما فراهم کرد تا بتوانیم بررسی جامعی بر روی انواع معماری‌های شبکه عصبی و الگوریتم‌های پردازش تصویر داشته باشیم و آن‌ها را از نظر سرعت و دقت مقایسه کنیم. شاید جذاب‌ترین بخش این پروژه  این بود که سعی کردیم قدم به قدم حرکت کنیم و چالش‌های جدیدی که با آن‌ها مواجه می‌شدیم را یک به یک برطرف کنیم. دفعات متعددی بود که به بن‌بست رسیده بودیم و ایده‌ای برای پیشبرد کار نداشتیم. گاهی اوقات هم نتایج چند هفته‌ای مان با شکست مواجه می‌شد که ناامید کننده بود و ناگزیر بودیم سرنخ دیگری را دنبال کنیم. اما از عواملی که در موفقیت ما در انجام پروژه اثرگذار بود، انعطاف‌پذیری بالا در برنامه‌ریزی‌های‌مان بود که با توجه به شرایط و نیازمندی‌هایی که در هر مرحله داشتیم، می‌توانستیم میان فریم‌ورک‌های Darknet و Tensorflow و PyTorch سوئیچ کنیم. اما مهم‌تر از همه، کار گروهی و روحیه تیمی بود که چه در ایده‌پردازی و چه در پیاده‌سازی، تجربه لذت بخشی را برای ما رقم زد.این پروژه نمونه کوچکی از کارهای چالش برانگیز و جذابی‌ست که در تیم داده‌ی دیوار پیش می‌بریم. امیدواریم مطالعه‌ی این دو نوشته به شما کمک کرده باشد تا آشنایی بیش‌تری با فضای کاری دیوار کسب کنید.برای اطلاع از فرصت‌های شغلی در دیوار و پیوستن به ما به این لینک سر بزنید.</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Sun, 22 Nov 2020 19:45:14 +0330</pubDate>
            </item>
                    <item>
                <title>تشخیص پلاک در آگهی‌های خودرو با استفاده از بینایی ماشین-بخش اول</title>
                <link>https://tech.divar.ir/تشخیص-پلاک-در-آگهیهای-خودرو-با-استفاده-از-بینایی-ماشین-r2hiofdxthb6</link>
                <description>درباره‌ی نویسنده (نیما سارنگ)من نزدیک به یک سال در جمع دیواری‌ها بودم. در سه ماه اول حضورم در دیوار، به عنوان کارآموز دیتا فعالیت میکردم و پس از آن به تیم خودروی دیوار پیوستم.قبل از ورودم به دیوار، تجربه‌ام در زمینه‌‌ یادگیری ماشین محدود به پروژه‌هایی نظیر Protein Design و بازی‌های Augmented Reality بود. این تجربه کمک کرد تا درباره‌ی مباحث Semantic Segmentation و Object Tracking و استفاده از کتاب‌خانه‌ی Keras دید خوبی داشته باشم.اما در دیوار بود که این فرصت فراهم شد تا در حوزه‌های Object Detection و Data Analysis و Client-side AI و مدل‌های Multi-task تجربه کسب کنم و مهارت برنامه‌نویسی با استفاده از کتاب‌خانه‌های PyTorch و TensorFlow را تمرین کنم. جلسات هم‌افزایی و اشتراک دانش که با تیم‌های دیتایی داشتم، تاثیر زیادی در سرعت یادگیری‌ام داشت.پروژه‌ای که در ادامه درباره آن صحبت می‌کنم یکی از ارزشمندترین تجربیات من در دیوار است. این پروژه یک کار جذاب در زمینه پردازش تصویر است؛ و البته به خاطر ملاک‌هایی که برای دقت و سرعت اجرای سرویس در نظر گرفته‌ایم چالش‌های بسیاری دارد. به خاطر این ماهیت چالشی، تحقیقات زیادی انجام دادیم و روش‌های متعددی را بررسی کردیم تا بتوانیم به نتیجه‌‌ی مطلوب برسیم.مقدمهدر این مقاله می‌خواهیم مروری بر سرویس محو پلاک خودرو، یکی از ‌سرویس‌های کاربردی تیم خودروی دیوار داشته باشیم. ما در تیم خودرو همواره در تلاشیم تا به واسطه‌ی بهره‌گیری از ظرفیت‌های فناوری و ایجاد شفافیت و اطمینان، تجربه‌ی خرید و فروش خودرو را از فرآیندی پیچیده، طولانی و پراسترس به تجربه‌ای لذت‌بخش تبدیل کنیم. برای پیاده‌سازی و اجرایی کردن سرویس محو پلاک در دیوار حدود ۶ ماه وقت گذاشتیم. مدت کوتاهی از اجرایی شدن این سرویس در دسته بندی سواری دیوار می گذرد. با توجه به تازگی اجرایی شدن این پروژه، می‌خواهیم به توضیح جزئیات فنی آن و تجربیاتی که حین پیاده‌سازی آن کسب کردیم، بپردازیم.این مطلب برای شما نوشته شده!اگر به الگوریتم‌های پردازش تصویر و مدل‌های شبکه‌ عصبی در زمینه بینایی ماشین (Computer Vision) علاقه‌مندید، این مطلب برای شما نوشته شده :) به دلیل طولانی شدن مقاله، تصمیم گرفتیم که آن را به دو نوشته تقسیم کنیم؛در نوشته اول (همین نوشته)، به تشخیص مسئله و بیان اهداف می‌پردازیم. سپس چند مفهوم ابتدایی و روش‌های موجود برای حل مسئله مورد‌نظر‌مان را توضیح داده و از تحقیقاتی که در این رابطه انجام داده‌ایم صحبت می‌کنیم تا پیش‌زمینه علمی مناسب را پیدا کنید. به طور خاص، نگاهی گذرا بر تعدادی از الگوریتم پردازش تصویر کلاسیک خواهیم داشت و سپس سراغ بحث اصلی که مدل‌های شبکه عصبی تشخیص شئ هستند خواهیم رفت و دو روش حل بنیادی که معماری‌های Faster R-CNN و EfficientDet بوده را شرح خواهیم داد. در انتها بخش کوتاهی را به معرفی مدل‌های شبکه عصبی بخش‌بندی اختصاص داده‌ایم.از خواننده انتظار داریم که با مفهوم Convolutional Neural Network و همچنین برخی مفاهیم پردازش تصویر مانند Edge Detection و Contours تا حدودی آشنا باشد.در نوشته دوم، درباره استفاده از این روش‌ها در پروژه‌مان صحبت می‌کنیم و مسیری را که طی کردیم تا به نقطه‌ی‌ فعلی برسیم، بررسی خواهیم کرد. پیشنهاد می‌کنیم اگر پیش‌‌زمینه لازم را دارید، مستقیما به سراغ این نوشته بروید.تلاش بر این بوده که تا حد امکان، مطالب را به منابع اصلی یا آموزشی ارجاع دهیم. بنابراین اگر در مواردی توضیحات کافی نبود، می‌توانید به آن‌ها مراجعه کنید.چرا محو پلاک؟یکی از دغدغه‌های مهم ما در تیم خودرو دیوار، عدم نمایش پلاک خودروها در آگهی‌ها است. نمایش پلاک خودرو می‌تواند نگرانی‌هایی را برای کاربران بابت نقض حریم شخصی‌‌شان به وجود بیاورد؛ اما از طرفی دیگر کاربران برای آنکه بتوانند تصاویر مناسبی را از خودروی خود بگیرند، در بیشتر موارد ناچارند که پلاک را نیز در کادر قرار دهند. این تناقض باعث شده بعضی مواقع کاربران عکس را به ‌گونه‌ای ثبت کنند که پلاک در آن دیده نشود یا اگر پلاک در کادر قرار گیرد، آن را به شیوه‌های مختلف از جمله رنگ‌آمیزی، قرار دادن شئ مانع و … مخدوش کنند تا اعداد آن مشخص نباشد. در نهایت هر دو مورد باعث افت کیفیت آگهی می‌شود که اتفاق مطلوبی نیست. در زیر چند مثال از تاثیر آن را می‌توانید مشاهده کنید.نمونه‌هایی از تصویر دست‌کاری شده توسط کاربران به منظور حذف پلاکاهدافهدف ما در گام اول، محو پلاک به روش مات کردن است. در گام دوم، در صورتی که سرویس دقت کافی داشته و امکان توسعه آن فراهم باشد، به جای مات کردن از چسباندن واترمارک دیوار بر روی پلاک استفاده می‌کنیم.ملاک‌هایی که برای ارزیابی کیفیت سرویس‌مان مشخص کردیم به ترتیب اولویت به شرح زیر است:قابل اطمینان بودن: یکی از مهم‌ترین ویژگی‌های این سرویس، توانایی آن برای محو تقریبا تمامی پلاک‌های خودرو در آگهی‌هاست. اگر فرضا ما سرویسی را اجرایی کنیم که قابلیت محو کردن ۸۰٪ پلاک‌ها را داشته باشد، ۲۰٪ تصاویر بدون محو پلاک منتشر شده و این موجب نگرانی کاربران عدم اطمینان آن‌ها به سرویس‌مان خواهد شد. بنابراین دو معیار سنجش را در نظر گرفتیم:بازیابی (Recall)ا ۹۵٪ : بتوانیم همه‌ی پلاک‌های مهم را محو کنیم.دقت (Precision)ا ۹۹.۵٪ : به اشتباه بخشی از تصویر غیر مرتبط را پلاک تشخیص ندهیم و محو نکنیم!سرعت اجرا: با توجه به حجم آگهی‌هایی که در دقیقه منتشر می‌شوند، انتظار داریم  پردازش هر عکس آگهی بر روی CPU به طور ماکزیمم ۳۰۰-۴۰۰ میلی‌ثانیه طول بکشد. این یکی از دشوار ترین معیار‌هایی بود که برای سرویس در نظر گرفتیم.دقت محو پلاک: مقدار Intersection over Union) IoU) را ۰.۸ در نظر گرفتیم؛ یعنی اشتراک مستطیل پلاک تشخیص داده شده با پلاک واقعی، تقسیم بر اجتماع آن‌ها از ۰.۸ بیشتر شود که این میزان دقت قابل توجهی است.تعریف مسئله به عنوان یک مسئله بینایی ماشینبرای محو کردن پلاک، در قدم اول نیازمند مشخص کردن موقعیت آن در تصویر آگهی هستیم. مسئله تشخیص پلاک را می‌شود به چند شکل مختلف مطرح کرد:۱. مشخص‌کردن چهارضلعی پلاک: پلاک را یک چهار‌ضلعی در نظر بگیریم که با توجه به زاویه‌ی عکس ثبت شده، این چهار‌ضلعی می‌تواند مستطیل، متوازی الاضلاع یا یک چهارضلعی بی‌قاعده باشد. یکی از شیوه‌های مشخص کردن این چهارضلعی، مشخص کردن ۴ راس آن است.۲. مشخص کردن مستطیل محیطی (Bounding Box or BBox): مستطیلی که همه‌ی قسمت‌های پلاک را در بر می‌گیرد و مساحت آن کمینه ممکن است. به طور کلی، یافتن BBox یکی از رایج‌ترین روش‌های تشخیص شئ است.۳. تخمین حدود پلاک به کمک ویژگی‌های آن: از روش‌های دیگر می‌توان به استفاده از ابزارهای تشخیص متن برای یافتن حروف پلاک و سپس تخمین زدن محدوده پلاک اشاره کرد. از دیگر ویژگی‌های قابل استفاده برای تخمین، نماد آبی رنگ ایران در سمت چپ پلاک است.قول معروفی است که می‌گوید «شناخت مسئله نیمی از حل آن است.» این نکته که ما مسئله را به چه شکلی طرح کنیم، اهمیت ویژه‌ای در نوع راه‌حلی که برای مسئله ارائه می‌دهیم دارد. در ادامه راهکارهای موجود را در قالب طرح‌های فوق بررسی می‌کنیم.بررسی راه‌حل‌هادر این قسمت به مرور راه‌حل‌هایی می‌پردازیم که طی تحقیقات‌مان با آن‌ها برخورد داشتیم. از آن‌جایی که در نهایت به سمت انتخاب مدل‌های تشخیص شئ رفتیم، در اینجا تمرکز ویژه‌ای بر این مدل‌ها خواهیم داشت.روش‌های پردازش تصویر کلاسیکاین روش‌ها الگوریتم‌های ساده‌ای‌اند که در بسیاری از مسائل پردازش تصویر کاربرد دارند. در اغلب این روش‌ها، یکی از اولین پیش‌پردازش‌ها این است که با استفاده از الگوریتم‌های Edge Detection نظیر Canny و Sobel، کرانه‌های اشیا موجود در تصویر را مشخص می‌کنند. خروجی این عمل، تصویری باینری خواهد بود که تنها پیکسل‌های مربوط به کرانه‌های اشیا سفید است. با در دست داشتن کرانه‌ها می‌توانیم الگوریتم‌های زیر را اجرا کنیم:۱. یافتن خطوط به وسیله الگوریتم Hough Transform: با استفاده از این الگوریتم می‌توان خطوط موجود در تصویر را به صورت تقریبی پیدا کرد. این الگوریتم دارای چندین هایپرپارامتر است که با توجه به مسئله می‌بایست مقادیر بهینه‌ آن‌ها را مشخص کرد.  پس از انجام این کار می‌توانیم دسته خطوطی را که تشکیل چهارضلعی می‌دهند پیدا کنیم و سپس به نحوی تعیین کنیم که این چهار‌ضلعی پلاک است یا خیر.۲. یافتن نقاط گوشه به وسیله الگوریتم Harris Corner Detection: الگوریتم هریس روشی مناسب برای پیدا کردن نقاط گوشه در تصویر است. اما از آن‌جایی که تعداد نقاط گوشه در تصویر خیلی زیاد است، در ابتدا باید بتوانیم محل تقریبی پلاک در تصویر را مشخص کنیم و سپس با اجرای این الگوریتم، چهارضلعی دقیق پلاک را بدست بیاوریم.۳. یافتن کانتور پلاک: با داشتن کرانه‌های اشیا موجود در تصویر، می‌توانیم با استفاده از الگوریتم Suzuki، تمام منحنی‌های پیوسته را بدست آورده و کانتور هر شئ را به صورت جداگانه داشته باشیم. سپس می‌توانیم چندضلعی هر کانتور را به کمک اجرای الگوریتم Douglas-Peucker و سپس به کمک Convex Hull خروجی آن تخمین بزنیم و کانتورهایی که شبیه مستطیلند را جدا کنیم تا به یافتن پلاک واقعی نزدیک‌تر شویم.۴. یافتن کاراکترهای پلاک: از روش‌های جالب دیگر این است که مانند روش قبل، کانتور تمام شئ‌ها را پیدا کنیم و از میان آن‌ها، عدد یا حرف را تشخیص دهیم. برای این کار کافی‌ست کانتور‌ها را به یک مدل ساده Classifier که بر روی اعداد و حروف فارسی آموزش داده شده بدهیم تا نوع هر کانتور مشخص شود. سپس تبیین کنیم کدام دسته از این کانتورها می‌توانند متعلق به یک پلاک باشند.مدل شبکه‌های عصبی تشخیص شئ Object Detectionمفهوم تشخیص شئ به معنای یافتن و مشخص کردن موقعیت اشیائی از یک کلاس خاص (مانند انسان، لپ‌تاپ، میز و..) در تصویر و ویدئو است. در این بخش به طور خاص می‌خواهیم درباره‌ی مدل‌های شبکه عصبی تشخیص شئ صحبت کنیم. این مجموعه از مدل‌ها با توجه به مجموعه داده‌ای که بر روی آن آموزش داده می‌شوند، وظیفه دارند مستطیل محیطی (Bounding Box / BBox) تمام اشیا موجود در تصویر را -که مطابق با دسته‌های تعریف شده است- تشخیص دهند. به طور مثال، مدلی که آموزش داده شده تا بتواند درخت‌ها و انسان‌ها را تشخیص دهد، می‌بایست برای هر یک از درخت‌ها و انسان‌ها یک BBox متمایز محاسبه کند. برای هر شئ دیگری که جزء این دو دسته نباشد، نباید تشخیصی را اعلام کند. پس به طور کلی این مدل‌ها باید دو چیز را مشخص کند:۱. مختصات BBox مربوط به تمام اجسامی که جزء دسته‌بندی‌های تعریف شده هستند. (Regression)۲. مشخص کردن این که هر BBox به کدام دسته تعلق دارد و نوع شئ آن چیست. (Classification)برای مسئله‌ی تشخیص پلاک، دسته‌بندی‌های تعریف تنها دو دسته‌ی «پلاک» و «غیر پلاک» خواهند بود. حال اگر بخواهیم از میان انبوهی از شبکه‌های عصبی تشخیص شئ، یک مورد را انتخاب کنیم، علاوه بر مقایسه دقت آن‌ها بر روی دیتاست معتبری مثل COCO، می‌بایست سرعت آن‌ها را نیز در نظر داشته باشیم. تقسیم‌بندی‌ای که در ادامه قرار است داشته باشیم، می‌تواند دید خوبی به ما دهد که یک معماری شبکه تشخیص شئ در چه جایگاهی از نظر سرعت و دقت قرار دارد.یکی از موارد چالش‌ برانگیز در حل این مسائل، متغیر بودن تعداد اشیا در تصویر است. ممکن در تصویری چند شئ وجود داشته باشد و در تصویر دیگری هیچ شئ‌ای نباشد. برای حل این چالش رویکرد‌های متفاوتی در نظر گرفته شده است. مدل‌های شبکه عصبی تشخیص شئ را به طور کلی به دو دسته زیر می‌توان تقسیم کرد:۱. مبتنی بر لنگر (Anchor-Based)۲. بدون لنگر (Anchor-Free)مدل‌های تشخیص شئِ مبتنی بر لنگر دارای سابقه‌ی بیشتری هستند و مقاله‌های متعددی در رابطه‌ با آن‌ها منتشر شده است. اما حدود دو سالی می‌شود که مدل‌های بدون لنگر نیز وارد عرصه رقابت شده و فاصله خود را از نظر دقت و سرعت اجرا کمتر کرده اند. برای اینکه با مفهوم لنگر آشنا شویم، لازم است چند معماری معروف را بررسی کنیم. واژه لنگر (Anchor) ابتدا در شبکه‌ی Faster-RCNN معرفی شد و پس از آن در مقاله‌های متعددی ایده آن ادامه پیدا کرد. معماری‌های مبتنی بر لنگر به دو دسته‌ی تک‌مرحله‌ای و دومرحله‌ای تقسیم می‌شوند. معمولا شبکه‌های مبتنی بر لنگرِ تک‌مرحله‌ای، از دو مرحله‌ای ها سریع‌ترند اما دقت پایین‌تری دارند. شبکه‌های بدون لنگر نیز جایگاهی بین این دو دارند.ممکن است این تقسیم‌بندی‌ها تا حدی پیچیده به‌نظر برسد. برای مشخص کردن این تفاوت، از هر دسته یک پرچم‌دار را انتخاب کرده و به توضیح آن‌ها می‌پردازیم.مدل Faster R-CNN - یک شبکه مبتنی بر لنگرِ دو مرحله‌ایشبکه‌ی Faster R-CNN یکی از معروف‌ترین شبکه‌های تشخیص شئ است. مقاله آن در سال ۲۰۱۵ منتشر شد و تا امروز تحقیقات برای بهبود آن ادامه دارد (به عنوان مثال، FPN, Composite Backbone, Cascade R-CNN). از این معماری حتی در شبکه‌های قطعه‌بندی مانند Mask R-CNN نیز استفاده می‌شود.این شبکه از نوادگان شبکه‌های R-CNN و Fast R-CNN است. اگر علاقه‌مندید تا درباره سیر تحول این شبکه بیشتر بدانید، پیشنهاد می‌کنیم نگاهی به مقاله‌های آن‌ها بیندازید. اینجا تنها مروری کلی بر ساختار شبکه خواهیم داشت.معماری این شبکه را می‌توان به ۴ بخش زیر تقسیم کرد:بخش Backbone: بک‌بن یک شبکه CNN است، که با گرفتن تصویر ورودی، ویژگی‌های ابتدایی (Low-Level) و معنی‌دار را استخراج می‌کند. در ادامه با استفاده از این ویژگی‌ها می‌توان راحت‌تر درباره ورودی نظر داد. به خروجی بک‌بن، یک Feature Map گفته می‌شود.امروزه بیشتر از معماری ResNet برای بک‌بن این شبکه استفاده می‌شود. اما به طور کلی هر شبکه CNN دیگری که برای مسئله Classification طراحی شده، با حذف لایه‌های Fully Connected انتهایی می‌توان از آن به عنوان بک‌بن این مدل شبکه‌های تشخیص شئ استفاده کرد.بخش (Region Proposal Network (RPN: در اینجا مدل می‌خواهد تشخیص دهد که چه قسمت‌هایی از تصویر، ارزش و محتوای بیشتری دارند تا با تمرکز بر آن بخش‌ها، اشیا را پیدا کند. این بخش از شبکه در نظر دارد فریم‌های مستطیل شکلی از تصویر را که در آن شئ وجود دارد (کلاس آن شئ مهم نیست)، پیدا کند که به اصطلاح به این فریم‌ها Region Proposal گفته می‌شود.بخش ROI Align: در این بخش تعداد ثابتی از بهترین Region Proposal ‌ها (آن‌هایی که مدل پیش‌بینی کرده احتمال حضور شئ داخل شان بیشتر است.) انتخاب می‌شوند و سپس مدل با استفاده از Feature Map ای که در بخش اول بدست آورده، ویژگی‌های مربوط به هر Region را از آن کراپ می‌کند و به دلیل اینکه اندازه این Regionها یکسان نیست، اندازه ویژگی‌های استخراج شده را ابتدا یکسان کرده و سپس تحویل بخش بعدی می‌دهد.بخش Detection Head: برای Proposal ‌های انتخاب شده مشخص می‌کند که شئ موجود در آن قسمت متعلق به کدام دسته است و همچنین BBox آن شئ رو به طور دقیق محاسبه می‌کند.اما جایگاه لنگر در این معماری کجاست؟نکته‌ای که در رابطه با ماژول RPN وجود دارد این است که  در آن واحد بر روی تمام Feature Map اجرا نمی‌شود.  بلکه یک شبکه CNN کوچک بر روی Feature Map حرکت داده شده (Sliding Window) و برای پنجره کوچکی از آن (یک مربع ۳*۳) Proposal تولید می‌کند. اما تولید Proposal برای هر پنجره به چه صورت است؟ مستطیل‌هایی با اشکال مختلف -که اندازه آن از پیش می‌بایست تعریف شود- بر روی این پنجره قرار داده شده و مدل برای هر کدام‌ از این مستطیل‌ها بایستی پیش‌بینی کند که آیا شئ‌ در داخل آن قرار می‌گیرد یا خیر. به این مستطیل‌ها لنگر گفته می‌شود. پس از آن که مشخص شد شئ در داخل لنگر قرار دارد، Proposal مربوط به آن با استفاده از موقعیت و اندازه لنگر محاسبه می‌شود.چرا به این شبکه، دو مرحله‌ای گفته می‌شود؟زیرا پیش‌بینی BBox ها در دو مرحله انجام می‌شود؛ در مرحله اول پیش‌بینی Proposal ها و در مرحله دوم پیش‌بینی BBox برای هر Proposal انجام می‌شود.مدل EfficientDet - یک شبکه مبتنی بر لنگرِ تک مرحله‌ایشبکه‌ی EfficientDet یکی از جدید‌ترین شبکه‌های تشخیص شئ است که زمان کمی از معرفی آن می‌گذرد. در این شبکه توجه ویژه‌ای به کم کردن تعداد پارامتر‌های مدل و بیش‌تر کردن سرعت اجرای آن شده است. سیر تحول این شبکه به صورت SSD =&gt; FPN =&gt; RetinaNet =&gt; EfficientDet است که در صورت علاقه می‌توانید بیشتر راجع به آن مطالعه کنید.به این شبکه‌ها تک‌ مرحله‌ای گفته می‌شود زیرا برخلاف شبکه Faster R-CNN، مجموعه Region Proposal تولید نمی‌کنند و به طور مستقیم BBox های مربوط به اشیا را پیش‌بینی می‌کنند. این مهم‌ترین دلیل سریع‌تر بودن شبکه‌های تشخیص شئ تک‌ مرحله‌ای نسبت به دو مرحله‌ای است.این‌ شبکه‌ها نیز مبتنی بر لنگر هستند چرا که تعداد بسیار زیادی لنگر به بخش‌های مختلف تصویر اختصاص داده شده که برای هر کدام از آن‌ها، مدل پیش‌بینی می‌کند که کلاس شئ‌ای که داخل آن لنگر افتاده چیست (عدم وجود شئ را نیز  کلاس مجزا در نظر می‌گیریم). و همچنین تشخیص می‌دهد این لنگر نسبت به موقعیت فعلی‌ش در تصویر، چقدر ‌می‌بایست جابجا گردد تا شئ دقیقا در درون آن قرار بگیرد و تبدیل به یک مستطیل محیطی شود. (مشابه اتفاقی که در شبکه Faster RCNN می‌افتد.)معماریاین شبکه را می‌توان به ۳ زیرشبکه تقسیم کرد: ۱. زیرشبکه Backbone: از معماری EfficientNet برای جمع آوری ویژگی‌های اولیه از تصویر ورودی استفاده می‌شود. EfficientNet شبکه‌ای است که معماری آن به کمک Neural Architecture Search بدست آمده و بسیار سبک و با تعداد پارامتر کم است.۲. زیر شبکه (Bidirectional Feature Pyramid Network (BiFPN: در این قسمت ویژگی‌هایی‌ که در مقیاس‌های مختلف از بک‌بن بدست آمده، به صورت دوطرفه با هم ترکیب می‌شوند تا ویژگی‌های غنی در مقیاس‌های مختلف نسبت به قبل به وجود آید.به طور دقیق‌تر، خروجی بک‌بن از تعدادی لایه کانولوشن عبور می‌کند که بعضی‌ از آن‌ها با stride برابر با ۲ هستند. پس از این عمل، Feature Map هایی خواهیم داشت که نسبت طول و عرض آن به تصویر ورودی ۱/۲، ۱/۴، … و ۱/۸ خواهد بود تا ویژگی‌هایی در مقیاس‌های مختلف داشته باشیم. مزیت این‌ عمل این است که ویژگی‌های در مقیاس ۱/۲ غالب تمرکزشان بر روی الگو‌ها و پیکسل‌های محلی است، در حالی که ویژ‌گی‌های با مقیاس ۱/۸ سعی می‌کنند بر روی مفهوم کلی تصویر (Global context) نظر بدهند.۳. زیرشبکه Detection Head: انتظار داریم این زیر‌شبکه با ثبت ویژگی‌ها در مقیاس‌های مختلف، برای تعداد زیادی لنگر که هر کدام به بخش‌های مختلفی از تصویر اختصاص داده شده اند، تعیین کند که در این لنگرها شئ از کدام دسته است (این یک مسئله طبقه‌بندی است). همچنین به صورت همزمان می‌بایست پیش‌بینی کند که این لنگر در چه جهت و اندازه‌ای جابجا شود تا دقیقا برای همان شئ که در داخل آن قرار دارد، به اندازه باشد تا کاملا تطابق با BBox پیدا کند.شبکه‌های عصبی بخش‌بندی Segmentationمدل‌های بخش‌بندی همانطور که از نام آن‌ها پیداست، اشیا موجود در تصویر را از پس‌زمینه جدا نموده و پیکسل‌های مربوط به آن‌ها را مشخص می‌کنند. این جداسازی‌ها انواع مختلفی دارند و راه‌حل‌هایی که برای آن‌ها ارائه می‌شود نیز متفاوت است. از این میان ۲ زیر دسته‌ی مهم که کاربردی بوده و حول آن‌ها تحقیقات بیشتری انجام شده، به شرح زیر است:۱. بخش‌بندی معنایی (Semantic Segmentation)هدف مدل‌های بخش‌بندی این است که مشخص کنند هر پیکسل در تصویر متعلق به چه کلاسی است. آیا پیکسل متعلق به دسته انسان است؟ یا متعلق به خودرو؟ یا متعلق به هیچ شئ تعریف‌شده‌ای نیست؟ (متعلق به کلاس پس‌زمینه است.) بنابراین در حالت ساده می‌توان به آن به عنوان مسئله طبقه‌بندی (Classification) هر پیکسل نگاه کرد. ‌دسته‌بندی‌های تعریف شده نیز وابسته به مجموعه داده‌ای است که مدل بر روی آن آموزش داده می‌شود. یکی از معروف‌ترین مدل‌های بخش‌بندی معنایی، U-Net است که طراحان این معماری از آن برای بخش‌بندی پیکسل‌های دیواره‌ سلولی استفاده کرده بودند. از قدرتمندترین مدل‌هایی که امروزه وجود دارد می‌توان به DeepLabV3+ و HRNetV2 اشاره کرد.۲. بخش بندی نمونه‌ای (Instance Segmentation)مشابه بخش‌بندی معنایی است با این تفاوت که علاوه بر اینکه پیش‌بینی می‌کند هر پیکسل متعلق به چه دسته‌ای است، همچنین می‌بایست میان نمونه‌های موجود در تصویر نیز تمایز قائل شود. به طور مثال فرض کنید ۲ شخص در یک تصویر حضور دارند. در بخش‌بندی معنایی فقط می‌توان مشخص کرد که کدام پیکسل‌ها مربوط به انسان هستند اما این تمایز را نمی‌توان قائل شد که کدام پیکسل مربوط به شخص شماره ۱ است و کدام مربوط به شخص شماره ۲. در بخش‌بندی نمونه‌ای، این تمایز میان نمونه‌ها نیز اعمال می‌شود.نکته‌ای حائز اهمیت این است که شبکه‌های بخش‌بندی نمونه‌ای غالبا از الگوی شبکه‌های تشخیص شئ برای بخش‌بندی تصویر استفاده می‌کنند. به این صورت که در ابتدا اشیا موجود در تصویر را پیدا کرده و BBox هر یک را محاسبه می‌کنند. به این شکل، نمونه‌ها از یکدیگر متمایز می‌شوند. سپس برای هر شئ تشخیص داده شده، برای پیکسل درون BBox آن بخش‌بندی معنایی انجام می‌دهند. پس می‌توان نتیجه گرفت که این مدل‌ها غالبا ترکیبی از شبکه‌های تشخیص شئ و بخش‌بندی معنایی هستند. یکی از معروف‌ترین ‌مدل‌های بخش‌بندی نمونه‌ای، Mask R-CNN بوده که ساختار آن بر پایه شبکه Faster R-CNN شکل گرفته‌است. از بین مدل‌های قدرت‌مند می‌توان به BlendMask و همچنین CenterMask اشاره کرد که دومی بر پایه شبکه‌‌ تشخیص شئ FCOS است.کاربرد این شبکه‌ها برای یافتن پلاک در تصویر چیست؟با آموزش مدل‌های بخش‌بندی می‌توانیم تمامی پیکسل‌های مربوط به پلاک رو بدست بیاوریم. وقتی که تمام پیکسل‌های مربوطه را داشته باشیم، به راحتی می‌توانیم چهارضلعی پلاک را مشخص کرده  و برای محو کردن از آن استفاده کنیم.جمع‌بندیدر این نوشته، سعی کردیم صورت مسئله را شرح دهیم و از اهدافی که برای راه‌اندازی این سرویس تعیین کرده‌بودیم صحبت کنیم. همچنین تلاش کردیم روش‌های حل مسئله را به نحوی تقسیم‌بندی کرده و هر کدام را مستقل بررسی کنیم. در نوشته‌ی بعدی، می‌خواهیم از راهکارهایی که امتحان کرده‌ایم بگوییم و نتایج کارمان را تحلیل کنیم.</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Sun, 22 Nov 2020 19:08:09 +0330</pubDate>
            </item>
                    <item>
                <title>دیوار چگونه از میلیون‌ها عکس نگهداری می‌کند؟</title>
                <link>https://tech.divar.ir/دیوار-چگونه-از-میلیونها-عکس-نگهداری-میکند-hsd6inwtpije</link>
                <description>این پست به قلم مهدی خراط زاده و مرتضی حسینی از توسعه‌دهندگان بکند دیوار، به جهت آشنایی مخاطبان با فضای کاری دیوار نوشته‌شده است. مهدی خراط زاده از حدود دو سال و اندی پیش به دیوار پیوسته و در این میان تجربه‌ی کار در تیم‌های مختلفی از جمله بررسی آگهی و زیرساخت را داشته است. مرتضی حسینی نیز از حدود دو سال پیش در جمع دیوار حضور دارد و تجربه‌‌ی کار در تیم‌های سرچ و سابمیت، زیرساخت و املاک در دیوار را داشته است. مهدی از زمان حضورش در دیوار به گفته‌‌ی خودش با تکنولوژی و ابزارهای بسیاری آشنا شده و در بالا نگه‌داشتن و افزایش اتکا‌پذیری سرویس‌های دیوار نقش داشته است. مهدی ارزشمند‌ترین تجربه‌ کاری ش را زمانی می‌داند که در شرایطی که بار سنگین روی سرویس‌های دیوار بوده، توانسته در توسعه و نگهداری سیستم‌ها نقش داشته‌باشد. به نظر مرتضی مهم‌ترین تجربه کاری او، کسب توانایی کار تیمی اثر بخش و رسیدن به یک سیستم مقاوم در برابر سختی‌هایی مثل بار و درخواست زیاد از سمت کاربران بوده‌است.این پست بیان تجربه از سری کارهایی است که به انجام رساندیم تا شرایط توسعه را برای ورتیکال‌ها راحت‌تر کنیم. مهم‌ترین جذابیت کار برای ما این بود توانستیم سرویسی را پیاده‌سازی کنیم که عکس‌ها را فارغ ازین‌که مربوط به کدام دسته بوده، به خوبی مدیریت کرده به صورتی که توسعه پذیری و  reliability بالا را برای ما فراهم کند. در نهایت اینکه پیاده‌سازی و ریویوی این سرویس حدود یک ماه در کنار کارهای دیگر تیم از ما زمان برد. پیاده‌سازی این سرویس در تیم خودرو، و ریویوی آن با همکاری زیرساخت دیوار انجام گرفت. با این مقدمه‌، به سراغ شرح این نوشته می‌رویم.عکس‌ها در دیوار چگونه‌اند؟
در دیوار روزانه حدودا ۵۰۰ هزار آگهی سابمیت می‌شود. با توجه به اینکه هر آگهی می‌تواند دارای یک یا چند عکس باشد در مجموع به تعداد ۱ میلیون و ۳۰۰ هزار عکس در دیوار، روزانه بارگذاری  انجام می‌شود. در عین حال با افزایش تعداد ورتیکال‌ها و تیم‌ها در دیوار نیاز به اینکه هر تیم بتواند بدون تاثیر روی سایر تیم‌ها، عکس‌های خود را مدیریت کند بیش از پیش احساس شده‌است. منظور از ورتیکال‌ تیم‌هایی هستند که با تمرکز بر یک دسته‌بندی خاص مانند خودرو، املاک و..سعی می‌‌کنند مشکلات کاربر‌های آن دسته‌بندی را حل نموده یا برای‌شان ارزش جدید تولید کنند.عکس‌های دیوار به صورت کلی شامل چند دسته‌ی زیر است:۱. عکس‌های صفحه مدیریت آگهی که فقط گذارنده‌ی آگهی به آن‌ها دسترسی دارد.۲. عکس‌های آگهی‌های منتشر شده۳. عکس‌های مختص سرویس‌های جانبی دیوار (مانند لوگوهای کسب و کار‌ها، عکس‌های کارشناسی خودرو، عکس املاک و ...)از جهت سیکل حضور عکس‌ها در دیوار به صورت کلی با ۲ دسته عکس روبرو هستیم:دسته اول شامل عکس‌هایی بوده که هنوز به حالت نهایی نرسیده‌اند و در چرخه‌های تکمیل نشده (سابمیت آگهی، اضافه کردن لوگو و ...) هستند و دسته دوم شامل عکس‌‌های نهایی شده (آگهی‌های سابمیت شده و ...) می‌باشد.برای اینکه بتوانیم در به کار بردن اصطلاحات راحت‌تر باشیم عکس‌های دسته اول را عکس‌های temp و عکس‌های دسته دوم را عکس‌های اصلی نام‌گذاری می‌کنیم.در ادامه رویکرد دیوار در مواجه با مساله مدیریت عکس‌ها را بررسی می‌‌‌کنیم.برخورد نزدیک از نوع «اول»: مدیریت عکس‌ها تیم‌های جدیدی در دیوار تشکیل دادیم که تجربه‌های تازه و ارزشمندی را با خود به همراه آوردند.حضور تیم‌های جدید باعث شد از لحاظ محصولی با محدودیت زمانی مواجه شویم چرا که قصد داشتند فیچرهای جدیدی را بر محصول پیاده‌سازی کنند. در نتیجه به این فکر افتادیم تعدادی از میکرو‌سرویس‌هایی که ما جزء میکروسرویس‌های هسته تلقی می‌کنیم را به روز رسانی کنیم تا علاوه بر‌ اینکه نیازمندی سرویس‌های جدید را برآورده کنند، در آینده بتوانند برای تیم‌ها محصولات جدیدی که در دیوار خلق می‌شوند، مورد استفاده قرار بگیرند.با تجربه‌ای که از نگهداری سرویس عکس دیوار داشتیم و با توجه به مشکلاتی که در محیط عملیاتی وجود داشت، تلاش کردیم تا در ابتدا مجموعه نیازمندی‌هایی تشکیل دهیم و سپس راهکارهای مختلف را بررسی کرده و راهکار مطلوب را انتخاب کنیم.پرسش بنیادین: چه می‌خواهیم؟ اگر بخواهیم نیازمندی های خود را به صورت کلی دسته بندی کنیم با موارد زیر روبرو خواهیم بود.بتوانیم عکس‌های ورتیکال‌های دیوار را به صورت جداگانه مدیریت کنیم به طوری که در یکدیگر اختلال ایجاد نکنند. لازم به ذکر است این روش باید در تمام ورتیکال‌ها یکپارچه انجام گیرد.عکس‌هایی که به یک آگهی مرتبط هستند (مانند عکس‌های کارشناسی یک خودرو که مربوط به آگهی همان خودرو در دیوار می‌شود) باید بتوانند مستقل از آن آگهی مدیریت شوند و با پاک شدن آن آگهی همچنان دسترسی مناسبی به آن عکس‌ها داشته باشیم.هنگامی که یک عکس توسط کاربر بارگذاری می‌شود قبل از اینکه آن آگهی ثبت شود یا به صورت کلی آن فرآیند تکمیل شود، در سیستم به صورت موقتی وجود دارد. اسم این‌گونه عکس ها را temp (موقتی) می‌گذاریم. باید بتوانیم اگر عکسی برای مدت زیادی temp باقی ماند آن را از سیستم حذف کنیم تا فضای اضافی مصرف نکنیم.بتوانیم عکس‌های اصلی (غیر temp) را در CDN ذخیره کنیم تا کاربر سریع‌تر بتواند به آن‌ها دسترسی داشته باشد.اگر عکسی از حالت موقتی خارج شد و در سیستم ماندگار و ذخیره شد، در پروسه انتقال این عکس، کاربر را منتظر تمام شدن عملیات نگذاریم و همیشه پاسخگوی درخواست عکس باشیم.آدرس عکس نهایی شده نباید قابل تولید باشد چون باعث می‌شود یک فرد خرابکار بتواند عکس‌های temp را وارد CDN کند و حجم آن اشغال شود.با دست‌های باز: انتخاب‌هاطبق نیازمندی ها، می‌خواهیم بتوانیم عکسهای temp  و اصلی را موقع serve کردن تشخیص بدهیم (که به ترتیب باید در CDN، مورد cache  قرار بگیرند یا نه). درخواست برای یک عکس temp  یا اصلی با استفاده از Url درخواست داده شده، مشخص می‌شود. همچنین عکس‌ها را باید در Rados Gateway ذخیره سازی کنیم که API ای مشابه AWS S3 دارد و برای محل قرار گیری عکس‌ها می‌توانیم در آن bucket بسازیم. برای این منظور از سرویس کیسه زیرک استفاده می‌کنیم.برای انجام این کارها، چند راه حل وجود دارد:۱. دو باکت مختلف برای عکس‌های temp و اصلی داشته باشیم و درخواست‌های عکس های temp را به باکت خودش و عکس‌های اصلی را به باکت خودشان بزنیم (و cache را روی عکسهای اصلی بگذاریم).در این صورت پروسه‌ی جابجایی از حالت temp به اصلی نیاز به move کردن خواهد داشت و بنابراین این پروسه‌ی move کردن باید به صورت async (با کمک یک سیستم صف مانند RabbitMQ) انجام پذیرد. مشکلی که این موضوع به‌وجود می‌آورد این است که در بازه‌ای عکس‌ها حالت temp ندارند اما هنوز در باکت temp ها هستند. اتفاق مذکور به این سبب رخ می‌دهد که ما مجبور هستیم برای سریع‌تر کردن response time مان، جابجایی عکس‌ها را به صورت async انجام دهیم. برای حل این مشکل باید یک سرویس میانی وجود داشته باشد که اگر عکس در جای اصلی آن پیدا نشد، ریکوئست را به باکت temp ها نیز بفرستد. این مورد، نیازمند خواندن از دیتابیس خواهد بود چرا که ما باید مطمئن شویم عکسی که هنوز منتشر نشده را به اشتباهی منتشر نکنیم و آن را در CDN نگذاریم.راه حل اول. استفاده از دو باکت کاملا جدا
۲. یک باکت برای هر دو حالت temp  و اصلی داشته باشیم و در آن صورت همه‌ی ریکوئست ها را به یک سرویس میانی بدهیم و برای هر ریکوئست دیتابیس را چک کنیم و بسته به حالت عکس، عکس را برگردانیم یا  برنگردانیم (چرا که نباید روی URLای که عکس‌های اصلی serve می‌شوند عکس‌های temp را برگردانیم). این روش نیاز به move را حذف می‌کند اما db hit بیشتری خواهد داشت.راه حل دوم. استفاده از یک باکت مشترک به همراه یک پایگاه داده کمکی
۳. یک باکت برای هر دو حالت temp  و اصلی داشته باشیم و منتشر بودن یا نبودن عکس‌ها را به جای دیتابیس با رمزنگاری متقارن اسم عکس‌ها انجام دهیم. در این حالت، تشخیص آن‌که یک عکس منتشر شده یا خیر را در یک سرویس میانی انجام می‌دهیم که وظیفه آن serve کردن عکس‌ها و reverse proxy کردن به موقعیت واقعی عکس‌هاست.این اتفاق به این صورت انجام می‌گیرد که وقتی یک عکس با اسم A از حالت temp به حالت اصلی تغییر می‌کند، با استفاده از یک کلید اسم جدید B را برای آن از روی A بسازیم به صورتی که بتوانیم از روی ‌‌B نیز اسم A را تشخیص بدهیم و فردی غیر از ما، این تبدیل را نتواند انجام دهد. این کار را می‌توانیم با استفاده از symmetric key encryption انجام دهیم.در این حالت اگر کسی درخواست عکس temp را داد، از داخل باکت serve می‌کنیم و اگر درخواست عکس اصلی با اسم B را فرستاد، اول اسم A را از روی B پیدا می‌کنیم و سپس از داخل باکت عکس A را serve می‌کنیم.راه حل سوم. استفاده از یک باکت مشترک بدون استفاده از پایگاه داده کمکی
مسیر سبز: انتخاب نهایی راه حل اول و دوم reliability کمتری دارند. چرا که هر دو برای پاسخ به درخواست‌ها نیاز به خواندن دیتابیس داشته و این احتمال از دسترس خارج شدن سرویس را بیشتر می‌کند. از طرفی زمانی‌که صرف خواندن از دیتابیس می‌شود، موجب می‌گردد مدت زمان بیشتری در کل فرآیند صرف کنیم.در عین حال راه حل سوم فقط یک بار به AWS S3 درخواست می‌دهد و این response time را نسبت به حالت اول بسیار بهتر می‌کند. همچنین در راه حل سوم نیازی به جابجایی عکس‌ها از فولدری به فولدر دیگر یا عوض کردن اسم‌ آن‌ها دیگر نیست.از بین راه های بررسی شده مسیری که در نهایت انتخاب کردیم را در ادامه بیان می‌کنیم. برای هر سرویس جدیدی که می‌خواهد عکس‌های مدیریت شده داشته باشد یک باکت در استوریج S3 درست می‌کنیم. هر تیم می‌تواند چند سرویس داشته باشد. داشتن یک باکت جداگانه این کمک را به ما می‌کند که می‌توانیم عکس‌های هر سرویس را بدون اینکه روی هم تاثیر داشته باشند، مدیریت کنیم. از طرفی چون صاحب هر باکت، تیمی مشخص است؛ اگر اشکالی در هر باکت پیدا شود (مانند Leakage عکس‌ها)، عیب‌یابی آن راحت‌تر خواهد بود.برای اینکه بتوانیم داده‌های بیش‌تری از عکس‌های وارد شده به سیستم داشته باشیم و هنگام بروز مشکل در سیستم دید بیش‌تری به روند ورود عکس‌ها داشته باشیم و همچنین در صورت عدم موفقیت در فرآیند انتقال عکس از temp به حالت اصلی بتوانیم عملیات را از اول انجام دهیم، از یک دیتابیس SQL با یک جدول که شامل ستون‌های زیر است استفاده می‌کنیم.Name: اسم عکس ذخیره شده روی سرور استSource: اسم سرویس صاحب عکس استState: وضعیت موقتی بودن یا نبودن عکس را مشخص می‌کندCreated at: تاریخ آپلود عکس را ذخیره می‌کندبرای پیاده سازی نیاز به دو API داریم:الف) Upload: این api سرویس مربوطه و عکس را می‌گیرد و برای عکس یک نام یکتا درست می‌کند و به صورت temp آن را در باکت سرویس مربوطه ذخیره می‌کند و نام تولید شده را برمی‌گرداند. همچنین یک رکورد به ازای این عکس در دیتابیس تعریف شده ایجاد می‌کند.ب) Make Permanent: این api عکس‌ها را از حالت temp خارج می‌کند و اسم جدیدی برای آن‌ها از روی اسم قدیمی‌شان می‌سازد (با استفاده از الگوریتم توضیح داده شده AES) و اسم‌های جدید را برمی‌گرداند.برای اینکه بتوانیم با توجه به مسیری که کلاینت از ما درخواست می‌کند عکس مناسب با آن مسیر را برگردانیم نیاز به یک سرویس میانی داریم که مسیر را به صورت temp یا اصلی می‌گیرد سپس عکس مناسب را پیدا می‌کند و به کاربر برمی‌گرداند. اسم این سرویس میانی را Resolver می‌گذاریم.همچنین به یک Job نیاز داریم که هر‌چند وقت یک بار عکس‌هایی که مدت زیادی temp بودند را پاک کند.برای اینکه CDN نیز داشته باشیم، رکورد‌های مسیر اصلی را وارد CDN می‌کنیم که درخواست‌ها را به Resolver ارسال کند و Resolver عکس‌ها را به CDN باز می‌گرداند تا در آن ذخیره شود. به این ترتیب فقط عکس‌های اصلی را در CDN ذخیره می‌کنیم.اثر شگفت‌انگیز یک مدیریت کارآمد پیاده‌سازی این سرویس تأثیر بسیار مثبتی در بهبود فرایند توسعه سرویس‌های جانبی دیوار داشت. این تأثیر مهم در جایی خود را نشان می‌دهد که دیگر برای ذخیره‌سازی عکس‌های سرویس‌هایی مانند کارشناسی خودرو نیاز به اضافه کردن شرط‌های اضافه در جای به جای کد نبوده‌ایم. این شرط‌های اضافه اکنون از جای جای کد جمع آوری شده و به صورت یک فرایند مشخص و به خصوص برای نگهداری عکس‌های هر سرویس جانبی دیوار درآمده‌است.از نظر کارایی، سرویس Image Resolution که برای serve کردن عکس منتشر شده با زبان برنامه‌نویسی Go پیاده‌سازی کرده‌ایم، زمان پاسخگویی قابل قبولی دارد. نمودار زمان پاسخدهی این سرویس در شکل زیر نمایش داده شده:علت انتخاب زبان برنامه‌نویسی ‌Go کارایی خوب این زبان در هندل کردن درخواست‌های با IO زیاد و نیز سادگی پیاده‌سازی منطق رمزگشایی و proxy کردن عکس‌های دیوار در این زبان بوده است.همچنین به علت مستقل بودن عملکرد این سرویس نسبت به دیگر زیرسیستم‌های دیوار، این سرویس آپ‌تایم مستقلی از دیگر بخش‌های دیوار داشته و این کمک نموده تا ورتیکال‌های دیوار مانند خودرو باعث ایجاد اختلال در سرویس‌دهی زیرسیستم‌های اصلی دیوار نشوند.حالا چه خبر...؟با گذشتن مدت خوبی از پیاده‌سازی این مسیر، چالش‌ها و نیازمندی‌هایی را مشاهده کردیم که می‌توانستیم در ابتدای مسیر برای آن‌ها چاره‌ای بیاندیشیم. در ادامه به تعدادی از آن‌ها اشاره می‌کنیم:با توجه به اینکه در سمت ذخیره سازی فایل کلاستر‌های متفاوتی داریم که بعضی نسبت به بعضی دیگر سریع‌تر هستند، اما هزینه‌ی بیشتری دارند، می‌توان عکس‌های temp را ابتدا در کلاستر کم هزینه‌تر ذخیره کرد سپس با نهایی شدن عکس آن‌ها را در کلاستر‌های سریع‌تر ذخیره نمود.راهکار Atomicی برای ذخیره‌سازی چند عکس نداریم. برای مثال اگر صفحه‌ای داشته باشیم که چند گروه متفاوت از کاربر عکس ورودی دریافت کند، راهکاری نداریم که اطمینان حاصل کنیم که تمام عکس‌ها با هم ذخیره شده باشد و تعدادی ذخیره نشده نداشته باشیم.حرف آخر اینکه برای حل هر چه بیش‌تر از چالش‌های پیش‌رو به یاری از سمت افراد تازه‌نفس و مشتاق به یادگیری نیاز داریم. امیدواریم مطالعه این پست به شما در آشنایی با چالش‌های فنی دیوار و شناخت مقیاس فنی چالش‌های ما کمک کرده باشد.برای پیوستن به دیوار به صفحه فرصت‌های شغلی ما سر بزنید.</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Tue, 08 Sep 2020 15:03:51 +0430</pubDate>
            </item>
                    <item>
                <title>معرفی چالش‌های جذاب داده‌ای در دیوار</title>
                <link>https://tech.divar.ir/introductiontodatascienceteams-r6vupryhizcl</link>
                <description>مقدمهحدود دو سال پیش محمد امین خشخاشی مقدم پستی را با عنوان سرگذشت تیم داده‌ی دیوار نوشت که در ابتدا درباره‌ی دلایل شکل‌گیری این تیم و اهداف آن صحبت ‌می‌کند، سپس از چگونگی شکل‌گیری ساختار تیم‌ها در دیوار و به طور خاص نقش و جایگاه چپتر داده توضیح می‌دهد و در ادامه به چالش‌های ذخیره‌سازی و پردازش داده‌ی انبوه که در آن زمان با آن‌ها مواجه بودیم اشاره می‌کند و در نهایت راه‌حل‌ها و تکنولوژی‌های مورد استفاده در زیرساخت داده برای حل برخی از این چالش‌ها را به طور مفصل توضیح می‌دهد.همان‌طور که در آن مقاله نیز به این اشاره شده، کارهای ما در زمینه‌ی داده به دو قسمت اصلی تصمیم‌گیری داده محور و توسعه محصولات داده‌ای تقسیم می‌شوند. در این مقاله سعی می‌کنیم برخی محصولات داده‌ای که تیم‌های مختلف دیوار در مدت اخیر مشغول توسعه یا بهبود آن‌ها بودند را معرفی کنیم.این نوشته به ۵ بخش مختلف تقسیم می‌شود که در هر بخش به طور مختصر به معرفی یک تیم دیوار می‌پردازیم و سعی می‌کنیم یکی از مسائل دیتایی آن تیم را مفصل‌تر توضیح دهیم. نکته‌ای که در معرفی این مسائل سعی شده به آن توجه گردد این است که عمیقا وارد بحث‌های فنی و جزئی نشده‌ایم بلکه به جای شرح و بسط مفصل یک مسئله، چند مسئله را به صورت خلاصه جهت آشنایی خواننده با شمایل چالش‌‌های دیتایی دیوار توضیح داده‌ایم.برای ما یکی از جنبه‌های جذاب مسائل دیتایی دیوار، گستردگی آن‌ها چه از منظر ماهیت و تعریف‌شان، و چه از منظر دیتاهایی بوده که برای حل هر مسئله بایستی در نظر بگیریم. به همین سبب تلاش کردیم تنوع مسائل را در انتخاب مسئله‌ای که هر تیم توضیح آن را داده، در نظر بگیریم.سینا مختارزاده از تیم خودرو درباره‌ی پروژه‌های پردازش تصویری‌ در این مدت اخیر توضیح می‌دهد. سینا حدود دوسال هست که ابتدا در تیم ریویو و سپس خودروی دیوار فعالیت داشته و بیشتر به حوزه بینایی ماشین علاقه‌مند است.امیر اقدم از تیم جویندگان درباره‌ی پروژه‌های اخیری که در زمینه‌ی پردازش متن به منظور بهبود سیستم جست‌وجو انجام دادند صحبت می‌کند. امیر حدود دو سال هست که در تیم جویندگان دیوار فعالیت می‌کند و قبل از آن تجربه‌ی دو ساله‌ی کار در تیم سرچ کافه‌بازار را داشته و بیش‌‌تر به کار با داده‌های متنی و NLP علاقه مند است.آرمان عیسی خانی از تیم املاک درباره‌ی سرویس‌های توصیه‌گری که تیم در حال توسعه‌ی آن هستند صحبت می‌کند. آرمان حدود دو سال هست که در بخش دیتای دیوار فعالیت می‌کند و قبل از آن تجربه‌ی سه ساله‌ی کار در کافه‌بازار را داشته‌، کارش در دیوار با تیم سرچ و جویندگان شروع کرد و بعد از آن برای مدتی وارد تیم ریویو شد و در حال حاضر در بخش املاک مشغول هست و بیشتر سابقه‌ی فعالیتش در زمینه‌ی سیستم‌های پیشنهاد دهنده است.علیرضا نوروزی از تیم بررسی آگهی درباره‌ی بات‌های مختلف این تیم برای بررسی خودکار آگهی توضیحاتی می‌دهد. علیرضا حدود دو سال هست که در تیم بررسی آگهی دیوار فعالیت داشته و بیشتر به کارهای کامپیوتر ویژنی با مدل های دیپ لرنینیگی علاقه دارد.در نهایت حسام حداد از تیم چت درباره‌ی مسئله‌ی پیشنهاد هوشمند به جهت بهبود و تسهیل مکالمه‌ی بین خریدار و فروشنده توضیحاتی می‌دهد. حسام حدود یک سال هست که در این تیم فعالیت داشته، و بیشتر سابقه کاری‌ش در زمینه داده‌های متنی و NLP است.مسئله‌ی تشخیص پلاک و زدن واترمارک دیوار در تیم خودرومعرفی تیمتیم خودروی دیوار برای حل مسائل موجود در دسته بندی خودروی دیوار تشکیل شده است. اهداف مختلفی مانند حضور در فرآیند تصمیم گیری خرید و فروش خودرو، افزایش کیفیت آگهی‌ها و تسهیل فرآیند یافتن آگهی مطلوب کاربر در این تیم در نظر گرفته شده و راه حل‌های دیتایی گوناگونی برای آن‌ها ارائه شده اند. برای مثال می توان به مدل تخمین قیمت خودرو، مدل تشخیص پلاک، مدل استخراج کننده‌ی اطلاعات از متن آگهی و سیستم توصیه گر آگهی اشاره کرد که نشان‌دهنده‌ی گوناگونی مسائل موجود در این تیم می‌باشد. در ادامه توضیح بیش‌تری درباره‌ی مسئله ی تشخیص پلاک می‌دهیم.شرح مسئلهپس از بررسی‌هایی که روی تصاویر منتشر شده در دسته بندی خودروی دیوار داشتیم مشاهده کردیم که حدود ۴۰٪ از این عکس‌ها با احتمال خوبی به دلیل تلاش برای عدم نمایش پلاک، کیفیت مناسبی ندارند. برای مثال فرد از انگشت‌ش برای پوشش پلاک استفاده کرده یا تصویر پلاک را خط خطی کرده‌است یا بعضی اوقات از زاویه‌های غیر عادی عکس گرفته است تا پلاک مشخص نباشد. این اتفاق نشان دهنده‌ي این است که افراد به هر دلیلی علاقه ای به نمایش شماره‌ی پلاک خودرو در عکس ندارند. در نتیجه تصمیم گرفتیم برای جلب رضایت کاربران و حفظ حریم خصوصی آن‌ها که در نهایت به افزایش کیفیت عکس‌های دیوار منجر می‌شود، سراغ پیاده‌سازی مدلی برویم که پلاک‌ها را تشخیص داده و محو کند. در ادامه با بهبود مدل‌ موردنظرمان به ایده‌ی جایگزینی پلاک با واترمارک دیوار رسیدیم.شکل ۱- نمونه‌هایی از عکس‌های با کیفیت پایین به دلیل تلاش برای عدم نمایش پلاک راه حل پیشنهادیبه منظور تشخیص پلاک می‌توان از روش‌های object detection مبتنی بر شبکه‌های عصبی کانولوشنی برای تشخیص مستطیل دربردارنده‌ی پلاک استفاده کرد. از نقطه ضعف این روش‌ها می‌توان به عدم تولید چند ضلعی‌های کاملا منطبق بر پلاک برای پلاک‌ها با زاویه‌های مختلف به منظور جایگزینی با واترمارک دیوار اشاره کرد. برای حل این مشکل در ابتدا ما یک راهکار دو مرحله‌ای ارائه دادیم. در مرحله‌ی اول یک مدل object detection و به طور خاص مدل Yolo-v3 آموزش دادیم که ناحیه‌ی مستطیلی دربردارنده‌ی پلاک را پیدا کند. در مرحله‌ی دوم ناحیه‌ی پیدا شده را به یک شبکه‌ی کانولوشنی دادیم تا بتواند چهار گوشه‌ی چهار ضلعی پلاک را تولید کند. بدین ترتیب می‌توانستیم با ثبت یک عکس ناحیه‌ی دقیق پلاک‌ها را پیدا و واترمارک دیوار را با پلاک‌ها جایگزین کنیم.مشکلی که راهکار دو مرحله‌ای مذکور داشت، مدت زمان اجرای نسبتا بالای آن بود. روزانه هزاران تصویر خودرو در دیوار بارگذاری شده که باید توسط الگوریتم ارائه شده پردازش شوند. ایده ای که برای حل این مشکل داشتیم ترکیب مراحل راهکار قبل در یک مدل Multi-Task یک مرحله‌ای بود. برای این کار به سراغ یکی از جدیدترین مدل‌های object detection به اسم EfficientDet رفتیم و با الهام از روش‌های موجود در مدل‌های Human Pose Estimation، شاخه‌ی جدیدی برای پیش بینی گوشه‌های پلاک اضافه کردیم. در نهایت می‌توانستیم با توجه به ناحیه‌ی مستطیلی یافت شده برای پلاک، نقاط دقیق را از این شاخه‌ی جدید به دست بیاوریم. استفاده از این روش هزینه‌ی محاسباتی مدل ما را به مقدار قابل توجهی کاهش داد و در نتیجه مشکل زمان اجرا نیز برطرف شد. اگر علاقه‌مند هستید جزئیات بیش‌تری درباره این مسئله بدانید، می‌توانید پست بعدی ما را دنبال کنید.شکل ۲ - نمونه‌هایی از خروجی مدل نهایی تاثیرگذاری و چالش‌های پیش‌روبرطرف کردن مشکلاتی که اشاره شد به ما این امکان را می‌دهد که مدل‌مان را در سطح محصول اجرا کنیم. پس از اضافه شدن تشخیص پلاک، کیفیت عکس‌ها شروع به بهبود تدریجی کرده و تا این لحظه درصد عکس‌های مخدوش به دلیل تلاش برای عدم نمایش پلاک از ۴۰ به ۳۳ کاهش یافته و این انتظار می‌رود که با افزایش آگاهی کاربران این مقدار کم‌تر گردد.همان‌طور که اشاره کردیم، افزایش کیفیت آگهی‌ها و به طور خاص عکس‌های دیوار یکی از اهداف تیم خودرو است. برای رسیدن به این هدف در ادامه در تلاش هستیم تا با ارائه‌ی راهکار‌هایی مثل فوکوس روی عکس خودرو و محو پس زمینه، عکس با کیفیت‌تری به کاربرها نمایش دهیم یا به صورت اتوماتیک فیدبکی نسبت به کیفیت عکس گرفته شده به کاربر دهیم که بتواند عکس با کیفیتی از خودروی خودش بارگذاری کند.مسئله پیشنهاد کوئری مشابه در تیم جویندگانمعرفی تیمیکی از اهداف مهم تیم جویندگان بهبود قابلیت یافت‌پذیری آگهی‌ها از طریق سیستم سرچ دیوار است. در همین راستا، همواره یکی از نقاط تمرکز تیم بهبود کیفیت نتایج هر جستجو بوده است. در طی فصل‌های گذشته کارهای متنوعی برای رسیدن به این هدف از طرف بخش دیتای تیم انجام شده است. یکی از آخرین پروژه‌های ما در این راستا، پیشنهاد کوئری‌های مشابه بوده که به تازگی در حال قرار گرفتن روی محصول است. در ادامه آشنایی بیشتری با این پروژه پیدا می‌کنیم.تعریف مسئلهیکی از معیارهای ما برای ارزیابی عملکرد سیستم جستجوی دیوار، میزان رضایت کاربران از نتایج جستجو است. برای نشان دادن نتایج به کاربر همیشه باید توازنی مهم برقرار باشد: از طرفی هرچه نتایج بیشتری به کاربر نشان دهیم، امکان اینکه آگهی مورد نظر کاربر در نتایج باشد بیشتر می‌شود. اما از طرف دیگر هرچه آگهی‌های نامرتبط با هدف کاربر در نتایج بیشتر باشد، سبب خستگی کاربر می‌شود. در کنار موازنه بالا در نمایش نتایج باید توجه داشته باشیم که آگهی های جدیدتر احتمالا جذابیت و اهمیت بیشتری دارند چرا که به احتمال کمتری فروش رفتند.یکی از ایده‌های ما برای برقراری موازنه بالا، استفاده از پیشنهاد کوئری مشابه به جای نمایش نتایج مرتبط در نتایج جستجو بود. با افزودن این پیشنهاد، علاوه بر اینکه مانع شلوغ شدن بیش از حد نتایج جستجو می‌شویم، امکان دسترسی سریع کاربر به نتایج کوئری‌های دیگر که ممکن است مقصود کاربر بوده باشد را نیز بسیار راحت‌تر می‌کنیم. همچنین این سیستم برای زمانی که کوئری اولیه نتایج کمی داشته، می‌تواند موثر باشد و عملا کوئری بهتری را به کاربر راهنمایی کند.ایده و روش کاربرای یافتن کوئری مشابه، ما از رفتار کاربران در جستجوهای گذشته کمک گرفتیم. کاربران معمولا وقتی در یک جستجو به هدف خود نمی‌رسند، به گونه‌های مختلفی عبارت خود را تغییر می‌دهند. گاهی کاربر به صورت کلی هدف خود را تغییر می‌دهد و به دنبال کالا یا خدمات دیگری می‌گردد. بعضی وقت‌ها عبارت جستجوی اولیه خیلی عمومی است و با دقیق‌تر کردن آن جواب‌های بهتری یافت می‌شود و برخی مواقع عکس این اتفاق می‌افتد. گاهی نیز کاربر سعی می‌کند از عبارات مشابه برای جستجوی جدید استفاده کند. دسته آخر از این تغییرات به صورت خاص مورد توجه ما برای ساخت مدل پیشنهاد کوئری مشابه قرار گرفت.ما برای یافتن کوئری‌های مشابه، زنجیره‌ای از جستجوهای عبارات مشابه را برای تمام کاربران جمع کردیم. سپس با استفاده از روشی مشابه Word2Vec بر روی این زنجیره‌ها فضای برداری شباهت کوئری‌ها در دیوار را ساختیم. در نهایت هم با توجه به ملاحظات مختلفی، مانند تعداد نتایج و پرتکرار بودن کوئری یا شهر و دسته جستجو، که برای پیشنهاد دادن یک کوئری داریم نمره‌ای ترکیبی به هر پیشنهاد اختصاص دادیم.چالش‌های عمده کارهمان‌طور که پیش‌تر گفتیم، کاربران رویکردهای متفاوتی پس از یک جستجوی ناموفق در پیش می‌گیرند و جستجوی کوئری مشابه تنها یکی از این روش‌هاست. بخش بزرگی از کاربران در یک سشن، هیچ‌وقت بیش از یک جستجو انجام نمی‌دهند. همین‌ موضوع جمع‌آوری حجم مناسب دیتا برای پروژه را سخت می‌کرد. ما برای جمع‌آوری دیتای مناسب برای مدل‌مان مجبور شدیم بیش از ۱ میلیارد جستجو را بررسی کنیم و از تمامی این موارد تنها ۲۰ میلیون سشن ساخته شد که از این تعداد به تنها ۴ میلیون سشن مناسب رسیدیم.بررسی این حجم از دیتا نیازمند توان محاسباتی و ذخیره‌سازی بسیار بالایی است، که ما تنها به کمک توان پردازشی و تکنولوژی‌های مورد استفاده در زیرساخت دیوار موفق به انجام آن شدیم. در زیرساخت داده دیوار با استفاده از موازی‌سازی اسپارک و دسترسی به تعداد زیادی سرور با منابع بسیار قوی محیطی مناسب برای کار روی کلان داده‌ها فراهم آورده شده‌است.از طرف دیگر کل این فرآیند احتیاج به بروزرسانی‌های دوره‌ای دارد که نیازمند ساخت مدل به شیوه‌ای است که امکان بروز رسانی خودکار مدل مهیا باشد که این مورد با توجه به حجم بالای داده، دقت ویژه‌ای می‌طلبد.نمونه خروجی نهاییدر تصویر زیر می‌توانید نمونه خروجی نهایی این مدل را در یک عبارت جستجوی فرضی ببینید:مسئله‌ی سیستم‌های پیشنهاد دهنده در تیم املاکمعرفی تیمتیم املاک دیوار برای حل مسائل موجود در دسته بندی املاک دیوار تشکیل شده است. تمرکز اصلی تیم در دو فصل اخیر بر روی افزایش کیفیت آگهی‌های املاک، بهبود فرایند دسترسی کاربران به این آگهی‌ها و بهبود پنل املاک بوده است. یکی از مسائل اصلی ما در بخش دیتا، مسئله‌ی سیستم‌های پیشنهاد دهنده به جهت برآورده کردن هدف دوم یعنی بهبود دسترسی به آگهی‌های املاک بوده که در ادامه در مورد آن توضیح بیشتری خواهیم داد.تعریف مسئلهمهم‌ترین هدف ما در دیوار برقراری ارتباط میان خریدار هر کالا و فروشنده‌ی مربوط به آن کالا است. در نتیجه مسئله‌ی تسهیل یافت‌پذیری آگهی‌های متناسب با سلیقه‌ی هر کاربر برای ما از اهمیت خیلی بالایی برخوردار است. تا قبل از این در بخش‌های مختلف دیوار مخصوصا بخش جست‌وجو کارهای زیادی در این راستا انجام داده بودیم اما پروژه‌ی جدیدی که در بخش املاک شروع کردیم توجه بیشتر به سیستم‌های پیشنهاد دهنده بود که هدف غایی این سیستم‌ها پیشنهاد کالا یا محصول متناسب با سلیقه‌ی هر کاربر است. روزانه ما چند صد گیگابایت دیتا از کاربران و تعامل آن‌ها با آگهی‌ها جمع‌آوری می‌کنیم که از یک طرف منبع غنی برای شناسایی بهتر نیاز هر کاربر بوده اما از طرف دیگر چالش‌هایی از قبیل مقیاس‌پذیری این سیستم را برای ما مطرح می‌کند.چالش‌های عمده کاربزرگ‌ترین چالش ما در توسعه‌ی این سرویس مسئله‌ی شروع سرد (cold-start) بود. این یکی از چالش‌های شناخته شده برای هر سرویس پیشنهاد دهنده به شمار می‌آید و به طور خلاصه به چگونگی عملکرد سیستم در مواجهه با کاربر یا آیتم (آگهی کالایی) جدیدی مربوط می‌شود که به تازگی وارد سیستم شده است و ما دیتا و اطلاعات کافی از آن‌ها هنوز در اختیار نداریم. به طور خاص این مسئله برای ما در دیوار بسیار پررنگ‌ بود چرا که بیش از نیمی از آگهی‌هایی که در دسته‌‌ی املاک هر روز مشاهده می‌شوند آگهی‌هایی هستند که از تاریخ انتشار آن‌ها کمتر از یک روز می‌گذرد و برای داشتن coverage معقول این سرویس باید در مدت خیلی کوتاهی پیشنهادهای مناسبی برای هر آگهی به دست بیاوریم. به همین دلیل مدل‌های مبتنی بر محتوا با توجه به‌ این‌که کمتر تحت تاثیر شروع سرد قرار می‌گرفتند از اهمیت بیشتری برخوردار بودند.دومین چالش، به روز بودن آگهی‌هایی است که به کاربران در این لیست‌ها نمایش می‌دهیم. معمولا هر چقدر زمان کمتری از انتشار آگهی گذشته باشد، احتمال این‌که آگهی مورد نظر فروش رفته کمتر است. به همین دلیل در کنار متریک‌های مثل coverage, MAP, .. متریکی مثل freshness برای ما از اهمیت خیلی بالایی برخوردار بود. این متریک‌ها باید در تست‌های آفلاین و آنلاین به دقت مورد بررسی قرار می‌گرفتند تا اطمینان حاصل کنیم که این سرویس جدیدمون تا جای ممکن آگهی‌های جدید رو به کاربر پیشنهاد دهد.تاثیرگذاری و دست‌آوردهای فعلیدر اولین گام توسعه این سرویس هدف ما تولید لیستی به نام آگهی‌های مشابه بود. در حال حاضر اگر وارد صفحه‌ی برخی آگهی‌ها شوید لیستی‌ با همین عنوان را مشاهده خواهید کرد. متریک‌های مختلفی را برای ارزیابی کمی و کیفی این سرویس به دست آوردیم. شاید جالب‌ترین متریکی که بیان‌کننده‌ی تاثیرگذاری این سرویس بود، افزایش CTR (نرخ تماس به بازدید) روی پست‌هایی است که از طریق این لیست مشاهده شده است. به طور خلاصه ما شاهد رشد سه برابری بر روی این متریک بودیم؛ به این معنی افرادی که با آگهی A تماس گرفته بودند احتمال این‌که بعد از مشاهده یک پست از لیست آگهی‌های مشابه A با آن پست مشابه تماس بگیرند، در مقایسه با حالت نرخ تماس به بازدید کاربران از طریق سرچ، ۳ برابر افزایش داشت. این فزایش به شکل معنی‌داری ما را به ادامه‌ی این مسیر و بهبود هرچه بیشتر آن در طول زمان امیدوارتر کرد.شکل ۱- در بالای تصویر مشخصات یکی از آگهی‌هایی که کاربر از آن بازدید داشته‌است را می‌بینید. در پایین تصویر نمونه‌ لیستی از آگهی‌های مشابه با آگهی اول را می‌بینید (بالای تصویر) که در صفحه‌ی مربوط به آگهی اول نمایش داده ‌می‌شوددر حال حاضر هدف ما علاوه بر گسترش این سرویس و بهبود آن، تمرکز روی لیست جدید پیشنهاد آگهی به هر کاربر هست که بعد از ورود به دیوار آگهی‌هایی که فکر می‌کنیم با توجه به سابقه‌ی فرد برای او جالب خواهد بود را نمایش دهیم و به این ترتیب مسیر رسیدن کاربران به آگهی‌های مورد نیازشان را کوتاه‌تر کنیم.مسئله‌ی بررسی خودکار آگهی در تیم بررسی آگهیمعرفی تیمتمام آگهی‌هایی که بر روی دیوار آپلود می‌شوند، باید دارای ویژگی‌هایی باشند تا اجازه انتشار به آن‌ها داده شود. در همین راستا، در هر هفته، میلیون‌ها آگهی روی دیوار مورد بررسی صدها ناظر انسانی و ده‌ها بات هوشمند قرار می‌گیرند تا از کیفیت آن‌ها اطمینان حاصل شود. برای واضح تر شدن بحث در لیست زیر تعدادی از قوانین و نکات مورد بررسی در انتشار آگهی آمده است:درست بودن دسته بندی آگهی: به عنوان نمونه آگهی‌های خودرو در دسته بندی املاک منتشر نشوند.تکراری نبودن آگهی‌ها: تکراری بودن آگهی‌ها تنوع محتوا بر روی دیوار را کاهش داده و تجربه کاربری نامناسبی برای کاربران به وجود می‌آورد.عکس باکیفیت و مرتبط با آگهی: وجود عکس بی‌کیفیت به دلیل این‌که برای بازدیدکنندگان مطلوب نیست، باعث کاهش اثرگذاری آگهی و احتمال موفقیت آن می‌شود. به همین دلیل، وجود عکس با کیفیت و مرتبط با آگهی (مثلا عکس واضح از زوایای مختلف خانه در آگهی‌های املاک)، یکی دیگر از قوانینی است که برای هر آگهی مورد بررسی قرار می‌گیرد.فرایند ورود آگهی به سیستم بررسی آگهی تا انتشار آن، دارای جزئیات زیاد و با ابعاد مختلف است که تیم بررسی آگهی دیوار، مسئول توسعه و نگهداری از آن‌هاست.در این راستا به طور کلی تیم بررسی آگهی دو هدف اصلی را دنبال می کند:۱. تسهیل فرایند بررسی آگهی برای ناظرهای انسانی۲.  اتوماسیون حداکثری در زمینه بررسی آگهی به منظور افزایش کیفیت و سرعت فرایند بررسی آگهی.در تیم بررسی آگهی، زیرتیم (پاد) دیتا، به طور خاص به دنبال برآورده کردن هدف افزایش اتوماسیون در زمینه فرایند بررسی آگهی است.نمونه چالش های دیتایی تیم بررسی آگهیتیم بررسی آگهی در نقطه مهمی از کل سیستم قرار گرفته است و تصمیمات اشتباه در رد یا تایید یک آگهی می‌تواند عواقب متعددی داشته باشد. به عنوان نمونه رد اشتباه یک آگهی می‌تواند تجربه تلخی در ذهن کاربر آگهی دهنده در دیوار ایجاد کند. از آن طرف تایید اشتباه یک آگهی که با قوانین یک آگهی صحیح در تناقض هستند، باعث کاهش کیفیت آگهی‌های روی سایت شده و برای کاربران تجربه ناخوشایندی را در پی خواهد داشت. در نتیجه سیستم‌هایی که در اتوماسیون بررسی آگهی مورد استفاده قرار می‌گیرند باید تست‌های زیادی را پشت سر گذاشته و آن‌ها را با موفقیت گذرانده باشند.علاوه بر این از نظر کا‌رهای دیتایی هر آگهی حاوی متن، عکس و تعداد زیادی فیلد مرتبط با هر دسته‌بندی است. این موضوع باعث می‌شود بررسی هر آگهی، نیازمند استفاده از تکنیک‌های مختلفی از پردازش زبان طبیعی (NLP) و بینایی کامپیوتر(Computer vision) باشد.برای رسیدن به عملکرد و دقت قابل قبول، باید از تکنولوژی‌های جدید در یادگیری ماشین کمک گرفت. اما سیستم‌های قدرتمند در زمینه بینایی کامپیوتر (مثل Deep CNNها) و در زمینه پردازش زبان طبیعی (مثل BERT) به توان محاسباتی بالایی در فرایند آموزش مدل‌ها و همچنین در استفاده از آن‌ها در محصول نیاز دارند، که این موضوع نیز از نمونه چالش‌های فنی در تیم بررسی آگهی دیوار است.معرفی بات بررسی خودکار آگهی - بات تشخیص آگهی تکراریبه عنوان یک مثال از سیستم بررسی خودکار آگهی، تعدادی از چالش‌های توسعه یک بات برای تشخیص آگهی تکراری در این بخش بررسی می‌شود. لازم به ذکر است که برچسب زدن یک آگهی به عنوان تکراری، قوانین متعددی دارد که در اینجا تنها تصویری کلی از موضوع ارائه می‌شود.در فرایند بررسی آگهی، هنگامی به یک آگهی آپلود شده تکراری گفته می‌شود که فرد آگهی گذارنده، در حال حاضر حداقل یک آگهی روی دیوار داشته باشد که همان محتوا/کالای آگهی جدید را پوشش داده باشد.برای تشخیص شباهت دو آگهی، نیاز است تمامی اطلاعات موجود در آگهی بررسی شود. این اطلاعات عبارتند از: عنوان و متن آگهی، تصاویر، دسته بندی، فیلدهای عمومی نظیر قیمت و شهر آگهی و فیلدهای خصوصی هر دسته بندی مثل متراژ و تعداد اتاق در دسته بندی املاک. یکسان بودن هر کدام از این اطلاعات بین دو آگهی، لزوما به معنی تکراری بودن آن دو آگهی نیست. در نتیجه بهترین نتیجه زمانی حاصل خواهد شد که تمامی اطلاعات در کنار هم  مورد بررسی قرار بگیرد.از طرفی، هر کدام از این اطلاعات، نوع متفاوتی دارند (فیلدهای کتگوریکال، عددی، تصویر و متن) که برای هرکدام باید معیار شباهت مختص به خود را تعریف کرد که هم‌راستا با قوانین آگهی‌های تکراری باشد. به عنوان مثال برای تشخیص شباهت بین دو تصویر، با مقایسه پیکسل به پیکسل می‌توان عکس‌های کاملا یکسان را تشخیص داد اما کوچک‌ترین تغییری (مثل یک چرخش جزئی یا فشرده سازی) می‌تواند دو تصویر کامل مشابه را از دید این معیار متفاوت جلوه دهد. از طرفی، ویژگی‌های بدست آمده از شبکه‌های CNN، به بسیاری از تغییرات مقاوم هستند، اما به دلیل در نظر گرفتن شباهت‌های سطح بالاتر، ممکن است تصاویر کاملا متفاوت (مثل یک پراید سفید و یک پراید مشکی) را نیز در یک سطح مشخص از حساسیت، مشابه تشخیص دهند.همین موضوع در مورد متن نیز صدق می کند. که این موضوع را به طور مثال با مقایسه شمارش n-gram ها و ویژگی‌های استخراج شده از لایه‌های ‌BERT می‌توان دید. از همین رو، ترکیب تمامی ویژگی‌ها با حساسیت‌ و پیش فرض‌های مختلف، از روش‌های موثر در تشخیص آگهی‌های تکراری است که در دیوار از آن‌ها استفاده می‌شود.پس از حل هر کدام از این چالش‌ها در تعیین شباهت بین متون و تصاویر دو آگهی، باید ارتباط بین تصاویر، متن و فیلدهای آگهی را در کنار هم در نظر گرفت و بر اساس تمامی جوانب نظر نهایی را اعلام کرد.شکل ۱- یک نمونه آگهی تکراری که با استفاده از متن به تنهایی ممکن است نتیجه مطلوبی بدست ندهد از نگاه فنی نیز، با بزرگ شدن سیستم بررسی شباهت بین دو آگهی، باید در نظر داشت که پیچیدگی زمانی اجرای این سیستم، به صورت خطی با تعداد آگهی‌هایی که باید از نظر شباهت با آگهی جدید مورد بررسی قرار گیرند رشد می‌کند، که این مورد نیز در توسعه و استفاده از این سیستم در عمل، پیچیدگی‌های مهندسی زیادی را ایجاد می‌کند.جمع بندیدر این بخش تلاش شده تا نگاهی کلی به اهداف و نمونه چالش‌های تیم بررسی آگهی دیوار داشته باشیم. با توجه به حجم و تنوع داده‌های ورودی در کنار قوانین متنوع روی متون و تصاویر آگهی‌ها، تلاش برای بهبود سیستم‌های مرتبط با اتوماسیون بررسی آگهی به طور دائم ادامه دارد و راه طولانی تا رسیدن به ایده آل‌ها در پیش است. تیم دیتای بررسی آگهی با استفاده از تکنولوژی‌های روز در تلاش است تا علاوه بر راحت تر کردن کار روزانه ناظر‌های انسانی دیوار، کیفیت آگهی‌هایی که بر روی دیوار منتشر می‌شوند را به طور مستمر بهبود دهد.مسئله‌ی پیشنهاد هوشمند پیام در تیم ارتباطات دیوارمعرفی تیم بررسی چتتیم ارتباطات دیوار با هدف برقراری ارتباط امن و آسان غیرحضوری بین فروشندگان و خریداران در بستر دیوار تشکیل شده است. این تیم شامل زیر تیمی به نام دیتا می‌باشد که پروژه‌های یادگیری ماشین و تحلیلی مرتبط با ارتباطات دیوار را پیگیری می‌کند. پروژه‌های یادگیری ماشین که در بخش ارتباطات دیوار انجام می‌گیرد در جهت تسهیل فرآیند خرید و فروش و همچنین جلوگیری از تجربه کاربری بد می‌باشد. در ادامه پروژه پیشنهاد هوشمند پیام به عنوان یکی از پروژه‌های تیم ارتباطات دیوار شرح داده شده‌است.چرا مسئله‌ی پیشنهاد هوشمند پیام؟شکل ۱- نمونه‌ای از پیشنهاد هوشمند پیام نمایش داده شده در پایین صفحه‌ی چت یک خریدار هدف پیشنهاد هوشمند پیام (Smart Suggestion)، ارائه‌ی پیشنهاداتی به کاربران در مکالمه است تا ادامه مکالمه به سادگی شکل گیرد. این چنین سیستم‌هایی در حال حاضر در GMail برای تسریع پاسخگویی به ایمیل‌ها، و همچنین در Uber برای سرعت بخشیدن به ارتباط بین راننده و مسافر استفاده شده و نتایج مناسبی کسب کرده است. هدف از پیگیری مسئله‌ی پیشنهاد هوشمند پیام در دیوار، دو مورد بود: یکی سرعت بخشیدن به انجام معامله در چت دیوار و دیگری راهنمایی خریدار برای پرسیدن سوالات فنی مرتبط با محصول، تا به این صورت حجم و کیفیت مکالماتی که در چت دیوار به منظور معامله انجام می‌شود افزایش پیدا کند. یکی از مواردی که ممکن است در معامله مشکل ایجاد کند عدم تقارن اطلاعات خریدار و فروشنده است، که دیوار از طرق گوناگون مانند اضافه کردن فیلدهای مختلف به آگهی و خدمات تخصصی ارزیابی محصول در برخی دسته‌ها به منظور انتقال اطلاعات راحت‌تر و سریع‌تر بین خریدار و فروشنده اقدام کرده است. در مسئله پیشنهاد هوشمند پیام، برای مثال وقتی سوال «گوشی ریجیستر شده؟» برای خریدار پیشنهاد می‌شود علاوه بر این که به تسهیل  فرآیند پرسیدن سوال کمک می‌کند، می‌تواند به عنوان یک راهنمایی برای خریدار عمل کند که به این نکته نیز در حین خرید توجه نماید.از محدودیت‌های فنی دیگر می‌توان به سریع بودن فرآیند پیشنهاد پیام اشاره کرد تا بتواند بر روی CPU با سرعت بالایی به خروجی دست پیدا کند. این مورد برای چت دیوار که تعداد پیام‌های روزانه آن از چند میلیون بالاتر می‌رود بایستی قابل عملیاتی شدن باشد. خروجی نهایی فعلی کلیه مراحل پیش‌پردازش، بازنمایی، پیدا کردن Intent، و پیشنهاد Intent بعدی را بر روی یک Core CPU در ۱۵ الی ۲۰ میلی ثانیه انجام می‌دهد.پیدا کردن Intent های مرتبط با هر دسته بندیبه منظور پیدا کردن Intent های مرتبط با هر دسته بندی، از ترکیب دو روش مختلف بهره بردیم: خوشه‌بندی بر روی بازنمایی جملات و دیگری استفاده از Information Gain. در کنار Information Gain، پارامترهای عددی دیگر بر روی احتمال رخداد گرام‌های مختلف کلمات در دسته‌بندی‌ها نیز مورد استفاده قرار گرفت. چالشی که این مسئله را سخت‌تر از مسائل معمولی خوشه‌بندی متون می‌کرد ساختار عامیانه و کوتاه جملات و همچنین وجود غلط‌های املایی بود. در نتیجه استفاده از روش‌هایی مانند LDA منجر به نتیجه مناسبی نشد. ترکیب دو روش ذکر شده در ابتدا، به همراه نظارت بر خروجی کمک کرد که بتوانیم در مدت زمان کوتاهی به لیست اولیه‌ای از خوشه‌های Intent های مطرح در هر دسته‌بندی برسیم. پس از این مرحله، یک مرحله فرآیند برچسب زدن نمونه‌های موجود در این خوشه‌ها انجام می‌گیرد تا خروجی قابل اطمینان باشد. پس از آن تشخیص هر Intent توسط بازنمایی جمله و جستجو تقریبی سریع انجام می‌شود که علاوه بر داشتن سرعت بالا، از کیفیت خوبی نیز برخوردار است.پیشنهاد سمت خریدار و فروشندهبرای پیشنهاد سمت خریدار مشکلی که وجود داشت مشکل Cold Start بود، به عبارت دیگر دیتای واقعی برای آموزش اینکه کجا و در چه موقعیتی از مکالمه باید این سوالات مطرح می‌شدند وجود نداشت چون تا زمان مذکور این Intent ها به کاربران نمایش داده نمی‌شدند. با توجه به این مشکل، به این نتیجه رسیدیم که همان مسئله  Intent Classification را بر روی پیام‌های دسته مورد نظر اجرا کنیم و خروجی را به عنوان ورودی مرحله بعدی در نظر بگیریم. برای پیشنهاد پیام سمت خریدار مدل‌های مختلفی از Transformation های مختلف Context اجرا شد. در نهایت از مدل مارکف استفاده کردیم که کیفیت مناسبی داشت و خروجی آن قابل تفسیر بود.پیشنهاد سمت فروشنده نیز به این صورت انجام گرفته است که به ازای هر یک از سوالاتی که خریدار می‌نویسد در صورتی که Intent تشخیص داده شود جواب‌های مرتبط با آن Intent به فروشنده پیشنهاد می‌شود. پیشنهاد هوشمند پیام در برخی از دسته‌بندی‌های دیوار جایگزین پیشنهاد پیام ثابت شده و در آن دسته‌ها ۱۵٪ پیام‌های خریداران و فروشندگان انتخاب شده از پیشنهاد هوشمند پیام است. قدم‌های بعدی در راستای این پروژه تکمیل کردن باقی دسته‌بندی‌ها و نیز آزمودن مدل‌های پیچیده‌تری است که در حالی که سرعت اجرای مورد نیاز ما را دارا باشد، با بازنمایی بهتر مکالمه و شخصی‌سازی بهتر بر اساس کاربر میزان استفاده از سرویس را افزایش دهند. صورت بگیرد.امیدواریم شما با خواندن این مقاله توانسته باشید دید روشن‌تری از مسائل مختلفی که دانشمندان داده در دیوار به آن مشغول هستند به دست بیاورید. به صفحه فرصت‌های شغلی دیوار سر بزنید.</description>
                <category>دیوار</category>
                <author>دیوار</author>
                <pubDate>Tue, 18 Aug 2020 19:11:05 +0430</pubDate>
            </item>
            </channel>
</rss>