مطالعه موردی مهندسی
پایپلاین تصویر محصول
یک فروشگاه ساعت و جواهر با کاتالوگی دهها هزارتایی، صدها محصول داشت که هیچ عکسی نداشتند. محصول بیعکس نه میفروشد و نه باید ایندکس شود؛ پس دو چیز ساختم: قاعدهای که آن را تمیز از قفسه بردارد، و پایپلاینی که عکسش را پیدا کند، از Photoshop روی کامپیوتر مالک بگذراند و سر جایش برگرداند.
مسئله تجاری
صدها محصول بدون هیچ تصویر شاخصی منتشر شده بودند. هرکدام برای موتور جستوجو یک صفحهی توخالی بود و برای مشتری یک بنبست. عکسها جایی وجود داشتند، در فروشگاههای رسمی برند و سایت نمایندگیها، ولی کسی وقت نداشت یکییکی پیدایشان کند، و هر ابزاری که این کار را خودکار میکرد باید آنقدر قابل اعتماد میبود که به عکسی که از قبل هست دست نزند.
سختی کار دانلود نبود. Photoshop روی کامپیوتر مالک است، نه روی سرور. سرور ربات که میتواند عکس را پیدا و دریافت کند نمیتواند Photoshop را باز کند، و از مالک هم نمیشود خواست بالای سر یک صف بایستد. پایپلاین باید کار را از این شکاف رد میکرد، هر قدر لازم است منتظر یک انسان میماند، و صادقانه میگفت هر محصول در چه وضعیتی است.
آنچه تحویل دادم
- یک قاعدهی کاتالوگ: محصول منتشرشدهای که تصویر شاخص ندارد با یک پرچمِ دلیل پیشنویس میشود و آدرسش تا رسیدن عکس، بهجای 404، با 302 به نزدیکترین دستهی موجود میرود. همین ابزار یک مجموعهی کامل را پیشنویس میکند، دستهی خالیشده را میبندد و noindex میکند و بعداً دقیقاً همان مجموعه را برمیگرداند؛ یک اخطار علامت تجاری علیه یک برند هم با همین ابزار پاسخ داده شد. هر دو افزونهی رفتاری کلید خاموشی دارند.
- یک پایپلاین ماشینحالت روی سرور ربات با هفت جدول و تیک پنجدقیقهای: جستوجوی سایتهای منبعِ تنظیمشده برای یک عکس مرجع، اعتبارسنجی و حذف تکراریها، ارسال فایل خام به کامپیوتر مالک، بازگرداندن تصویر نهایی، الصاق آن و انتشار دوبارهی محصول.
- یک ایجنت روی کامپیوتر مالک که فایلهای خام را به پوشهی دستهای Photoshop میبرد و تصاویر تمامشده را بیرون میآورد، بهعلاوهی یک API ایجنت روی سرور ربات که با آن حرف میزند. تأیید پوشهای است نه عکسبهعکس: مالک هرچه را رد میکند پاک میکند و بقیه بالا میرود.
- یک سیاست سخت به نام ONLY_EMPTY: پایپلاین جای خالی تصویر را پر میکند و هرگز عکس موجود را جایگزین نمیکند.
- یک اسکریپت Bulk Composite برای Photoshop که عکسهای خام ساعت را به JPEG اصلی و گالری تبدیل میکند، با ۱۰۷ مورد تست mockشده که با هر تغییر اجرا میشوند.
- اندپوینتهای REST روی فروشگاه برای سرور ربات: فهرست محصولهای بیتصویر، یافتن و الصاق رسانه، گزارش وضعیت تصویر. احراز هویت با هدر توکن و فهرست مجاز IP است، و همین اجازه داد کلید SSH روتِ سرور ربات به سایت لغو و حذف شود.
رویکرد فنی
- تطبیق امتیازدهی میشود، نه حدس. تطابق SKU، یا وجود شمارهی مرجع در URL یا عنوان، ۱۰۰ امتیاز میگیرد؛ واریانت ۸۰؛ زیر ۷۵ پذیرفته نمیشود. کاندیدا باید دستکم ۶۰۰ پیکسل باشد با نسبت ابعاد بین ۰٫۵ تا ۲، و تکراریها با sha256 و با pHash تا فاصلهی ۶ حذف میشوند.
- خطاها با فاصلهی ۱، ۵، ۱۵ و ۶۰ دقیقه تکرار میشوند و بعد بهجای چرخیدن، به NEEDS_REVIEW میروند. بعد از یک توقف چهاردهساعته، که یک اسلش داخل یک شمارهی مرجع مسیر نامعتبری ساخته و کل تیک را کشته بود، حالا هر فاز در try/except خودش اجرا میشود تا یک محصول خراب بقیه را متوقف نکند.
- گام انسانی حول غیبت طراحی شده. ایجنت مالک یک بار بیش از چهارده ساعت ساکت بود در حالی که ستون وضعیتش هنوز ONLINE میگفت؛ حالا داشبورد سنِ آخرین گزارش را نشان میدهد. وقتی بیش از ۲۰ فایل خام منتظر است و ایجنت بیش از سه ساعت ساکت بوده، یک پیام Telegram با دستور دقیق فرستاده میشود، و هرگز بیش از یک بار در دوازده ساعت.
- پیشفرض اسکریپت Photoshop با شواهد عوض شد. آخرین نسخه حذف پسزمینهی سفید با Magic Wand بومی را پیشفرض کرد، چون فرمانهای هوش مصنوعی Photoshop روی کامپیوتر مالک بعد از دو عکس هنگ میکردند؛ برش هوش مصنوعی بهعنوان یک حالت صریح سر جایش مانده.
- منبعیابی پیش از گسترش اندازهگیری شد. حدود نیمی از محصولهای بیتصویر اصلاً هیچ سایت منبعی نداشتند. افزودن دو فروشگاه رسمی منطقهای برای یک برند پوشش آن را از ۳۲٪ به ۴۵٪ رساند؛ یک سایت نمایندگی بزرگ فقط چند تطابق اضافه کرد؛ پورتال تأمینکننده معلوم شد اصلاً فیلد تصویر ندارد. همین اعداد تعیین میکنند تلاش بعدی برای منبع کجا برود.
نتیجه و شواهد
دامنهی صادقانه. پایپلاین از شهریور ۱۴۰۵ زنده است و روی یک محصول از سر تا ته تأیید شده: پیدا شد، به کامپیوتر مالک رفت، پردازش شد، الصاق شد، دوباره منتشر شد. ۱۰۷ تست mockشدهی اسکریپت Photoshop با هر تغییر اجرا میشوند؛ اجرا روی یک دسته عکس واقعی روی کامپیوتر مالک هنوز بدهکار است، و Photoshop خودم را نمیشود از شل راند، پس ادعای اجرای واقعی ندارم. در شمارش میانهی ماه، صدها فایل خام روی کامپیوتر مالک منتظر دسته بودند و هیچکدام هنوز از آن سو بیرون نیامده بود. چیز دیگری هنوز اندازهگیری نشده.
اهمیت برای کارفرما
محصول بیعکس صفحهای است که نمیتواند بفروشد و نباید ایندکس شود. پیشنویس کردنش با یک ریدایرکت، امروز دسته را حفظ میکند؛ پایپلاین آن را با عکس برمیگرداند بیآنکه مالک حتی یک صفحهی محصول را باز کند. همین الگو به هر فروشگاهی با کاتالوگ بزرگ و عکسهای گمشده منتقل میشود، و به توزیعکنندههایی که تصاویر تأمینکننده را همگام میکنند.
خلاصه اجرایی خوانا
خلاصه_اجرایی {
پروژه: "Product Image Pipeline"
وضعیت: "زنده از شهریور ۱۴۰۵؛ روی یک محصول از سر تا ته تأیید شده"
قاعده: "بدون تصویر شاخص -> پیشنویس با پرچم دلیل؛
آدرس با 302 به نزدیکترین دستهی موجود، هرگز 404"
پایپلاین: "سرور ربات، ماشینحالت ۷ جدولی، تیک ۵ دقیقهای، API ایجنت؛
ایجنت کامپیوتر مالک خام را میبرد، نهایی را میآورد"
سیاست: "ONLY_EMPTY؛ عکس موجود هرگز جایگزین نمیشود"
تطبیق: "SKU ۱۰۰ / مرجع ۱۰۰ / واریانت ۸۰، آستانه ۷۵؛
دستکم 600px، نسبت ۰٫۵ تا ۲؛ تکراری با sha256 + pHash <= 6"
تکرار: "۱ / ۵ / ۱۵ دقیقه / ۱ ساعت، سپس NEEDS_REVIEW"
فتوشاپ: "Bulk Composite، آخرین نسخه؛ حذف پسزمینهی سفید بومی پیشفرض،
برش هوش مصنوعی صریح؛ ۱۰۷ تست mockشده با هر تغییر"
دسترسی: "هدر توکن + فهرست مجاز IP؛ کلید SSH روت لغو شد"
}ارزش حرفهای این پروژه
بخشی که دوست دارم بازبین نگاهش کند مرز با انسان است. ایجنتی که چهارده ساعت ساکت است و ONLINE گزارش میدهد از بیوضعیتی بدتر است؛ نشان دادن سنِ آخرین گزارش و یادآوری با دستور دقیق، حداکثر دو بار در روز، فرق پایپلاینی است که راه میرود با پایپلاینی که بیصدا تا ابد منتظر میماند.
دو پیشفرض با شواهد تعیین شدند نه سلیقه: برش هوش مصنوعی جایش را به Magic Wand داد چون روی ماشین واقعی هنگ میکرد، و ONLY_EMPTY پیش از حرکت اولین تصویر قطعی شد، چون پایپلاینی که بتواند یک عکس خوب را بازنویسی کند، بالاخره این کار را میکند.