Disseny de prompts
- Fine-tuning vs. prompting
- Prompt com a contracte
- Few-shot com a especificació
- Chain-of-thought per a models estàndard
- Models de raonament i prompting
- Errors de disseny habituals
- Prompts com a artefactes de codi
- Instruccions permanents de projecte (AGENTS.md)
Aquest document tracta el prompt com un artefacte de programari: com especificar el comportament del model amb instruccions, exemples i tècniques de raonament, i com mantenir-lo i provar-lo com qualsevol altre codi. Com es crida el model des del codi és a Integració i execució, i com es componen diverses crides en sistemes, a Orquestració amb workflows i agents.
Mira què rep realment el model en una crida d’un assistent de suport: el system prompt amb les regles, tres fragments recuperats de la base de coneixement, els quatre torns anteriors de la conversa, i el resultat de l’eina consultar_comanda que s’ha cridat fa un torn. Tot junt, al mateix context, cada vegada. El prompt ja no és una frase: és aquest paquet, i sol créixer a cada interacció. Compondre’l i mantenir-lo net és el que s’anomena context engineering.
Les peces que el formen es tracten per separat: les instruccions del sistema, els exemples com a especificació i les tècniques de raonament en aquest document, i la composició del context complet (sortida estructurada, gestió de la memòria, integració de resultats d’eines) a Integració i execució. Entendre cada peça per separat és necessari; construir sistemes robustos requereix entendre com interactuen.
Fine-tuning vs. prompting
Fine-tuning modifica els pesos del model per adaptar-lo a una tasca; prompting utilitza el model tal com és, guiant-lo amb instruccions i exemples dins del text d’entrada:
| Criteri | Prompting | Fine-tuning |
|---|---|---|
| Dades disponibles | Poques o cap | Centenars a milers d’exemples |
| Necessitat d’adaptació | Format de resposta | Coneixement específic del domini |
| Cost | Baix (només inferència) | Alt (entrenament + GPU) |
| Temps de desplegament | Immediat | Hores a dies |
| Manteniment | Fàcil d’iterar | Cal reentrenar |
Regla pràctica: comença sempre amb prompting (zero-shot → few-shot → chain-of-thought). Si la tasca és de raonament complex i el model estàndard no és suficient, prova un model de raonament abans de passar a fine-tuning. El fine-tuning és l’últim recurs: és car, lent d’iterar i no sempre supera un bon prompt.
Prompt com a contracte
Un prompt no és una instrucció informal adreçada a un assistent: és la interfície de programació entre el sistema i el model. Defineix el comportament esperat, les restriccions de la tasca i el format de la sortida. Canviar el prompt canvia el comportament del sistema, igual que canviar el codi.
Els models de l’API de chat reben una seqüència de missatges amb rols diferenciats (el protocol Chat Completions presentat a Arquitectura de sistemes LLM):
system: instruccions del desenvolupador. Defineix el rol, el context i les restriccions del model per a tota la conversa. Habitualment és el primer missatge i apareix una sola vegada. L’usuari no el veu ni el pot modificar. Cada context o desplegament pot tenir un system prompt diferent. Cada proveïdor usa terminologia pròpia per a aquest rol (developer message, instruccions de prioritat), però la semàntica és la mateixa. Els models de raonament apliquen regles pròpies per al system prompt (vegeu Models de raonament i prompting).user: entrada de l’usuari o del sistema que genera la petició.assistant: resposta del model. En una conversa multi-torn, l’historial de missatges anteriors es passa explícitament a cada crida.
El model no té estat: no recorda res entre crides. El que sembla una sessió és una il·lusió mantinguda per l’aplicació, que reenvia l’historial complet de missatges en cada crida: el model veu tot el context cada vegada, com si fos la primera. El cas habitual és que el system prompt es fixi al principi i només creixin els torns user i assistant. Vegeu Estat, memòria i multi-torn.
El system prompt és la peça més important del disseny: estableix les regles del joc per a tota la interacció. Ha de ser precís, concís i testable.
La distinció entre posar instruccions al system prompt o al contingut de l’usuari importa principalment en converses multi-torn: en una crida puntual amb entrada de confiança, la diferència pràctica és mínima. Els dos casos on el system prompt manté l’avantatge fins i tot en crides individuals: la resistència a la injecció de prompt (quan el missatge de l’usuari conté dades externes no controlades, les instruccions al system prompt són més difícils de sobreescriure) i l’eficiència del caching de prefix (quan moltes crides comparteixen el mateix system prompt, el proveïdor el pot reutilitzar de la memòria cau; vegeu Prefix caching).
messages = [
{
"role": "system",
"content": "Ets un analista de sentiment per a ressenyes de productes. "
"Respon sempre en JSON amb els camps 'sentiment' i 'confiança'."
},
{
"role": "user",
"content": "El producte és fantàstic, però el lliurament va trigar massa."
}
]
Few-shot com a especificació
La manera més eficaç d’especificar un comportament complex no és descriure’l amb paraules, sinó mostrar-lo amb exemples.
Per què les paraules fallen
Una instrucció com “extreu les accions pendents com a JSON” deixa una dotzena de preguntes sense resposta: si no hi ha termini, s’omet el camp, s’escriu null, o ""? Si hi ha múltiples accions, van en una llista o en missatges separats? “Abans de divendres” és un termini vàlid o cal normalitzar-lo? Es pot intentar cobrir cada cas amb més frases, però cada frase nova obre ambigüitats noves.
Com funcionen els exemples
El model és, fonamentalment, un completador de patrons. Quan veu un missatge d’usuari seguit d’una resposta d’assistent, aprèn: donat aquest tipus d’entrada, produeix aquest tipus de sortida. La instrucció li diu què fer; l’exemple li mostra exactament com. Un sol exemple comunica el nom dels camps, la granularitat, el tractament de nuls i l’estructura de la llista, tot allò que és tediós o ambigu de descriure amb paraules.
messages = [
{
"role": "system",
"content": "Extreu les accions pendents d'un text de reunió."
},
# exemple: defineix el format, el tractament de terminis i l'estructura
{
"role": "user",
"content": "Reunió 15/03: cal revisar el disseny abans de divendres."
},
{
"role": "assistant",
"content": '{"accions": [{"tasca": "revisar el disseny", "termini": "divendres"}]}'
},
# petició real
{
"role": "user",
"content": text_reunió_real
},
]
L’analogia amb TDD
Els exemples few-shot són l’equivalent LLM dels tests com a especificació. En TDD, els tests defineixen el contracte de manera precisa i executable: no es descriu el comportament en prosa, es mostra. Uns pocs exemples ben triats (cas feliç, termini absent, múltiples accions) cobreixen l’espai de comportament millor que un paràgraf de regles, i el model generalitza a partir d’ells.
Quan usar-los
El zero-shot és suficient quan la sortida és inequívoca (classificar com a positiu/negatiu). Cal afegir exemples quan hi ha un esquema JSON específic, casos límit que cal tractar de manera consistent, o un to i format difícil de descriure. Normalment 1–3 exemples són suficients; el rendiment incremental cau ràpidament a partir de 5.
Chain-of-thought per a models estàndard
⚠️ Aquesta tècnica és per a models estàndard. Els models de raonament generen el raonament internament sense que calgui demanar-ho: afegir-hi instruccions CoT no millora el resultat i pot empitjorar-lo. Vegeu Models de raonament i prompting.
La tècnica chain-of-thought (CoT) demana al model que raoni explícitament pas a pas abans de donar la resposta final. En lloc de produir directament la resposta, el model genera una cadena de raonament intermèdia que millora la qualitat en tasques que requereixen múltiples passos: matemàtiques, lògica, planificació, diagnosi.
La forma més senzilla és afegir una instrucció al prompt:
messages = [
{
"role": "system",
"content": "Raona pas a pas abans de donar la resposta final."
},
{
"role": "user",
"content": "Una botiga té 48 productes. El 25% estan en oferta. Quants productes no estan en oferta?"
},
]
El model generarà: “El 25% de 48 és 12. Per tant, 48 − 12 = 36 productes no estan en oferta.” La cadena de raonament redueix errors i fa la resposta verificable, en lloc d’un simple “36” que pot ser correcte per accident.
Zero-shot CoT: la instrucció "Pensa pas a pas" sol ser suficient. No cal cap exemple.
Few-shot CoT: proporcionar exemples on la resposta inclou el raonament explícit. Més efectiu per a tasques amb un format de raonament molt específic.
Quan ajuda: raonament multi-pas, aritmètica, problemes de lògica, diagnosi de causes. Quan no ajuda: classificació simple, extracció de dades, tasques on la resposta correcta és directa. En aquests casos, CoT afegeix tokens sense benefici.
Tradeoff: CoT incrementa la longitud de la sortida (i per tant el cost i la latència). Per a sistemes en producció amb sortida estructurada, s’usa sovint un camp "raonament" al JSON que es descarta un cop validat: permet al model raonar sense contaminar la sortida final.
class RespostaAmbRaonament(BaseModel):
raonament: str # cadena de pensament, es descarta
resposta: str # l'únic camp que es propaga al sistema
# la crida demana aquest esquema amb response_format (vegeu Integració i execució)
resultat = RespostaAmbRaonament.model_validate_json(resposta.choices[0].message.content)
sortida_final = resultat.resposta # el raonament queda intern
Models de raonament i prompting
Els models de raonament representen una família diferent que no es pot tractar com un model estàndard de chat. La diferència fonamental: el model genera una cadena de pensament interna (scratchpad) abans de produir la resposta, consumint tokens d’entrada i sortida addicionals que no arriben a l’usuari. El raonament cru no sol ser accessible; alguns proveïdors n’exposen un resum com a camp opcional per a monitoratge i depuració, però no és pensament per a l’usuari final.
En comptes d’un pressupost fix de tokens de raonament, els models actuals tendeixen a exposar un paràmetre d’esforç (nivells de low a max) i a decidir ells mateixos quant pensen a cada petició. És el control principal del compromís entre qualitat, latència i cost, i val la pena calibrar-lo per ruta: sovint el nivell més alt no és el que dona millor resultat per euro.
Regles de prompting per a models de raonament:
- No demanis que raoni pas a pas: ja ho fa, i afegir-hi CoT explícit pot interferir amb el procés intern i reduir qualitat.
- Prompts concisos i directes: el model gestiona la complexitat internament; el prompt no ha de guiar el procés de raonament, només definir la tasca i les restriccions.
- Menys few-shot: uns pocs exemples o cap solen ser suficients. El model de raonament generalitza bé des de poc context.
- No esperis controlar la variabilitat amb
temperature: el raonament intern ja aporta diversitat, i molts models de raonament directament rebutgen els paràmetres de mostreig (vegeu Mostreig i control de sortida). Regula l’esforç, no la temperatura. - El raonament visible és una eina de depuració, no una estratègia de disseny. Si un proveïdor n’exposa un resum, s’usa per entendre per què el model falla, no per mostrar-lo a l’usuari.
- Autoritat del system prompt reduïda: alguns models de raonament apliquen les instruccions del system prompt amb menys pes que els models estàndard, perquè el procés intern de raonament pot sobreescriure restriccions declarades. Les instruccions han de ser curtes i clares; les llistes llargues de regles solen tenir menys efecte que en models estàndard.
Quan usar un model de raonament vs. CoT en model estàndard:
| Situació | Recomanació |
|---|---|
| Tasca complexa de raonament multi-pas, pressupost alt | Model de raonament |
| Raonament multi-pas, pressupost limitat | Model estàndard + CoT |
| Extracció, classificació, tasques directes | Model estàndard sense CoT |
| Tasca on el procés de raonament és auditable | Model de raonament amb thinking exposat |
Els models de raonament costen significativament més per token i tenen latència més alta. La decisió de quan usar-los és econòmica tant com tècnica.
Errors de disseny habituals
Ambigüitat: si el prompt admet múltiples interpretacions, el model n’escollirà una de forma inconsistent entre crides. “Sigues breu” és ambigú; “Respon en una sola frase” no ho és.
Excés d’instruccions: un system prompt amb moltes regles fa que el model ignori les menys prominents. Millor menys regles, ben prioritzades, que una llista exhaustiva.
Absència de restricció de format: sense especificar el format de sortida, el model el variarà entre crides. Sempre cal especificar el format explícitament, preferiblement amb sortida estructurada.
Regles crítiques enterrades enmig del prompt: els models presten més atenció al principi i al final del context que al mig (vegeu Estat, memòria i multi-torn). Les restriccions imprescindibles (format, prohibicions, prioritats) han d’anar al principi del system prompt o just abans de la pregunta de l’usuari, no entre paràgrafs d’instruccions secundàries.
Injecció de prompt: un usuari pot intentar sobreescriure les instruccions del sistema. És un vector d’atac amb el seu propi tractament; vegeu Seguretat, guardrails i validació.
Prompts com a artefactes de codi
Un prompt és lògica d’aplicació, no un string literal al mig del codi. Ha de viure en un fitxer propi, estar sota control de versions i passar pel mateix procés de revisió que qualsevol altra peça de codi. Canviar un prompt sense tests és equivalent a canviar una funció sense tests: pot trencar comportament de forma silenciosa.
Això connecta directament amb l’avaluació: quan es modifica un prompt, cal un mecanisme per verificar que el comportament resultant és l’esperat. Una eval és un test automatitzat del comportament del model: una parella entrada / sortida esperada (o un criteri de correctesa) que el sistema executa contra el model i verifica. A diferència dels tests unitaris convencionals, les evals han de tolerar que la sortida no sigui idèntica entre crides: el criteri de correctesa pot ser coincidència exacta, similitud semàntica, o un model jutge que avaluï la qualitat. La combinació prompt versionat + suite d’evals és la base d’un flux de treball sostenible. Per a l’arquitectura completa d’avaluació, vegeu Avaluació.
Instruccions permanents de projecte (AGENTS.md)
Els agents de programació llegeixen un fitxer d’instruccions del repositori (AGENTS.md, CLAUDE.md o equivalent) i l’afegeixen al context de cada sessió:
# AGENTS.md
- Fes servir pytest per validar els canvis.
- No modifiquis els tests.
- No afegeixis dependències sense mirar si ja hi ha una alternativa.
Sembla configuració, però és un system prompt guardat al repositori. Ningú no comprova que l’agent el compleixi: si modifica un test, no hi ha res que l’aturi. Fa uns comportaments més probables, i prou.
D’aquí surt la regla pràctica: si una cosa s’ha de complir sempre, no la deixis al fitxer. “No modifiquis els tests” escrit a AGENTS.md és una preferència; el mateix com a permís que bloqueja l’escriptura a tests/ és una garantia. El fitxer inclina el comportament, el codi l’assegura, i aquest codi és el que envolta el model, no el model (vegeu El model i el harness).
Per a la mateixa regla tens tres nivells de duresa, i val la pena triar-lo conscientment:
| On la poses | Què passa si l’agent la vol saltar |
|---|---|
Línia a AGENTS.md | pot fer-ho; és una preferència |
Permís que denega l’escriptura a tests/ | no pot: l’acció no s’executa |
| Hook que intercepta la crida abans d’executar-la | no pot: es rebutja i el model rep l’error |
| Test o CI que falla si els tests han canviat | pot fer-ho, però no arriba a main |
| No exposar-li l’eina d’escriptura | impossible per construcció |
El detall pràctic d’aquests mecanismes és a IA per al desenvolupament: els permisos, contenidors i llistes de comandes a Execució aïllada, i les portes automàtiques (linters, tipus, tests, CI) a Harness engineering. Allà hi trobaràs també el criteri per mantenir el fitxer d’instruccions curt i útil: Decisions de disseny explícites.
La resta ja s’ha vist a Errors de disseny habituals: les regles ambigües es compliran de forma inconsistent, i com més llarga sigui la llista, més probable és que el model n’ignori les menys destacades.