modulo 08 / lezione 36
Prompt in produzione e governance
Prompt template nel codice: variabili, versioni, test
Trasformare prompt ricorrenti in template mantenibili, tipizzati e verificabili dentro la codebase.
Prompt template nel codice: variabili, versioni, test
Un prompt usato una volta può vivere in chat. Un prompt usato da un’applicazione deve vivere nel codice, con la stessa disciplina di una funzione: input chiari, output atteso, versioni, test e responsabilità.
Il passaggio da prompt manuale a prompt template è uno dei momenti in cui molti progetti LLM diventano fragili. Se ti limiti a concatenare stringhe, dopo poche settimane non sai più quali parti sono istruzioni, quali sono dati, quali esempi sono ancora validi e quale modifica ha cambiato il comportamento.
Perché questa lezione conta
In produzione il prompt non è testo decorativo. È logica applicativa. Classifica, decide, riscrive, estrae, propone azioni, attiva tool. Deve quindi essere leggibile, versionabile e testabile.
Un template ben progettato permette di:
- cambiare prompt senza riscrivere codice applicativo;
- validare variabili obbligatorie;
- evitare injection accidentali da input utente;
- confrontare versioni;
- collegare prompt, schema ed eval;
- fare rollback.
Obiettivo operativo
Alla fine della lezione devi saper prendere un prompt ricorrente e trasformarlo in un template con variabili esplicite, contratto di rendering, versione, schema di output e test minimi.
Separare parti stabili e variabili
Un prompt template ha almeno quattro parti:
Istruzioni stabili. Regole del task, priorità, vincoli, stile, criteri di rifiuto.
Variabili. Dati che cambiano a ogni richiesta: ticket, diff, lingua, profilo utente, contesto.
Esempi. Few-shot o casi limite, se servono. Vanno trattati come parte versionata del comportamento.
Output contract. Formato atteso: testo, markdown, JSON, schema, tool call.
Esempio:
Sei un classificatore di ticket tecnici.
Regole:
- usa solo le categorie ammesse;
- se il ticket contiene dati sensibili, non ripeterli;
- se la categoria non è chiara, imposta needs_human_review=true.
Categorie ammesse:
{{allowed_categories}}
Ticket:
<ticket>
{{ticket_body}}
</ticket>
Rispondi in JSON conforme allo schema {{schema_version}}.
Qui è chiaro cosa è istruzione e cosa è dato. I delimitatori non sono sicurezza completa, ma riducono ambiguità e aiutano review.
Interfaccia del template
Ogni template dovrebbe dichiarare le variabili richieste:
type ClassifyTicketPromptInput = {
ticketBody: string;
allowedCategories: string[];
language: "it" | "en";
schemaVersion: "v1";
};
Questo evita prompt renderizzati con campi mancanti, placeholder dimenticati o valori incompatibili. Se usi un linguaggio senza tipi statici, definisci comunque uno schema runtime.
Versioni
Versiona separatamente ma collega:
- template prompt;
- schema di output;
- dataset di eval;
- modello o classe di modello;
- parametri rilevanti.
Non ogni correzione richiede una major version, ma ogni modifica di comportamento deve essere tracciabile.
Esempio:
classify-ticket/
v1/
prompt.md
output.schema.json
eval-cases.jsonl
README.md
v2/
prompt.md
output.schema.json
eval-cases.jsonl
changelog.md
Se cambi solo una parola per chiarezza e l’eval non cambia, puoi annotarlo come patch. Se cambi categorie, formato, esempi o criteri di rifiuto, stai cambiando comportamento.
Test minimi
I test sui prompt non verificano se il modello “capisce”. Verificano prima che il sistema costruisca correttamente la richiesta.
Test utili:
Rendering completo. Tutte le variabili vengono sostituite.
Variabili obbligatorie. Input mancante produce errore, non prompt rotto.
Escape e delimitazione. Input utente con caratteri strani non rompe struttura e delimitatori.
Snapshot mirati. Il prompt renderizzato è leggibile in diff, ma non contiene dati sensibili.
Schema collegato. Il template dichiara la stessa versione di schema che il parser userà.
Input limite. Ticket vuoto, testo lunghissimo, lingua non ammessa, categoria sconosciuta.
Esempio di test concettuale:
Dato ticketBody vuoto
Quando renderizzo il template
Allora il renderer rifiuta l'input con errore "ticketBody required"
E non chiama il modello
Compatibilità
Un template può rompere consumatori a valle anche se il testo sembra migliore. Se il codice si aspetta priority e il prompt ora risponde con severity, hai introdotto una breaking change.
La compatibilità va valutata su:
- nomi dei campi;
- enum;
- semantica delle categorie;
- lunghezza output;
- presenza di spiegazioni;
- condizioni di rifiuto;
- tool call disponibili.
Laboratorio guidato
Scegli un prompt che usi spesso. Trasformalo in template:
- estrai istruzioni stabili;
- identifica variabili;
- definisci tipo o schema dell’input;
- definisci formato di output;
- scrivi due casi di rendering;
- aggiungi un README con scopo, owner, versione e limiti.
Poi modifica il template in una seconda versione e scrivi un changelog breve: cosa cambia, perché, quali eval devono passare.
Output atteso
Devi produrre una piccola directory:
prompts/classify-ticket/
prompt.md
input.schema.json
output.schema.json
render.test.md
eval-cases.jsonl
README.md
Non serve implementare una piattaforma completa. Serve una forma che il team possa leggere, testare e versionare.
Errori comuni
Concatenare stringhe senza confini. Rende difficile distinguere istruzioni e dati.
Nascondere prompt nel codice applicativo. La review diventa difficile e i diff sono rumorosi.
Non testare il renderer. Molti bug avvengono prima della chiamata al modello.
Cambiare schema senza migrazione. Il prompt può rompere parser, dashboard o workflow a valle.
Checklist di verifica
- il template ha variabili dichiarate;
- il renderer rifiuta input incompleti;
- prompt, schema ed eval sono collegati;
- una modifica produce diff leggibile;
- so distinguere patch, minor e breaking change del prompt.
Collegamenti
- Modulo: Prompt in produzione e governance — questa lezione è la numero 36 del corso.
- Si collega alla lezione 15 sugli output strutturati e alla lezione 27 sulle regressioni.