Naar inhoud springen
15/30Hoofdstuk 15 van 30

Prompt engineering, gemeten: wat de output verandert

Zestig tickets, dezelfde woorden in zes volgordes, accuracy van 26,7% tot 85,0%. Plus vier internettrucs met foutmarges.

Op deze pagina

Hier is een supportticket, en vier wachtrijen waar het naartoe zou kunnen.

TEXT
The label on the parcel has my old surname on it.
    -> billing / technical / shipping / account

Om het te routeren heb je drie dingen nodig in de prompt: de definities van de wachtrijen, het ticket en de instructie om er één te kiezen. Drie blokken. Je kunt ze in zes volgordes zetten, en de blokken bevatten in alle zes exact dezelfde tekens.

Over zestig tickets met bekende antwoorden scoren de zes volgordes tussen 26,7 % en 55,0 %. Verplaats dezelfde twee blokken uit de user-turn naar de system-turn, zonder ook maar één woord te veranderen, en hetzelfde model scoort 76,7 %. Wikkel het ticket in een XML-achtige tag en het haalt 85,0 %.

Niets aan het model veranderde. Niets aan de taak veranderde. Geen enkel woord werd herschreven. Een verschil van achtenvijftig punten kwam voort uit het rangschikken van dezelfde tekst.

Dat is waarom dit hoofdstuk bestaat, en ook waarom dit onderwerp het meest door cargo cults geteisterde onderwerp in het veld is. De effecten zijn echt en groot, waardoor elke anekdote bevestigd voelt; en ze zijn instabiel over modellen en taken heen, waardoor een anekdote meestal alles is wat advies ooit is. Daarom heeft dit hoofdstuk één regel, en alles erin is ondergeschikt aan die regel:

Over een prompt discussieer je niet: je meet hem. Vier varianten over twintig cases onderscheiden helemaal niets.

Voor de metingen eerst één feit dat stilletjes de helft verklaart van wat volgt.

Het model heeft geen geheugen. Tussen twee calls onthoudt het niets — niet je vorige vraag, niet zijn eigen vorige antwoord, niet het bestand dat je hebt bijgevoegd, niet het feit dat je het al twee keer hebt gevraagd. Elke call start met een lege machine, en het enige wat die machine weet is de reeks tokens die je hem net hebt gegeven.

Wat in een chatinterface op geheugen lijkt, is je client die het hele gesprek opnieuw verstuurt, elke turn, vanaf het begin. Het model leest alles opnieuw vanaf nul, elke keer. Hoofdstuk 13 mat wat dat herlezen kost in een forward pass; Hoofdstuk 16 zet het om in een regel op een factuur. Wat hier telt, is het gevolg voor ontwerp: de prompt is geen bericht aan een systeem dat state heeft. Hij is de state.

Dat ruimt een hele familie verwarringen op. "Het model is vergeten wat ik het vertelde" betekent meestal dat het nooit is meegestuurd. "Het negeerde mijn eerdere instructie" betekent meestal dat de instructie uit het venster viel toen de historie werd afgekapt. "Het gedroeg zich anders in productie" betekent meestal dat productie een andere prompt samenstelt dan de prompt die je hebt getest. Geen van deze dingen is een modelprobleem, en geen ervan wordt opgelost door iets te herformuleren.

De bewering "deze prompt is beter" is een bewering over een verdeling, en je kunt geen verdeling zien door naar één output te kijken. Wat je nodig hebt is saai: cases met bekende antwoorden, N varianten en een interval.

De harness is vijftig regels TypeScript met dezelfde vorm als de client uit Hoofdstuk 14 — een request, een deadline, wat concurrency, een telling. Hij keert terug in Hoofdstuk 19 om een retriever te evalueren en in Hoofdstuk 29 als de golden set.

bench.tsTS
export type Case = { input: string; expected: string };
export type Variant = { name: string; build: (c: Case) => ChatMessage[] };

async function pooled<T, R>(xs: T[], n: number, f: (x: T) => Promise<R>) {
  const out: R[] = new Array(xs.length);
  let i = 0;
  await Promise.all(
    Array.from({ length: n }, async () => {
      while (i < xs.length) {
        const k = i++;
        out[k] = await f(xs[k]);
      }
    }),
  );
  return out;
}

export async function runVariant(v: Variant, cases: Case[], concurrency = 6) {
  const hits = await pooled(cases, concurrency, async (c) => {
    const answer = await complete(v.build(c));      
    return answer.trim().toLowerCase() === c.expected;
  });
  return { name: v.name, hits, k: hits.filter(Boolean).length, n: cases.length };
}

Het getal dat terugkomt is niet het resultaat. Dit is het:

stats.tsTS
/** 95 % Wilson score interval for a proportion. Chapter 4 derives it. */
export function wilson(k: number, n: number, z = 1.96) {
  const p = k / n;
  const d = 1 + (z * z) / n;
  const centre = (p + (z * z) / (2 * n)) / d;
  const half = (z * Math.sqrt((p * (1 - p)) / n + (z * z) / (4 * n * n))) / d;
  return [Math.max(0, centre - half), Math.min(1, centre + half)] as const;
}

Hoofdstuk 4 maakte het argument en dit hoofdstuk verzilvert het. Zeventien goed van de twintig is 85 %, en het 95%-interval loopt van 64 % tot 95 %. Een variant die 13 van de 20 scoort — 65 %, wat duidelijk slechter voelt — heeft een interval van 43 % tot 82 %. Die twee intervallen overlappen over bijna hun hele lengte. Twintig cases kunnen geen goede prompt van een middelmatige onderscheiden, en het meeste gepubliceerde prompt-advies is op minder gevalideerd.

Zestig cases, wat dit hoofdstuk gebruikt, is nog steeds niet veel. Het is genoeg om grote effecten te zien en eerlijk genoeg om toe te geven wanneer het kleine niet kan zien — en dat zal hieronder meerdere keren gebeuren.

Drie blokken — de regels R, het ticket T, de instructie I — samengevoegd tot één user-bericht. Alle zes permutaties, byte-identieke content, zestig cases elk.

volgorde van de drie blokkencorrectaccuracy, 95 % Wilson
regels, instructie, ticket33/6055,0 % [42,5, 66,9]
regels, ticket, instructie30/6050,0 % [37,7, 62,3]
ticket, regels, instructie22/6036,7 % [25,6, 49,3]
instructie, ticket, regels21/6035,0 % [24,2, 47,6]
instructie, regels, ticket17/6028,3 % [18,5, 40,8]
ticket, instructie, regels16/6026,7 % [17,1, 39,0]

Van beste naar slechtste is 28,3 punten, en de intervallen overlappen niet, dus dit is geen verhaal over ruis. Omdat elke arm op dezelfde zestig items wordt gescoord, is de scherpere vraag de gepaarde: van de cases waarin twee armen het oneens zijn, hoe scheef is de verdeling? Van de slechtste volgorde naar de beste gaan draaide 21 cases naar goed en 4 naar fout — exacte gepaarde probability 0,0009.3

Lees de tabel om zijn vorm, niet om zijn winnaar. De twee beste rijen eindigen allebei met het ticket; de twee slechtste begraven allebei de instructie in het midden of laten hem na de data komen. Dat is hetzelfde fenomeen dat Liu et al. Lost in the Middle noemden: materiaal aan de randen van een prompt wordt betrouwbaarder gebruikt dan materiaal in het midden.4 Hoofdstuk 16 beprijst het venster en Hoofdstuk 24 meet het effect netjes op lengte, waar het midden instort zoals beschreven en het herstel helemaal aan het einde niet terugkeert. Hier valt de praktische regel vanzelf uit: taak bovenaan, data onderaan, niets belangrijks in het midden.

Verplaats nu dezelfde woorden tussen turns. Hoofdstuk 11 stelde vast dat de chattemplate geen decoratie rond het model is, maar er deel van uitmaakt — <|im_start|>system en <|im_start|>user zijn echte tokens die het model tijdens fine-tuning miljoenen keren heeft gezien, precies op die posities. Het zou er dus toe moeten doen aan welke kant van die markers je instructie landt, en dat doet het:

waar dezelfde woorden staancorrectaccuracy, 95 % Wilson
regels en instructie in de system-turn, ticket alleen in de user-turn46/6076,7 % [64,6, 85,6]
regels in de system-turn, instructie en ticket in de user-turn44/6073,3 % [61,0, 82,9]
regels en instructie in de system-turn, instructie herhaald na het ticket42/6070,0 % [57,5, 80,1]
alle drie blokken in één user-turn33/6055,0 % [42,5, 66,9]

De regels en de instructie over de templategrens heen verplaatsen leverde 21,7 punten op — 19 cases gewonnen, 6 verloren, gepaarde probability 0,0146 — zonder er een teken van te veranderen. Dit is het concrete antwoord op system prompt versus user prompt: het zijn niet twee manieren om hetzelfde te zeggen. Het zijn twee verschillende tokenposities in een structuur waarop het model is getraind, en de system-positie is waar instructies thuishoren die voor het hele gesprek gelden.

Let ook op de derde rij. De instructie herhalen na het ticket — een vaak aanbevolen truc — scoorde lager dan hem één keer noemen. Op dit model, bij deze taak, was het twee keer zeggen slechter dan het één keer zeggen.

Delimiters, en de statistische les die erin verscholen zit

Link naar de sectie: Delimiters, en de statistische les die erin verscholen zit

Dezelfde prompt, beste plaatsing, zestig cases. Het enige wat verandert is wat de tickettekst omringt.

hoe het ticket is afgebakendcorrectaccuracy, 95 % Wilson
een XML-achtige tag51/6085,0 % [73,9, 91,9]
helemaal niets48/6080,0 % [68,2, 88,2]
een Markdown-kop47/6078,3 % [66,4, 86,9]
een label, Ticket:46/6076,7 % [64,6, 85,6]
hash fences45/6075,0 % [62,8, 84,2]
triple backticks44/6073,3 % [61,0, 82,9]
dubbele aanhalingstekens40/6066,7 % [54,1, 77,3]

Een spreiding van achttien punten door interpunctie. Maar kijk naar de twee extreme intervallen: [73,9, 91,9] en [54,1, 77,3]. Ze overlappen. Volgens de grove lezing — vergelijk de foutbalken, en als ze elkaar raken, zeg je niets — bewijst deze tabel helemaal niets.

Die grove lezing is hier verkeerd, en begrijpen waarom is waardevoller dan de tabel. Elke variant is gescoord op dezelfde zestig tickets, dus de twee metingen zijn geen onafhankelijke samples; ze zijn gepaard. Het grootste deel van de breedte van elk interval komt uit een onzekerheidsbron die beide armen delen — of deze zestig tickets representatief zijn — en die bron valt weg wanneer je ze met elkaar vergelijkt. Stel in plaats daarvan de gepaarde vraag en het antwoord is scherp: van dubbele aanhalingstekens naar de XML-tag gaan draaide 12 cases naar goed en 1 naar fout, gepaarde probability 0,0034. Dat is een echt verschil.

En daarna laat dezelfde test de kop leeglopen. De XML-tag versloeg het gewone Ticket:-label met 8,3 punten, het getal dat een blogpost in zijn titel zou zetten. Gepaarde test: 6 gewonnen, 1 verloren, probability 0,1250. Niet vastgesteld. Zeven cases is waar die beroemde verbetering op rust.

Er zijn dus twee vragen met twee verschillende instrumenten, en ze door elkaar halen is hoe prompt-advies in twee richtingen tegelijk misgaat:

Hoe goed is deze prompt? Het Wilson-interval op zijn eigen accuracy. Breed, tenzij je honderden cases hebt. Dit is het getal dat je rapporteert aan iemand die beslist of je gaat shippen.

Is B beter dan A? De gepaarde test over de cases waarin ze verschillen. Veel gevoeliger, omdat de gedeelde moeilijkheid van de set wegvalt. Dit is het getal dat je gebruikt om tussen twee kandidaten te kiezen.

De algemene bevinding — dat modellen sterk en onvoorspelbaar gevoelig zijn voor formattingkeuzes zonder semantische inhoud — is niet nieuw. Sclar et al. varieerden niets anders dan scheidingstekens, spatiëring en hoofdlettergebruik over tientallen taken en vonden accuracy-spreidingen die groot genoeg waren om gepubliceerde modelranglijsten om te keren.5 Het praktische gevolg is niet "gebruik XML-tags". Het is dat formatting een hyperparameter is, niets kost om te sweepen, en dat elke vergelijking van twee modellen die één format vastzet net zo goed formats als modellen vergelijkt.

In-context learning — het model uitgewerkte voorbeelden in de prompt laten zien en het daaruit laten generaliseren zonder enige weight update — is de capability die GPT-3 beroemd maakte.6 De praktische vraag is nooit of het werkt. Het is hoeveel voorbeelden je wilt betalen.

Voorbeelden gaan erin als echte eerdere turns, afwisselend user en assistant, omdat dat de structuur is waarop de template is getraind. Elke k werd uitgevoerd met vijf verschillende random trekkingen uit een afzonderlijke pool van zestien gelabelde tickets:

voorbeeldengemiddelde accuracyslechtste en beste trekkingspreiding over trekkingen
076,7 %
178,7 %78,3 – 80,0 %1,7 punten
283,7 %80,0 – 86,7 %6,7 punten
481,7 %78,3 – 86,7 %8,3 punten
883,7 %78,3 – 88,3 %10,0 punten
1689,3 %85,0 – 93,3 %8,3 punten

Twee voorbeelden leverden zeven punten op. De volgende zes voorbeelden leverden niets meetbaars op — 83,7, dan 81,7, dan 83,7, een reeks die binnen zijn eigen ruis dwaalt. Zestien leverden nog eens vijfenhalf op. De curve is geen soepele klim; het is een stap, een plateau en een stap.

De belangrijkste kolom is de laatste. Bij k = 8 verplaatste welke acht voorbeelden je toevallig koos de accuracy met 10 punten — groter dan de volledige winst van twee naar acht voorbeelden gaan. En de onderste rij is de scherpste versie ervan: bij k = 16 is de pool uitgeput, dus alle vijf runs bevatten exact dezelfde zestien voorbeelden, alleen in een andere volgorde. Alleen de volgorde verplaatste accuracy 8,3 punten.

Dat is het resultaat dat Lu et al. rapporteerden en het houdt stand overal waar ernaar is gezocht: voorbeeldvolgorde is een echte hyperparameter met effecten die vergelijkbaar zijn met voorbeeldaantal.7 Het eerlijke advies over few-shot prompting is dus geen getal. Het is:

Begin bij nul en voeg alleen voorbeelden toe tegen een meting

Link naar de sectie: Begin bij nul en voeg alleen voorbeelden toe tegen een meting

De eerste twee zijn meestal de moeite waard. Daarna gok je, en die gok kost tokens op elke afzonderlijke call voor de rest van de levensduur van het product.

Behandel de selectie als onderdeel van de prompt

Link naar de sectie: Behandel de selectie als onderdeel van de prompt

Twee goed gekozen voorbeelden verslaan acht slordig gekozen voorbeelden. Als je voorbeelden van de bovenkant van een spreadsheet kwamen, is dat de variabele om te sweepen voordat je er meer toevoegt.

Sweep de volgorde één keer, en zet hem dan vast

Link naar de sectie: Sweep de volgorde één keer, en zet hem dan vast

Het is gratis, het is een echt effect, en anders dan het meeste in dit hoofdstuk vraagt het geen herschrijving om te proberen.

Vier voorbeelden met allemaal hetzelfde label leren het model het label, niet de taak. Dat dit model instortte op de wachtrij die als laatste werd genoemd, is dezelfde fout in een ander kostuum.

Nu de folklore. Elk hiervan is één zin die vóór een verder identieke system prompt wordt gezet, op dezelfde zestig cases.

zin toegevoegd aan de system promptcorrectaccuracy, 95 % Wilsongepaard tegen baseline
niets toegevoegd46/6076,7 % [64,6, 85,6]
"Take a deep breath and work on this problem carefully."47/6078,3 % [66,4, 86,9]+4 / −3, p = 1,000
"This is very important to my career."46/6076,7 % [64,6, 85,6]+5 / −5, p = 1,000
"You are a world-class customer support operations expert with twenty years of experience."42/6070,0 % [57,5, 80,1]+3 / −7, p = 0,344
"I will tip you $200 if you answer correctly."41/6068,3 % [55,8, 78,7]+1 / −6, p = 0,125
"You will be penalised for every ticket you send to the wrong queue."25/6041,7 % [30,1, 54,3]+3 / −24, p < 0,001

Vier van de vijf deden niets. Niet "een beetje"; niets wat zestig gepaarde cases kunnen zien. De expertpersona en de omkoping scoorden allebei onder de onaangeraakte baseline, en zelfs die dalingen halen de gepaarde test niet — het is ruis die naar beneden wijst.

De derde rij is degene om bij stil te staan. "This is very important to my career" produceerde exact dezelfde accuracy, 46 van de 60 — en tien van de zestig antwoorden veranderden, vijf in elke richting. De samenvattende statistiek was identiek en het gedrag niet. Als je evaluatie één getal over een kleine set is, kan een wijziging die een zesde van je outputs herschrijft eruitzien als een wijziging die niets deed, en je shipped hem in de overtuiging dat hij gratis was.

En dan de dreiging, de enige zin die de naald bewoog en hem 35 punten omlaag bewoog, waarbij 24 cases van goed naar fout draaiden. Dat is geen afrondingsartefact; het is ander modelgedrag. De les is niet "bedreig een model nooit". Het is dat emotionele framing niet inert is. Het verschuift de verdeling, soms hard, in een richting die niemand kan voorspellen door de zin te lezen — precies daarom moet het worden gemeten in plaats van beredeneerd.

Een kanttekening die dit hoofdstuk je verschuldigd is: deze vijf zinnen zijn getest op één klein model en één taak. Sommige hebben elders gepubliceerde steun — "take a deep breath" kwam uit een paper dat naar hoog scorende instructies zocht in plaats van ze te verzinnen, wat een andere en betere claim is dan de claim die daarna rondging.8 Wat generaliseert zijn niet de zinnen. Het is dat de lijst die blogposts overleefde en de lijst die meting overleeft twee verschillende lijsten zijn, en de enige manier om te weten welke je in handen hebt is de bench draaien.

Een regel die iedereen herhaalt — zeg wat je wilt, niet wat je niet wilt — met de gebruikelijke afwezigheid van een getal. Hier is het getal. Dezelfde formatvereiste, op drie manieren geschreven, waarbij het model vrij genereert zodat compliance kan worden geobserveerd:

hoe de formatregel is geschrevenoutput was exact één toegestaan woordgemiddelde outputtokens
"Answer with one word."10/60 (16,7 %)2,6
"Do not explain yourself. Do not write a sentence. Do not add punctuation."1/60 (1,7 %)14,0
beide samen41/60 (68,3 %)2,3

Drie verboden deden het slechter dan één instructie, en lieten het model vijf keer meer tekst schrijven — precies het tegenovergestelde van alle drie tegelijk. De positieve zin terug toevoegen redde het naar 68 %.

Het mechanisme is niet mysterieus zodra je Hoofdstuk 8 onthoudt. Het model kiest een next token uit een verdeling die is geconditioneerd op alles ervoor, en een verbod zet het verboden ding in die conditionering. Er is geen operator voor ontkenning; er is een context waarin een woord nu verschijnt.

Dat is rechtstreeks meetbaar. Neem de baseline prompt en voeg één regel toe: Do not use the shipping queue for software problems. Kijk dan alleen naar de vijfenveertig tickets die geen shipping-tickets zijn:

shipping gekozengemiddelde probability op shippingtotale accuracy
baseline11,1 % van de 45 cases0,13176,7 % [64,6, 85,6]
nadat het bij naam verboden werd37,8 %0,37451,7 % [39,3, 63,8]

Een wachtrij noemen om hem uit te sluiten liet het model die drie keer vaker kiezen, bijna verdrievoudigde de probability mass die het eraan toekende, en kostte 25 punten totale accuracy — 16 cases verloren tegenover 1 gewonnen, gepaarde probability 0,0003.

Denk niet aan een olifant, gemeten. De herschrijving is altijd dezelfde: vervang het verbod door de positieve regel die het overbodig maakt. Niet "gebruik shipping niet voor softwareproblemen" maar "gebruik shipping alleen wanneer er een fysiek pakket bij betrokken is".

Het eerlijke tegenvoorbeeld: chain of thought dat kost en niets oplevert

Link naar de sectie: Het eerlijke tegenvoorbeeld: chain of thought dat kost en niets oplevert

Hoofdstuk 12 bouwde chain of thought netjes op — eerst als promptingtechniek,910 daarna als iets dat met verifieerbare rewards is getraind — en eindigde met een waarschuwing die het naar dit hoofdstuk doorschoof: een model vertellen om stap voor stap te denken stopt met helpen zodra het model zelf redeneert, en kan schaden. Hier is die waarschuwing met een tabel eronder, op een taak waarbij het makkelijk is om aan te nemen dat meer denken beter moet zijn.

Beide armen worden met hetzelfde instrument op dezelfde positie gelezen. Het enige verschil is of een chain of thought die het model zelf schreef eerst in de context staat.

armcorrectaccuracy, 95 % Wilsonextra outputtokens per case
geen chain of thought37/6061,7 % [49,0, 72,9]0
chain of thought, tot 60 tokens34/6056,7 % [44,1, 68,4]53,1
chain of thought, tot 200 tokens34/6056,7 % [44,1, 68,4]97,7

Accuracy ging omlaag en kosten gingen omhoog, en de eigen regel van dit hoofdstuk geldt voor het eigen resultaat van dit hoofdstuk: de daling is 7 cases gewonnen tegenover 10 verloren, gepaarde probability 0,629, wat niet is vastgesteld. Wat wel is vastgesteld, is dat het achtennegentig extra outputtokens per call produceerde en er niets meetbaars voor kocht. De onzekerheid zit volledig aan de batenkant. De rekening is zeker.

Een chain die faalt is leerzamer dan een die werkt. Gevraagd om te redeneren over "Your Slack integration stopped posting messages after Tuesday", schreef het model:

TEXT
1. Check if the issue persists on Monday.
2. Verify if there are any updates or changes in your Slack setup that
   might affect message posting.
3. If no update has been made since Tuesday, check for any recent system
   restarts or downtime affecting Slack functionality.
4. If you have recently installed new software or updated your
   environment, ensure it's compatible with Slack version.
5. Contact Slack support for further assistance or troubleshooting steps.

Dat is competent troubleshootingadvies en het is niet de taak. Gevraagd om te denken, dwaalde het model af naar het genre waar "think step by step about this support ticket" in zijn trainingsdata het meest op lijkt — en beantwoordde daarna een classificatievraag met vijfhonderd tekens aan ongerelateerde reasoning in zijn eigen context. Chain of thought helpt bij problemen met tussenliggende state die het waard is om te berekenen: rekenen, multi-hop lookups, constraint satisfaction. Een zin in een van vier buckets routeren heeft geen tussenliggende state. Er is niets voor de chain om vast te houden, dus voegt hij alleen plausibele tekst toe die de uiteindelijke beslissing vervolgens moet overleven.

Twee praktische corollaria. Ten eerste is de instructie voor een model dat is getraind om te redeneren — de RLVR-modellen uit Hoofdstuk 12 — erger dan overbodig: hij kan de lange chain die het model zou hebben geproduceerd vervangen door een korte, prompt-vormige chain. En meerdere chains samplen en stemmen, wat self-consistency doet,11 kan een taak met niets om het over oneens te zijn niet redden: het vermenigvuldigt de kosten met het aantal samples om ties te breken die er niet zijn. Hoofdstuk 12 mat die trade-off waar hij wel van toepassing is. Ten tweede: let op wat de vergelijkingssteiger zelf kostte. Het antwoord afdwingen in een Final queue:-regel liet de arm zonder reasoning dalen van 76,7 % naar 61,7 %. Vijftien punten, betaald om de twee armen vergelijkbaar te maken. Structuur die voor jouw gemak bestaat is ook niet gratis.

Nog één meting, omdat dit de vraag is die iedereen stelt na het eerste verrassende resultaat. Zestig prompts, greedy decoding, herhaald uitgevoerd:

  • Dezelfde call herhaald terwijl alles vast werd gehouden leverde bit-identieke probabilities op. Deterministisch.
  • Dezelfde call gebatcht met andere buren — batchgroottes 1, 4, 12, 30 en 60 — leverde probabilities op die tot 0,0128 verschilden. Het gekozen label veranderde nooit, in 0 van de 60 cases.

Het label overleefde omdat het ruimte had: over de zestig cases was de kleinste kloof tussen de top twee wachtrijen 0,0459, drieënhalf keer de drift. De stabiliteit was geen eigenschap van het algoritme. Het was een marge, en marges raken op. Hoofdstuk 17 is waar de rekenkundige reden staat en waar de samplingknoppen die die kloven breder en smaller maken uit elkaar worden gehaald. De reden om het hier te planten is dat het begrenst wat elke prompt-meting kan betekenen: de bench meet een systeem dat alleen tot op een tolerantie reproduceerbaar is, en een verschil van twee punten tussen varianten valt op een slechte dag binnen die tolerantie.

Alles hierboven is een mens die een variant kiest en een machine die hem beoordeelt. De voor de hand liggende volgende stap is de machine ook de varianten laten kiezen.

APE doet precies dat: een model stelt kandidaatinstructies voor, ze worden gescoord op held-out voorbeelden, en de beste blijven over.8 De instructies die het vindt zijn vaak instructies die geen mens zou schrijven, en dat is het punt — de search gaat over wat scoort, niet over wat professioneel klinkt.

DSPy gaat verder en is het nuttigere idee voor een product.12 Je declareert wat elke stap van een pipeline neemt en teruggeeft, en het framework compileert dat naar prompts, selecteert demonstrations en optimaliseert instructies tegen je metric. Verander je van model, dan compileer je opnieuw in plaats van te herschrijven. De prompt stopt met source code te zijn die iemand met de hand afstemt en wordt een artefact dat tegen een metric wordt gegenereerd, wat het altijd al had moeten zijn.

Geen van beide haalt de noodzaak voor de bench weg. Beide maken hem het enige wat je nodig hebt, omdat een optimiser zonder metric niets optimaliseert.

Wat overblijft is discipline. Prompts horen in version control, in files, naast de code die ze verstuurt — niet in een databaserij die iemand op een dinsdag heeft bewerkt. Ze hebben een versie-ID nodig dat naast elke output wordt opgeslagen die ze hebben geproduceerd, anders kun je op de dag dat iets regresseert niet achterhalen wat er veranderde. Ze hebben de bench nodig in continuous integration, omdat een prompt het ene deel van je systeem is dat een vendor stilletjes ongeldig kan maken door een nieuw model te deployen. En ze hebben cases nodig: geen honderd slimme, alleen de saaie twintig die vorig kwartaal stukgingen, voor altijd bewaard. De bench is de deliverable. De prompt is er een bijproduct van.

Alles in dit hoofdstuk is gemeten in accuracy. Elk van die varianten heeft ook een prijs.

De system prompt die 21,7 punten opleverde wordt op elke call verstuurd, voor altijd. De twee voorbeelden die zeven punten opleverden worden op elke call verstuurd, voor altijd. De zestien die er twaalf opleverden worden op elke call verstuurd, voor altijd, en ze zijn ongeveer tien keer zo lang als de vraag die de gebruiker echt stelde. De chain of thought die niets opleverde produceerde achtennegentig extra tokens per request, en outputtokens zijn de dure soort.

Niets daarvan is zichtbaar in een tabel met accuracies, en alles ervan is zichtbaar op een factuur.

Hoofdstuk 16 gaat over de eenheid waarin die beslissingen echt worden uitgedrukt. De token als billing unit, de context window als budget in plaats van geheugen, waarom een gesprek van veertig turns veel meer kost dan veertig keer de eerste turn, wat prompt caching wel en niet betaalt, en waarom de volgorde van je prompt bepaalt of de cache überhaupt hit — wat een tweede, volledig economische reden blijkt om het stabiele materiaal eerst te zetten en het variabele materiaal laatst.


De bench en elke tabel zijn geproduceerd met Qwen/Qwen2.5-0.5B-Instruct onder greedy decoding, dus ze reproduceren exact. De Hugging Face-documentatie over chattemplates is de referentie voor waar de template-markers van Hoofdstuk 11 daadwerkelijk naar expanden, en voor het feit dat een model dat met de verkeerde template shipped een echte en terugkerende fout is. Voor de positie- en format-effecten op productieschaal in plaats van laboratoriumschaal zijn de citaties hierboven de primaire bronnen; de prompting guides van vendors zijn nuttig vanwege hun voorbeelden en moeten worden gelezen in de wetenschap dat geen van hen een interval publiceert.

  1. Anthropic, Effective context engineering for AI agents (29 september 2025), voor het onderscheid tussen prompt en context dat in dit hoofdstuk wordt gebruikt en in Hoofdstuk 24 wordt uitgewerkt.

  2. Zhao, Z., Wallace, E., Feng, S., Klein, D. en Singh, S. Calibrate Before Use: Improving Few-Shot Performance of Language Models. arXiv:2102.09690 (2021). Majority-label-, recency- en common-token-bias, en waarom de rotatie in de bench van dit hoofdstuk niet optioneel is.

  3. McNemar, Q. Note on the sampling error of the difference between correlated proportions or percentages. Psychometrika 12(2), pp. 153–157 (1947). De gepaarde vergelijkingen in dit hoofdstuk gebruiken de exacte binomiale vorm in plaats van de chi-kwadraatbenadering, omdat de discordante aantallen klein zijn.

  4. Liu, N. F. et al. Lost in the Middle: How Language Models Use Long Contexts. arXiv:2307.03172 (2023). Hier aangehaald voor het positie-effect; op lengte gemeten in Hoofdstuk 24.

  5. Sclar, M., Choi, Y., Tsvetkov, Y. en Suhr, A. Quantifying Language Models' Sensitivity to Spurious Features in Prompt Design. arXiv:2310.11324 (2023). Alleen scheidingstekens en spatiëring verplaatsen accuracy genoeg om model-leaderboards te herordenen.

  6. Brown, T. B. et al. Language Models are Few-Shot Learners. arXiv:2005.14165 (2020). De paper die in-context learning introduceerde als capability in plaats van curiositeit; sectie 3 is de bron van de zero-shot / one-shot / few-shot-woordenschat die iedereen nu gebruikt.

  7. Lu, Y., Bartolo, M., Moore, A., Riedel, S. en Stenetorp, P. Fantastically Ordered Prompts and Where to Find Them: Overcoming Few-Shot Prompt Order Sensitivity. arXiv:2104.08786 (2021). Het resultaat dat in de few-shot-tabel hierboven is gereproduceerd.

  8. Zhou, Y. et al. Large Language Models Are Human-Level Prompt Engineers. arXiv:2211.01910 (2022). Automatic prompt engineering via voorstel en scoring. De veel geciteerde "take a deep breath"-instructie komt van Yang, C. et al., Large Language Models as Optimizers, arXiv:2309.03409 (2023), die hem vond door search op één taak met één model — een claim die de reis naar blogposts niet intact overleefde. 2

  9. Wei, J. et al. Chain-of-Thought Prompting Elicits Reasoning in Large Language Models. arXiv:2201.11903 (2022).

  10. Kojima, T., Gu, S. S., Reid, M., Matsuo, Y. en Iwasawa, Y. Large Language Models are Zero-Shot Reasoners. arXiv:2205.11916 (2022). Het "let's think step by step"-resultaat, en de moeite waard om te lezen vanwege hoe smal de omstandigheden waren.

  11. Wang, X. et al. Self-Consistency Improves Chain of Thought Reasoning in Language Models. arXiv:2203.11171 (2022). Gemeten met de kosten erbij in Hoofdstuk 12.

  12. Khattab, O. et al. DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines. arXiv:2310.03714 (2023).

Klaar om LIA te laten kiezen?

Bouw met elk AI-model op één plek — begin vandaag nog gratis.