Ert första test av AI-svaren, på en eftermiddag

Från ”det känns bra” till ”46 av 50 rätt” på en eftermiddag. Ett kalkylark, femtio riktiga frågor och ett litet skript som visar vad varje ändring förstör.

Kort sagt

  • Ett test av AI-svar är en lista med riktiga frågor och vad svaren måste och inte får innehålla.
  • Femtio frågor, varav tio som assistenten inte ska kunna svara på, räcker för att börja.
  • Kör samma frågor före och efter varje ändring och titta på det som slutade fungera.
  • Det tar en eftermiddag och ger er en siffra, modet att ändra och underlaget för att släppa.
I den här artikeln · 7 avsnitt
  1. 01Vad ett test är, på vanlig svenska
  2. 02Steg 1: Femtio riktiga frågor (en timme)
  3. 03Steg 2: Skriv vad svaret måste innehålla (en timme)
  4. 04Steg 3: Ett kort skript som kör allt (en timme)
  5. 05Steg 4: Jämför före och efter
  6. 06Vad ni får för en eftermiddag
  7. 07Nästa steg, när ni är redo

Sara har ändrat en mening i prompten. Assistenten lät lite stel, så hon lade till ”svara vänligt och hjälpsamt”. Hon testar med tre frågor. Svaren blir mycket trevligare. Hon trycker på knappen och ändringen går ut.

Två veckor senare upptäcker någon att assistenten har börjat svara ”Ja, vi har öppet!” på frågor om helgdagar den inte vet något om. Den har blivit så hjälpsam att den gissar. Glatt, säkert och fel, ungefär som en sommarvikarie som inte vill göra någon besviken.

Ingen gjorde något dumt. Sara testade, som alla gör: några frågor, en känsla av att det blev bättre. Problemet är att en känsla bara testar det man tittar på. Den som har ändrat en prompt vet att den påverkar mer än det man tänkt på.

Vad ett test är, på vanlig svenska

Ett test av AI-svar är inget konstigt. Det är en lista med frågor, och för varje fråga en beskrivning av vad ett bra svar måste innehålla. Sedan låter ni assistenten svara på alla frågorna och kontrollerar svaren mot listan.

Det kallas ofta evals, från engelskans evaluations. Men glöm ordet. Tänk på det som ett prov med facit som assistenten får skriva varje gång något ändras. Skillnaden mot skolan är att den här eleven aldrig klagar på att provet var orättvist.

Det fina är att ni inte behöver veta exakt vad svaret ska vara, ord för ord. Ni behöver bara veta vad det måste innehålla och vad det inte får innehålla.

Steg 1: Femtio riktiga frågor (en timme)

Öppna ett kalkylark. Gå till ert supportsystem, er inkorg eller chatten där kollegor ställer frågor, och kopiera femtio riktiga frågor. Ta dem som de är, med stavfel och allt.

Blanda:

  • De vanligaste frågorna, de som kommer tio gånger om dagen.
  • Några svåra, där även en ny medarbetare skulle tveka.
  • Tio frågor den inte ska kunna svara på, till exempel om saker som inte finns i underlaget. Här är rätt svar ”det vet jag inte”.

Ta bort namn, telefonnummer och andra personuppgifter innan frågorna hamnar i kalkylarket. Ersätt dem med påhittade.

Steg 2: Skriv vad svaret måste innehålla (en timme)

För varje fråga, fyll i två kolumner:

Fråga Måste innehålla Får inte innehålla
Hur länge har jag på mig att returnera en vara? 30 dagar 14 dagar
Min lampa kom trasig, vad gör jag? bild betala
Har ni öppet på midsommarafton? vet inte öppet till

Kolumnen ”får inte innehålla” är den som oftast glöms bort, och den som fångar de farligaste felen. Ett svar som innehåller ”14 dagar” när policyn säger 30 är fel även om det låter bra.

Steg 3: Ett kort skript som kör allt (en timme)

Här behövs en utvecklare, men inte länge. Spara kalkylarket som en fil där varje rad är en fråga. Formatet heter JSONL och ser ut så här:

first-eval/cases.jsonl
{"id":"retur-30-dagar","question":"Hur länge har jag på mig att returnera en vara?","mustInclude":["30 dagar"],"mustNotInclude":["14 dagar"]}
{"id":"retur-skadad","question":"Min lampa kom trasig, vad gör jag?","mustInclude":["bild"],"mustNotInclude":["betala"]}
{"id":"leverans-tid","question":"När kommer mitt paket?","mustInclude":["två arbetsdagar"]}
{"id":"ingen-gissning","question":"Har ni öppet på midsommarafton?","mustInclude":["vet inte"],"mustNotInclude":["öppet till"]}

Sedan behövs ett skript som ställer varje fråga till er assistent och kontrollerar svaret. Hela skriptet är några rader:

first-eval/first-eval.ts
/**
 * The whole first eval: ask every question, check every answer, report.
 * `answer` is your system, whatever it is: a prompt and a model call,
 * a RAG pipeline, an existing endpoint. Nothing here depends on how it works.
 */
export async function runCases(cases: Case[], answer: (question: string) => Promise<string>): Promise<Result[]> {
  const results: Result[] = [];
  for (const c of cases) {
    const text = await answer(c.question);
    const lower = text.toLowerCase();
    const why = [
      ...c.mustInclude.filter((s) => !lower.includes(s.toLowerCase())).map((s) => `saknar "${s}"`),
      ...(c.mustNotInclude ?? []).filter((s) => lower.includes(s.toLowerCase())).map((s) => `innehåller "${s}"`),
    ];
    results.push({ id: c.id, pass: why.length === 0, why, answer: text });
  }
  return results;
}

Funktionen answer är er assistent, hur den än är byggd. Skriptet bryr sig inte om vilken modell ni använder eller hur prompten ser ut. Det ställer frågan och läser svaret, precis som en användare.

Resultatet är en lista: vilka frågor som klarades, och för de som inte gjorde det, varför, på vanlig svenska: saknar ”vet inte”, innehåller ”öppet till”.

Steg 4: Jämför före och efter

Det här är steget som hade räddat Sara. Kör testet innan en ändring, spara resultatet, gör ändringen och kör igen. Sedan jämför ni:

first-eval/first-eval.ts
/** What got worse since last time: the question to ask before every change ships. */
export function compare(before: Result[], after: Result[]) {
  const was = new Map(before.map((r) => [r.id, r.pass]));
  return {
    passRate: after.filter((r) => r.pass).length / Math.max(1, after.length),
    newlyFailing: after.filter((r) => was.get(r.id) === true && !r.pass).map((r) => r.id),
    newlyPassing: after.filter((r) => was.get(r.id) === false && r.pass).map((r) => r.id),
  };
}

Det enda som behöver kollas varje gång är listan newlyFailing: frågor som klarades förut och inte gör det nu. Det är exakt de saker en ändring har förstört, och de är oftast inte de saker man tittade på.

I exemplet bakom koden, som körs som test varje gång vi ändrar något i den, gör ändringen ”svara hjälpsamt” att frågan om midsommarafton börjar misslyckas. Resultatet går från 4 av 4 till 3 av 4, och skriptet säger precis vilken fråga och varför.

Vad ni får för en eftermiddag

Efter tre timmars arbete har ni något de flesta AI-projekt saknar:

  • En siffra. Ni kan svara på ”hur bra är den?” med ”46 av 50 på riktiga frågor”, inte med en känsla.
  • Modet att ändra. Prompten är inte längre farlig att röra, eftersom ni ser direkt vad en ändring gör.
  • Ett underlag för beslutet att släppa. Siffran jämförs med ribban ni bestämde i Hur bra är bra nog?, och är svaret på den första rädslan i Demon fungerade. Varför släpper vi den inte?

Nästa steg, när ni är redo

Det här är ett första test, inte ett slutgiltigt. När det har blivit en vana finns det tre naturliga steg vidare:

  1. Kör det automatiskt varje gång någon ändrar prompten eller koden, så att ingen behöver komma ihåg det.
  2. Lägg till nya frågor varje gång en användare hittar ett fel. Felet ska aldrig kunna komma tillbaka utan att testet märker det.
  3. Bli fler. Femtio frågor räcker för att börja; några hundra behövs för att se små skillnader mellan två versioner.

Hur man bygger ut det till en riktig spärr i utvecklingsflödet, med statistik som avgör om en ändring verkligen är sämre, beskrivs i Evals as CI på engelska. All kod i den här artikeln finns också i vårt publika kodrepo.

Nästa del i Våga hela vägen handlar om hur ni släpper till de första användarna: Släpp till tio användare först.

Läs härnäst →Släpp till tio användare förstVåga hela vägen · Nr 04 · 6 min

Vanliga frågor

Behöver vi ett särskilt verktyg för att testa AI?
Inte för att börja. Ett kalkylark med riktiga frågor och vad svaren måste innehålla, och ett kort skript som kör frågorna, räcker långt. Verktyg blir användbara när ni har hundratals fall och flera versioner att jämföra.
Var hittar vi testfrågor?
I verkligheten. Kundmejl, ärenden i supportsystemet, frågor kollegor ställer i chatten. Påhittade frågor testar det ni redan tänkt på, riktiga frågor testar det användarna faktiskt gör.
Hur ofta ska vi köra testerna?
Varje gång något ändras som kan påverka svaren, alltså prompten, modellen, dokumenten den läser eller koden runt den. Helst automatiskt, så att ingen behöver komma ihåg det.