اگر امروز برای استخراج دستهبندیها از مدلهای زبانی استفاده میکنید، احتمالاً با پاسخهایی مواجه شدهاید که با اطمینان ۹۰٪ ادعایی غلط میکنند. Jevper این بازی را تغییر میدهد و مدل را مجبور میکند بهجای گپ زدن، احتمالات خام را تحویل دهد. در حالی که اکثر مدلهای زبانی بزرگ (LLM) برای پاسخدهی به صورت متنی و نثر طراحی شدهاند، ابزار جدید jevper آنها را مجبور میکند چت کردن را متوقف کرده و احتمالات خام (Raw Probabilities) را ارائه دهند.
این ابزار در واقع یک لایه پوششی (Wrapper) است که مدلهای زبانی بزرگ — مثل کتابخانهداری که میلیاردها صفحه را خوانده و حالا با همان لحن کتابها جواب میدهد — را به موتورهای طبقهبندی تبدیل میکند. طبق اعلام توسعهدهندگان، Jevper با پیادهسازی فرمت System One، خروجیهای متنی را به امتیازات اطمینان (Confidence Scores) تبدیل میکند تا توسعهدهندگان بتوانند بهجای تحلیل متن، با اعداد دقیق سروکار داشته باشند. این ابزار هر مدل سازگار با OpenAI را به یک موتور طبقهبندی دقیق تبدیل میکند که بهجای متنهای محاورهای، امتیازات اطمینان را خروجی میدهد.
بسیاری از توسعهدهندگان در حال حاضر با مشکل «اطمینان توهمی» (Hallucinated Confidence) دستوپنجه نرم میکنند؛ وضعیتی که در آن مدل ادعا میکند ۹۰٪ مطمئن است، اما در واقع در حال حدس زدن است. این ابزار در زمانی عرضه شده که صنعت به سمت معماریهای «سیستم ۱» (سریع و شهودی) و «سیستم ۲» (کند و استدلالی) حرکت میکند. همانطور که در تحلیلهای قبلی ما اشاره کردیم، در حالی که پروژههایی مثل Astra شرکت OpenAI بهدلیل نقصهای خودمختار با چالش مواجه شدند، روند فعلی به سمت کنترل تنگتر و پیشبینیپذیرتر بر خروجیهای مدل برای محیطهای عملیاتی (Production) است. این رویکرد در راستای تلاش برای ایجاد تصمیمات محدود و قابل پیشبینی است، مشابه آنچه در بررسی ۳۳ پروژه منتخب برای پیادهسازی تصمیمات محدود در TypeSafe Jev مورد تحلیل قرار دادیم.
مکانیزم دستیابی به دقت
jevper با پوشاندن هر کلاینتی که متدهای responses.create یا chat.completions.create را ارائه دهد، کار میکند. بر اساس مستندات گیتهاب، این ابزار برای سازگاری با مدلهای میزبانیشده یا سرورهای محلی llama.cpp (لاماسیپلاسپلاس) از قابلیت duck-typing استفاده میکند و در زمان اجرا به SDK رسمی OpenAI وابسته نیست. این بدان معناست که کدهای نوشته شده برای Jev، بدون توجه به اینکه بکاند یک مدل میزبانیشده باشد یا یک سرور محلی، بدون تغییر به کار خود ادامه میدهند.
طبق مستندات گیتهاب، این ابزار چهار روش متمایز برای استخراج تصمیمات ارائه میدهد. پارامتر method تعیین میکند که تصمیم چگونه استخراج شود و هر چهار روش از یک نگاشت برچسب-به-گزینه (label-to-option mapping) مشترک استفاده میکنند:
- logprobs: با استفاده از
logprobs=trueوtop_logprobs=20برای اجرای تابع سافتمکس (Softmax) روی اولین توکن پاسخ، توزیع احتمالی را استخراج میکند. این روش نیازمند ارائهدهندهای است که logprobs چت را برگرداند. - grammar: از گرامرهای GBNF در
extra_bodyاستفاده میکند. این روش برای سرورهای Chat Completions که گرامر را میپذیرند، مانند llama.cpp، طراحی شده است. - structured: مدل را مجبور میکند یک طرحواره JSON سختگیرانه برگرداند که در آن برای هر گزینه یک احتمال ذکر شده است. اگر مجموع این اعداد بیش از 1e-6 با عدد ۱ فاصله داشته باشد، ابزار آنها را مجدداً مقیاسبندی میکند تا مجموع آنها دقیقاً ۱ شود.
- discrete: از یک طرحواره JSON سختگیرانه برای برگرداندن یک برچسب واحد استفاده میکند و سپس ابزار آن را به یک توزیع one-hot تبدیل میکند.
منطق تفکیک خودکار (Auto)
از آنجا که قابلیت logprobs در همه مدلها یکسان نیست، Jevper بهصورت پیشفرض از method="auto" استفاده میکند. این امر ضروری است زیرا مدلهای استدلالی (Reasoning Model) در OpenAI درخواستهای logprobs را رد میکنند و نقاط انتهایی (Endpoints) سازگار با OpenAI برای Anthropic و Gemini هرگز از آنها پشتیبانی نکردهاند.
در حالت auto، سیستم در جاهایی که logprobs وجود دارد، آنها را میخواند تا توزیع واقعی مدل را بهجای گزارش شخصی مدل (Self-report) ارائه دهد و در جاهایی که این قابلیت وجود ندارد، به خروجیهای ساختاریافته JSON تغییر مسیر میدهد. سیستم حکم نهایی را برای هر مدل و هر سطح (Surface) به خاطر میسپارد تا فراخوانیهای بعدی بهینه شوند.
مدیریت پرسشهای پیچیده
کاربران میتوانند سه نوع پرسش را برای استخراج اشکال خاصی از دادهها تعریف کنند. هر پرسش به یک فراخوانی مجزا برای ارائهدهنده تبدیل میشود و اجازه میدهد آنها بهصورت موازی با مقدار پیشفرض max_concurrency برابر با ۸ اجرا شوند. پاسخها بر اساس شناسههای پرسش (Question IDs) و به ترتیب درج، برگردانده میشوند:
- Noul: پاسخهای بله/خیر را با یک احتمال واحد برمیگرداند. این نوع پرسش نیازمند معیارهایی برای «درست» (true) و «غلط» (false) است.
- Choice: یکی از ۲ تا ۲۵۵ گزینه برچسبدار را انتخاب کرده و برچسب انتخاب شده، یک دیکشنری کامل از احتمالات و یک امتیاز اطمینان ارائه میدهد. برای مثال، یک قصد پرداخت (billing intent) ممکن است گزینه "billing" را با اطمینان ۰.۸۳ برگرداند.
- Score: ورودی را در یک مقیاس مرتب شده از ۲ تا ۱۰ سطح رتبهبندی میکند. این متد یک شاخص سطح وزندار احتمالات (Σ i·pᵢ، با شروع از صفر)، یک راهنما (Legend) و امتیاز اطمینان را برمیگرداند.
برای جلوگیری از خطا در مجموعههای بزرگ گزینهها، Jevper بهطور خودکار متد را تغییر میدهد. از آنجا که روشهای logprobs و grammar به ۲۶ گزینه محدود هستند (زیرا اولین توکن "AA" همان "A" است)، متد auto بهطور بیسروصدا برای گزینههای گستردهتر به خروجیهای ساختاریافته مبتنی بر JSON سوییچ میکند. اگر کاربر بهصورت دستی متدی را اجبار کند و تعداد گزینهها از ۲۶ مورد بیشتر شود، ابزار خطای InvalidQuestionError را صادر میکند.
استدلال و یادگیری با نمونه اندک
برای کارهای سختتر طبقهبندی، این ابزار از ReasoningConfig پشتیبانی میکند. این قابلیت به مدل اجازه میدهد قبل از طبقهبندی، «فکر» کند. با ارسال reasoning=ReasoningConfig(effort="medium") در زنجیره تفکر (Chain-of-Thought) — مثل وقتی شاگرد ریاضی پای تخته بلند بلند فکر میکند تا به جواب برسد — توسعهدهنده میتواند از طریق reasoning_text(response.reasoning) به ردپای استدلال دسترسی داشته باشد.
در سطح Responses، این ابزار از استدلال بومی ارائهدهنده استفاده میکند. در Chat Completions، یک مسیر دو مرحلهای «فکر کن-سپس طبقهبندی کن» را پیاده میکند که در آن متن تحلیل، پیش از پاسخ نهایی به عنوان یک نوبت دستیار (Assistant turn) بازپخش میشود. میزان مصرف (Usage) این فراخوانی دو مرحلهای در response.usage ردیابی میشود.
توسعهدهندگان همچنین میتوانند نمونههای یادگیری با نمونه اندک (Few-shot Learning) — نوبتهای چتی شامل یک وضعیت نمونه، یک بلوک پرسش و پاسخ مورد انتظار — را در سه سطح اولویت تزریق کنند:
- سطح پرسش (Question Level): مستقیماً به یک شیء
Choice،NoulیاScoreمتصل میشود. - سطح فراخوانی (Call Level): در طول یک فراخوانی خاص
system_oneارسال میشود. - سطح سازنده (Constructor Level): بهصورت جهانی در سازنده
SystemOneClientبه عنوان جایگزین (Fallback) تعریف میشود.
ترتیب اولویت به صورت «پرسش ← هر فراخوانی ← سازنده» است و اولین سطح غیرخالی برنده میشود. برای حفظ سازگاری با فرمت Jev، نمونهها از model_dump() حذف میشوند.
پایداری و مدیریت خطا
jevper یک سلسلهمراتب خطای سختگیرانه دارد تا مشکلات پیکربندی محلی را از شکستهای ارائهدهنده (Provider) تفکیک کند. مشکلات محلی، مانند نگاشت پرسشهای خالی یا وضعیت غیرقابل استفاده، قبل از ارسال هر درخواستی باعث شکست میشوند.
- خطاهای محلی: شامل
InvalidQuestionError(پرسش یا نمونه نامعتبر)،UnsupportedMethodError(استفاده از گرامر در سطح Responses)،ClientCapabilityError(فقدان ویژگیهای کلاینت) وJevperError(استفاده نادرست از سازنده). - خطاهای Readout: خطای
LabelReadoutErrorزمانی رخ میدهد که توکن اول یک برچسب نباشد یا logprobs مفقود شده باشند. خطایMalformedAnswerErrorزمانی رخ میدهد که اشکال JSON پس از تلاشهای اصلاحی غیرقابل استفاده باشند. - خطاهای ارائهدهنده: خطای
ProviderErrorپس از نهایی شدن تمام پرسشها منتشر میشود و تاریخچه تلاشها را با خود حمل میکند.
سیستم شامل یک سیاست تلاش مجدد (Retry) قدرتمند برای شکستهای گذرا (HTTP 429, 500, 502, 503, 504, 529) و مهلتهای زمانی اتصال (Connection Timeouts) است. این ابزار از عقبنشینی نمایی (Exponential Backoff) با فرمول min(base_delay * 3ⁿ, max_delay) استفاده میکند که مقدار پیشفرض base_delay آن ۰.۵ و max_delay آن ۸.۰ است و تا ۲ بار تلاش مجدد برای هر فراخوانی را اجازه میدهد. پاسخهای غیرقابل خواندن یک تلاش اصلاحی (n_retry_malformed) دریافت میکنند که در آن شکست قبلی به گفتگو پیوست میشود.
پیادهسازی و اعتبارسنجی
اعتبارسنجی این ابزار از طریق یک سرور HTTP محلی با استفاده از stdlib ThreadingHTTPServer انجام میشود. این امر تضمین میکند که کل مجموعه بدون نیاز به API Key فعال یا دسترسی به شبکه اجرا شود و مسیر سریالسازی SDK را به چالش بکشد. برای کسانی که میخواهند تست زنده انجام دهند، مجموعه test_live.py در صورتی که LLM_MODEL و OPENAI_API_KEY تنظیم شده باشند، در دسترس است.
این تغییر رویکرد به سمت خروجیهای احتمالی، فرض بنیادی ادغام LLMها را تغییر میدهد. بهجای نوشتن Regexهای پیچیده برای تحلیل متن مدل برای رسیدن به پاسخ نهایی، توسعهدهندگان اکنون میتوانند با مدل مانند یک طبقهبندیکننده سنتی با بازه اطمینان قابل اندازهگیری برخورد کنند.
برای یک توسعهدهنده، این یعنی امکان تعیین آستانههای سخت برای اتوماسیون؛ مثلاً اگر اطمینان مدل برای دستهبندی «صورتحساب» زیر ۰.۸۰ بود، سیستم میتواند بهطور خودکار تیکت را بهجای ریسک پاسخ خودکار غلط، به یک اپراتور انسانی ارجاع دهد.
برای شروع پیادهسازی، میتوانید این بسته را از طریق پایتون ۳.۱۰ به بالا نصب کنید؛ تنها وابستگی زمان اجرای آن pydantic>=2.7 است. برای توسعه، پروژه را میتوان از گیتهاب کلون کرد و با دستور uv pip install -e '.[test]' نصب نمود.
گام بعدی شما
- اگر از مدلهای محلی با llama.cpp استفاده میکنید، Jevper را برای جایگزینی پرامپتهای «فقط بله یا خیر بگو» امتحان کنید.
- برای کاهش نرخ خطای اتوماسیون، یک آستانه اطمینان (Confidence Threshold) برای هر دستهبندی تعریف کنید.
- از
ReasoningConfigبرای طبقهبندیهایی که نیاز به تحلیل عمیق دارند استفاده کنید تا دقت مدل را بسنجید.
اما برای کسانی که به دنبال کاهش هزینه استنتاج در مقیاس بالا هستند، استراتژیهای کوانتش وزنها مسیر متفاوتی را دنبال میکنند — به تحلیل ما دربارهی مدلهای کوچکتر و بهینه مراجعه کنید.




گفتگو