SSD Nodes Learn 🎉 VPS $4.99/মাস থেকে
নির্দেশিকা Matt Connorদ্বারা Matt Connor · আপডেট করা হয়েছে 2026-08-07

AI agent-এর self-hosted eval কীভাবে তৈরি করবেন

নিজের repository-তেই eval loop তৈরি করুন: বাস্তব trace থেকে golden case, আগে সস্তা deterministic check, পরে LLM judge, এবং প্রতিটি commit-এ pass rate ট্র্যাক করুন।

AI agent-এর self-hosted eval কী

AI agent-এর self-hosted eval হলো আপনার নিজের repository-তে রাখা চারটি জিনিস: সংরক্ষিত case-গুলোর একটি file, সেগুলোর ওপর agent চালানোর একটি script, প্রতিটি উত্তর মূল্যায়নের জন্য কিছু check, এবং query করা যায় এমন ফলাফলের একটি table। এই তালিকার কোনো কিছুর জন্য vendor প্রয়োজন নেই। পুরো loop কয়েকশো লাইনের Python এবং একটি SQLite file দিয়েই তৈরি করা যায়।

Demo-তে agent কাজ করেছিল, কারণ পাঁচটি input আপনি নিজেই বেছে নিয়েছিলেন। দ্বিতীয় সপ্তাহে এটি ব্যর্থ হলো, কারণ prompt-এর একটি line পরিবর্তিত হয়েছিল, অথবা model পরিবর্তিত হয়েছিল, অথবা tool-এর description বদলেছিল, অথচ এর কোনো কিছুই কোনো measurement-এ ধরা পড়েনি। Eval loop "এখন মনে হচ্ছে খারাপ" কথাটিকে "commit 4f1c9ab-এ 60টির মধ্যে pass rate 58 থেকে 51-এ নেমেছে"-এ রূপান্তর করে।

এই loop-এ চারটি ধাপ আছে, এবং এই guide-এ প্রতিটি ধাপের জন্য একটি করে section রয়েছে: বাস্তব trace সংগ্রহ করা, গুরুত্বপূর্ণ trace-গুলোকে case-এ রূপান্তর করা, প্রতিটি পরিবর্তনে প্রতিটি case-এর মূল্যায়ন করা, এবং যে commit ফলাফল তৈরি করেছে তার পাশে pass rate সংরক্ষণ করা। আপনি agent যেভাবেই চালান না কেন, একই loop কাজ করে। চালানোর উপযোগী self-hosted agent framework-গুলোর পার্থক্য মূলত trace-এর কতটা অংশ তারা বিনা খরচে আপনাকে দেয়, তাতে।

দ্বিতীয় সপ্তাহে agent কেন ব্যর্থ হয়

একটি agent হলো একটি prompt, একটি model, কিছু tool definition এবং run time-এ retrieved হওয়া context। আপনার application code পরিবর্তন না করেও এই চারটির যেকোনোটি পরিবর্তিত হতে পারে। তাই সাধারণ code review-তে আপত্তি করার মতো কিছু দেখা যায় না।

সবচেয়ে সাধারণ কারণ হলো prompt edit। অভদ্র উত্তর বন্ধ করতে আপনি একটি বাক্য যোগ করেন। সেই বাক্য এমন input-এর আচরণও পরিবর্তন করে, যেগুলো কেউ পুনরায় পরীক্ষা করেনি। Trace-এ বিষয়টি স্পষ্ট দেখা যায়: একই প্রশ্নের জন্য গত সপ্তাহের trace-এ একটি create_refund tool call ছিল, কিন্তু এই সপ্তাহের trace-এ তা নেই এবং তার বদলে উত্তরটি ভদ্রভাবে ক্ষমা চায়। কোনো error তৈরি হয়নি, তাই কোনো alert-ও চালু হয়নি।

দ্বিতীয় কারণ হলো model। প্রতিটি run-এর সঙ্গে পাঠানো exact model string সংরক্ষণ করুন, claude-haiku-4-5-20251001; আপনার মনে রাখা shorthand সংরক্ষণ করবেন না। কারণ model পরিবর্তনের দিন pass rate কমে গেলে, row-তে model-এর নাম থাকলেই কেবল বিষয়টি নির্ণয় করা যায়।

তৃতীয় কারণ হলো tools। কোনো tool-এর description নতুনভাবে লিখলে model কখন সেটি call করবে, তা পরিবর্তিত হয়। আপনার tools যদি VPS-এ চলা MCP server থেকে আসে, তাহলে schema অন্য একটি process-এ থাকে। ফলে আপনার repository-তে কোনো diff না থাকলেও সেটি পরিবর্তিত হতে পারে। চতুর্থ কারণ হলো retrieval: একই প্রশ্ন এমন একটি index-এ যায়, যা রাতের মধ্যে rebuild করা হয়েছে, এবং উত্তরটি নতুন document অনুসরণ করে।

আগে থেকেই সংগ্রহ করা trace থেকে golden set তৈরি করুন

Eval case নিজে থেকে বানাবেন না। এগুলো traffic থেকেই নিন। আপনি যদি ইতিমধ্যে আপনার agent-এর জন্য self-hosted Langfuse tracing চালান, তাহলে প্রতিটি request তার input, tool call এবং output-সহ সংরক্ষিত থাকে। একটি case তৈরির জন্য এটিই প্রয়োজনীয় raw material।

Public API ব্যবহার করে root observation-এর একটি সময়সীমা export করুন। এতে basic authentication ব্যবহৃত হয়। Username হিসেবে আপনার public key এবং password হিসেবে আপনার 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]'

কোনো parsing লেখার আগে একটি record পড়ুন। Row-গুলো data-এর অধীনে আসে। তবে question এবং reply ধারণকারী field-এর নাম আপনার agent কীভাবে তার span instrument করে তার ওপর নির্ভর করে। তাই প্রত্যাশিত নাম নয়, বাস্তবে যে field দেখছেন সেটি map করুন। এরপর evals/cases.jsonl-এ প্রতিটি লাইনে একটি করে JSON object লিখে case তৈরি করুন:

{"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."}

এই 5টি নিয়ম set-টিকে কার্যকর রাখে:

  • শুরু করার জন্য 40 থেকে 80টি case যথেষ্ট। 20টির কম হলে একটি flaky case pass rate-কে 5 point পরিবর্তন করতে পারে। কারণ ছাড়া ওঠানামা করা এমন সংখ্যাকে কেউ গুরুত্ব দেয় না।
  • যে production bug ঠিক করবেন, ঠিক সেদিনই সেটিকে একটি case-এ পরিণত করুন। এই অভ্যাস set-কে সঠিক দিকে বাড়ায়।
  • প্রতিটি case-এ একটি behaviour রাখুন। কোনো case-এ একসঙ্গে refund amount এবং tone পরীক্ষা করলে সেটি ব্যর্থ হওয়ার পর আসল সমস্যা বোঝা যায় না।
  • id কখনও পরিবর্তন করবেন না। এই id-র মাধ্যমেই আজকের run-এর সঙ্গে গত মাসের run তুলনা করা হয়।
  • commit করার আগে তথ্য redaction করুন। এই file git-এ যাবে। তাই customer name এবং আপনার মালিকানাধীন নয় এমন order number মুছে দিন।

প্রথমে deterministic check দিয়ে grade করুন, কারণ এগুলোর খরচ নেই

যে বিষয়ের সঠিক উত্তর নির্ধারণ করা যায়, সেটিতে সরাসরি assertion ব্যবহার করুন। কোনো model call দরকার নেই, খরচ নেই, এবং ambiguity নেই। Deterministic check-এ structural regression ধরা পড়ে। এই regression-গুলোই আপনার agent-এর চারপাশের system ভেঙে দেয়: JSON parse হয় না, tool কখনো call করা হয়নি, নিষিদ্ধ phrase আবার ফিরে আসে, অথবা উত্তরে কোনো source উদ্ধৃত করা হয় না।

শুধু একটি function আপনার agent সম্পর্কে জানে। Harness-এর অন্য সবকিছু generic।

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

ওই তালিকায় tool budget রাখুন। কোনো agent আজ 3টি call-এ একটি case সমাধান করে এবং আগামীকাল 11টি call নেয়, তাহলে final answer সঠিক হলেও এটি regression। কারণ agent যতবার call করে, প্রতিবার তার জন্য আপনাকে খরচ দিতে হয়।

LLM-কে বিচারক হিসেবে ব্যবহার এবং যে চারভাবে এটি ভুল করে

Assertions পার হওয়া প্রতিটি উত্তরের জন্য এমন একজন grader দরকার, যে উত্তরটি পড়ে বিচার করতে পারে। LLM judge হলো একটি দ্বিতীয় model call: এটি প্রশ্ন, agent-এর উত্তর এবং একটি criterion পায়, তারপর একটি verdict দেয়। “উত্তরটি কি ব্যবহারকারীর প্রশ্নের উত্তর দিয়েছে?”—এটি যাচাই করার একমাত্র বাস্তবসম্মত উপায় হলো এই পদ্ধতি।

একটি judge ব্যবহারযোগ্য করতে চারটি নিয়ম মানুন:

  • Binary verdict দিন, কখনো 1 থেকে 10-এর score নয়। একটি scale প্রায় সব কিছুর জন্য 7 বা 8 ফেরত দেয়। ফলে সংখ্যাটি প্রায় বদলায় না এবং আপনি কিছু শিখতে পারেন না।
  • প্রতি call-এ একটি criterion রাখুন। একবারে refund amount বা tone—যেকোনো একটি সম্পর্কে জিজ্ঞেস করুন; দুটো একসঙ্গে নয়।
  • Case-এ expected answer থাকলে judge-কে সেটি দিন। Reference-এর সঙ্গে মিলিয়ে grading করা abstract grading-এর চেয়ে অনেক সহজ।
  • Output shape নির্দিষ্ট করে দিন এবং কঠোরভাবে 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)

এখন failure mode-গুলো দেখা যাক। প্রতিটির জন্য আপনি আজই একটি test চালাতে পারেন। এগুলো চালানো গুরুত্বপূর্ণ, কারণ unchecked judge এমন সংখ্যা তৈরি করে যা নির্ভুল বলে মনে হয়, কিন্তু বাস্তবে কোনো অর্থ বহন করে না।

Length bias। উত্তর যত দীর্ঘ হয়, pass হওয়ার সম্ভাবনাও তত বাড়ে। এটি পরীক্ষা করতে judge যে দশটি উত্তরকে fail করেছে, সেগুলো নিন। প্রতিটিতে এমন confident filler-এর দুটি paragraph যোগ করুন, যা নতুন কোনো তথ্য দেয় না। এরপর আবার judge করুন। কোনো verdict pass-এ বদলে গেলে সেটি length bias-এর লক্ষণ, এবং যে বিষয়টি ঠিক করতে হবে তা হলো rubric।

Self-preference। একটি judge প্রায়ই নিজের model family-এর output-কে অন্য model family-এর output-এর চেয়ে বেশি অনুকূলভাবে grade করে। একই 30টি উত্তর দুটি ভিন্ন family-এর judge দিয়ে grade করুন এবং case অনুযায়ী verdict তুলনা করুন। যেখানে মতভেদ হবে, সেই case নিজে পড়ে বিচার করুন।

Position bias। দুটি উত্তর, A এবং B, তুলনা করতে judge ব্যবহার করলে তাদের ক্রম বদলে আবার চালান। ক্রম বদলানোর পর verdict বদলে গেলে বুঝবেন, ওই rubric-এর জন্য pairwise comparison এখনো নিরাপদ নয়।

Rubric drift। অস্পষ্ট criterion agreeable judge তৈরি করে। “উত্তরটি কি helpful?”—এমন criterion প্রায় সবকিছুকেই pass করায়। “উত্তরটি কি dollars-এ refund amount উল্লেখ করেছে?”—এটি শুধু আপনার যাচাই করতে চাওয়া বিষয়টিকেই pass করায়। প্রতিটি criterion এমনভাবে rewrite করুন, যাতে কোন fact যাচাই করা হচ্ছে তা স্পষ্টভাবে উল্লেখ থাকে।

চারটি সমস্যাই সামলানোর জন্য একটি guard ব্যবহার করুন। হাতে label করা 30টি case সংরক্ষণ করুন। Judge model বা judge prompt পরিবর্তন করলেই আপনার label-এর সঙ্গে judge-এর score তুলনা করুন। প্রতি দশটি case-এ একটির বেশি ক্ষেত্রে judge আপনার সঙ্গে একমত না হলে, তার pass rate বিশ্বাস করার আগে rubric ঠিক করুন। Judge হলো code; তাই code-এর মতোই এটিকে version করা এবং review করা উচিত।

সস্তা মডেল দিয়ে মূল্যায়ন করুন, প্রয়োজনে frontier model-এ উন্নীত করুন

প্রতিটি commit-এ প্রতিটি case সবচেয়ে ব্যয়বহুল model দিয়ে মূল্যায়ন করলে eval-এর খরচ যে agent-কে পরীক্ষা করা হচ্ছে তার খরচকেও ছাড়িয়ে যায়। Grader-গুলোকে খরচ অনুযায়ী সাজান এবং উত্তর স্পষ্ট হলেই থেমে যান।

ChartCost to judge 1,000 eval cases, list prices, August 2026
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"
  }
]

এই হিসাবের জন্য প্রতি judge call-এ প্রায় 1,200 input token এবং 120 output token ধরা হয়েছে। একটি question, একটি answer এবং একটি criterion-এর জন্য এটি বাস্তবসম্মত আকার। 1,000 case মূল্যায়নের খরচ Claude Haiku 4.5-এ 1.80 US dollar এবং Claude Opus 5-এ 9.00। পার্থক্যটি প্রথমে সামান্য মনে হয়। কিন্তু সংখ্যাটি বাড়তে থাকলে খরচ দ্রুত বাড়ে। প্রতি commit-এ মূল্যায়ন করা 60 case-এর একটি set, সপ্তাহে 40টি commit হলে, nightly job চালানোর আগেই সপ্তাহে 2,400টি judge call তৈরি করে।

Eval-এর ক্ষেত্রে দুটি discount সরাসরি প্রয়োগ করা যায় এবং এগুলো একসঙ্গে ব্যবহার করা যায়। Eval run interactive নয়। তাই asynchronous delivery-এর বিনিময়ে Batch API input এবং output—উভয় price অর্ধেক করে। Chart-এর প্রথম row-তে এটিই দেখানো হয়েছে। প্রতিটি call-এ rubric এবং instruction byte-for-byte একই থাকে। তাই prompt caching উপযোগী: cache read-এর খরচ base input price-এর এক-দশমাংশ, আর পাঁচ মিনিটের cache write-এর খরচ base input-এর 1.25 গুণ। ফলে একটি hit-এর পরই cache-এর খরচ উঠে আসে। এগুলো August 2026 পর্যন্ত Anthropic-এর list price। Sonnet 5-এর introductory pricing 31 August 2026 পর্যন্ত চালু আছে। তাই ওই তারিখের পরে তৃতীয় bar-এর উচ্চতা বাড়বে।

ধাপগুলো ক্রমানুসারে:

  • প্রতিটি case-এ deterministic check চালান। কোনো API cost নেই।
  • ওই check পেরিয়ে যাওয়া case-গুলোতে small model judge ব্যবহার করুন।
  • small judge fail বললে, অথবা low confidence সহ pass বললে, কেবল তখনই frontier judge ব্যবহার করুন।
  • সপ্তাহে একবার অল্প কিছু sample-এ human review করুন।
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"]

এই পদ্ধতিতে grading accuracy কিছুটা কমে এবং খরচ কমে। তাই অনুমান না করে এই বিনিময়টি মাপুন। মাসে একবার strict judge দিয়ে পুরো set-ও grade করুন এবং দুটি column তুলনা করুন। কয়েকটির বেশি case-এ ফল আলাদা হলে বুঝবেন small model-এর জন্য rubric যথেষ্ট নির্দিষ্ট নয়। তখন rubric-ই সংশোধন করুন। Agent নিজে কত খরচ করবে তা নিয়ন্ত্রণ করা আলাদা কাজ। এটি VPS-এ একটি AI agent-এর cost control-এ আলোচনা করা হয়েছে।

নিজের মালিকানাধীন সিস্টেমে সময়ের সঙ্গে pass rate ট্র্যাক করুন

যে pass rate-কে কোনো commit-এর সঙ্গে যুক্ত করা যায় না, সেটি শুধু একটি ধারণা। প্রতিটি run-এ প্রতিটি case-এর জন্য একটি row সংরক্ষণ করুন। সেই row-এর মধ্যে commit এবং model রাখুন।

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;

sqlite3 evals/results.db < evals/schema.sql দিয়ে schema লোড করুন। এরপর sqlite3 -box evals/results.db < evals/passrate.sql দিয়ে trend পড়ুন। 60টি case-এ এক বছর ধরে প্রতিদিন run করলে প্রায় 22,000টি row হবে। তাই store নিজেই আলাদা project হয়ে উঠবে না। VPS-এ production-এ SQLite চালানো-এ সেই settings ব্যাখ্যা করা হয়েছে, যেগুলো এই file একাধিক machine-এর মধ্যে share করা হলে গুরুত্বপূর্ণ হয়ে ওঠে।

Runner একজন ব্যক্তির জন্যও একই তথ্য print করে:

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 ভেঙে যেতে পারে, সেসব পরিবর্তনের ওপর suite চালান। এর মধ্যে prompt edit, model change এবং tool change অন্তর্ভুক্ত। repository-এর প্রতিটি commit-এ suite চালানোর দরকার নেই। দ্রুত subset-এর জন্য একটি pre-push hook যথেষ্ট:

cat > .git/hooks/pre-push <<'EOF'
#!/bin/sh
python3 evals/run.py --set smoke || exit 1
EOF
chmod +x .git/hooks/pre-push

Full run ধীর। এগুলো schedule অনুযায়ী চালান। VPS-এ একটি nightly systemd service এবং timer deployed prompt-এর বিপরীতে পুরো set চালায়। এর মাধ্যমে repository-এর বাইরের পরিবর্তনও ধরা পড়ে, যেমন কোনো hosted tool-এর behaviour পরিবর্তিত হওয়া।

মানব পর্যালোচনা, সম্পূর্ণ নয়; নমুনাভিত্তিক

judge-কে মানব-প্রদত্ত label-এর সঙ্গে calibrate করা হয়, তাই কাউকে সেই label তৈরি করতে হবে। প্রতি সপ্তাহে একটি নমুনা পড়ুন: judge যেসব case-এ ব্যর্থ হয়েছে, সেগুলো সব; এর সঙ্গে এলোমেলোভাবে বেছে নেওয়া দশটি pass। এলোমেলোভাবে বেছে নেওয়া pass-গুলোই গুরুত্বপূর্ণ অংশ, কারণ judge যদি নীরবে খারাপ answer pass করা শুরু করে, তাহলে নিজের verdict দিয়ে তৈরি যেকোনো dashboard-এ সেটিকে নিখুঁত দেখাবে।

প্রতি case 3 মিনিট ধরে 15টি case পর্যালোচনা করতে সপ্তাহে 45 মিনিট লাগে। এর বিনিময়ে আপনি rubric-এ এমন correction পান, যেখানে আপনার এবং judge-এর মতভেদ রয়েছে। এমন failure type-এর জন্যও নতুন case পাওয়া যায়, যেগুলো কেউ আগে ভাবেনি। একই table-এ human verdict লিখুন এবং graded_by-এর মান human সেট করুন। তাহলে judge ও human-এর agreement স্মৃতির বিষয় না থেকে একটি query-তে পরিণত হবে।

eval harness নিজেই কীভাবে ব্যর্থ হয়

প্রথম পূর্ণ run-এ anthropic.RateLimitError একসঙ্গে 60টি case পাঠালে আপনার tier-এর request বা token limit অতিক্রম করে। concurrency সর্বোচ্চ 4টি worker-এ সীমাবদ্ধ রাখুন এবং nightly run-টি Batch API-তে স্থানান্তর করুন।

judge থেকে json.JSONDecodeError: Expecting value: line 1 column 1 (char 0) model prose-এ উত্তর দিয়েছে, অথবা তার JSON-কে code fence-এর মধ্যে রেখেছে। একবার retry করুন, তারপর case-টিকে error হিসেবে record করুন। কোনো parse failure-কে কখনো pass হিসেবে গণনা করবেন না। কারণ যে suite error-কে pass-এ রূপান্তর করে, সেটির pass rate 100%-এর দিকে বাড়তে থাকে, কিন্তু agent-এর মান খারাপ হয়।

Flaky case। agent তার output sample করার কারণে একই input এক run-এ pass করে এবং পরের run-এ fail করে। Flaky case তিনবার run করুন এবং case মুছে না দিয়ে fraction record করুন। কোনো case তিনটির মধ্যে দুইটি run-এ pass করলে সেটি প্রকৃত robustness bug, এবং customer সেটি খুঁজে পাবে।

Golden set-এর অবক্ষয়। suite-কে green দেখানোর জন্য কেউ expected answer সম্পাদনা করতে পারে। agent-এর diff-এর মতোই evals/cases.jsonl-এর diff-ও সতর্কতার সঙ্গে review করুন, কারণ ওই file-ই correct-এর লিখিত সংজ্ঞা।

এমন suite যা কখনো fail করে না। এক মাস ধরে pass rate 100%-এ স্থির থাকলে বোঝা যায়, set-টি product-এর আচরণ আর অনুসরণ করছে না। সাম্প্রতিক 10টি trace নিন, agent যেগুলো খারাপভাবে handle করেছে সেগুলো খুঁজে বের করুন এবং সেগুলো যোগ করুন।

FAQ

একটি AI agent eval set-এ কতগুলো case দরকার?

40 থেকে 80 দিয়ে শুরু করুন এবং বাস্তব ব্যর্থতা থেকে set-এর আকার বাড়ান। প্রায় 20টির কম case থাকলে একটি অস্থির ফল pass rate-কে 5 point পরিবর্তন করে, ফলে সংখ্যাটি আর কার্যকর তথ্য দেয় না। কয়েকশ case পেরিয়ে গেলে প্রতিটি run-এ প্রকৃত অর্থ ও সময় খরচ হয়, অথচ অতিরিক্ত case খুব কম coverage যোগ করে। গুরুত্বপূর্ণ মাপটি case-এর সংখ্যা নয়; আপনার পরিচিত production failure type-গুলোর কত অংশ set-এ অন্তত একবার আছে, সেটিই গুরুত্বপূর্ণ।

আমার agent-এর মূল্যায়নের জন্য কি LLM judge-কে বিশ্বাস করা যায়?

নিজস্ব label-এর সঙ্গে পরিমাপ করার পরেই কেবল বিশ্বাস করুন। হাতে grade করা 30টি case সংরক্ষণ করুন। Judge model বা judge prompt পরিবর্তন করলে প্রতিবার এই case-গুলোর বিপরীতে judge-এর score নির্ণয় করুন। Judge-দের length bias থাকে; অর্থাৎ অপ্রয়োজনীয়ভাবে দীর্ঘ answer বেশি pass করে। তাদের self-preference-ও থাকে; অর্থাৎ নিজেদের model family-এর output বেশি সদয়ভাবে grade করা হয়। দুটিই পরীক্ষা করা যায়: ব্যর্থ answer-এ অতিরিক্ত text যোগ করে আবার judge করুন, অথবা অন্য model family-এর judge দিয়ে একই answer grade করান। Judge যদি আপনার label-এর সঙ্গে প্রতি 10টি case-এ 1টির বেশি ক্ষেত্রে একমত না হয়, তবে rubric এত অস্পষ্ট যে এটি ব্যবহার করা যাবে না।

Eval grade করার জন্য কোন model ব্যবহার করা উচিত?

কম খরচের model দিয়ে grade করুন এবং প্রয়োজনে উন্নত model-এ পাঠান। Deterministic assertion-এর কোনো খরচ নেই, তাই প্রতিটি case-এ এগুলো প্রথমে চালান। স্পষ্ট pass-এর ক্ষেত্রে একটি ছোট model যথেষ্ট। শুধু fail এবং low-confidence verdict-গুলো frontier model-এ পাঠান। August 2026-এর list price অনুযায়ী, Claude Haiku 4.5 দিয়ে 1,000টি case judge করতে প্রায় 1.80 US dollar এবং Claude Opus 5 দিয়ে প্রায় 9.00 খরচ হয়। Eval run asynchronous হওয়ায় Batch API ব্যবহার করলে উভয় খরচই অর্ধেক হয়।

Eval কি production monitoring-এর বিকল্প?

না, কারণ এগুলো ভিন্ন প্রশ্নের উত্তর দেয়। Eval suite জানায়, আপনি যে পরিবর্তনটি শিগগির release করতে যাচ্ছেন সেটি একটি নির্দিষ্ট case set-এ ফল ভালো করেছে নাকি খারাপ করেছে। Tracing এবং monitoring জানায়, বাস্তব user-রা বর্তমানে কী ব্যবহার করছে; এর মধ্যে এমন input-ও থাকে যা কোনো case-এ নেই। এগুলো পরস্পরকে তথ্য দেয়: trace থেকে নতুন case তৈরি হয়, আর eval suite নির্ধারণ করে আপনার fix সত্যিই কাজ করেছে কি না।