هشت ماه کار در صف ادغام (merge queue) گیتهاب اکشنز، چیزی را به شما میآموزد که ماتریسهای مقایسه ویژگیها هرگز نخواهند آموخت. یک فریمورک میتواند پنجاه معیار، داشبوردهای خیرهکننده و استنادات از آزمایشگاههای تحقیقاتی معتبر ارائه دهد. اما اگر به دلیل اینکه امتیاز یک "vibe check" از ۰.۷۲ به ۰.۶۸ تغییر کرده، مانع از انتشار (deploy) شما شود، از بیفایده هم بدتر است. این فریمورک به یک تهدید فعال برای سرعت انتشار شما تبدیل میشود.
این همان فیلتری است که اکثر جمعبندیهای ارزیابی LLM نادیده میگیرند. آنها قابلیتها را میشمارند، اما بهندرت تنها سوالی را میپرسند که در یک صف ادغام اهمیت دارد: آیا این بررسی، در هر بار اجرا، دقیقاً به یک شکل پاس یا فیل میشود؟
من این را با انجام کارهای دشوار یاد گرفتم. من شش فریمورک ارزیابی متنباز LLM را به یک خط لوله (pipeline) واقعی CI متصل کردم. آنها به مدت هشت ماه روی Pull Requestهای واقعی در محیط تولید (production) اجرا شدند. دو مورد حق ماندن به عنوان دروازهبان (gatekeeper) را کسب کردند. بقیه به داشبوردهای مشاورهای تنزل یافتند، به کارهای شبانه (nightly jobs) منتقل شدند یا کلاً حذف شدند. درس تلخ و پرهزینه این بود: وقتی از شاخه اصلی (main branch) محافظت میکنید، ساختار قطعی (deterministic) بر کیفیت احتمالی (probabilistic) برتری دارد.
وظیفه واقعی یک دروازه ادغام (Merge Gate)
یک دروازه CI محیط تحقیقاتی نیست؛ بلکه یک نگهبان (bouncer) است. تمام هدف آن این است که به یک تغییر خاص نگاه کند و پاسخ «بله» یا «خیر» بدهد. بله، این PR میتواند به شاخه اصلی بپیوندد. خیر، نمیتواند. این پاسخ باید در عرض چند ثانیه ارائه شود، هزینه آن ناچیز باشد و هرگز به صورت گذشتهنگر تغییر نکند. اگر همان خط لوله را در یک سهشنبه آرام و یک جمعه پرمشغله روی همان کامیت اجرا کنید، نتیجه باید یکسان باشد.
اینجاست که اکثر فریمورکهای ارزیابی LLM دچار لغزش میشوند. آنها توسط دانشمندان داده برای دانشمندان داده ساخته شدهاند. آنها برای بینش، کاوش و امتیازدهی دقیق بهینه شدهاند. اما یک صف ادغام برای تصمیمات باینری (صفر و یک)، سرعت و عدم بیثباتی (zero flakiness) بهینه میشود. این دو هدف تنها تا حدودی با هم همپوشانی دارند.
چرا مدل به عنوان داور (LLM-as-Judge) صف را مختل میکند
ابزارهایی که در تست من شکست خوردند، یک گناه طراحی مشترک داشتند: آنها بیش از حد به فراخوانیهای LLM-as-judge به عنوان مکانیسم اصلی دروازه تکیه میکردند.
یک پرامپت LLM-as-judge از مدل میخواهد که به یک خروجی از یک تا ده امتیاز دهد، یا بین دو پاسخ بهتر را انتخاب کند، یا میزان صحت واقعیت را رتبهبندی کند. این رویکرد برای درک روندهای کیفی قدرتمند است، اما برای یک بررسی مسدودکننده (blocking) در CI، مانند سم است. یک ورودی یکسان میتواند در روزهای مختلف امتیازهای متفاوتی تولید کند، زیرا پارامترهایی مثل دما (temperature)، نسخهبندی مدل و قالببندی پرامپت همگی باعث ایجاد نویز میشوند. وقتی آن امتیاز به یک آستانه سختگیرانه و یک کد خروج (exit code) قطعی گره خورده باشد، صف شما بر اساس «ارواح» (خطاهای بیاساس) متوقف میشود.
شکستها به سرعت زنجیرهای میشوند. یک بررسی غیرقطعی (nondeterministic) باعث ایجاد صفهای طولانی میشود. مهندسان یاد میگیرند تا زمانی که عدد مطلوب به دست نیاید، دوباره تلاش کنند، که این کار باعث میشود تیم عادت کند به بیلدهای قرمز (خطا) بیتوجهی کند. هزینههای توکن بالا میرود چون هر تلاش مجدد، اعتبار API بیشتری مصرف میکند. بدتر از همه، سیگنال بیمعنی میشود. یک بیلد قرمز باید به معنای «شما یک باگ وارد کردهاید» باشد. اگر به معنای «مدل داور امروز بدقلق شده است» باشد، اعتماد از بین میرود.
تفاوت در عملکرد بازماندگان
Promptfoo و DeepEval زنده ماندند زیرا با بررسیهای قطعی (deterministic) به عنوان شهروندان درجه اول و با امتیازهای داور LLM به عنوان سیگنالهای ثانویه و غیرمسدودکننده برخورد میکنند. آنها میدانند که یک دروازه به یک کد خروج نیاز دارد، نه یک عدد اعشاری که نظر شخصی دارد.
Promptfoo، که تحت لایسنس MIT منتشر شده، برای خط فرمان (command line) ساخته شده است. این ابزار بررسیهایی مانند تطبیق regex، اعتبارسنجی JSON schema، بررسی وجود کلمات (contains) و مقایسه دقیق رشتهها را اجرا میکند. اینها چیزهای پیچیدهای نیستند؛ بلکه دستورات پیشرفتهای از نوع grep و jq هستند. دقیقاً به همین دلیل است که در CI کار میکنند. یک regex یا مطابقت دارد یا ندارد. یک JSON schema یا معتبر است یا خطا میدهد. Promptfoo کدهای خروج استاندارد یونیکس را برمیگرداند، بنابراین GitHub Actions به طور بومی میفهمد که چه زمانی ادغام را متوقف کند. این ابزار مستقل از زبان برنامهنویسی است زیرا به عنوان یک ابزار CLI عمل میکند. شما نیازی ندارید که فقط برای اعتبارسنجی خروجیها، یک اکوسیستم Python را داخل یک مخزن سرویس Node.js نصب کنید.
DeepEval، با لایسنس Apache 2.0، انتخابی برای تیمهای پایتون است. این ابزار مانند pytest یکپارچه میشود. شما تستها را با سینتکس آشنا مینویسید و یک شکست، به طور طبیعی کل مجموعه تست را متوقف میکند. DeepEval کاتالوگ عظیمی از معیارها را ارائه میدهد، اما نکته حیاتی این است که باید با احتیاط از آنها استفاده کنید. برای دروازهها، بر معیارهای قطعی (deterministic) یا اکتشافی (heuristic) تکیه کنید. اگر از G-Eval یا سایر امتیازدهندههای مبتنی بر داور استفاده میکنید، آنها را به جای استفاده از assertهای سخت، در قالب گزارشسازهای غیرمسدودکننده (non-blocking) قرار دهید. وقتی به این روش استفاده شود، DeepEval ارگونومی یک فریمورک تست را بدون بیثباتیِ یک دفترچه یادداشت تحقیقاتی (research notebook) به شما میدهد.
جایگاه چهار مورد دیگر
چهار فریمورکی که به عنوان دروازه دوام نیاوردند، هنوز ارزشمند هستند. آنها صرفاً متعلق به بخش دیگری از زنجیره ابزار (toolchain) شما هستند.
Future AGI (Apache 2.0) ships over fifty metrics and targets teams building custom SDKs. The metrics are thorough. The problem is that the tool expects you to write your own harness to drive it in a CI queue. In a research context, that is a reasonable trade. In a merge queue, every layer of custom wiring is a new source of instability. It is a capable evaluation engine, but not a ready gatekeeper.
RAGAS (Apache 2.0) excels at measuring retrieval-augmented generation quality. Its faithfulness and answer relevance metrics are genuinely useful for understanding how a knowledge base performs over time. Unfortunately, those metrics lean heavily on LLM judges. They are excellent for a nightly quality job that posts trends to Slack. They are poor bouncers for a pull request. Move RAGAS to your scheduled analysis pipeline, not your merge blockers.
Arize Phoenix carries the Elastic License 2.0 and sits at a different intersection entirely. It connects distributed tracing with evaluation, giving you observability into why a model behaved a certain way. You want this when you are debugging a production incident or tracing a hallucination back to a bad retrieval chunk. You do not want a tracing tool deciding whether a junior developer’s feature branch can ship. Its architecture is built for insight, not binary gates.
MLflow Evaluate (Apache 2.0) inherits its pedigree from experiment tracking. It is heavy. Pulling it into a lean CI image adds startup time and dependencies that slow down every single job. If you absolutely must use it inside a pipeline, stick to its heuristic metrics for structural checks. Even then, you are fighting the framework’s fundamental design. MLflow wants to log runs and compare experiments across weeks. A merge queue wants a verdict in under a minute.
Practical Rules for Gating
If you take nothing else from this experiment, take these three rules.
First, gate structure, not vibe. You can enforce that an output is valid JSON. You can enforce that it contains required keys. You can enforce that a classification label belongs to an allowed enum. These checks are fast, cheap, and deterministic. You cannot reliably enforce that a summary is "friendly" or that a rewrite is "creative." Those qualities belong in human review or periodic batch evaluation, not in automated gates.
Second, if a score moves on unchanged input, demote it immediately. Run your evaluation suite twice against the exact same artifact. If any metric flips from pass to fail, it has lost its right to block a merge. Promote it to an advisory dashboard where variance is expected and tolerable.
Third, respect the exit code. A pretty HTML report with a red banner does not stop a merge. A nonzero exit code does. Your evaluation tool must speak the native language of your CI platform. Standard out is for humans. Exit codes are for machines.
The Takeaway
We are still early in figuring out how to test LLM-powered applications. The temptation is to treat evaluation like a human grading rubric: nuanced, contextual, and slightly subjective. That works in a research paper. It collapses in a merge queue.
After eight months of production traffic, my pipeline now runs Promptfoo for structural and schema assertions across services, and DeepEval for Python-side behavioral checks that map cleanly to pass-fail conditions. Everything else reports to nightly dashboards. The queue is stable. The signal is clean. The team trusts a red build again.
You do not need more metrics at your gate. You need fewer metrics that tell the truth every single time.
Based on original testing and write-up shared on Dev.to. For more discussions on building reliable AI systems, join the GyaanSetu community on Telegram.
