ارزیابی عملکرد مدل
وضعیت evalهای hosted
در حال حاضر AvalAI اندپوینت hosted برای /v1/evals ارائه نمیکند. فعلا integration عملیاتی خود را روی https://api.avalai.ir/v1/evals نسازید. از workflow محلی و CI زیر با فراخوانیهای عادی API AvalAI استفاده کنید.
ارزیابیها (evals) تستهای ساختاریافته برای رفتار هوش مصنوعی هستند. با eval میتوانید مدلها را مقایسه کنید، رگرسیون پرامپت را پیدا کنید، tool use را اعتبارسنجی کنید و تصمیم بگیرید آیا یک تغییر برای deploy امن است یا نه. این راهنما توصیههای رسمی OpenAI برای evaluation را با اندپوینتهای OpenAI-compatible در AvalAI تطبیق میدهد.
مفهومهای hosted Evals، Datasets و Graders در OpenAI الگوهای طراحی مفیدی هستند، اما مدل object مربوط به hosted Evals در OpenAI را قرارداد API برای AvalAI فرض نکنید. caseهای eval، خروجیهای مورد انتظار، rubricها و thresholdها را در فایلهای قابلحمل نگه دارید تا امروز محلی اجرا شوند و اگر AvalAI بعدا زیرساخت hosted eval ارائه کرد، تمیز migrate شوند.
پلتفرم hosted Evals خود OpenAI نیز در دوره deprecation قرار دارد: Evalهای موجود برای کاربران فعلی در ۳۱ اکتبر ۲۰۲۶ read-only میشوند و خاموشی کامل پلتفرم برای ۳۰ نوامبر ۲۰۲۶ برنامهریزی شده است. بنابراین workflow AvalAI را به یک object model میزبانیشده خاص گره نزنید. بخش پایدار راهنمای OpenAI همان چرخه objective، dataset، metric، run/compare و continuous evaluation است؛ runner را قابلتعویض نگه دارید.
مسیر عملی فعلی: eval محلی و CI
تا زمانی که evalهای hosted AvalAI فعال شوند، داراییهای eval را داخل مخزن خود نگه دارید:
- Dataset: پرامپتهای نماینده، labelهای مورد انتظار، پاسخهای مرجع یا rubricهای داوری.
- Data schema: قراردادی شبیه JSON Schema برای هر ردیف تست، مشابه مفهوم
data_source_configدر OpenAI، بدون وابستگی به object میزبانیشده/v1/evals. - Runner: Promptfoo، pytest، یک اسکریپت کوچک یا pipeline CI.
- Models: مدل production و مدل candidate در AvalAI، با پیکربندی از طریق متغیر محیطی.
- Assertions: exact match، JSON schema، semantic similarity، LLM-as-judge، دقت tool call، رفتار refusal، latency و آستانه هزینه.
برای نمونه قابل اجرا، ارزیابی با Promptfoo و AvalAI را ببینید که با اقتباس از OpenAI Cookbook رسمی و openai/openai-cookbook و با تغییر endpoint، API key و model برای AvalAI تهیه شده است.
طراحی Eval
از همان چرخه پنجمرحلهای پیشنهادی OpenAI برای evaluation شروع کنید:
- هدف را تعریف کنید: رفتاری را مشخص کنید که باید بهتر شود یا پایدار بماند.
- Dataset را جمعآوری کنید: نمونههای شبیه production، edge caseها، ورودیهای چندزبانه، ورودیهای خراب و promptهای adversarial را اضافه کنید.
- Metricها را تعریف کنید: pass/fail، exact match، امتیاز rubric، دقت tool call، precision/recall در retrieval یا review انسانی را انتخاب کنید.
- اجرا و مقایسه کنید: مدل production فعلی را با prompt، model ID یا routing candidate مقایسه کنید.
- پیوسته ارزیابی کنید: شکستهای production را از logها به eval set اضافه کنید و suite را در هر release اجرا کنید.
از evalهای حسی مثل «پاسخ خوب به نظر میرسد» پرهیز کنید. قبل از تغییر prompt یا model معیار قابل اندازهگیری بنویسید.
Anti-patternهایی که باید از آنها پرهیز کرد
راهنمای بهترین شیوههای evaluation در OpenAI برای پیدا کردن طراحی ضعیف eval بسیار کاربردی است. این failure modeها را از release gateهای AvalAI دور نگه دارید:
| Anti-pattern | چرا شکست میخورد | الگوی بهتر در AvalAI |
|---|---|---|
| فقط metricهای عمومی آکادمیک | BLEU، ROUGE یا perplexity ممکن است correctness، safety و رفتار ابزار در task واقعی را نشان ندهند | checkهای task-specific مثل label دقیق، JSON schema، دقت citation و اعتبار argument ابزار اضافه کنید. |
| Dataset بایاسدار یا بیش از حد تمیز | مجموعه کوچک و دستچینشده کیفیت را بیش از واقع نشان میدهد و drift تولید را پنهان میکند | logهای production، edge caseها، ردیفهای چندزبانه، ورودی خراب و تلاشهای adversarial را ترکیب کنید. |
| تأیید حسی | «خوب به نظر میرسد» regressionها را نمیگیرد و candidateها را قابل اعتماد مقایسه نمیکند | پیش از تغییر prompt، model، ابزار یا routing معیار pass/fail تعریف کنید. |
| Grader خودکار بدون calibration | LLM judge و scoreهای heuristic ممکن است از قصد reviewer فاصله بگیرند | تصمیم grader را با label انسانی مقایسه کنید، caseهای اختلاف را نگه دارید و پیش از اعتماد به CI gate rubric را اصلاح کنید. |
| فقط امتیاز end-to-end | یک عدد کلی پنهان میکند workflow در کدام مرز شکست خورده است | مرزها را جدا بسنجید: classification، retrieval، tool call، پاسخ نهایی و safety handling. |
تا حد امکان taskهایی را انتخاب کنید که مقایسهپذیرند. انتخاب pairwise، classification، امتیازدهی بر اساس rubric و دقت tool-call معمولا پایدارتر از promptهای باز مثل «یک پاسخ خوب بنویس» grade میشوند.
Flywheel ارزیابی پیوسته
Eval را مثل سیستم زنده release در نظر بگیرید، نه یک benchmark یکباره:
- Instrument: request ID، model ID، نسخه prompt، tool callها، شناسه سندهای retrieval، token usage، latency و failureهای قابل مشاهده توسط کاربر را log کنید.
- Mine: خطاهای production، ticketهای پشتیبانی، یافتههای red-team و اختلاف نظر reviewerها را به ردیف eval جدید تبدیل کنید.
- Calibrate: پیش از اعتماد به threshold جدید، تصمیم grader خودکار را با یک batch کوچک human-labeled مقایسه کنید.
- Gate: smoke evalها را روی هر pull request و suite کامل را پیش از تغییر model، prompt، retrieval یا schema ابزار اجرا کنید.
- Refresh: ردیفهای تکراری را حذف کنید، edge caseهای سخت را نگه دارید و با تکامل محصول و ترکیب مدلها failure modeهای جدید اضافه کنید.
برای هر ردیف metadataهایی مثل case_id، source، risk_level، expected_behavior، owner و added_after_incident نگه دارید. این context به نگهدارندگان بعدی کمک میکند بفهمند چرا یک ردیف وجود دارد و آیا regression candidate قابل قبول است یا نه.
مقایسه providerها و مسیرهای deployment
راهنمای OpenAI درباره eval برای external modelها بین مدلهای native، مدلهای third-party و custom endpointها تفاوت میگذارد. همین مدل ذهنی را در AvalAI نگه دارید، اما بهجای object میزبانیشده /v1/evals آن را با evalهای محلی و CI اجرا کنید:
- dataset و rubric را ثابت نگه دارید و فقط
model، route endpoint یا گزینههای provider-specific را عوض کنید. - هر اجرا را با مسیر provider، endpoint (
/v1/responses،/v1/chat/completionsیا route بومی)، feature flagها، region در صورت وجود، و service tier label کنید. - پشتیبانی ابزارها را یک بعد جدا بدانید. ممکن است مدل در کیفیت متن pass شود اما اگر function call، MCP، web/file search یا streaming روی route candidate متفاوت باشد، در production شکست بخورد.
- وقتی داده از مرز provider عبور میکند، assertionهای privacy و safety اضافه کنید: رفتار refusal، مدیریت prompt injection، نشت source و logging با redaction.
- candidate را فقط وقتی ارتقا دهید که دقت، latency، هزینه، ظرفیت quota و gateهای safety برای همان مسیر deployment قابل قبول باشند.
این کار مقایسه providerها را در routeهای مدل AvalAI قابلحمل نگه میدارد و از وابستگی به model picker یا catalog شخصسازیشده یک پلتفرم eval میزبانیشده جلوگیری میکند.
قرارداد Dataset را صریح کنید
Evals API در OpenAI اسکیمای ردیفها (data_source_config) را از قوانین امتیازدهی (testing_criteria) جدا میکند. همین جداسازی را در evalهای محلی AvalAI نگه دارید تا تستها قابلحمل بمانند:
{ "item": { "ticket_text": "مانیتور من روشن نمیشود.", "correct_label": "Hardware" } }
{ "item": { "ticket_text": "کلاینت VPN بعد از login crash میکند.", "correct_label": "Software" } }
{ "item": { "ticket_text": "برای ناهار نزدیک دفتر پیشنهادی داری؟", "correct_label": "Other" } }ticket_textورودی مدل است که در Chat Completions یا Responses template میکنید.correct_labelهمان ground truth بازبینیشده توسط انسان است و معادل الگوی{{ item.correct_label }}در OpenAI محسوب میشود.- پاسخ تولیدشده معادل محلی
{{ sample.output_text }}است؛ آن را در خروجی runner نگه دارید تا failureها قابل debug باشند. - فایل داده را مثل کد production بازبینی کنید: labelها را review کنید، edge case اضافه کنید و قبل از تغییر prompt، شکستهای جدید production را وارد suite کنید.
فیلدهای Annotation اضافه کنید
workflow مربوط به Dataset در OpenAI، خروجیهای تولیدشده، ratingها و feedback را بخشی از داده evaluation میداند. همین الگو را محلی نگه دارید تا انسان و grader خودکار از یک مجموعه ردیف مشترک استفاده کنند:
| فیلد | کاربرد |
|---|---|
item.* | متغیرهای prompt و فیلدهای ground truth مثل ticket_text، correct_label یا reference_answer. |
sample.output_text | خروجی مدل candidate که از Chat Completions یا Responses ذخیره شده است. |
human_rating | label بازبین مثل pass، fail، better_than_baseline یا needs_review. |
output_feedback | نقد کوتاه بازبین که توضیح میدهد چه چیزی شکست خورده و prompt، ابزار یا retrieval چگونه باید بهتر شود. |
grader_score | امتیاز خودکار از string check، schema check، semantic similarity یا LLM judge. |
برای taskهای subjective یا تخصصی، پیش از اعتماد به grader خودکار، یک batch کوچک را به subject-matter expert بدهید تا annotate کند. ردیفهای اختلاف بین انسان و grader را برای اصلاح rubric نگه دارید، نه اینکه از dataset حذف کنید.
مثال: Eval طبقهبندی
این مثال یک classifier برای ticket پشتیبانی را تست میکند. همین تست را میتوانید امروز با Chat Completions و برای مدلهای پشتیبانیشده با Responses اجرا کنید.
# evals/support-ticket-classifier.yaml
description: Classify IT support tickets
prompts:
- |-
Classify the support ticket as Hardware, Software, or Other.
Return only the label.
Ticket: {{ticket_text}}
providers:
- id: openai:chat:gpt-5.5
label: production
config:
apiHost: https://api.avalai.ir/v1
apiKey: ${AVALAI_API_KEY}
- id: openai:chat:gpt-5.4
label: candidate
config:
apiHost: https://api.avalai.ir/v1
apiKey: ${AVALAI_API_KEY}
tests:
- vars:
ticket_text: "مانیتور من روشن نمیشود."
correct_label: Hardware
assert:
- type: equals
value: Hardware
- vars:
ticket_text: "کلاینت VPN بعد از login crash میکند."
correct_label: Software
assert:
- type: equals
value: SoftwareAVALAI_API_KEY=... promptfoo eval -c evals/support-ticket-classifier.yamlاین config همان dataset را روی هر دو provider اجرا میکند. فقط وقتی candidate را ارتقا دهید که pass rate، latency و cost قابل قبول باشند و هیچ ردیف پرریسکی regression نداشته باشد. برای suiteهای بزرگتر، خروجی JSON/HTML پرامپتفو را بهعنوان artifact در CI ذخیره کنید و labelهای provider (production در برابر candidate) را بین releaseها مقایسه کنید.
پیادهسازی Chat Completions
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["AVALAI_API_KEY"],
base_url="https://api.avalai.ir/v1",
)
def classify_ticket(ticket: str) -> str:
response = client.chat.completions.create(
model=os.getenv("AVALAI_EVAL_MODEL", "gpt-5.5"),
messages=[
{
"role": "system",
"content": (
"Classify the support ticket as Hardware, Software, or Other. "
"Return only the label."
),
},
{"role": "user", "content": ticket},
],
temperature=0,
)
return response.choices[0].message.content.strip()نسخه معادل Responses API
وقتی مدل انتخابی از /v1/responses پشتیبانی میکند، از این نسخه استفاده کنید. messages به input منتقل میشود، دستورالعملها در instructions قرار میگیرند و متن نهایی از response.output_text خوانده میشود.
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["AVALAI_API_KEY"],
base_url="https://api.avalai.ir/v1",
)
def classify_ticket(ticket: str) -> str:
response = client.responses.create(
model=os.getenv("AVALAI_EVAL_MODEL", "gpt-5.5"),
instructions=(
"Classify the support ticket as Hardware, Software, or Other. "
"Return only the label."
),
input=ticket,
temperature=0,
)
return response.output_text.strip()messages→input- دستورهای system/developer →
instructions choices[0].message.content→response.output_text- dataset و assertionها را ثابت نگه دارید تا نتایج Chat و Responses قابل مقایسه باشند.
چه چیزی را Eval کنیم؟
به جای یک امتیاز عمومی، تستها را متناسب با architecture طراحی کنید:
| معماری | تمرکز eval | پرسش نمونه |
|---|---|---|
| prompt تکنوبتی | instruction following، classification، formatting | آیا خروجی فقط شامل label مجاز است؟ |
| workflowهای RAG | context recall، دقت citation، نرخ hallucination | آیا پاسخ از context بازیابیشده استفاده کرده و claim بدون پشتوانه ندارد؟ |
| workflowهای ابزار | tool selection، استخراج argument، مدیریت خطا | آیا مدل function درست را با argumentهای JSON درست فراخوانی کرده است؟ |
| Agentها | دقت handoff، شرط توقف، safety کاربر | آیا agent به متخصص درست route کرده و وارد loop نشده است؟ |
| اپهای چندوجهی | پوشش modality، دقت OCR/vision، رفتار refusal | آیا reasoning تصویری جزئیات مهم را حفظ کرده است؟ |
برای workflowهای چندمرحلهای، پیش از تکیه بر امتیاز end-to-end، هر مرز را جداگانه eval کنید. مثلا یک workflow پشتیبانی ممکن است یک eval برای intent classification، یک eval برای استخراج order ID، یک eval برای درستی argument ابزار و یک eval برای پاسخ نهایی روبهمشتری نیاز داشته باشد. این روش debug شکستها را از یک امتیاز کلی «کیفیت» سادهتر میکند.
پوشش Edge Caseها
ردیفهایی اضافه کنید که شکستهای واقعی کاربر و ابزار را نشان دهند:
- ورودیهای چندزبانه، mixed-language، پر از typo و بسیار کوتاه؛
- JSON، XML، Markdown، CSV یا logهای copy-paste شده و خراب؛
- درخواستهای متعارض کاربر که میخواهند دستورهای developer را override کنند؛
- مکالمههای طولانی که fact مهم در میانه یا ابتدای context قرار دارد؛
- خروجی ابزار با نام فیلد مبهم، نتیجه خالی، داده stale یا خطای قابل بازیابی؛
- فراخوانی ابزار تکراری، استخراج argument اشتباه، handoff چرخشی و مسیرهای refusal.
وقتی incident در production رخ میدهد، قبل از تغییر prompt، model، schema ابزار یا منطق retrieval، همان case شکستخورده را به dataset eval اضافه کنید.
LLM-as-Judge
برای خروجیهای subjective، فقط بعد از تعریف rubric و calibration با labelهای انسانی از judge model استفاده کنید.
- Pairwise comparison یا pass/fail را به امتیاز مبهم ۱ تا ۱۰ ترجیح دهید.
- برای کاهش verbosity bias، طول پاسخها را مشابه نگه دارید.
- در تستهای pairwise ترتیب پاسخها را جابهجا کنید تا position bias کمتر شود.
- قبل از اعتماد به judge در CI، میزان توافق آن را با reviewerهای انسانی اعتبارسنجی کنید.
- برای داوری اولیه از مدل قوی مثل
gpt-5.5استفاده کنید، سپس اگر rubric پایدار شد مدلهای ارزانتر را بسنجید.
انتخاب Grader مناسب
راهنمای grader در OpenAI حتی بدون /v1/evals میزبانیشده هم برای evalهای محلی AvalAI کاربرد دارد. کوچکترین graderی را انتخاب کنید که رفتار مورد نظر را ثابت کند:
- برای label، شناسه، enum و عبارتهای الزامی از string check استفاده کنید.
- برای خروجی ساختاریافته، قبل از امتیازدهی معنایی، JSON schema را بررسی کنید.
- وقتی تفاوتهای جزئی در wording قابل قبول است، از semantic similarity استفاده کنید.
- فقط برای کیفیت مبتنی بر rubric، safety، helpfulness یا partial credit از LLM judge استفاده کنید.
- در workflowهای ابزار، هم نام ابزار انتخابشده و هم argumentهای JSON را grade کنید؛ برای argumentهایی مثل آدرس، تاریخ یا واحدهای normalizeشده که چند شکل معادل دارند، grading معنایی مناسبتر است.
برای الگوی پیادهسازی محلی، Graderهای محلی برای Evalهای AvalAI را ببینید.
Evaluatorها را آگاهانه ترکیب کنید
راهنمای evaluation در OpenAI بین checkهای metric-based، review انسانی و model graderها تفاوت میگذارد، چون هرکدام failure mode متفاوتی را پیدا میکنند. در CI مربوط به AvalAI آنها را بر اساس ریسک ترکیب کنید:
| لایه eval | مناسب برای | gate انتشار |
|---|---|---|
| checkهای قطعی | labelها، اعتبار JSON، citationهای الزامی، نام ابزار، شکل argument | باید روی هر PR پاس شود |
| score معنایی یا retrieval | شباهت پاسخ، context recall، context precision، grounding citation | threshold همراه با نمونهبرداری برای review انسانی |
| LLM judge | helpfulness، nuance سیاست، partial credit، کیفیت مقایسهای | پیش از block کردن CI با label انسانی calibrate شود |
| review انسانی | دامنههای high-impact، rubric تازه، اختلاف grader، incident production | برای launchهای پرریسک الزامی است |
خروجی evaluatorها را در artifact اجرا جدا نگه دارید. یک امتیاز ترکیبی برای dashboard مفید است، اما ستونهای جدا سریع نشان میدهند regression از retrieval، انتخاب ابزار، formatting، safety یا کیفیت پاسخ نهایی آمده است.
ارزیابی Agent بر اساس Trajectory
در workflowهای agentic فقط پاسخ نهایی را grade نکنید. کل trajectory را ثبت کنید تا regressionها قابل مشاهده باشند. برای الگوی کامل trace و CI، ارزیابی گردشکارهای عاملمحور را ببینید:
- Plan: آیا agent هدف، محدودیتها و شرط توقف درست را تشخیص داده است؟
- ترتیب ابزارها: آیا ابزارهای درست را با ترتیب درست و argumentهای امن فراخوانی کرده است؟
- مدیریت state: آیا
previous_response_id، context بازیابیشده، خروجی ابزارها و محدودیتهای کاربر را بین turnها حفظ کرده است؟ - Recovery: آیا خطای ابزار، نتیجه retrieval خالی، refusal و timeout را بدون loop مدیریت کرده است؟
- پاسخ نهایی: آیا نتیجه را توضیح داده، در صورت نیاز evidence آورده و از claim بدون پشتوانه پرهیز کرده است؟
آیتمهای خروجی تایپشده Responses، argumentهای tool call، خروجی ابزارها، request IDها و دلیل pass/fail را log کنید. قبل از تغییر prompt، شکستهای production را به dataset اضافه کنید تا eval همان bug اصلی را بگیرد.
چکلیست CI و Release
- smoke evalهای سریع را روی هر pull request اجرا کنید.
- suite کامل را قبل از تغییر model ID، prompt، ابزار یا منطق retrieval اجرا کنید.
- model، endpoint، نسخه prompt، request ID، latency، input/output tokens، cached tokens و دلیل pass/fail را ثبت کنید.
- قبل از اصلاح prompt، شکستهای جدید production را به dataset اضافه کنید.
- برای تصمیمهای safety، compliance یا مالی، releaseهای پرریسک را به review انسانی وابسته کنید.
وقتی Hosted Evals فعال شد
وقتی AvalAI اندپوینتهای hosted eval را منتشر کرد، suite محلی/CI را همچنان منبع حقیقت نگه دارید و از hosted evals برای اجرای متمرکز، history و reporting استفاده کنید. hosted eval باید مکمل datasetهای version-controlled و checkهای CI باشد، نه جایگزین آنها. هنگام launch، schema واقعی AvalAI را بررسی کنید و parity با هر شکل API مربوط به hosted eval در OpenAI را فرض نکنید.