ncodelab.
← Wszystkie wpisy

12 maj 2026 · 6 min · Tomasz Chmielarz

Napisz eval zanim napiszesz prompt

Praktyczny wzorzec budowania agentów, którym możesz zaufać — zacznij od rubryki oceniającej, skończ na mierzalnym score, i nigdy więcej nie wypuścisz systemu opartego na wyczuciu.

Makrofotografia światłowodu świecącego elektrycznym indygo na ciepłym ciemnym tle.

Większość projektów z LLM-ami pada w ten sam sposób: ktoś pisze prompt, wygląda dobrze na pięciu przykładach, idzie na produkcję, a potem padnie na szóstym — tyle że nikt tego nie zauważa przez trzy miesiące, bo nie ma evala.

Naprawa jest niemodna. Napisz eval zanim napiszesz prompt.

Czym "eval" właściwie jest

Zbiór ewaluacyjny to lista wejść sparowanych z tym, jak wygląda dobry wynik. Tyle. Format zależy od zadania:

  • Klasyfikator: wejście → oczekiwana etykieta.
  • Drafter: wejście → wzorcowy draft albo rubryka oceny.
  • Agent wieloetapowy: wejście → lista narzędzi, które powinny zostać wywołane + akceptowalna końcowa odpowiedź.

Celuj w 30 do 100 przypadków. Mniej niż 30 — nie odróżnisz sygnału od szumu. Więcej niż 100 — nigdy tego nie utrzymasz.

Mieszaj trzy rodzaje przypadków:

  1. Happy paths. Przypadki, które system zobaczy najczęściej.
  2. Adwersarialne. Edge case'y, niejednoznaczne wejścia, rzeczy o których wiesz, że gdzieś nawalają.
  3. Poza zakresem. Przypadki, których agent ma odmówić obsługi.

Jak oceniać

Poza klasyfikacją masz trzy opcje. Wybierz tę, która pasuje do Twojej tolerancji kosztu i ceremonii.

Ocena ludzka. Najtańsza w pieniądzach, droga w czasie. Najlepsza dla pierwszej wersji. Dwóch reviewerów na przypadek. Rozbieżności idą do trzeciego i rozmowy.

LLM-as-judge. Tanio i szybko. Ryzyko: model-sędzia ma uprzedzenia, które dzieli z agentem. Mitygacja: użyj silniejszego modelu niż agent, napisz dokładną rubrykę, zwaliduj sędziego na próbce ocen ludzkich.

Reguły. Gdy odpowiedź jest ustrukturyzowana (JSON, obecność cytatu, wyekstrahowane pole), sprawdzaj kodem. Najbardziej niezawodne. Używaj, gdziekolwiek się da.

Konkretny starter

Oto najmniejszy harness ewaluacyjny, który robi użyteczną robotę:

type Case = {
  id: string
  input: string
  expected: string
  category: 'happy' | 'adversarial' | 'out-of-scope'
}

type Verdict = { id: string; pass: boolean; reason: string }

async function score(cases: Case[], run: (input: string) => Promise<string>) {
  const verdicts: Verdict[] = []
  for (const c of cases) {
    const out = await run(c.input)
    const pass = await judge(c.expected, out, c.category)
    verdicts.push({ id: c.id, pass: pass.ok, reason: pass.reason })
  }
  return {
    overall: verdicts.filter((v) => v.pass).length / verdicts.length,
    byCategory: groupBy(verdicts, (v) => cases.find((c) => c.id === v.id)!.category),
    verdicts,
  }
}

Dwieście linii później masz pipeline ewaluacyjny. Wepnij w cron i patrz, jak score się zmienia w czasie.

Dlaczego to zmienia wszystko

Gdy masz score, trzy rzeczy stają się możliwe.

Możesz refaktoryzować bez strachu. Zmień model, prompt, definicje narzędzi — i w ciągu minut wiesz, czy coś popsułeś.

Możesz ustawić kontrakt. "Wypuścimy, gdy eval trafia 0.85 na happy paths i 0.65 na adwersarialnych." Operator wie, co dostaje. Ty wiesz, co dostarczasz.

Możesz iterować w nieskończoność. Każdy bug na produkcji to nowy case w evalu. Eval rośnie razem z systemem. Po roku masz regression suite wart więcej niż kod.

Co ludzi blokuje

Trzy rzeczy, w kolejności częstotliwości.

"Jeszcze nie wiemy, jak wygląda dobre." No to zbuduj najpierw eval — to jest właśnie discovery. Nie masz projektu, masz życzenie.

"Model się poprawi i eval będzie nieaktualny." Nie. Lepsze modele dostają wyższe score na tych samych przypadkach. Eval staje się bardziej użyteczny, nie mniej.

"To dużo pracy." Owszem. Tak samo jak wypuszczenie zepsutego systemu i odkrycie tego za trzy miesiące, gdy klient się poskarży.

Napisz najpierw eval.