راهنمای پیادهسازی ارزیابی خودمیزبان برای ایجنتهای AI
با ساخت یک چرخه ارزیابی خودمیزبان شامل تستهای قطعی و LLM judge، تغییرات کد خود را دقیق بسنجید. نرخ موفقیت را در هر commit ردیابی کنید و وابستگی به سرویسهای جانبی را حذف کنید.
ارزیابیهای خودمیزبان (self-hosted) برای ایجنتهای هوش مصنوعی چیست
ارزیابیهای خودمیزبان برای ایجنتهای هوش مصنوعی شامل چهار موردی است که در مخزن کد خود نگهداری میکنید: فایلی از نمونههای ذخیرهشده، اسکریپتی که ایجنت را روی آنها اجرا میکند، مجموعهای از بررسیها که به هر پاسخ نمره میدهد، و جدولی از نتایج که میتوانید آن را پرسوجو کنید. هیچکدام از این موارد نیازی به فروشنده (vendor) ندارند. کل این چرخه تنها چند صد خط کد Python و یک فایل SQLite است.
ایجنت در نسخه دمو کار میکرد چون شما خودتان آن 5 ورودی را انتخاب کرده بودید. در هفته دوم به دلیل تغییر یک خط در prompt، تغییر مدل، یا تغییر در توضیحات ابزار (tool description) از کار افتاد و هیچ معیاری این تغییرات را پوشش نمیداد. یک چرخه ارزیابی، جمله «حس میکنم الان بدتر شده» را به «نرخ موفقیت در commit 4f1c9ab از 58 از 60 به 51 از 60 کاهش یافت» تبدیل میکند.
این چرخه چهار مرحله دارد و این راهنما برای هر مرحله یک بخش در نظر گرفته است: جمعآوری ردپاهای (traces) واقعی، ارتقای موارد جالب به نمونههای آزمایشی، نمرهدهی به هر نمونه در هر تغییر، و ذخیره نرخ موفقیت در کنار commit تولیدکننده آن. این چرخه فارغ از اینکه ایجنت را روی چه چیزی اجرا میکنید کار میکند و فریمورکهای ایجنت خودمیزبانی که ارزش اجرا دارند عمدتاً در میزان ردپایی که بهصورت رایگان در اختیار شما قرار میدهند، با هم تفاوت دارند.
چرا ایجنت در هفته دوم دچار اختلال میشود
یک ایجنت شامل پرامپت، مدل، مجموعهای از تعاریف ابزار و هر نوع متنی است که در زمان اجرا بازیابی میشود. هر چهار مورد میتوانند بدون تغییر در کد برنامه شما تغییر کنند، بنابراین در یک بررسی کد (code review) معمولی، هیچ مورد مشکوکی دیده نمیشود.
شایعترین علت، ویرایش پرامپت است. شما یک جمله اضافه میکنید تا از پاسخهای بیادبانه جلوگیری کنید. همان جمله رفتار مدل را در ورودیهایی که کسی دوباره تست نکرده است تغییر میدهد و این موضوع در لاگهای رهگیری (traces) بهوضوح دیده میشود: رهگیری هفته گذشته برای همان سؤال شامل یک فراخوانی ابزار create_refund است، اما رهگیری این هفته هیچ فراخوانی ندارد و پاسخ فقط یک عذرخواهی مؤدبانه است. چون هیچ خطایی رخ نداده، هیچ هشداری نیز فعال نشده است.
علت دوم، مدل است. رشته دقیق مدلی که با هر اجرا ارسال کردهاید را ثبت کنید، claude-haiku-4-5-20251001 بهجای نام اختصاری که در ذهن دارید؛ زیرا افت نرخ موفقیت در روزی که مدل را تغییر دادهاید، تنها زمانی قابلتشخیص است که نام مدل در ردیف دادهها ثبت شده باشد.
علت سوم، ابزارها هستند. تغییر در متن توضیحات یک ابزار، زمان تصمیمگیری مدل برای فراخوانی آن را تغییر میدهد. اگر ابزارهای شما از طریق سرورهای MCP در حال اجرا روی یک VPS دریافت میشوند، طرحواره (schema) در یک پردازش دیگر قرار دارد و میتواند بدون هیچ تغییری در مخزن کد شما، تغییر کند. علت چهارم، بازیابی است: همان سؤال به ایندکسی برخورد میکند که شبانه بازسازی شده است و پاسخ، از سند جدید پیروی میکند.
ساخت مجموعه طلایی (golden set) از تریسهایی که قبلاً جمعآوری کردهاید
موارد ارزیابی را از خودتان ابداع نکنید. آنها را از ترافیک واقعی استخراج کنید. اگر در حال حاضر از ردیابی Langfuse برای ایجنت خود به صورت self-hosted استفاده میکنید، هر درخواست به همراه ورودی، فراخوانی ابزارها و خروجی آن ذخیره میشود؛ این دقیقاً همان ماده خامی است که یک مورد ارزیابی به آن نیاز دارد.
یک بازه از root observationها را از طریق API عمومی خروجی بگیرید. این API از احراز هویت پایه (basic authentication) استفاده میکند که در آن کلید عمومی (public key) شما به عنوان نام کاربری و کلید مخفی (secret key) به عنوان رمز عبور عمل میکند.
export LF_HOST="https://langfuse.example.com"
curl -sS -u "$LF_PUBLIC_KEY:$LF_SECRET_KEY" \
"$LF_HOST/api/public/v2/observations?limit=50&isRootObservation=true&fromStartTime=2026-07-01T00:00:00Z" \
| jq '.data[0]'پیش از نوشتن هرگونه کد برای پارس کردن، ابتدا یک رکورد را بخوانید. سطرها در زیر data بازگردانده میشوند، اما نام فیلدهایی که پرسش و پاسخ را در خود نگه میدارند، به نحوه instrument کردن spanها توسط ایجنت شما بستگی دارد؛ بنابراین به جای تکیه بر آنچه انتظار داشتید، آنچه را که واقعاً مشاهده میکنید نگاشت کنید. سپس موارد ارزیابی را به صورت دستی، هر شیء JSON در یک خط، در evals/cases.jsonl بنویسید:
{"id": "refund-double-charge", "tags": ["smoke"], "input": "I was charged twice for order 41822.", "must_call": ["lookup_order", "create_refund"], "must_not_include": ["I cannot help"], "rubric": "The reply confirms exactly one refund for order 41822 and states the amount."}پنج قانون برای حفظ کارایی این مجموعه وجود دارد:
- 40 تا 80 مورد برای شروع کافی است. زیر 20 مورد، یک مورد ناپایدار (flaky) نرخ موفقیت را 5 واحد تغییر میدهد و عددی که بدون دلیل جهش داشته باشد، نادیده گرفته میشود.
- هر باگ تولید (production bug) که رفع میکنید، باید در همان روز به یک مورد ارزیابی تبدیل شود. این عادت باعث میشود مجموعه در مسیر درست رشد کند.
- هر مورد ارزیابی فقط یک رفتار را بررسی کند. موردی که همزمان مبلغ بازپرداخت و لحن پاسخ را چک میکند، در صورت شکست، هیچ اطلاعات مفیدی به شما نمیدهد.
- مقدار
idهرگز تغییر نمیکند، زیرا از این شناسه برای مقایسه اجرای امروز با اجرای ماه گذشته استفاده میشود. - پیش از commit کردن، اطلاعات حساس را حذف (redact) کنید. این فایل در git ذخیره میشود، بنابراین نام مشتریان و هر شماره سفارشی که متعلق به شما نیست را پاک کنید.
ابتدا با بررسیهای قطعی (deterministic) ارزیابی کنید، زیرا هزینهای ندارند
هر چیزی که پاسخ درست مشخصی دارد، باید با یک assertion ساده بررسی شود. بدون فراخوانی مدل، بدون هزینه و بدون ابهام. بررسیهای قطعی، رگرسیونهای ساختاری را شناسایی میکنند؛ همان مواردی که باعث اختلال در سیستمهای پیرامون agent شما میشوند: JSON تجزیه نمیشود، ابزار هرگز فراخوانی نشده است، عبارت ممنوعه بازگردانده شده است، یا پاسخ هیچ منبعی را ذکر نمیکند.
تنها یک تابع از جزئیات agent شما آگاه است. سایر بخشهای چارچوب ارزیابی (harness) باید عمومی باشند.
import json, os, urllib.request
def run_agent(case):
req = urllib.request.Request(
os.environ["AGENT_URL"],
data=json.dumps({"input": case["input"]}).encode(),
headers={"content-type": "application/json"},
)
with urllib.request.urlopen(req, timeout=120) as resp:
return json.load(resp)
def deterministic(case, result):
text = result.get("output", "")
called = [c["name"] for c in result.get("tool_calls", [])]
failures = []
for tool in case.get("must_call", []):
if tool not in called:
failures.append(f"tool not called: {tool}")
for phrase in case.get("must_not_include", []):
if phrase.lower() in text.lower():
failures.append(f"forbidden phrase: {phrase}")
if len(called) > case.get("max_tool_calls", 12):
failures.append(f"too many tool calls: {len(called)}")
return failuresبودجه استفاده از ابزار را در آن لیست لحاظ کنید. agentای که امروز یک مورد را با 3 فراخوانی حل میکند و فردا با 11 فراخوانی، حتی اگر پاسخ نهایی درست باشد، دچار رگرسیون شده است؛ زیرا شما برای هر فراخوانی که انجام میدهد هزینه پرداخت میکنید.
مدل زبانی به عنوان داور و چهار روشی که در آن دچار خطا میشود
هر آنچه از بررسیهای خودکار (assertions) عبور میکند، به یک ارزیاب نیاز دارد که محتوا را بخواند. استفاده از یک مدل زبانی (LLM) به عنوان داور، در واقع فراخوانی دوم مدل است: این مدل پرسش، پاسخِ عامل (agent) و یک معیار را دریافت کرده و سپس نتیجه را اعلام میکند. این تنها روش عملی برای ارزیابی این موضوع است که «آیا پاسخ، پرسش کاربر را پوشش میدهد یا خیر».
چهار قاعده، یک داور را قابل استفاده میکند:
- نتیجه باید دوحالتی (Binary) باشد، هرگز از امتیاز 1 تا 10 استفاده نکنید. مقیاس عددی برای تقریباً همه چیز امتیاز 7 یا 8 میدهد، بنابراین اعداد تغییر نمیکنند و شما چیزی از آنها نمیآموزید.
- در هر فراخوانی فقط یک معیار را بررسی کنید. درباره مبلغ بازپرداخت بپرسید یا درباره لحن پاسخ، اما نه هر دو به صورت همزمان.
- هرگاه موردِ آزمون پاسخ مشخصی دارد، آن پاسخِ مورد انتظار را به داور بدهید. ارزیابی بر اساس یک مرجع، بسیار آسانتر از ارزیابی انتزاعی است.
- شکل خروجی را اجباری کنید و آن را به دقت پارس (parse) کنید.
from anthropic import Anthropic
client = Anthropic() # reads ANTHROPIC_API_KEY from the environment
def judge_prompt(case, output):
return (
"You grade one answer against one criterion.\n"
"Reply with JSON only, in this exact shape:\n"
'{"verdict": "pass", "confidence": "high", "reason": "one short sentence"}\n'
f"Criterion: {case['rubric']}\n"
f"Question: {case['input']}\n"
f"Answer: {output}\n"
"Length is not a criterion. Judge only the criterion above."
)
def judge(case, output, model):
msg = client.messages.create(
model=model,
max_tokens=200,
messages=[{"role": "user", "content": judge_prompt(case, output)}],
)
return json.loads(msg.content[0].text)حال به بررسی حالتهای شکست میپردازیم. برای هر کدام آزمونی وجود دارد که میتوانید همین امروز اجرا کنید؛ اجرای این آزمونها ضروری است، زیرا داوری که کنترل نشود، اعدادی تولید میکند که دقیق به نظر میرسند اما هیچ معنایی ندارند.
سوگیری طول (Length bias). پاسخهای طولانیتر بیشتر تأیید میشوند. آن را تست کنید: ده پاسخ که داور آنها را رد کرده است بردارید، هر کدام را با دو پاراگراف متن پرکننده (filler) که با اعتمادبهنفس نوشته شده اما هیچ واقعیت جدیدی اضافه نمیکند، طولانیتر کنید و دوباره آنها را قضاوت کنید. هر نتیجهای که به «تأیید» تغییر کند، نشاندهنده سوگیری طول است و باید دستورالعمل (rubric) را اصلاح کنید.
خودپسندی (Self-preference). داور اغلب خروجیهای خانواده مدل خودش را نسبت به خروجیهای مدلهای دیگر، با مهربانی بیشتری ارزیابی میکند. آن را تست کنید: 30 پاسخ یکسان را با داورهایی از دو خانواده مدل متفاوت ارزیابی کنید و نتایج را مورد به مورد مقایسه کنید. در مواردی که اختلاف نظر دارند، خودتان آن مورد را بررسی کنید.
سوگیری موقعیت (Position bias). اگر از داور برای مقایسه دو پاسخ A و B استفاده میکنید، جای آنها را عوض کرده و دوباره اجرا کنید. نتیجهای که با جابهجایی تغییر کند، به این معناست که مقایسه جفتی (pairwise) هنوز برای آن دستورالعمل ایمن نیست.
انحراف دستورالعمل (Rubric drift). معیارهای مبهم، داورهای سهلگیر تولید میکنند. «آیا پاسخ مفید است» تقریباً هر چیزی را تأیید میکند. «آیا پاسخ مبلغ بازپرداخت را به دلار ذکر کرده است» فقط آنچه مد نظر شماست را تأیید میکند. هر معیار را تا زمانی که واقعیتِ مورد بررسی را به صراحت نام ببرد، بازنویسی کنید.
یک محافظ، هر چهار مورد را پوشش میدهد. 30 مورد را که خودتان با دست برچسبگذاری کردهاید نگه دارید و هر بار که مدل داور یا پرامپت داور را تغییر میدهید، عملکرد داور را بر اساس برچسبهای خودتان امتیازدهی کنید. اگر داور در بیش از یک مورد از هر ده مورد با شما اختلاف نظر داشت، پیش از اعتماد به هر نرخ قبولی که تولید میکند، دستورالعمل را اصلاح کنید. داور در واقع کد است، بنابراین باید مانند کد، نسخهبندی و بازبینی شود.
رتبهبندی ارزان، ارتقا به مدلهای پیشرفته
قضاوت هر مورد با گرانترین مدل در هر commit، دلیلی است که هزینه ارزیابی از هزینه خودِ عاملی (agent) که در حال تست آن هستید، پیشی میگیرد. ارزیابها را بر اساس قیمت مرتب کنید و به محض اینکه پاسخ مشخص شد، متوقف شوید.
The data behind this chart
[
{
"label": "Haiku 4.5, Batch API",
"usd_per_1000_judge_calls": "0.90"
},
{
"label": "Haiku 4.5",
"usd_per_1000_judge_calls": "1.80"
},
{
"label": "Sonnet 5",
"usd_per_1000_judge_calls": "3.60"
},
{
"label": "Opus 5",
"usd_per_1000_judge_calls": "9.00"
}
]این ارقام فرض را بر حدود 1,200 توکن ورودی و 120 توکن خروجی در هر فراخوانی ارزیاب میگذارند که اندازهای واقعبینانه برای یک پرسش، یک پاسخ و یک معیار است. قضاوت 1,000 مورد با Claude Haiku 4.5 هزینه 1.80 دلار آمریکا و با Claude Opus 5 هزینه 9.00 دلار در بر دارد. این اختلاف تا زمانی که آن را ضرب نکنید، ناچیز به نظر میرسد. یک مجموعه 60 موردی که در هر commit ارزیابی شود، با 40 commit در هفته، پیش از آنکه کسی job شبانه را اجرا کرده باشد، به 2,400 فراخوانی ارزیاب در هفته میرسد.
دو تخفیف بهخوبی برای کارهای ارزیابی اعمال میشوند و با هم جمعپذیر هستند. اجرای ارزیابیها تعاملی نیست، بنابراین Batch API قیمت ورودی و خروجی را در ازای تحویل غیرهمگام (asynchronous) نصف میکند که این موضوع در ردیف اول جدول دیده میشود. دستورالعملها و معیارهای ارزیابی (rubric) در هر فراخوانی بایت به بایت یکسان هستند، بنابراین prompt caching مناسب است: هزینه خواندن از کش یکدهم قیمت پایه ورودی است و هزینه نوشتن در کش برای پنج دقیقه، 1.25 برابر قیمت پایه ورودی است؛ بنابراین کش پس از یک بار استفاده، هزینه خود را جبران میکند. اینها قیمتهای رسمی Anthropic تا اوت 2026 هستند و Sonnet 5 تا تاریخ 31 اوت 2026 دارای قیمتگذاری مقدماتی است، بنابراین نوار سوم پس از این تاریخ افزایش مییابد.
نردبان رتبهبندی به ترتیب:
- بررسیهای قطعی (Deterministic) روی همه موارد. بدون هیچ هزینه API.
- یک مدل ارزیاب کوچک برای مواردی که از آن بررسیها عبور کردهاند.
- یک ارزیاب پیشرفته (frontier) فقط در مواردی که ارزیاب کوچک اعلام شکست میکند یا با اطمینان پایین اعلام موفقیت میکند.
- بررسی انسانی روی یک نمونه کوچک، یک بار در هفته.
CHEAP = "claude-haiku-4-5-20251001"
STRICT = "claude-opus-5"
def grade(case, result):
hard = deterministic(case, result)
if hard:
return False, "deterministic", "; ".join(hard)
first = judge(case, result["output"], CHEAP)
if first["verdict"] == "pass" and first["confidence"] == "high":
return True, CHEAP, first["reason"]
second = judge(case, result["output"], STRICT)
return second["verdict"] == "pass", STRICT, second["reason"]این روش بخشی از دقت رتبهبندی را فدای هزینه میکند، بنابراین بهجای فرض کردن، این تفاوت را اندازهگیری کنید. ماهی یک بار، کل مجموعه را با ارزیاب سختگیر نیز رتبهبندی کنید و دو ستون را با هم مقایسه کنید. اگر آنها در بیش از چند مورد اختلاف نظر داشتند، معیار ارزیابی شما برای مدل کوچک بیش از حد آزاد است و آنچه باید اصلاح کنید، همان معیار است. کنترل هزینههای خودِ عامل (agent) یک وظیفه جداگانه است که در کنترل هزینه برای یک عامل هوش مصنوعی روی VPS پوشش داده شده است.
ردگیری نرخ موفقیت در طول زمان در سیستمی که مالک آن هستید
نرخ موفقیتی که نتوانید آن را به یک commit خاص پیوند دهید، صرفاً یک احساس است. به ازای هر مورد در هر اجرا، یک ردیف در دیتابیس ذخیره کنید که شامل commit و مدل مورد استفاده در همان ردیف باشد.
CREATE TABLE IF NOT EXISTS results (
run_id TEXT NOT NULL,
ran_at TEXT NOT NULL,
git_sha TEXT NOT NULL,
agent_model TEXT NOT NULL,
case_id TEXT NOT NULL,
passed INTEGER NOT NULL,
graded_by TEXT NOT NULL,
reason TEXT
);SELECT run_id, git_sha, agent_model,
count(*) AS cases,
round(100.0 * sum(passed) / count(*), 1) AS pass_pct
FROM results
GROUP BY run_id
ORDER BY ran_at DESC
LIMIT 10;طرح (schema) را با sqlite3 evals/results.db < evals/schema.sql بارگذاری کنید و سپس روند تغییرات را با sqlite3 -box evals/results.db < evals/passrate.sql بخوانید. یک سال اجرای روزانه برای 60 مورد، حدود 22,000 ردیف ایجاد میکند؛ بنابراین این ذخیرهسازی هرگز به یک پروژه مستقل تبدیل نخواهد شد. مقاله اجرای SQLite در محیط عملیاتی روی VPS تنظیماتی را پوشش میدهد که اگر این فایل بین چندین ماشین به اشتراک گذاشته شود، اهمیت پیدا میکنند.
اجراکننده (runner) همان اطلاعات را برای مشاهده انسان نیز چاپ میکند:
run 2026-08-05T09:14:22Z sha 4f1c9ab model claude-sonnet-5 58/60 pass (96.7%)
FAIL refund-double-charge deterministic: tool not called: create_refund
FAIL pto-policy-question judge(opus): reply gives no dollar amountمجموعه تستها را روی تغییراتی اجرا کنید که میتوانند یک agent را مختل کنند؛ این یعنی تغییرات در prompt، تغییرات مدل و تغییرات ابزار، نه هر commit در هر جای مخزن. یک hook از نوع pre-push زیرمجموعه سریع تستها را پوشش میدهد:
cat > .git/hooks/pre-push <<'EOF'
#!/bin/sh
python3 evals/run.py --set smoke || exit 1
EOF
chmod +x .git/hooks/pre-pushاجراهای کامل کندتر هستند و باید طبق زمانبندی انجام شوند. یک سرویس و تایمر systemd روی VPS که شبانه اجرا میشود، کل مجموعه تستها را روی prompt مستقر شده (deployed) اجرا میکند؛ این همان کاری است که تغییرات ناشی از منابع خارج از مخزن شما—مانند ابزاری میزبانیشده که رفتار آن تغییر کرده است—را شناسایی میکند.
بازبینی انسانی، بهصورت نمونهگیری و نه جامع
داور بر اساس برچسبهای انسانی کالیبره میشود، بنابراین شخصی باید این برچسبها را تولید کند. هر هفته یک نمونه را مطالعه کنید: تمام مواردی که داور در آنها شکست خورده است، بهعلاوه ده مورد موفق که بهصورت تصادفی انتخاب شدهاند. موارد موفق تصادفی نیمه مهم کار هستند، زیرا داوری که بیسروصدا شروع به تأیید پاسخهای نادرست کرده است، در هر داشبوردی که بر اساس قضاوتهای خودش ساخته شده باشد، عالی به نظر میرسد.
پانزده مورد با زمان سه دقیقه برای هر کدام، معادل 45 دقیقه در هفته است و اصلاحاتی را به دستورالعمل بازمیگرداند که در آن شما و داور اختلاف نظر دارید، بهعلاوه موارد جدیدی از انواع شکست که هیچکس تصور نمیکرد. قضاوت انسانی را در همان جدولی بنویسید که graded_by روی human تنظیم شده است، تا توافق بین داور و انسان به یک کوئری تبدیل شود، نه یک خاطره.
چه چیزی در خودِ ابزار ارزیابی (eval harness) دچار اختلال میشود
anthropic.RateLimitError در اولین اجرای کامل. اجرای همزمان 60 مورد، از حد مجاز درخواست یا توکن برای سطح (tier) شما فراتر میرود. تعداد همزمانی (concurrency) را روی 4 worker محدود کنید و اجرای شبانه را به Batch API منتقل نمایید.
json.JSONDecodeError: Expecting value: line 1 column 1 (char 0) از سمت داور. مدل به صورت متنی پاسخ داده یا خروجی JSON خود را داخل code fence قرار داده است. یک بار دوباره تلاش کنید، سپس آن مورد را به عنوان خطا ثبت کنید. هرگز اجازه ندهید شکست در پارس (parse failure) به عنوان موفقیت محسوب شود، زیرا مجموعهای که خطاها را به موفقیت تبدیل میکند، در حالی که عملکرد عامل (agent) بدتر میشود، به سمت 100% پیش میرود.
موارد ناپایدار (Flaky cases). ورودی یکسان در یک اجرا موفق و در اجرای بعدی ناموفق است، زیرا عامل خروجی خود را نمونهبرداری (sample) میکند. مورد ناپایدار را سه بار اجرا کنید و به جای حذف آن، کسر موفقیت را ثبت کنید. موردی که در دو اجرا از سه اجرا موفق میشود، یک باگ واقعی در پایداری است و مشتری حتماً آن را پیدا خواهد کرد.
فرسودگی مجموعه طلایی (Golden set rot). شخصی پاسخ مورد انتظار را ویرایش میکند تا وضعیت مجموعه سبز شود. تغییرات (diffs) در evals/cases.jsonl را به همان دقت تغییرات در عامل بررسی کنید، زیرا آن فایل تعریف مکتوب شما از پاسخ صحیح است.
مجموعهای که هرگز شکست نمیخورد. نرخ موفقیت که برای یک ماه روی 100% ثابت مانده، به این معنی است که مجموعه دیگر محصول را دنبال نمیکند. ده trace اخیر را استخراج کنید، مواردی که عامل در آنها عملکرد بدی داشته را پیدا کرده و به مجموعه اضافه کنید. سپس عمداً بخشی را خراب کنید و تأیید کنید که اجرا قرمز میشود؛ این همان بررسی تست جهش (mutation testing) روی مجموعه تست است و تنها راهی است که بفهمید مجموعه شما هنوز کارایی دارد.
FAQ
یک مجموعه ارزیابی (eval set) برای ایجنت هوش مصنوعی به چند مورد نیاز دارد؟
با 40 تا 80 مورد شروع کنید و این مجموعه را بر اساس شکستهای واقعی توسعه دهید. زیر 20 مورد، یک نتیجه ناپایدار (flaky) نرخ موفقیت را تا 5 واحد تغییر میدهد، بنابراین این عدد دیگر حاوی اطلاعات مفیدی نخواهد بود. پس از چند صد مورد، هر اجرا هزینه مالی و زمانی واقعی به همراه دارد، در حالی که موارد حاشیهای پوشش چندانی اضافه نمیکنند. معیاری که اهمیت دارد تعداد نیست، بلکه سهم انواع شکستهای شناختهشده در محیط عملیاتی (production) است که حداقل یک بار در مجموعه ظاهر شدهاند.
آیا میتوان به یک LLM judge برای نمرهدهی به ایجنت اعتماد کرد؟
تنها پس از آنکه آن را با برچسبهای خودتان سنجیدید. 30 موردی را که شخصاً ارزیابی کردهاید نگه دارید و هر زمان که مدل یا پرامپت judge را تغییر دادید، عملکرد آن را با این موارد بسنجید. مدلهای judge دچار سوگیری طول (length bias) هستند، که در آن پاسخهای طولانیتر بیشتر قبول میشوند، و همچنین سوگیری خود-ترجیحی (self-preference) دارند که در آن خروجیهای خانواده مدل خودشان را با ارفاق بیشتری نمره میدهند. هر دو مورد قابل آزمایش هستند: یک پاسخ شکستخورده را با افزودن متن طولانیتر کنید و دوباره آن را بسنجید، یا همان پاسخها را با یک judge از خانوادهای دیگر نمرهدهی کنید. اگر judge در بیش از یک مورد از هر 10 مورد با برچسبهای شما اختلاف داشت، دستورالعمل (rubric) بیش از حد مبهم است و نباید استفاده شود.
کدام مدل باید ارزیابیها را نمرهدهی کند؟
ارزان نمرهدهی کنید و در صورت نیاز به مدلهای قویتر ارجاع دهید. بررسیهای قطعی (Deterministic assertions) هزینهای ندارند، بنابراین در هر مورد ابتدا باید اجرا شوند. یک مدل کوچک موارد واضح را مدیریت میکند. فقط موارد شکست و نتایج با اطمینان پایین به یک مدل پیشرو (frontier model) ارسال میشوند. بر اساس قیمتهای لیستشده در اوت 2026، نمرهدهی 1,000 مورد با Claude Haiku 4.5 حدود 1.80 دلار آمریکا و با Claude Opus 5 حدود 9.00 دلار هزینه دارد؛ و از آنجا که اجرای ارزیابیها بهصورت غیرهمگام (asynchronous) است، استفاده از Batch API هر دو رقم را به نصف کاهش میدهد.
آیا ارزیابیها جایگزین مانیتورینگ محیط عملیاتی (production) میشوند؟
خیر، زیرا آنها به پرسشهای متفاوتی پاسخ میدهند. یک مجموعه ارزیابی به شما میگوید که آیا تغییری که قصد انتشار آن را دارید، یک مجموعه ثابت از موارد را بهبود میبخشد یا بدتر میکند. ردیابی (tracing) و مانیتورینگ به شما میگویند که کاربران واقعی در حال حاضر با چه چیزی مواجه هستند، از جمله ورودیهایی که هیچ موردی آنها را پوشش نمیدهد. این دو مکمل یکدیگرند: ردیابیها موارد جدید را تأمین میکنند و مجموعه ارزیابی تعیین میکند که آیا اصلاح شما واقعاً مؤثر بوده است یا خیر.