Strategy
Tokenkosten productbeschrijving-agent: 17 valkuilen
Je had de cijfers van de AI-productbeschrijving-agent al doorgerekend voordat je groen licht gaf. De eerste factuur was vier keer wat je sheet aangaf. Dit is waarom.

De juni-factuur van de LLM-leverancier kwam binnen om 23:14 op een dinsdag. €18.400, op een budget van €4.000. Je had de som tweemaal gemaakt. Je had zelfs een klein spreadsheet gebouwd — gemiddelde promptlengte, gemiddelde output, leveranciersprijs per miljoen tokens, vermenigvuldigd met 42.000 SKU-varianten. Jouw getal kwam uit op €3.800. Het werkelijke getal was bijna vijf keer dat.
De agent werkt. De beschrijvingen zijn prima. De catalogus staat live. De kosten kloppen niet, en de kosten zullen vanaf nu elke maand niet kloppen, totdat je uitvindt welke van de zeventien plekken je verkeerd hebt gemodelleerd.
Dit is die lijst, gerangschikt op de naarste vraag die je kunt stellen: als je morgenochtend de fout opmerkt, wat kost het om hem te herstellen? Eén regel in een prompt-template, een avond de catalogus opnieuw embedden, of een volledige rebuild van de retrieval-laag.
De economie, vóór de lijst
Een productbeschrijving-agent kent drie kostenposten die founders routinematig als één behandelen. De input tokens die je verstuurt (briefing, brand voice, voorbeelden, productattributen). De output tokens die het produceert (de beschrijving zelf, plus eventuele reasoning die je hebt gevraagd). De embedding tokens die je éénmalig betaalt wanneer je de catalogus indexeert voor retrieval. Elke post heeft een eigen prijs, een eigen model, en een eigen knop. Kosten verkeerd toerekenen tussen deze drie is de erfzonde van elke overschrijding die wij ooit op tafel hebben gekregen.
De som die het eerst waard is om te maken: voor één variant-generatie, hoeveel input tokens zijn uniek voor die variant, en hoeveel zijn gedeeld met elke andere call in de batch? Het gedeelde deel is wat Anthropic's prompt caching factureert tegen ongeveer een tiende van het standaard input-tarief, na de eerste hit. Als 90% van je prompt gedeeld is — brand voice, tone guide, format-regels, few-shot-voorbeelden — en je hebt caching niet aanstaan, betaal je tien keer voor dat deel over 42.000 calls. Dat alleen verklaart het gat bij de meeste overschrijdingen die we onder ogen krijgen.
Fouten die je terugdraait in één prompt-template
Punten één tot tien. Verander een regel, deploy de orchestrator opnieuw, en de volgende batch kost wat hij hoort te kosten. De volgorde is grof — meeste impact eerst.
1. Modelniveau gekozen vanuit de playground-demo. Je hebt tien varianten getest in de chatconsole met een frontier-model, de tekst klonk warm, en je hebt dat niveau in productie gezet. Je hebt de briefing nooit opnieuw gedraaid op een Haiku-klasse model. Voor 42k varianten van een gestructureerde taak met een vaste brand voice en drie goede few-shot-voorbeelden slaagt het goedkopere niveau bijna altijd. Fix: verander het model-id in de orchestrator en draai een blinde A/B-test van 200 items voordat je vastlegt.
2. Prompt caching uit. Het staat standaard uit. Je moet er expliciet voor opteren met een cache_control-breakpoint of het equivalent van je leverancier. De brand voice, format-regels en het voorbeeldblok komen allemaal in aanmerking. Met caching aan kost dezelfde prompt op het gecachte deel ongeveer 10% van wat het was.
3. Wisselende data boven het stabiele blok. De cache hasht van boven naar beneden door de prompt. Als de SKU-id, de timestamp of de magazijncode in de eerste regel van het system-bericht staat, invalideert elke call en betaal je tot in de eeuwigheid het volle tarief.
# Slecht: een verse timestamp bovenaan zet de cache bij elke call buiten werking.
system = f"""
Generated at: {now}
SKU: {sku_id}
Brand voice: {brand_voice} # 8k tokens, verandert nooit
...examples, format rules...
"""
# Goed: stabiel blok eerst, gemarkeerd voor caching. Variantvelden onderaan.
messages = [{
"role": "system",
"content": [
{
"type": "text",
"text": BRAND_VOICE + FORMAT_RULES + EXAMPLES, # ~8k, stabiel
"cache_control": {"type": "ephemeral"},
},
{
"type": "text",
"text": f"SKU: {sku_id}\nAttributes: {attrs}", # ~300, vers
},
],
}]
4. Alleen input tellen. Output tokens kosten bij elke grote leverancier vier tot vijf keer zo veel als input. Een beschrijving van 600 tokens vermenigvuldigd met 42.000 varianten is de regel die het budget echt opblies. Schatten op basis van alleen input is hoe het spreadsheet er een factor vier naast zat.
5. Chain-of-thought die je nooit leest. Je vroeg om "reasoning" en "description" in de JSON omdat een blogpost zei dat het de output verbetert. Je hebt geen enkel reasoning-veld geopend. Het model produceerde er 400 output tokens van per variant. Strip het veld.
6. Uitgebreid JSON-schema. Het model schrijft braaf "meta_keywords_array_localized_nl_NL" omdat jij het veld zo hebt genoemd. Kortere veldnamen kosten minder output tokens, en je parser heeft er geen mening over.
7. Vertalen met het dure model. Eerst EN genereren, vervolgens dezelfde Sonnet-klasse call vragen om NL, DE en FR te renderen. Een goedkopere tweede pass — zelfs Haiku die Haiku vertaalt — doet dit werk voor een fractie. Beter nog: schrijf de briefing eenmaal in het Nederlands en vertaal vanaf daar.
8. De volledige taxonomie meesturen bij elke call. Je plakt de categorieboom van 12.000 tokens bij elke variant in de system-prompt. Cache het (zie #2). Beter: haal vooraf de drie categorieën op die voor deze variant relevant zijn en stuur alleen die mee.
9. Eén call per variant terwijl varianten 90% van de content delen. Een zwart T-shirt in S/M/L/XL is één beschrijving met vier maatregels. Batch per ouderproduct, vraag het model om n variantblokken in één call, post-process. Input tokens dalen 70–80%.
10. Observability-tool factureert per ingeladen karakter. Sommige gehoste tracing-tools rekenen op logvolume. Bij 42k runs × 8k tokens × retry-pogingen wordt die regel een eigen verrassing. Sample 5% in productie, log alles in dev.
Prompt caching invalideert zodra het gecachte prefix met één karakter verandert. Pin het brand-voice-blok aan een geversioneerd bestand en rol pas een nieuwe versie uit als je bereid bent te betalen voor het opnieuw opwarmen van de cache over de volgende duizend calls.
Fouten die een re-embed van de catalogus forceren
Punten elf tot vijftien. Geen van deze is een one-line fix. Elk kost een avond catalogus-verwerking en een zorgvuldige eval voordat je de retriever omzet. Het werk is onglamoureus en onvermijdelijk.
11. Embedding-model gekozen op een leaderboard, niet op je eigen tekst. MTEB-scores op Engelstalige Wikipedia voorspellen geen prestaties op Nederlandse productcopy met merkjargon. Bouw een gold set van 200 items uit je eigen catalogus en test drie kandidaten op recall@5. Multilingual modellen die op het Nederlands zijn afgesteld verslaan vaak de bekendere naam. Re-embed.
12. Ruwe HTML embedden. Iemand heeft de live productpagina door de embedder gepompt. Zestig procent van elke vector is <div class="row"> en Tailwind-class-ruis. Strip naar schone attributen — titel, merk, materiaal, kleur, hoofdkenmerken — en embed die. Re-embed.
13. 3072-dim embeddings voor een catalogus van 42k. Voor deze omvang is 1024-dim prima, kost ongeveer een derde aan opslag, en queries zijn merkbaar sneller. De grootste dimensie is zelden de juiste voor een kleine catalogus met gestructureerde attributen.
14. Per-product in plaats van per-variant chunks. De retriever geeft de ouderbeschrijving terug terwijl de agent de kleurvariant nodig had. Elke variant wordt een eigen rij, met de gedeelde ouderattributen eraan gehecht. Re-chunken, re-embed.
15. Geen taalkolom in de vector store. Meertalige catalogi halen Duitse buren binnen bij een Nederlandse generatie-call, omdat cosine similarity geen mening heeft over taal. Voeg een taalfilter toe op retrieval, normaliseer opnieuw met consistente stopwoorden, en re-embed.
Fouten die een rebuild van de catalogus forceren
Punten zestien en zeventien. Deze raken het schema of de index van de retrieval-laag. Plan een rustige week en een zorgvuldige cut-over.
16. Brute-force similarity search. pgvector zonder ivfflat- of hnsw-index doet een O(n)-scan op elke query. Bij 42.000 vectors en enig serieus verkeer stijgen zowel je retrieval-latentie als je CPU-rekening. De fix — een afgestemde index bouwen — is mechanisch simpel, maar je laadt de catalogus opnieuw zodra je weet welke parameters je wilt, en je moet je eval opnieuw draaien op de geïndexeerde store voordat je productie omzet.
17. Retrieval-grens gekoppeld aan de verkeerde sleutel. De agent haalt op via product_id, maar je team denkt in style_id, en een style groepeert varianten die de klant samen ervaart. De embedding is gebouwd tegen de verkeerde betekeniseenheid. Om dit te herstellen verander je het export-schema, re-embed je, hertune je de prompts die naar opgehaalde chunks verwijzen, en re-eval. Plan een week.
Wat je morgenochtend doet
Open één log-entry van gisteren. Tel de tokens en splits ze in drie regels: gecachte input, verse input, output. Als je niet kunt zien welke regel welke is, kun je punten één tot tien niet repareren. Toen wij de productcopy-pipeline opnieuw bouwden voor een Nederlandse woonaccessoireklant met ongeveer 38.000 SKU-varianten, liepen we tegen punt drie aan — een build-timestamp stond bovenaan de system-prompt en de cache hit geen enkele call. Door dat blokje vier regels naar beneden te schuiven daalde hun maandfactuur met 71%. De langere playbook voor dat soort werk staat onder AI-agents.
Kern
De meeste overschrijdingen bij een productbeschrijving-agent komen door prompt-cache-missers en alleen input tokens tellen. Beide zijn one-line fixes als je ze vindt voordat je de catalogus opnieuw embedt.
FAQ
Hoeveel kan prompt caching daadwerkelijk besparen op een productbeschrijving-agent?
Bij een typische opzet waar 80–90% van de prompt bestaat uit gedeelde brand voice en format-instructies, factureert het gecachte deel na de eerste hit tegen ongeveer 10% van het standaard input-tarief. Netto facturen dalen meestal 40–70%.
Is een Haiku-klasse model echt goed genoeg voor productbeschrijvingen?
Voor gestructureerde tekst met een duidelijke voice-guide en drie solide few-shot-voorbeelden bijna altijd wel. Draai een blinde vergelijking van 200 items tegen je huidige model op echte SKU's voordat je de hele catalogus omzet.
Hoe weet ik dat het embedding-model verkeerd is zonder alles opnieuw te embedden?
Bouw een gold set van 200 query/verwacht-resultaat-paren uit je eigen catalogus. Re-embed alleen die subset met twee of drie alternatieven en meet recall@5. Twee uur werk, geen productiewijziging.
Wat is het eerste om te checken als de factuur je verrast?
Open één log-entry en tel gecachte input, verse input en output tokens afzonderlijk. De meeste overschrijdingen zijn al zichtbaar in de eerste prompt waar je naar kijkt.