تصور کنید در راهروی یک سوپرمارکت هستید و یک بارکد را اسکن میکنید؛ این کد دقیقاً یک محصول را در جهان شناسایی میکند، اما اکثر پیادهسازیهای هوش مصنوعی با این دقت به جای یک قانون، مانند یک پیشنهاد برخورد میکنند. CannyCart، یک اپلیکیشن خرید مبتنی بر صوت، این مشکل را با سلب قدرت خلق از مدل زبانی حل کرده و Claude را به جای یک تولیدکننده، به یک نرمالساز سختگیر داده تبدیل کرده است.
این چرخش معماری در زمانی رخ میدهد که توسعهدهندگان با چالش توهم (Hallucination) — شبیه دوستی که خاطرهای را با اطمینان اما اشتباه تعریف میکند — در محیطهای عملیاتی دستوپنجه نرم میکنند. برای مقابله با این پدیده، بسیاری از تیمها به معماریهای RAG برای حذف توهمات از طریق جستوجوی برداری روی آوردهاند. همانطور که در تحلیل قبلی ما دربارهی سیستمهای توصیهگر اشاره کردیم، در برخی حوزهها خلاقیت مدل مزیت است، اما در لیست خرید، یک محصول اشتباه بدتر از نبودِ محصول است. در محیط فروشگاه، حدسهای اشتباه هوش مصنوعی غیرقابل تأیید است و دادههای کاربر را مسموم میکند.
بازبینی امکانسنجی
تیم توسعه پیش از کدنویسی، یادداشتی برای بررسی امکانسنجی تهیه کرد تا دو واقعیت دشوار را مدیریت کند. اول اینکه در حالی که خانواده دادههای Open*Facts در بریتانیا قوی است، این اپلیکیشن از ارزهای کشورهای نیجریه، غنا، کنیا و آفریقای جنوبی پشتیبانی میکند. طبق بررسیهای تیم، کالاهای تولیدی محلی در لاگوس یا نایروبی بهندرت در پایگاههای جهانی هستند؛ بنابراین ورود دستی دادهها باید یک مسیر اصلی باشد، نه یک جایگزین اضطراری.
دوم اینکه تیم دریافت هیچ API رایگان و قانونی برای قیمتهای لحظهای سوپرمارکتهای بریتانیا وجود ندارد. غولهایی مثل Tesco و Sainsbury's چنین دادهای منتشر نمیکنند و استخراج داده (Scraping) هم نقض قوانین است و هم ناپایدار. راهکار آنها تکیه بر دادههایی بود که کاربر خودش دارد: رسیدهای اسکنشده. این روش یک تاریخچه قیمتی قانونی، رایگان و دقیق فراهم میکند که مختص فروشگاههای مورد علاقه هر کاربر است.
هشدارهای مستندات برنامهریزی
در یادداشت امکانسنجی، هشدار مهمی برای توسعهدهندگان آینده درج شده است: شرایط طرحهای رایگان تغییر میکنند. تیم توصیه میکند تمام شرایط پیش از ادغام بررسی شوند و هشدار میدهد که نباید به اعداد موجود در هیچ سند برنامهریزی، حتی سند خودشان، اعتماد مطلق کرد. این رویکرد محتاطانه تضمین میکند که اپلیکیشن با افزایش مقیاس، پایدار بماند.
بر اساس یک گزارش فنی منتشر شده در ۲۲ اوت ۲۰۲۶، تیم CannyCart یک زنجیره تأمینکننده را پیاده کرده است که اولویت را به جستوجوی دقیق (Exact Lookup) میدهد تا هوش مصنوعی زاینده (Generative AI). سیستم از یک سلسلهمراتب سختگیر پیروی میکند: ابتدا حافظه موقت (Cache) محلی بررسی میشود و سپس چهار پایگاهداده Open*Facts (غذا، زیبایی، محصولات و غذای حیوانات) از طریق یک آداپتور واحد مورد پرسش قرار میگیرند. این رویکرد ترکیبی از مسیرهای بازیابی مختلف، مشابه استراتژیهای شناسایی روابط ساختاری کد با ترکیب جستوجوی نمادین و برداری، دقت سیستم را افزایش میدهد.
زنجیره تأمینکننده ضدخطا
از آنجا که چهار پایگاهداده Open*Facts ساختار API یکسانی دارند، آنها به عنوان یک آداپتور با چهار میزبان پیاده شدهاند:
world.openfoodfacts.org(Open Food Facts)world.openbeautyfacts.org(Open Beauty Facts)world.openproductsfacts.org(Open Products Facts)world.openpetfoodfacts.org(Open Pet Food Facts)
برای جلوگیری از هنگ کردن اپلیکیشن در فروشگاه، تیم یک سیستم «فیوز» برای هر فراخوانی API طراحی کرده است:
- محدودیت زمانی ۳ ثانیهای: هر تأمینکننده دارای یک زمان انتظار ۳۰۰۰ میلیثانیهای است. اگر میزبان کند باشد، سیستم بلافاصله آن را رد میکند. یک پاسخ کند بدتر از یک پاسخ سریع «یافت نشد» است.
- خطاهای غیرمرگبار: از دسترس خارج شدن یک پایگاهداده هرگز باعث شکست کل جستوجو نمیشود؛ زنجیره صرفاً به تأمینکننده بعدی میرود.
- منطق اولین برنده: سیستم اولین پاسخ معتبر را میپذیرد و رکوردها را با هم ادغام نمیکند. مدیریت یک رکورد ناقص راحتتر از مدیریت دو نام متضاد است.
- قابلیت گسترش: کاتالوگهای پولی مانند UPCitemdb را میتوان از طریق کلیدهای محیطی به انتهای لیست اضافه کرد. تغییر تأمینکننده فقط نیاز به تغییر در Lambda دارد و نیازی به انتشار نسخه جدید در اپاستور نیست.

جزئیات پیادهسازی فنی
- حافظه موقت سمت کاربر: قبل از فراخوانی Lambda، ابتدا حافظه محصولات در سمت کلاینت بررسی میشود تا اسکنهای تکراری فوراً و بدون هزینه محاسباتی پاسخ داده شوند.
- شهروندی دیجیتال: اپلیکیشن از یک رشته User-Agent واقعی و توصیفی استفاده میکند. چون Open Food Facts یک پروژه داوطلبانه است، شناسایی فراخوان برای «شهروند خوب» بودن در این پایگاهداده رایگان الزامی است.
- منطق زنجیره: توالی به این صورت است: حافظه کلاینت $ \rightarrow $ چهار پایگاهداده Open*Facts $ \rightarrow $ یافت نشد.
Claude در نقش نرمالساز
وقتی دادهای یافت میشود، اغلب مجموعهای نامنظم از ورودیهای جامعه است؛ شامل زبانهای مختلف، لیست برندهای جدا شده با کاما و رشتههای مبهمی مثل «415 g» برای اندازه. این یک مسئله مناسب برای مدل زبانی است، اما با یک محدودیت سخت: قبل از اینکه دادهها به دست Claude برسند، محتوا فقط به ۱۱ فیلد ضروری کوتاه میشود. رکورد کامل Open Food Facts شامل ماتریسهای تغذیه و تاریخچه ویرایش است که باعث هدر رفتن توکن (Token) — تکههای کوچکی از متن شبیه برشهای کیک که مدل میخورد — و ایجاد نویز میشود. بهینهسازی مصرف توکنها در مدلهای Claude موضوعی حیاتی است، چنانکه بنچمارکهای اخیر نشان داد مهارتهای Fonderie میتواند مصرف توکن Claude Code را تا ۶۶٪ کاهش دهد.
از Claude خواسته شده سه خروجی مشخص تولید کند:
۱. نام: نام محصول بدون برند، با فرمت Title Case.
۲. مقدار + واحد: تبدیل رشتههایی مثل «415 g» به عدد (۴۱۵) و واحد («g»).
۳. دستهبندی: نگاشت محصول به دقیقاً یک کلید موجود از لیست از پیش تعریف شده (مثل لبنیات، نانوایی و ...) یا بازگرداندن مقدار null.
پرامپت صراحتاً مدل را از ابداع جزئیات منع میکند. اگر بارکد در هیچ پایگاهدادهای یافت نشود، Lambda مقدار { found: false, barcode } را برمیگرداند. سیستم هرگز از مدل نمیخواهد یک محصول را از روی یک عدد ۱۳ رقمی حدس بزند. اگر مدل تردید داشته باشد، دستور گرفته است که null را به حدس زدن ترجیح دهد.
استراتژی حافظه جهانی
یکی از اثرگذارترین تصمیمات، حذف userId از مدل محصول بود. در حالی که هر مدل دیگر در اپلیکیشن دارای شناسه Cognito است، حافظه محصولات یک مدل جهانی است چون بارکد یک حقیقت جهانی است.
این کار یک چرخه مثبت ایجاد میکند: وقتی کاربری در آکرا یک محصول محلی را اسکن میکند که در پایگاههای اروپایی نیست، ورود دستی او، حافظه را برای تمام کاربران آینده پر میکند. یک بنبست به یک دارایی تبدیل میشود. برای جلوگیری از خراب شدن پایگاهداده توسط غلطهای تایپی، چندین حفاظ تعبیه شده است:
- اولین запись برنده است: محصولات موجود هرگز توسط ورودیهای دستی جدید بازنویسی نمیشوند.
- ردپای بازرسی: ردیفهای دستی با برچسب
source: "manual"علامتگذاری میشوند تا در صورت یافتن منبع رسمی در آینده، جایگزین شوند. - ذخیره خام: دادههای خام تأمینکننده در ردیف ذخیره میشود تا در صورت بهروزرسانی پرامپت یا مدل، نیاز به دریافت مجدد داده نباشد.

تجربه کاربری و بازخورد
اسکنر بر اساس اصل «خویشتنداری» طراحی شده است. یک قفل اسکن تضمین میکند در هر عکس فقط یک جستوجو انجام شود و اسکنهای تکراری فقط مقدار محصول را زیاد میکنند. برای کاهش خطای خوانش، شناسهها فقط به کدهای محصول (EAN-13/8, UPC-A/E) محدود شدهاند. اسکنها در یک سینی موقت جمع میشوند تا در پایان یکبار بررسی شوند و کاربر بین هر آیتم با مودالهای تأیید اذیت نشود.
صفحه نمایش برای پایداری طراحی شده و فقط با ضربه روی ✕ بسته میشود. هیچ قابلیت swipe-down یا ضربه به پسزمینه وجود ندارد تا یک اسکرول اتفاقی، سبد خرید بررسیشده را پاک نکند.
حلقه بازخورد بر اساس «سکوت به عنوان سیگنال» است:
- موفقیت: یک صدای بیپ شاتر-مانند و یک لرزش (Haptic) موفقیت.
- تکراری: سکوت به همراه یک لرزش هشدار، تا کاربر یاد بگیرد دوباره اسکن نکند.
- یکپارچگی صوتی: صدا در iOS با موسیقی پسزمینه ترکیب (Mix) و در اندروید صدای موسیقی کم (Duck) میشود.
- ورود دستی: ورود دستی هرگز بیپ نمیکند چون یک رویداد کپچر نیست.
ردیابی قیمت و رنگ مرجانی
در نهایت، اپلیکیشن قابلیت ردیابی قیمت را اضافه کرده است. در صفحه بررسی نهایی، عبارت «آخرین خرید ۲.۴۰ پوند · ارزانترین ۱.۹۵ پوند» نمایش داده میشود. این مقدار از تاریخچه رسیدهای خود کاربر محاسبه میشود و تطبیق بر اساس نام نرمالشده است (نه بارکد) تا محصولاتی که با صوت یا دست اضافه شدهاند را هم پوشش دهد. سیستم فقط از رسیدهای ارز محلی استفاده میکند و قیمت واحد را محاسبه میکند تا مقدار محصول، مقایسه را خراب نکند.
این ویژگی رنگ «مرجانی» را معرفی میکند که منحصراً برای لحظات صرفهجویی در هزینه رزرو شده است. این اولین بار است که این رنگ در اپلیکیشن ظاهر میشود و در ۱۴ پست قبلی تعمداً نگه داشته شده بود.
این رویکرد فرض بنیادی درباره ادغام مدلهای زبانی در اپلیکیشنهای کاربردی را تغییر میدهد. ثابت میکند که بالاترین ارزش یک مدل زبانی همیشه در توانایی خلق نیست، بلکه در توانایی نگاشت دادههای نامنظم دنیای واقعی به یک واژگان سختگیر و مالکیتمحور است.
برای کسانی که سیستمهای مشابه میسازند، چالش حیاتی بعدی مدیریت نظارت چندکاربره برای حافظههای مشترک است؛ مشکلی که تیم CannyCart فعلاً به تعویق انداخته اما در مستندات برنامهریزی برای مقیاسهای آینده ثبت کرده است.
گام بعدی شما
- اگر در حال ساخت ابزاری هستید که با دادههای دنیای واقعی سر و کار دارد، مدل زبانی را به جای «تولیدکننده»، به عنوان «فیلتر و نرمالساز» در انتهای زنجیره قرار دهید.
- برای کاهش نرخ توهم، ورودیهای مدل را به شدت محدود (Trim) کنید و فقط فیلدهای ضروری را ارسال کنید.
- از استراتژی «اولین برنده» در زنجیره APIها استفاده کنید تا سرعت پاسخدهی در محیطهای متحرک (مثل فروشگاه) فدای جامعیت داده نشود.
اما مدیریت دادههای تولید شده توسط کاربران در مقیاس میلیونی چالش بعدی است — به تحلیل ما دربارهی سیستمهای نظارت توزیعشده مراجعه کنید.




گفتگو