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
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:
{"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:
/**
* 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:
/** 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:
- Kör det automatiskt varje gång någon ändrar prompten eller koden, så att ingen behöver komma ihåg det.
- 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.
- 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.