تنها ۹ دلار هزینه کرد تا یک توسعهدهنده بتواند یک خط لولهی گرانقیمت از مدلهای زبانی بزرگ (LLM) را با یک مدل محلی و کوچک جایگزین کند. طبق گزارشی که در ۱۷ سپتامبر ۲۰۲۶ در وبسایت petervijeh.com منتشر شد، این شخص با صرف این مبلغ برای خرید برچسبهای داده از Gemini 3.1 Pro، یک مدل محلی GLiNER را آموزش داد تا عملیات بازشناسی موجودیتهای نامدار (NER) را روی نظرات ردیت با دقت ۰.۸۳ F1 انجام دهد.
این رویکرد مستقیماً «مالیات API» را هدف قرار میدهد؛ مشکلی که یک نقطه درد مشترک در تولیدات مبتنی بر هوش مصنوعی است. بسیاری از توسعهدهندگان کار خود را با مدلهای قدرتمندی مثل Gemini شروع میکنند چون این مدلها بدون نیاز به تنظیمات خاص، بلافاصله جواب میدهند، اما هزینهها با افزایش حجم دادهها بهصورت خطی رشد میکنند. این مسئله یادآور تحلیلهای پیشین ما درباره هدررفت بودجه در استفاده از مدلهای پرچمدار برای کارهای ساده است که نشان میداد چگونه انتخاب مدل نامناسب میتواند هزینههای عملیاتی را بهشدت افزایش دهد. برای مثال، برای یک اسکرپر (Scraper) که قصد رصد چاقوهای آشپزخانه ردهبالا را دارد، پرداخت هزینه برای هر تککامنت بهسرعت غیرپایدار و غیرممکن میشود. این وضعیت بازتابدهنده نوساناتی است که در قابلیت اطمینان LLMها دیدهایم؛ مشابه پوششهای قبلی ما درباره اینکه چگونه توهمات Gemini یک بار باعث شد توسعهدهندهای را به جعل هویت در لینکدین بکشاند.
تصور کنید ابزاری میسازید که روندهای محصول را رصد میکند. شما باید برندها، مدلها و متریالها را از متنهای بههمریخته و غیررسمی انجمنها استخراج کنید. دو راه دارید: یا برای هر خط متن به یک مدل غولپیکر پول بدهید، یا از آن مدل غولپیکر بهعنوان یک «معلم» استفاده کنید تا به یک مدل «شاگرد» که روی سختافزار خودتان زندگی میکند، آموزش دهد.
استراتژی تقطیر
هدف توسعهدهنده این بود که از یک مدل باز Zero-shot به یک مدل تخصصی حرکت کند. مدل GLiNER در حالت Zero-shot — یعنی حالتی که مدل بدون دیدن هیچ نمونهای از دادههای هدف سعی در پاسخدهی دارد — در ابتدا تنها امتیاز ۰.۶۵ F1 را در مقایسه با برچسبهای Gemini کسب کرد. برای پر کردن این شکاف، یک خط لولهی سهمرحلهای پیادهسازی شد:
- برچسبگذاری: مدل Gemini تعداد ۴۲۹۰ نظر را با هزینه ۹ دلار (تقریباً ۰.۰۰۲۱ دلار برای هر کامنت) برچسبزد. این مجموعه داده شامل ۱۵۷۵ نمونه مثبت (۶۹.۶٪) و ۶۷۵ نمونه منفی بود.
- آموزش: از این برچسبها برای تنظیم دقیق (Fine-tuning) مدل GLiNER large v2.5 با ۴۵۹ میلیون پارامتر استفاده شد. این مدل بر پایه یک انکودر DeBERTa-v3-large ساخته شده است.
- استقرار: مدل نهایی اکنون بهصورت محلی اجرا میشود و هزینههای API را بهطور کامل حذف کرده است. به شرطی که مدل روی سختافزار GPU شخصی اجرا شود، این مدل از کامنت ۴۲۹۱ به بعد، هزینهی اولیه خود را بازمیگرداند و سودده میشود.
جزئیات فنی پیادهسازی
برای جلوگیری از تلههای رایج که در آن LLMها با آفستهای کاراکتری (Character Offsets) مشکل دارند، توسعهدهنده بهجای درخواست شمارهی جایگاه (Index)، زیررشتههای دقیق را از Gemini خواست. مدلهای زبانی معمولاً در شمارش کاراکترها ضعیف هستند و بازههایی را برمیگردانند که دو یا سه جایگاه خطا دارند. در عوض، پرامپتها بهگونهای طراحی شدند که زیررشته دقیق و برچسب مربوطه را برگردانند (مثلاً "Benchmade" بهعنوان "برند چاقو"، "940" بهعنوان "مدل چاقو" و "S30V" بهعنوان "فولاد چاقو"). سپس یک لایهی TypeScript جایگاههای دقیق را محاسبه کرد؛ اگر رشتهای در کامنت پیدا نمیشد، آن موجودیت حذف و در لاگها ثبت میشد.
پردازش داده و توکنسازی
نام محصولات اغلب حاوی علائمی هستند که توکنسازها (Tokenizers) — ابزارهایی که متن را به تکههای کوچک تبدیل میکنند — آنها را میشکنند. برای جلوگیری از این اتفاق، از یک عبارت منظم (Regex) استفاده شد تا رشتههای خاصی مثل VG-10، CPM-154 و 1.4116 بهصورت یکپارچه باقی بمانند. هر کاراکتر غیر-فاصلهی دیگری بهعنوان توکنهای مجزا ارسال شد. بازههایی (Spans) که همچنان با مرز توکنها همخوانی نداشتند، بهجای حدس زدن، حذف شدند.
آموزش خصمانه
برای اینکه مدل فقط به حدس زدن عادت نکند، «نمونههای منفی خصمانه» (Adversarial Negatives) به مجموعه آموزشی اضافه شد. حدود ۳۰٪ دادهها شامل نظراتی بود که کلمات تحریککننده مثل "gyuto"، "carbon"، "handle" یا "patina" داشتند اما هیچ نام محصول خاصی در آنها وجود نداشت. این کار مدل را مجبور کرد تفاوت بین یک دستهبندی کلی (Category) و یک برند خاص (Specific Brand) را یاد بگیرد.
کابوس عیبیابی
این پروژه بدون اصطکاک نبود. از ۱۰ اجرای آموزشی، ۵ مورد منجر به مدلهای غیرقابل استفاده شد. توسعهدهنده در پنج تلاش اول با چندین شکست بحرانی مواجه شد:
- خطاهای پیکربندی: در اجرای اول، مقدار پیشفرض
max_steps=10000در GLiNER برnum_train_epochs=3اولویت یافت و منجر به ۳۹ دور (Epoch) آموزش شد. این مشکل با تنظیم صریحmax_stepsحل شد. - استراتژی ارزیابی: اجرای دوم شکست خورد زیرا از
load_best_model_at_endبدون تعریف یکeval_strategyاستفاده شده بود. راه حل، تنظیمeval_strategy="steps"بود. - ناهماهنگی State-Dict: در اجرای سوم، Trainer کلیدهای state-dict را بدون پیشوند "model." ذخیره کرد، در حالی که لودرِ GLiNER انتظار این پیشوند را دارد. توسعهدهنده مجبور شد پیشوند را هنگام ذخیرهسازی بهصورت دستی بازگرداند.
- برچسبگذاری منفیها: اجرای چهارم شکست خورد زیرا
ner_labelsدر نمونههای منفی غایب بود. این امر مستلزم تنظیم لیست برچسبها برای تکتک نمونهها بود. - تلهی Word Mask: گرانترین شکست (در اجراهای ۴ و ۵) مربوط به تنسور
words_maskبود. از آنجایی که تابعtokenize_inputsدر GLiNER روی ایموجیهای خراب ردیت کرش میکرد، توسعهدهنده آن را پچ کرد. این پچ مستلزم پر کردن تنسورwords_maskبود.
در ابتدا، توسعهدهنده با words_mask مانند یک ماسک توجه باینری برخورد کرد (۱ برای توکنهای واقعی، ۰ برای Padding). اما در واقعیت، GLiNER انتظار دارد words_mask یک ایندکس کلمه باشد: ۰ برای توکنهای خاص، پرامپت و پدینگ، و سپس ۱، ۲، ۳ برای اولین زیر-توکنِ هر کلمه واقعی.
چون توسعهدهنده آن را با یکها پر کرده بود، مدل تصور میکرد کل کامنت یک توکن عظیم و واحد است. در نتیجه، بخش امتیازدهی بازهها (Span-scoring head) نمیتوانست بازههای برند یا متریال را درون یک توکن پیدا کند. این منجر به یک Loss تخت شد (که از ۱۳۰ به ۷۰ تغییر میکرد اما یادگیری رخ نمیداد) و یادگیری صفر بود. هیچ کرش یا مقدار NaN برای هشدار دادن وجود نداشت؛ چکپوینتها طبق برنامه ذخیره میشدند اما F1 نزدیک به صفر بود.
عملکرد نهایی و هزینه
پس از اصلاح منطق تنسورها، مدل در ۲۴ دقیقه روی یک GPU مدل Tesla T4 با استفاده از HF Trainer همگرا شد. تنظیمات شامل per_device_train_batch_size برابر ۲، gradient_accumulation_steps برابر ۸، learning_rate برابر 1e-5 و threshold برابر ۰.۴۵ بود.
نتایج نهایی روی یک مجموعه اعتبارسنجی قفلشدهی ۲۲۵ تایی (که قبل از اجرای دوم کنار گذاشته شده بود) به این شرح بود:
- امتیاز F1 کلی: ۰.۸۳ (در مقایسه با ۰.۶۵ حالت Zero-shot).
- تفکیک موجودیتها: مدل ۴۵۹ میلیون پارامتری به امتیاز ۰.۸۷۷ برای برندها و ۰.۸۲۹ برای محصولات دست یافت.
- بازیابی متریال (Recall): ۰.۹۱۱. این نتیجه با استفاده از آستانههای مجزا برای هر کلاس بهجای یک حد قطع جهانی بهدست آمد، زیرا نام فولادهایی مثل MagnaCut، S35VN و HAP40 معمولاً اعتماد (Confidence) کمتری نسبت به برندها کسب میکنند.
- هزینه کل: ۹ دلار برای برچسبها و ۲.۵ دلار برای زمان GPU در طول ۱۰ اجرا.
تحلیل: چرخش به سمت گردشکار «معلم-شاگرد»
این پروژه یک تغییر حیاتی در مهندسی عملی AI را برجسته میکند. گلوگاه دیگر در دسترس بودن برچسبهای باکیفیت نیست، بلکه «لولهکشی» (Plumbing) بین داده و مدل است. توسعهدهنده اشاره کرد که مدل و دادهها بهندرت مشکلساز بودند؛ بلکه شکست خاموش یک تک تنسور ورودی بود که باعث تلف شدن روزها کار شد.
در یکی از اجراهای اولیه، امتیاز ۰.۸۷۹ روی یک تقسیمبندی تصادفی (Random Split) بهدست آمد، اما توسعهدهنده آن را نپذیرفت. در تقسیمهای تصادفی، افت F1 اغلب ناشی از این بود که کدام کامنتهای خاصی در مجموعه اعتبارسنجی قرار گرفتهاند، نه تغییرات واقعی در مدل. در نهایت، مدل بزرگ ۴۵۹ میلیون پارامتری از مدل متوسط ۲۰۹ میلیون پارامتری (که به ۰.۸۰۰ رسید) پیشی گرفت، بهویژه در جاهایی که واژگان کاملاً تخصصی دامنه بودند.
برای یک توسعهدهنده متوسط، این بدان معناست که ارزشمندترین مهارت دیگر مهندسی پرامپت (Prompt Engineering) نیست، بلکه توانایی اعتبارسنجی تنسورها و درک حلقههای داخلی آموزش مدلهای زبانی کوچک (SLM) است. این ثابت میکند که برای کارهای محدود مثل NER، یک مدل ۴۵۹ میلیون پارامتری میتواند بهطور موثری از یک LLM پیشرو تقلید کند، اگر فرآیند تقطیر بهدرستی مدیریت شود. مدل اکنون درک میکند که "carbon steel" یک دستهبندی است و نه یک فولاد خاص، و اینکه "PM2" میتواند هم به مدل Spyderco Paramilitary 2 اشاره کند و هم صرفاً مجموعهای از حروف باشد.
اگر در حال حاضر برای یک تسک استخراج تکراری، هزینه API در حجم بالا میپردازید، احتمالاً بیش از حد هزینه میکنید. مسیر بهینه، استفاده از مدلهای پیشرو برای ساخت جایگزین محلی و تخصصی خودتان است.
برای دیدن این سیستم در عمل، میتوانید پروژه "New Knife Day" را که از این مدل خاص برای رصد روندهای چاقو در ردیت استفاده میکند، بررسی کنید.




گفتگو