GenAI in 10 Minutes è una guida tecnica per ingegneri che vogliono padroneggiare lo sviluppo di applicazioni basate su LLM. L’obiettivo è fornire una mappa operativa chiara per navigare la complessità della GenAI, focalizzandosi sui trade-off architetturali e sulle best practice necessarie per passare dal prototipo alla produzione.
Contenuti della serie:
- Dalle basi ai Foundation Model
- Progettare l’Architettura di un’Applicazione Enterprise
- CONTROLLO DELL’INFERENCE TRAMITE PROMPT ENGINEERING (questo articolo)
- Retrieval-Augmented Generation (RAG) e Knowledge Integration
- Fine-Tuning e Allineamento
- Architetture di Deployment, Serving e Scalabilità dei Modelli
- Eval Automatici e Monitoring della Qualità
- Sicurezza dei Sistemi GenAI
Questo articolo introduce tecniche e pattern di prompt engineering per rendere l’inferenza più controllabile, riducendo ambiguità, errori di formato e variabilità dell’output.
Interagire con un Large Language Model (LLM) è un’esperienza paradossale: stiamo dialogando con un’entità che ha letto tutto il sapere umano, ma che interpreta le nostre richieste con una letteralità disarmante. La qualità, l’accuratezza e la struttura della risposta non dipendono solo dall’intelligenza del modello, ma in modo critico da come viene posta la domanda.
Molti sviluppatori trattano il prompt come se il LLM possa leggerci nel cervello, oppure come una “ricerca su Google” un po’ più verbosa. È un errore costoso. In un contesto di produzione, il Prompt Engineering smette di essere un’arte empirica fatta di tentativi casuali e diventa una disciplina ingegneristica rigorosa.
L’obiettivo di questo articolo è trasformare il prompting da pratica empirica a programmazione in linguaggio naturale. Vedremo come rendere più controllabile l’output probabilistico di un LLM, come supportare compiti di ragionamento complessi e quali pattern (come Chaining e Templating) aiutano a costruire software robusto.
Anatomia di un prompt
Un prompt non è una semplice stringa di testo ma un pacchetto di istruzioni che configura lo stato iniziale della rete neurale per l’inferenza. Rappresenta l’unico canale di comunicazione per dirigere il comportamento del modello durante l’inferenza. Se consideriamo il modello come una funzione f(x), il prompt è l’argomento x complesso che determina se f restituirà un risultato utile o meno.
A differenza del Fine-Tuning (che vedremo nella Parte 5), il Prompt Engineering non modifica i pesi del modello. Sfrutta le capacità latenti già presenti. Per farlo in modo affidabile, è utile abbandonare prompt monolitici e adottare una struttura modulare composta da elementi funzionali distinti:
Un prompt efficace non è un blocco di testo monolitico, ma un sistema composto da elementi funzionali distinti:
- Instruction ⭢ Il comando esplicito (es. “Riassumi”, “Classifica”).
- Context ⭢ Informazioni di background per ancorare la risposta (es. documenti o dati specifici).
- Esempi ⭢ Casi concreti di input e output attesi (es. coppie domanda-risposta).
- Input Data ⭢ Il contenuto su cui operare.
- Output Formatting ⭢ La struttura richiesta (JSON, Markdown, lista puntata).
- Persona/Role ⭢ L’assegnazione di un ruolo (es. “Agisci come un esperto di finanza”) per modellare tono e stile.
La vera abilità non sta nell’usare tutti questi componenti sempre, ma nel saperli calibrare. Un prompt per un riassunto veloce richiede solo Instruction e Input Data. Un prompt per un’analisi legale richiede Context, Persona e Example.
Una volta vista questa scomposizione, diventa chiaro che molte tecniche avanzate — dall’In-Context Learning al Prompt Chaining fino al RAG — non sono altro che modi diversi di popolare e combinare questi stessi blocchi in modo sistematico.
In-Context Learning
Una delle capacità più rivoluzionarie degli LLM è l’In-Context Learning (ICL). Invece di dover riaddestrare il modello per imparare un nuovo compito (un processo lento e costoso), possiamo insegnarglielo semplicemente fornendo degli esempi all’interno del prompt. È una forma di apprendimento temporaneo: il modello non modifica i suoi “pesi” interni, ma adatta il suo comportamento solo per la durata di quella specifica conversazione. Rappresenta una delle abilità emergenti (non previste) più sorprendenti, nota sin dall’uscita di GPT-3.
In base a quanti esempi forniamo, cambia radicalmente il modo in cui il modello lavora:
- Zero-Shot (Nessun esempio) ⭢ Ci affidiamo interamente alla conoscenza generale del modello.
Esempio: “Traduci in inglese: ‘Il gatto è sul tavolo’.”
Quando usarlo: Funziona benissimo per compiti standard che il modello ha visto milioni di volte durante il suo addestramento (traduzioni, riassunti, cultura generale). - One-Shot / Few-Shot (Uno o più esempi) ⭢ Non ci fidiamo solo della sua conoscenza, ma gli mostriamo un pattern da replicare.
Quando usarlo: Fondamentale quando il compito è ambiguo, richiede un formato speciale o segue una logica aziendale specifica che il modello non può conoscere.
Quando si ricorre al Few-Shot Prompting si sta di fatto costruendo un mini dataset all’interno del prompt. Questo dataset va curato esattamente come se fosse destinato all’addestramento di un modello di ML. Questo significa che bisogna fornire esempi rilevanti e di qualità, con categorie non sbilanciate. In questo modo, ad esempio, si può istruire un modello di un sistema di support clienti a mappare i messaggi ricevuti da un cliente (es. “La cerniera è rotta”) in operazioni da innescare (es. “Reso”).
Tuttavia, va ricordato che aggiungere troppi esempi riempie la finestra di contesto del modello e di conseguenza si traduce in maggiori costi (computazionali ed economici). Per questo l’abilità dell’AI Engineer è quella di trovare il giusto bilanciamento tra quantità di esempi forniti e qualità dell’output del modello.
Sbloccare il ragionamento complesso
Mentre l’ICL aiuta a seguire dei pattern, i compiti logici o matematici richiedono strategie diverse. I LLM non “ragionano” nel senso umano; predicono token. Per risolvere problemi complessi, dobbiamo forzarli a esplicitare i passaggi intermedi.
Una delle tecniche più potenti — ormai integrata nei cosiddetti modelli di “reasoning” — consiste nel non chiedere direttamente la soluzione, ma istruire il modello a generare una catena di pensiero. Nella forma più semplice questo si riduce ad aggiungere una frase trigger come “Let’s think step by step” dopo la richiesta. Questo permette al modello di spendere più tempo (e più token di output) prima di rispondere, portandolo a scomporre il problema macro in sotto-problemi più semplici, riducendo drasticamente il tasso di errore. In casi più complessi, è possibile fornire al modello esempi di “problema + traccia di ragionamento e output” per guidarlo nel ragionamento.
Il CoT funziona ma ha un difetto: se il modello sbaglia un passaggio intermedio, l’errore si propaga a cascata. La tecnica della Self-Consistency risolve questo problema con un approccio di “voto democratico”:
- Si esegue lo stesso prompt CoT più volte.
- Si generano diversi percorsi di ragionamento.
- Si seleziona la risposta finale più frequente (voto di maggioranza).
Questo metodo scarta i percorsi di ragionamento “allucinati” (meno probabili) e fa convergere il risultato verso la soluzione più robusta. Tuttavia, necessita di un costo computazionale decisamente maggiore e va considerata solo per problemi particolarmente complessi.
Pattern Ingegneristici: Dai prompt alle applicazioni
Quando si passa dalla sperimentazione a un’applicazione reale, emerge rapidamente un problema: i prompt complessi sono fragili. Se si accorpano troppi requisiti in una singola richiesta, il modello tende a confondersi, omettere vincoli o produrre contenuti non supportati. Per costruire software affidabile, non possiamo fare completamente affidamento al modello. Per farlo funzionare bene è importante costruire prompt ottimi e per raggiungere questo obiettivo bisogna iniziare a trattare il prompt come un componente ingegneristico. Ecco tre pattern molto comuni che trovano applicazione in moltissime situazioni concrete:
1 – Prompt Chaining
Si consideri il caso dell’analisi automatica di una mail di un cliente insoddisfatto: bisogna capire il problema, estrarre le informazioni rilevanti e produrre una risposta formale. Se si chiede tutto in un unico prompt (monolitico), il rischio di errore aumenta.
Il Prompt Chaining risolve il problema spezzando il compito in una catena sequenziale, dove l’output di un passaggio diventa l’input del successivo. Funziona come una catena di montaggio:
- Analisi ⭢ Il primo prompt legge la mail ed estrae solo la categoria (es. “Reclamo Spedizione”).
- Estrazione ⭢ Il secondo prompt cerca i dettagli specifici (es. Numero Ordine, Data).
- Generazione ⭢ Il terzo prompt riceve i dati puliti dai passaggi precedenti e scrive il testo della risposta finale.
Spezzare un compito difficile in più parti ha anche un altro vantaggio. Infatti, se la risposta finale è sbagliata, sai esattamente dove guardare. Se ha sbagliato la categoria, correggi il primo prompt. Se il tono è sbagliato, correggi il terzo. Il debugging diventa possibile.
2 – Prompt Templating
In un’applicazione, non è sostenibile scrivere manualmente un prompt per ogni richiesta. Serve un template riutilizzabile. Il Prompt Template è proprio questo: un testo base con segnaposto che il software popola automaticamente al momento dell’uso.
Invece di scrivere:
“L’utente Mario si lamenta della batteria…”
Scrivi un template (usando framework come LangChain):
“L’utente {nome_utente} si lamenta del problema: {descrizione_problema}. Rispondi in modo gentile.”
Questo approccio separa la logica (le istruzioni fisse che dai al modello) dai dati (le variabili che cambiano ogni volta). È l’unico modo per rendere il sistema scalabile e manutenibile.
3 – Structured Output
I software tradizionali amano i dati strutturati (come i file CSV o i JSON), mentre gli LLM amano chattare. Se si chiede a un modello di “estrarre i dati in JSON”, spesso potrebbe rispondere con: “Certo! Ecco il JSON che hai chiesto: { … }”. Per un essere umano va bene, ma quel testo introduttivo (“Certo! Ecco…”) rende fragile il parsing in un sistema che si aspetta solo JSON.
La soluzione è l’Output Strutturato. Usando librerie specifiche (come Pydantic in Python), si può definire uno schema (un contratto) che il modello deve rispettare. Non si chiede solo “dammi un JSON”, ma “dammi un oggetto JSON che deve avere un campo nome di tipo testo e un campo età di tipo numero”. Questo rende l’output integrabile in pipeline software con minori rischi di errori di formato.
Best Practice: Regole per non sbagliare
Il Prompt Engineering non deve essere visto come un obiettivo una tantum, ma come un processo iterativo: si scrive, si testa e si itera. Probabilmente il prompt “perfetto” non si troverà mai, ma non è questo l’obiettivo. In produzione serve un prompt che funzioni sufficientemente bene rispetto ai requisiti dell’applicazione. Per farlo servono metodi per misurare la qualità del prompt: l’argomento verrà ripreso nella parte sulle eval.
Per ora, si possono elencare alcune regole d’oro, che si sono dimostrate efficaci praticamente in tutte le situazioni:
- Chiarezza e Direttività ⭢ Evitare ambiguità. “Sii breve” è soggettivo; meglio “Rispondi in massimo 3 frasi”. “Non usare slang” è troppo generico; meglio “Usa un linguaggio formale e professionale”. Istruzioni positive e vincoli numerici tendono a funzionare meglio.
- Delimitatori: Aiutare il modello a distinguere istruzioni e testo da analizzare. Usare simboli chiari come ### o tag XML.
Esempio: “Riassumi il testo racchiuso tra <testo> e </testo> .” Questo riduce il rischio di confusione se il testo da riassumere contiene a sua volta delle domande. - System Prompt ⭢ Usare il messaggio di “sistema” (disponibile nelle API come quella di OpenAI) per impostare il ruolo e il tono del modello. Se nel system prompt si imposta “Sei un assistente fiscale esperto e prudente”, il modello tenderà a mantenere quel profilo per tutta la conversazione.
- Trattarlo come Codice ⭢ Evitare prompt salvati in file di testo sparsi. Versionare i prompt (v1.0, v1.1) e testarli su esempi diversi per evitare regressioni.
Key Takeaways
➭ PROGRAMMAZIONE IN LINGUAGGIO NATURALE
Il prompt engineering è la disciplina di progettare input per guidare il comportamento del modello senza riaddestramento.
➭ IN-CONTEXT LEARNING
Fornire esempi (Few-Shot) nel prompt trasforma l’istruzione in un micro-dataset di addestramento temporaneo, riducendo le ambiguità.
➭ RAGIONAMENTO GUIDATO
Tecniche come Chain-of-Thought e Self-Consistency permettono ai modelli di risolvere problemi complessi “pensando” ad alta voce e verificando i propri percorsi logici.
➭ INGEGNERIZZAZIONE DEI FLUSSI
Per applicazioni robuste, si usano pattern come il Chaining (scomposizione dei task) e lo Structured Output (risposte in JSON/Pydantic) per integrare l’AI nei sistemi software tradizionali.
Nel prossimo articolo affronteremo uno dei limiti principali degli LLM: la conoscenza ferma alla data di addestramento. Vedremo come superarlo con la RAG (Retrieval-Augmented Generation).




0 commenti