ارزیابی گردشکارهای عاملمحور
ارزیابی Agent باید کل گردشکار را بسنجد، نه فقط پاسخ نهایی را. وقتی مدل ابزار فراخوانی میکند، state چندنوبتی نگه میدارد، guardrail اعمال میکند، context بازیابی میکند یا کار را به متخصص دیگری میسپارد، از این نوع eval استفاده کنید. این راهنما توصیههای OpenAI برای ارزیابی agent را با APIهای سازگار با OpenAI در AvalAI تطبیق میدهد.
هشدار
AvalAI در حال حاضر trace grading میزبانیشده یا endpointهای /v1/evals ارائه نمیکند. مفهومهای trace، dataset، grader و eval run در OpenAI را مرجع طراحی بدانید. برای production امروز، output itemهای تایپشده /v1/responses را log کنید و evalهای محلی یا CI را با فراخوانی عادی API AvalAI اجرا کنید.
چه چیزهایی را ثبت کنیم
برای هر اجرای agent، شواهد کافی برای بازپخش و grade کردن trajectory ذخیره کنید:
- Context ورودی: درخواست کاربر، strategy وضعیت مکالمه، snippetهای بازیابیشده و model ID.
- Plan: هدف، محدودیتها، معیار موفقیت و شرط توقفی که agent تشخیص داده است.
- Tool callها: نام ابزار، argumentهای JSON، side effectها، خطاها، retryها و خروجی ابزار.
- Guardrail و handoff: تصمیمهای moderation، شکستهای schema validation، actionهای مسدودشده، مبدأ/مقصد handoff به متخصص و دلیل هر handoff.
- State: مقدار
previous_response_id، شناسه conversation، فایلهای انتخابشده، citationها، مقصد handoff و فیلدهای برگشتی آیتمهای assistant مثلphaseوقتی کلاینت شما output itemهای Responses را دستی replay میکند. - پاسخ نهایی: خروجی قابلنمایش به کاربر، evidence ذکرشده، متن refusal و request ID.
فقط response.output_text را grade نکنید. بیشتر شکستهای agent زودتر رخ میدهند: انتخاب ابزار اشتباه، argument ناامن، نبود فیلتر retrieval، loop شدن یا از دست دادن state بین turnها.
سطحهای ارزیابی
| سطح | کاربرد | مسیر امروز در AvalAI |
|---|---|---|
| مرور trace | Debug یک failure یا رفتار غیرمنتظره | output itemهای Responses، ورودی/خروجی ابزار، request ID و زمانبندی را log کنید. |
| Trace grading | امتیازدهی trajectory کامل در مقیاس | traceها را به JSONL تبدیل کنید و با Promptfoo، pytest یا runner سفارشی grade کنید. |
| Eval مبتنی بر dataset | مقایسه prompt، ابزار، مدل یا تغییر routing | caseهای eval را version-controlled نگه دارید و در CI اجرا کنید. |
| مانیتورینگ production | کشف drift بعد از deploy | نمونهای از runهای واقعی را با حذف داده حساس بررسی کنید و شکستها را به dataset برگردانید. |
OpenAI پیشنهاد میکند وقتی رفتار هنوز در حال تغییر است با traceها شروع کنید، و وقتی رفتار خوب روشن شد به dataset و evalهای تکرارپذیر بروید. در AvalAI همین روند را با logهای برنامه و runnerهای محلی اجرا کنید.
پرسشهای Triage برای Trace
هنگام review کردن trace، قبل از تغییر prompt یا model به این پرسشها پاسخ دهید:
- آیا agent ابزار درست را انتخاب کرده، از ابزارهای ممنوع دوری کرده و بعد از evidence کافی متوقف شده است؟
- آیا handoff زمانی که باید رخ داده، و agent مبدأ context درست را منتقل کرده است؟
- آیا workflow دستور developer، policy ایمنی، rule مربوط به schema یا محدودیت کاربر را نقض کرده است؟
- آیا context بازیابیشده، file IDها یا خروجی ابزار واقعا پاسخ نهایی را پشتیبانی میکنند؟
- آیا retry، نتیجه خالی یا timeout مسیر recovery امن ایجاد کرده یا باعث loop شده است؟
- آیا پاسخ نهایی جزئیات داخلی ابزار را لو داده، citation الزامی را حذف کرده یا بیش از حد مطمئن حرف زده است؟
هر پاسخ تکرارشونده از نوع «بله، اینجا شکست داریم» را ابتدا به یک grader deterministic تبدیل کنید. فقط وقتی failure به ظرافت tone، کیفیت reasoning یا partial credit وابسته است از LLM judge استفاده کنید.
workflow محلی برای Trace Grading
وقتی هنوز رفتار agent را debug میکنید و dataset پایدار ندارید، از این loop استفاده کنید:
- Traceهای نماینده انتخاب کنید: برای هر مسیر ابزار یا handoff، یک run موفق، یک failure و یک edge case بگذارید.
- قرارداد grader بنویسید: ابزارهای الزامی، ابزارهای ممنوع، قوانین argument امن، citationهای لازم و شرط توقف را فهرست کنید.
- اول چک deterministic اجرا کنید: JSON trace را parse کنید و در صورت نبود tool call لازم، argument نامعتبر، side effect ناامن یا پاسخ نهایی بدون citation سریع fail کنید.
- LLM grading را فقط برای judgment اضافه کنید: بعد از پاس شدن چکهای deterministic، از آن برای کیفیت recovery، دلیل handoff، tone یا reasoning با امتیاز جزئی استفاده کنید.
- به eval مبتنی بر dataset ارتقا دهید: وقتی rubric پایدار شد، caseهای trace را به JSONL نسخهدار تبدیل کنید و در CI برای هر تغییر prompt، ابزار، مدل یا routing اجرا کنید.
Rubric برای Trajectory عامل
قبل از افزودن LLM-as-judge، چکهای pass/fail صریح بنویسید:
- تشخیص هدف: آیا agent وظیفه و محدودیتها را درست فهمیده است؟
- انتخاب ابزار: آیا ابزار لازم را انتخاب کرده و از ابزارهای غیرضروری پرهیز کرده است؟
- ایمنی argument: آیا argumentهای ابزار کامل، معتبر و در محدوده side effect مجاز هستند؟
- مدیریت state: آیا state پاسخ قبلی، preference کاربر و context بازیابیشده را حفظ کرده است؟
- بازیابی از خطا: آیا نتیجه خالی، خطای ابزار، refusal و timeout را بدون loop مدیریت کرده است؟
- Grounding: آیا پاسخ نهایی evidence بازیابیشده را cite کرده یا گفته چه چیزی کم است؟
- شرط توقف: آیا در زمان درست متوقف شده و ابزار را بیش از حد فراخوانی نکرده است؟
برای workflowهای high-impact، علاوه بر grader خودکار، review انسانی هم لازم بگذارید.
تصمیمگیری درباره Handoff و پیچیدگی
راهنمای evaluation در OpenAI پیشنهاد میکند برای تصمیمگیری درباره پیچیدهتر کردن workflow عاملمحور از eval استفاده کنید. فقط چون معماری چند agent تمیزتر به نظر میرسد، workflow را به چند متخصص تقسیم نکنید. ابتدا با trace یا dataset ثابت کنید که یک loop ساده prompt/tool در یک مرز مشخص شکست میخورد.
agent جدید، handoff، مرحله retrieval یا guardrail را فقط وقتی اضافه کنید که eval نشان دهد کدام مرز به آن نیاز دارد:
- ازدحام ابزارها: agent بارها ابزار اشتباه را انتخاب میکند چون ابزارهای فعال زیاد هستند.
- تعارض policy: یک task نسبت به بقیه workflow دستورهای safety یا compliance سختگیرانهتری میخواهد.
- از دست رفتن context: یک متخصص context متمرکز میخواهد که نباید در همه turnها وارد شود.
- شکست recovery: loop فعلی نمیتواند نتیجه خالی، خطای ابزار یا تغییر موضوع کاربر را امن مدیریت کند.
بعد از افزودن handoff، caseهای eval صریح برای «handoff باید رخ دهد»، «handoff نباید رخ دهد» و «handoff باید کنترل را برگرداند» اضافه کنید. این کار routing چرخشی و agentهای متخصصی را که خارج از محدوده خود پاسخ میدهند آشکار میکند.
نمونه Trace قابل حمل با JSONL
caseهای trace را قابلحمل نگه دارید تا امروز محلی اجرا شوند و اگر AvalAI بعدا hosted eval اضافه کرد، قابل مهاجرت باشند.
{
"id": "refund-policy-tool-route",
"input": "Can I refund unused credits?",
"expected": {
"must_call_tool": "search_policy",
"must_not_call_tools": [
"issue_refund"
],
"final_answer_must_cite": [
"refund-policy.md#credits"
]
},
"trace": [
{
"type": "function_call",
"name": "search_policy",
"arguments": {
"query": "unused credits refund policy"
}
},
{
"type": "function_call_output",
"name": "search_policy",
"output": {
"source_id": "refund-policy.md#credits",
"text": "Unused credits are refundable within 14 days."
}
},
{
"type": "message",
"output_text": "Unused credits are refundable within 14 days [refund-policy.md#credits]."
}
]
}ابتدا با چکهای deterministic grade کنید: نام ابزار، side effect ممنوع، citation لازم و نبود claim بدون پشتوانه.
الگوی لاگگیری با Responses API
وقتی agent را با /v1/responses میسازید، stream تایپشده خروجی یا آرایه نهایی response.output را log کنید.
import json
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["AVALAI_API_KEY"],
base_url="https://api.avalai.ir/v1",
)
response = client.responses.create(
model="gpt-5.5",
instructions="Use tools only when needed. Cite source IDs in final answers.",
input="Can I refund unused credits?",
tools=[
{
"type": "function",
"name": "search_policy",
"description": "Search internal policy snippets.",
"parameters": {
"type": "object",
"properties": {"query": {"type": "string"}},
"required": ["query"],
"additionalProperties": False,
},
}
],
)
trace_items = [item.model_dump() for item in response.output]
print(json.dumps({"response_id": response.id, "trace": trace_items}, indent=2))اگر مدل function call برگرداند، آن را در برنامه اجرا کنید، یک function_call_output اضافه کنید و loop مربوط به Responses را ادامه دهید. همه گامهای loop را در trace نگه دارید تا eval بتواند route را grade کند، نه فقط answer را. اگر از previous_response_id استفاده نمیکنید و output itemهای برگشتی را خودتان replay میکنید، فیلدهای برگشتی آیتم assistant مثل phase را وقتی وجود دارند بدون تغییر حفظ کنید؛ حذف آنها میتواند در turnهای بعدی preamble ابزار یا update میانی را شبیه پاسخ نهایی جلوه دهد.
چکلیست CI
- برای هر incident در production، قبل از تغییر prompt یک eval case اضافه کنید.
- اگر pull request پرامپت، ابزار، retrieval یا routing را تغییر میدهد، smoke trajectory eval اجرا کنید.
- model IDهای candidate را با dataset و tool schema یکسان مقایسه کنید.
- latency، تعداد tool callها، retry count و token usage را کنار pass/fail ثبت کنید.
- secretها را در fixtureهای trace نگذارید؛ نمونههای redacted را در repo نگه دارید.