Головна / Статті

Оцінка агентів та навичок на практиці: траєкторії, оцінювачі, критерії проходження та інструменти

Як оцінювати агентів та навички: набори для запуску та виконання, порядок сили оцінювача, точність та відтворюваність, pass@k проти pass^k, невеликий інструментарій на Python та вибір засобів.

Видавець: REACTAPP.TOP11 хв читання2573 слів

Джерела: Evals: A Crash Course for Agents and Skills

Рано чи пізно кожна команда, яка розробляє агентів та навички, стикається з однією проблемою: демо-версія справляє враження, але справжній трафік виявляє недоліки, яких ніхто не помітив. Оцінювання замінює здогадки на точні показники. Далі наведено практичний посібник щодо того, що потрібно вимірювати, як створювати тести та критерії оцінювання, а також як запустити цикл вдосконалення, який справді покращить агента.

Ментальна модель

Оцінювання — це повторюваний експеримент. Надайте агенту вхідні дані та середовище, а потім спостерігайте за двома аспектами: траєкторією, тобто тим, що робив агент протягом процесу, та результатом, тобто кінцевим продуктом, який він створив.

Оцінюйте обидва аспекти:

  • Результат: чи відповідає готовий продукт поставленій задачі?
  • Траєкторія: чи обрав агент правильні навички та інструменти, уникає небезпечних дій та працює ефективно?

Відполірована кінцева відповідь може приховувати погану стратегію виконання завдання, а незграбна стратегія все одно може призвести до пристойного результату. Розглядаючи лише один аспект, ми бачимо лише половину картини.

Рівні оцінки

Жодне окреме число не може свідчити про те, що агент є хорошим. Розділіть завдання на рівні, кожен з яких має свою перевірку:

  • Вибір навички. Чи була обрана правильна навичка? Перевірте точність, повноту та випадкові спрацювання.
  • Дотримання інструкцій навички. Чи справді дотримувалися інструкцій навички, включаючи необхідні кроки та заборонені дії?
  • Використання інструментів. Чи правильно викликалися інструменти з належними аргументами, у правильному порядку та без зайвих викликів?
  • Результат виконання завдання. Чи є результат корисним? Тести, перевірки схем та поведінкові асертації допомагають відповісти на це питання.
  • Якість. Чи є результат стабільним та придатним? Це вирішує рубрика чи оцінювач.
  • Безпека. Чи дотримувалися обмежень щодо конфіденційної інформації, руйнівних операцій та введення команд?
  • Ефективність. Скільки коштував успіх у токенах, затримках, викликах та повторних спробах?
  • Для навички потрібні два набори оцінок

    Навичка — це більше, ніж просто набір інструкцій. Вона включає рішення про те, коли її активувати, та план дій після цього, тому їй потрібні два окремі набори оцінок.

    Оцінки запуску перевіряють, чи навичка активується для правильних команд. У кожному випадку команда поєднується з очікуваною навичкою або з навичкою, яка не повинна активуватися:

    - prompt: "Patch the vulnerable npm dependencies"
      expected_skill: cve-remediation
    - prompt: "Review authentication input validation"
      forbidden_skill: cve-remediation
    

    Приховуйте очевидні позитивні аспекти, перефразуйте позитивні коментарі, описуйте майже помилкові негативні ситуації, неоднозначні запити та конфлікти між двома ймовірними навичками. Звітуйте матрицею плутанини замість простої точності, адже хибно позитивний результат може завдати такої ж шкоди, як і пропущений сигнал.

    Оцінка виконання перевіряє, чи покращує використання навички якість роботи. Порівняйте агента, який не має цієї навички, з тим самим агентом, оснащеним нею, використовуючи ідентичні випадки, середовище, модель та інструменти, та повторіть тести, оскільки агенти є недетерміністичними. Навичка заслуговує на своє місце лише тоді, коли отримане покращення виправдовує її додаткову складність та витрати на обробку даних.

    Як виглядає хороший випадок

    Віддавайте перевагу реалістичним знімкам репозиторію перед ізольованими дрібницями. Хороший випадок є самодостатнім та може бути перевірений машиною:

    {
      "id": "fix-null-condition",
      "prompt": "Fix saving rules with a null condition",
      "fixture": "repos/null-condition",
      "setup": ["npm install"],
      "checks": [
        "npm test -- null-condition.test.js",
        "git diff --check"
      ],
      "rubric": [
        "Fixes the root cause",
        "Preserves existing behavior",
        "Adds a regression test",
        "Avoids unrelated changes"
      ],
      "forbidden": [
        "deleting existing tests",
        "hard-coded fixture-specific output"
      ]
    }
    

    Інструменти оцінювання: використовуйте найсильніший з наявних

    Віддавайте перевагу найбільш надійним інструментам оцінювання, а вдаватися до суб’єктивного судження слід лише у крайніх випадках. Приблизно від найсильніших до найслабших:

    1. точні твердження
    2. компіляція та модульні чи інтеграційні тести
    3. перевірка схеми чи дерева синтаксису
    4. перевірка поведінки через браузер чи API
    5. статичний аналіз траєкторії
    6. LLM, який оцінює за певною шкалою
    7. людський огляд

    Інструменти оцінювання, створені за допомогою LLM, оцінюють такі якості, як чіткість та відповідність архітектурі, проте вони не повинні замінювати виконувані перевірки. Приховуйте від оцінювача, яка версія дала результат, та змінюйте порядок порівнянь.

    Показники, які варто відстежувати

    • Рівень успішності — це частка виконань, які пройшли всі критичні перевірки.
    • Pass@k — це ймовірність того, що принаймні одна з k спроб буде успішною.
    • Pass^k — це ймовірність того, що всі k спроб будуть успішними, що є найточнішим показником надійності.
    • Точність та відтворюваність маршрутизації описують якість вибору стратегії.
    • Швидкість регресії враховує випадки, коли об’єкт раніше працював коректно, а тепер — ні.
    • Витрати на кожне успішне завдання, медіана та час відгуку, кількість викликів інструментів, частота повторних спроб та кількість разів, коли доводилося втручатися людині, також мають бути відображені на панелі керування.

    Для продакшн-агентів стабільна надійність зазвичай краща за вражаючі результати у найкращих умовах.

    Створення набору даних

    Почніть з 20–50 прикладів, взятих з реальної роботи: попередніх невдач та інцидентів підтримки, повсякденних завдань, крайніх випадків, оманливих чи ворожих запитів, недостатньо прописаних завдань, завдань, які слід відхилити або уточнити, а також ситуацій, де жодна навичка не повинна активуватися.

    Потім розділіть їх на три набори:

    • набір для розробки — який можна використовувати під час вдосконалення навички
    • набір у спокої — який залишають недоторканим до моменту перевірки
    • набір для виявлення регресії — до якого постійно додають усі виявлені невдачі

    Уникайте оптимізації лише на основі одного фіксованого публічного набору, адже агенти швидко адаптуються під його формулювання.

    Робочий цикл

    Уявіть це як розробку, засновану на тестах, для поведінки агента:

    1. Запишіть реальну невдачу.
    2. Перетворіть її на відтворюваний приклад.
    3. Запишіть оцінку ще до того, як почнете працювати з навичкою чи агентом.
    4. Виконайте кілька базових тестів.
    5. Зробіть одну цільову зміну.
    6. Знову запустіть цей конкретний випадок разом із усім набором тестів на регресію.
    7. Порівняйте якість, надійність, затримку та витрати.
    8. Збережіть зміну лише у разі покращення загального балансу.

    Поширені помилки

    • Оцінювання лише кінцевого тексту
    • Використання лише запитів у форматі „щасливого шляху“
    • Перевірка того, чи були інструкції повторені, а не виконані
    • Запит у суддю у вигляді ШІ про факти, які можна перевірити за допомогою тесту
    • Виконання тесту лише один раз та вважання результату детермінованим
    • Зміна запиту, моделі, інструментів та навички одночасно
    • Вважання успіхом видалених тестів чи маніпуляцій з оцінювачем
    • Використання синтетичних випадків, які зовсім не схожі на реальну роботу користувача
    • недостатній контроль за вставкою запитів, прихованою у файлах чи результаті роботи інструментів

    Показники маршрутизації у конкретних термінах

    Припустимо, існує навичка перевірки безпеки, і оцінювач для кожного запиту вирішує, чи слід його активувати. Існує чотири можливі результати:

    • Правдиво позитивний результат (TP): запит мав бути активований і був активований.
    • Хибно позитивний результат (FP): запит не мав бути активований, але був активований — це хибна активація.
    • Хибно негативний результат (FN): запит мав бути активований, але не був активований.
    • Правдиво негативний результат (TN): запит не мав бути активований, і не був активований.

    Точність визначає, наскільки часто активація була правильною: TP поділене на (TP + FP). Якщо навичка активувалася десять разів, і вісім з них були правильними, то точність становить 80%. Висока точність означає мінімум хибних активацій.

    Реколи — це кількість запитів, які потребували певної навички та були насправді розпізнані: TP поділене на (TP + FN). Якщо десять запитів потребували цієї навички, а було розпізнано сім, то реколи становить 70%.

    Хибний запуск — це просто хибно позитивний результат. Прикладом є запит на кшталт "Upgrade React dependencies", який помилково активує процедуру перевірки безпеки. Багато хибних запусків означають низьку точність.

    Матриця плутанини підраховує все. При TP = 8, FN = 2, FP = 3 та TN = 7 запити, які мали б бути оброблені, діляться на 8 та 2, а запити, які не мали б цього робити, — на 3 та 7. Точність становить 8 / 11, приблизно 72,7%, а реколи — 8 / 10, тобто 80%. Висока точність означає, що навичка рідко активується помилково. Висока реколи означає, що вона рідко пропускає релевантні запити. Широкі формулювання умов запуску зазвичай підвищують реколи та знижують точність.

    З чого почати

    Для важливої навички компактний набір дуже корисний. Зіберіть десять запитів, які мають її активувати, та десять ситуацій, коли це не має відбуватися, а також п’ять реалістичних завдань для виконання. Додайте перевірки детерміністичних результатів, три–п’ять повторень кожного завдання, базовий запуск без цієї навички та набір тестів на регресію, який фіксуватиме кожну знайдену проблему.

    Така проста конфігурація виявляє більшість проблем з маршрутизацією та показує, чи справді навичка допомагає, чи просто здається складною.

    Мінімальна структура, яку можна скопіювати

    Достатньо теорії. Невеликий код на звичайному Python із лише стандартною бібліотекою може оцінити як маршрутизацію навички, так і результат виконання завдання агентом. Він складається приблизно з 70 рядків та демонструє кожну з вищезазначених ідей: файли прикладів, багатошарові оцінювачі, повторні запуски та показники надійності.

    Структура папок:

    evals/
      cases/
        skills/security-review.trigger.json
        agents/fix-null-condition.json
      graders.py
      metrics.py
      runner.py
      run.py        # CLI entry1. Case files. A skill trigger case is just positives and negatives. An agent case is a prompt plus graders and a run count.
    

    У файлі випадку запуску перелічується назва навички разом із підказками щодо того, що має та що не має її активувати:

    // cases/skills/security-review.trigger.json
    {
      "skill": "security-review",
      "positives": [
        "Audit this endpoint for SQL injection",
        "Check the login flow for auth bypasses",
        "Is this file-upload handler safe?"
      ],
      "negatives": [
        "Upgrade React dependencies",
        "Rename this variable across the repo",
        "Add a loading spinner to the form"
      ]
    }
    

    У справі агента є ідентифікатор, запит, елемент конфігурації та перевірки, які потрібно застосувати:

    // cases/agents/fix-null-condition.json
    {
      "id": "fix-null-condition",
      "prompt": "Fix saving rules with a null condition",
      "fixture": "fixtures/null-condition",
      "setup": ["npm ci"],
      "runs": 5,
      "graders": [
        { "type": "shell", "cmd": "npm test -- null-condition", "critical": true },
        { "type": "shell", "cmd": "git diff --check" },
        { "type": "forbidden", "pattern": "it\\.skip|xit\\(", "message": "must not disable tests" }
      ]
    }
    

    Далі йдуть оцінювачі. Один виконує команди оболонки, такі як набір тестів, інший сканує траєкторію на наявність змін, які були заборонені, а модель судді, яка не бачить, яку саме версію вона оцінює, відповідає за суб’єктивні якості.

    # graders.py
    import re, subprocess
    def shell(step, ctx):
        r = subprocess.run(step["cmd"], cwd=ctx.workdir, shell=True,
                           capture_output=True, text=True)
        ok = r.returncode == 0
        return {"pass": ok, "score": 1 if ok else 0, "detail": r.stdout[-400:]}
    def forbidden(step, ctx):
        bad = re.search(step["pattern"], ctx.diff) is not None
        return {"pass": not bad, "score": 0 if bad else 1,
                "detail": step["message"] if bad else ""}
    def judge(step, ctx):
        v = ctx.llm.rate(step["rubric"], ctx.artifact)  # 0..1, blinded
        return {"pass": v >= step.get("threshold", 0.7), "score": v}
    GRADERS = {"shell": shell, "forbidden": forbidden, "judge": judge}3. Metrics. Success rate, pass@k, pass^k, and the routing confusion matrix — exactly the numbers from earlier.
    

    Модуль метрик перетворює списки результатів виконання на числа:

    # metrics.py
    def success_rate(rs):
        return sum(1 for r in rs if r["pass"]) / len(rs)
    def pass_at_k(rs):
        return 1 if any(r["pass"] for r in rs) else 0
    def pass_hat_k(rs):
        return 1 if all(r["pass"] for r in rs) else 0
    def routing(positives, negatives, fired):
        tp = sum(1 for p in positives if fired(p))
        fp = sum(1 for n in negatives if fired(n))
        fn = len(positives) - tp
        tn = len(negatives) - fp
        return {"tp": tp, "fp": fp, "fn": fn, "tn": tn,
                "precision": tp / (tp + fp or 1),
                "recall": tp / (tp + fn or 1)}4. The runner. One function per suite. The agent runner repeats each case so pass^k is meaningful; the skill runner just asks the router which skills fire.
    

    Бігун завантажує кейси, викликає оцінювачів, повторює кожен запуск та виводить метрики:

    # runner.py
    import json
    from graders import GRADERS
    from metrics import success_rate, pass_at_k, pass_hat_k, routing
    def run_agent_case(agent, path):
        c = json.load(open(path))
        runs = []
        for _ in range(c.get("runs", 3)):
            ctx = agent.run(c["prompt"], fixture=c["fixture"], setup=c["setup"])
            ok = True
            for step in c["graders"]:
                g = GRADERS[step["type"]](step, ctx)
                if step.get("critical") and not g["pass"]:
                    ok = False
            runs.append({"pass": ok})
        return {"id": c["id"], "success": success_rate(runs),
                "pass_at_k": pass_at_k(runs), "pass_hat_k": pass_hat_k(runs)}
    def run_skill_trigger(router, path):
        c = json.load(open(path))
        fired = lambda prompt: c["skill"] in router.route(prompt)
        return {"skill": c["skill"], **routing(c["positives"], c["negatives"], fired)}5. Run it. The CLI just dispatches on the case type and prints the metrics.
    

    Його запуск дає такий результат:

    $ python run.py cases/agents/fix-null-condition.json
    fix-null-condition   success=0.80   pass@5=1.00   pass^5=0.20
    $ python run.py cases/skills/security-review.trigger.json
    security-review      precision=0.86  recall=1.00   (tp=6 fp=1 fn=0 tn=5)
    

    Читайте ці рядки так, як рекомендує весь цей підхід. Агент виконує чотири запуски з п’яти, тож pass@5 здається ідеальним, проте pass^5 з показником 0,20 свідчить про те, що він ще ненадійний. Цей інструмент фіксує кожен справжній запит із рівнем відтворення 1,0, але один раз спрацював тоді, коли не повинен був, із рівнем точності 0,86, тож є один хибний сигнал, який потрібно усунути.

    Саме в цьому сенс оцінювань: перетворити фразу „здається, це спрацювало“ на числа, які можна покращувати. Почніть із подібної структури, додавайте нові випадки щоразу, коли щось ламається, і дозвольте набору даних для регресійного аналізу розвиватися до вашого робочого визначення того, що є хорошим.

    Використовуйте існуючі фреймворки, коли це можливо

    Домашній фреймворк корисний для вивчення механізмів та для повного контролю, але готові відкриті проекти вже містять запуски, оцінювачі, набори даних та панелі керування. Перегляньте їх, перш ніж створювати власні.

    Загальні запити та оцінювання LLM

    OpenAI Evals — це оригінальна платформа у стилі реєстру, яка дозволяє визначати тестування у форматі YAML за допомогою інструментів Python для оцінки будь-якої моделі; вона підходить для перевірки рівня вихідних даних та класифікації. promptfoo базується на налаштуваннях, відображає запити до моделей у вигляді матриці поруч один з одним, містить такі механізми перевірки, як перевірка наявності елементів, регулярні вирази, схеми JSON та критерії оцінки LLM, а також має режим «червоної команди», що робить його хорошою основою для визначення навичок та виявлення регресій у запитах. DeepEval функціонує як pytest для LLM, пропонуючи показники вірності, релевантності та галюцинацій, а також користувацькі критерії оцінки G-Eval, і легко інтегрується в процеси CI. Ragas орієнтований саме на пайплайни RAG, оцінюючи точність та повноту контексту, вірність та релевантність відповідей. Функція оцінки LLM у MLflow дозволяє відстежувати та порівнювати результати, якщо вже використовується MLflow.

    Відстеження, набори даних та платформи для оцінки

    LangSmith пропонує набори даних, засоби відстеження траєкторій та інструменти оцінки, які корисні, коли потрібно переглянути всю траєкторію, а не лише результат. Langfuse є програмним забезпеченням з відкритим кодом, яке можна розмістити на власному сервері та є незалежним від конкретної моделі; воно містить засоби відстеження, оцінки та набори даних для моніторингу в умовах реальної роботи. Braintrust розглядає процеси оцінки як частину інструментарію CI, пропонуючи функції оцінювання, набори даних з версіонуванням та функцію порівняння для аналізу експериментів. Arize Phoenix базується на технології відстеження OpenTelemetry та включає шаблони оцінки, що допомагають виявляти регресії у роботі систем у реальному часі. Inspect від UK AI Safety Institute — це ретельно спроєктована система для розв’язання задач та оцінювання, яка все більше використовується для серйозних оцінок агентів та їхньої безпеки.

    Бенчмарки агентів

    SWE-bench та SWE-bench Verified є стандартом для визначення того, чи може агент вирішити реальну проблему у GitHub, використовуючи власні тести репозиторію як критерій оцінки. AgentBench, WebArena, GAIA та τ-bench пропонують зовнішні показники для оцінки використання інструментів, виконання веб-завдань та багатоетапних агентів. Фреймворки на кшталт AutoGen та LangGraph надають механізми тестування для перевірки викликів інструментів та проміжних кроків.

    Вибір

    • Якщо потрібні лише функції формування запитів та направлення завдань за навичками, promptfoo — це найшвидший спосіб налаштування та перевірки.
    • Для метрик, орієнтованих на код та призначених для використання в CI, розгляньте DeepEval або Braintrust.
    • Для оцінки розвитку багатоетапних агентів скористайтеся LangSmith, Langfuse або Inspect.
    • Для технології RAG додайте Ragas.
    • Для справжнього бенчмарку кодуючих агентів використовуйте SWE-bench Verified.

    Ця схема працює скрізь: у випадках, оцінювачах, повторних запусках та відстеженні з часом. Фреймворк економить зусилля, тож дотримуйтесь дисципліни та обирайте інструмент, який підходить до вашої технологічної стеку. Спеціальні рішення краще використовувати для прогалин, які залишають ці інструменти, або для проєктів, які вимагають повної відсутності залежностей у CI.