Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Avaluació de sistemes LLM

Les evals són el mecanisme de verificació sistemàtica del comportament d’un sistema LLM. Es poden usar durant el desenvolupament (per validar canvis de prompt) i en producció (per detectar regressions de qualitat). Aquest document cobreix la metodologia; la integració amb el monitoratge en producció s’explica a Sistemes LLM en producció.

Per què els prompts necessiten tests

La prova manual — provar el sistema a mà i veure que “funciona” — no és suficient per a un sistema en producció. Els LLMs fallen de forma no determinista i en casos límit que no s’anticipen durant el desenvolupament. Un canvi al prompt que millora un cas pot trencar-ne un altre silenciosament. Sense un mecanisme de verificació sistemàtic, és impossible saber si un canvi millora o empitjora el sistema.

Les evals compleixen el mateix rol que els tests unitaris en el programari convencional, però adaptats a les propietats dels LLMs: sortida no determinista, qualitat graduada (no binària), i fluxos multi-pas.

La distinció fonamental que s’aplica aquí és la mateixa que per a qualsevol sistema ML: el codi determinista (parsing de la sortida, validació d’esquemes, routing, eines) es testa amb pytest convencional; el comportament del model (qualitat de la resposta, correcció de la tasca) es valida amb evals. Consulta Validació i qualitat per als patrons generals de testing i CI/CD en sistemes ML.

Anatomia d’una eval

Cada eval es compon de quatre elements:

  • Tasca: una entrada concreta i uns criteris d’èxit definits. Exemple: “donat aquest text de suport, classifica el sentiment com a positiu/negatiu/neutre”.
  • Trial: una execució de la tasca. Com que el model és no determinista, una sola execució no és suficient per jutjar el comportament — cal múltiples trials.
  • Avaluador (grader): la lògica que puntua la sortida del model per a cada trial.
  • Resultat (outcome): el veredicte final — la tasca s’ha superat o no.

Com construir el dataset d’evals

Tenir clar QUÈ és una eval no és suficient si no se sap d’on surten els casos de prova. El dataset és la part més valuosa de la suite — i la més difícil de construir bé.

Fonts de casos

Casos escrits manualment (seed set): el punt de partida. Escriu 10–20 casos que cobreixin les situacions que el sistema ha de gestionar correctament: el cas feliç, els casos límit coneguts i les entrades malicioses o ambigües previsibles. Serveixen per tenir una línia base abans de tenir dades reals.

Fallades de producció: la font més valuosa. Cada vegada que el sistema falla en producció — resposta incorrecta, format inesperat, comportament inconsistent — aquell cas entra al dataset. Les fallades reals capturen els casos límit que el dissenyador no anticipa; els casos sintètics tendeixen a cobrir els casos fàcils que el model ja resol bé.

Generació sintètica: útil per ampliar la cobertura quan falten dades reals. Un LLM pot generar variants d’un cas existent (paràfrasis, entrades en idiomes diferents, variacions de format). El risc és que les variants sintètiques siguin massa similars entre elles i no aportin cobertura nova. Cal revisar manualment una mostra.

Format del dataset

El format estàndard és JSONL — una línia per cas, fàcil de llegir i d’ampliar incrementalment:

{"input": "El producte va arribar trencat.", "expected": "negatiu", "criteria": "sentiment correcte"}
{"input": "M'ha agradat molt, tornaria a comprar.", "expected": "positiu", "criteria": "sentiment correcte"}
{"input": "El paquet va trigar però el producte és bo.", "expected": "neutre", "criteria": "sentiment correcte quan hi ha valoracions mixtes"}

Cada cas té com a mínim: l’entrada al sistema, el resultat esperat (o un criteri en llenguatge natural per als casos on no hi ha resposta única), i una nota que explica per què aquell cas és rellevant. Aquesta nota és important quan el dataset creix i cal entendre per què un cas va fallar mesos després.

Manteniment del dataset

El dataset no és estàtic. Cal:

  • Afegir casos des de producció: cada fallada nova que el sistema cometi en producció entra al dataset. És la font més valuosa perquè captura els casos límit que el dissenyador no anticipa.
  • Etiquetar els casos per categoria (casos feliços, casos límit, entrades malicioses) per poder analitzar on fallen els canvis de forma selectiva.
  • Fer rotació periòdica: un dataset que no s’actualitza envelleix — els usuaris canvien d’hàbits i els casos acaben representant el comportament passat, no el present. Mostrejar tràfic real mensualment i revisar-ne una mostra manualment evita que les evals es converteixin en un fals certificat de qualitat. En la mateixa revisió, elimina els casos que han quedat obsolets per canvis de funcionalitat.

Un dataset de 50 casos ben triats és més útil que un de 500 casos mal etiquetats o redundants.

Tipus d’avaluadors

Avaluador basat en codi: compara la sortida amb un valor esperat de forma determinista. Ràpid, barat i reproduïble. Adequat quan la sortida és estructurada i la correcció és binària.

Avaluador basat en model (LLM-as-judge): un segon LLM avalua la qualitat de la resposta seguint un criteri en llenguatge natural. Flexible i capaç de capturar matisos que el codi no pot. Adequat quan la qualitat és subjectiva o la sortida és text lliure.

def avaluar_qualitat(resposta: str, criteri: str) -> dict:
    resultat = client.chat.completions.create(
        model=MODEL,
        messages=[
            {"role": "system", "content": "Avalua si la resposta compleix el criteri. "
                                           "Retorna JSON amb 'aprovat' (bool) i 'raó' (str)."},
            {"role": "user", "content": f"Criteri: {criteri}\nResposta: {resposta}"},
        ],
        response_format={"type": "json_object"},
    )
    return json.loads(resultat.choices[0].message.content)

Avaluador humà: la referència de qualitat màxima. Lent i car, però necessari per calibrar els avaluadors automàtics i per als casos on cap automatisme és suficient.

La tria de l’avaluador és una decisió de disseny: combinar els tres tipus en una mateixa suite és habitual — codi per als casos estructurats, model per als subjectius, i humans periòdicament per validar que els avaluadors automàtics segueixen sent fiables.

Biaixos i fiabilitat del LLM-as-judge

El LLM-as-judge és un avaluador potent, però introdueix biaixos sistemàtics que cal conèixer per no confiar-hi cegament.

Biaix de verbositat: el model tendeix a puntuar millor les respostes llargues, fins i tot quan una resposta curta i precisa és superior. Una resposta de tres paraules que respon correctament pot rebre pitjor puntuació que una de tres paràgrafs que “sembla” més completa.

Biaix de posició: en comparacions entre dues respostes (A vs. B), el model sovint afavoreix la que apareix primer, independentment de la qualitat. Invertir l’ordre i prendre la majoria elimina aquest biaix.

Biaix d’autopresència: un model tendeix a puntuar millor les respostes generades per models de la mateixa família. GPT-4 avaluant respostes de GPT-4 pot ser menys crític que avaluant respostes d’un altre proveïdor.

Mitigacions pràctiques

Demanar raonament abans del veredicte: forçar el model a argumentar la seva decisió abans de donar la puntuació final redueix el biaix de posició i verbositat, perquè obliga a considerar la resposta en detall.

{"role": "system", "content": "Primer explica els punts forts i febles de la resposta. "
                               "Després, a la darrera línia, retorna JSON amb 'aprovat' (bool)."}

Comparació en ambdós ordres: si l’eval compara dues respostes, executar-la amb A→B i amb B→A i prendre la majoria elimina el biaix de posició.

Calibrar el jutge contra etiquetes humanes: la forma més rigorosa de validar un avaluador automàtic. Pren un subconjunt del dataset, etiqueta’l manualment i mesura quant acorda el jutge amb els humans. Un acord per sota del 80% és un senyal que el jutge no és fiable per a aquell criteri.

def acord_amb_humans(etiquetes_humanes: list[bool], etiquetes_jutge: list[bool]) -> float:
    coincidencies = sum(h == j for h, j in zip(etiquetes_humanes, etiquetes_jutge))
    return coincidencies / len(etiquetes_humanes)

Si el jutge no és fiable per a un criteri concret, cal redissenyar el prompt del jutge, canviar de model o recórrer a avaluació humana.

Panell de jutges: en lloc d’un sol LLM-as-judge, executar el mateix criteri amb múltiples jutges de famílies diferents (p.ex. un de Claude, un de GPT, un de Gemini) i agregar els veredictes per majoria. Aborda especialment el biaix d’autopresència — un jutge de la mateixa família que el sistema avaluat tendeix a puntuar-lo millor. La desacord entre jutges és en si mateixa un senyal: els casos on els jutges es divideixen s’envien a revisió humana en lloc de forçar una majoria. El cost és proporcional al nombre de jutges, cosa que limita el panell a la suite ràpida o als casos crítics; la suite nocturna completa sol usar un jutge únic ben calibrat.

No-determinisme: pass@k i pass^k

Com que el model pot donar respostes diferents per a la mateixa entrada, cal executar cada tasca múltiples vegades (trials) i agregar els resultats. Hi ha dues mètriques complementàries. pass@k és estàndard en benchmarks de codi (HumanEval, SWE-bench); pass^k és una extensió menys universal — útil com a eina conceptual per raonar sobre fiabilitat en producció, però no sempre trobada amb aquesta notació a la literatura:

  • pass@k: la probabilitat que almenys un dels k trials superi l’eval. Mesura el potencial del sistema — pot resoldre la tasca?
  • pass^k: la probabilitat que tots els k trials la superin. Mesura la fiabilitat en producció — sempre la resol?

Per a sistemes en producció, la mètrica rellevant és pass^k: un sistema que resol una tasca el 60% de les vegades no és desplegable. Quan pass@k és alt però pass^k és baix, el sistema pot resoldre la tasca però no de forma consistent — normalment un senyal que el prompt és ambigú o que cal sortida estructurada.

Evals d’agents

Avaluar un agent és més complex que avaluar una crida única, perquè hi ha dos nivells a jutjar:

Resultat final: l’agent ha assolit l’objectiu? Aquesta és la mètrica principal, equivalent a un avaluador de torn únic sobre l’estat final del sistema.

Trajectòria: ha pres el camí adequat? Ha cridat les eines correctes? Ha evitat passos innecessaris? Un agent que arriba a la resposta correcta fent crides redundants o innecessàries no és un agent eficient ni fiable.

Eval d'agent
    ├── Resultat final     → avaluador de codi o model sobre l'output
    └── Trajectòria        → inspecció del transcript: eines cridades, ordre, arguments

El transcript — el registre complet de la conversa incloent totes les crides a eines i els seus resultats — és la unitat d’anàlisi per a les evals d’agents. Llegir transcripts regularment és la manera més ràpida de detectar patrons de fallada que els avaluadors automàtics no capturen.

Evals per a RAG

Els sistemes RAG presenten un repte d’avaluació específic: hi ha dues etapes que poden fallar de forma independent, i una eval global sobre la resposta final no distingeix on és el problema.

Consulta de l'usuari
        │
        ▼
  Recuperació         ← pot fallar: fragments poc rellevants
        │
        ▼
  Generació           ← pot fallar: resposta infidel als fragments
        │
        ▼
  Resposta final

Les tres mètriques del marc RAGAS cobreixen aquest espai:

MètricaPregunta que responCom s’avalua
Context relevanceEls fragments recuperats són rellevants per a la consulta?LLM-as-judge: quina fracció del fragment és útil per respondre?
FaithfulnessLa resposta es basa únicament en els fragments recuperats?LLM-as-judge: cada afirmació de la resposta es pot atribuir als fragments?
Answer relevanceLa resposta respon realment la pregunta de l’usuari?LLM genera preguntes a partir de la resposta i comprova si coincideixen amb la original

Per què avaluar les dues etapes per separat

Una resposta final correcta no implica que el sistema funcioni bé: pot ser que el model hagi respost correctament malgrat haver recuperat fragments poc rellevants (perquè la resposta era trivial). Inversament, una resposta incorrecta pot deure’s a una recuperació deficient o a una generació infidel — i el remei és diferent en cada cas.

Context relevance baix  → problema de recuperació: ajustar l'embedding, la query o el chunking
Faithfulness baixa      → problema de generació: el model al·lucina o ignora el context
Answer relevance baixa  → la resposta no respon la pregunta: problema de prompt o de tasca mal definida

Avaluar les tres mètriques per separat permet diagnosticar on falla el sistema i aplicar la solució correcta.

El cicle prompt → eval → millora

Les evals no són una verificació puntual — són el mecanisme de feedback que fa sostenible l’evolució del sistema:

  1. Escriu evals per a la funcionalitat (idealment, abans de canviar el prompt)
  2. Executa les evals → mesura la línia base
  3. Modifica el prompt
  4. Executa les evals → compara amb la línia base
  5. Si millora: desplega. Si empitjora: reverteix o ajusta.

Un conjunt inicial de 20–50 casos derivats de fallades reals és més valuós que centenars de casos sintètics. Les fallades reals capturen els casos límit que el dissenyador no anticipa; els casos sintètics tendeixen a cobrir els casos fàcils que el model ja resol bé.

📝 Per a una visió detallada de les evals d’agents, incloent la distinció entre avaluadors de codi, model i humans, i la interpretació de pass@k en sistemes reals, consulta l’article d’Anthropic Demystifying Evals for AI Agents.

Evals offline i online

Hi ha dos moments en el cicle de vida d’un sistema LLM on s’executen evals, amb propòsits complementaris:

Evals offline (abans del desplegament): s’executen sobre un dataset fix i conegut, de forma determinista i repetible. Detecten regressions conegudes — casos que el sistema resolia bé i que un canvi ha trencat. Són el mecanisme de validació abans de desplegar qualsevol canvi.

Evals online (en producció): s’executen de forma asíncrona sobre una mostra del tràfic real. Detecten modes de fallada desconeguts — casos que no estan al dataset offline perquè ningú els havia anticipat. No bloquegen el desplegament, però alimenten el dataset offline amb casos nous.

Canvi de prompt/model
        │
        ▼
  Evals offline      ← dataset fix, bloquejant
        │
   ok → desplega
        │
        ▼
  Producció
        │
  mostra de tràfic
        │
        ▼
  Evals online       ← asíncrones, no bloquejants
        │
  fallades noves → afegir al dataset offline

Les evals offline responen a “hem trencat alguna cosa?”; les online responen a “hi ha alguna cosa que no sabíem que podia fallar?”. Les dues juntes tanquen el cicle de qualitat.

La connexió entre evals online i el monitoratge de producció s’explica a Sistemes LLM en producció.

Last change: , commit: a968e7c