1. Introduzione
A volte nei corsi di prompt engineering mostrano una formula magica:
«Non inventare fatti e di’ “non lo so” se non ci sono informazioni.»
Purtroppo (o per fortuna), per una ChatGPT App questo non funziona come una bacchetta magica. Il motivo è semplice: il modello vede non solo il tuo system‑prompt, ma anche:
- l’elenco degli strumenti con le loro descrizioni e gli schemi;
- i risultati di tali strumenti;
- la cronologia del dialogo, inclusi i follow‑up precedenti.
Se questi tre livelli — system‑prompt, descrizioni degli strumenti (tools), pattern di follow‑up — si contraddicono o semplicemente “rimangono scoperti”, il modello inizia a comportarsi come un classico junior: diligente, ma incline a inventare.
Nel corso usiamo l’idea della “difesa a tre livelli dalle allucinazioni” (defense in depth):
- livello 1 — regole globali nel system‑prompt;
- livello 2 — vincoli locali nella definizione di ogni strumento;
- livello 3 — gestione di errori, risultati vuoti e follow‑up.
In questa lezione uniremo tutti e tre i livelli in un unico contratto coerente per la nostra app didattica GiftGenius.
Insight
Nella nuova architettura delle ChatGPT Apps il campo per il system‑prompt è scomparso — formalmente non esiste più. Ma ciò non significa che devi rinunciare a istruzioni globali per il modello. C’è un trucco: per ChatGPT le descrizioni degli strumenti sono testo di prompt a tutti gli effetti, proprio come il classico system. Attraverso di esse puoi reintrodurre il “firmware mentale” completo dell’applicazione.
Crea uno strumento di servizio, per esempio about o about_app. Non è pensato per essere invocato spesso, ma la sua description è letta dal modello alla pari con gli altri strumenti. Quindi nella descrizione puoi incorporare il system‑prompt completo. Meglio posizionarlo dopo una breve descrizione tecnica dello strumento stesso. In questo modo, all’avvio il modello riceve il tuo system‑prompt in forma pura — e lo applica a tutto il dialogo successivo e alle chiamate dei tools.
Per semplificare la manutenzione, consiglio di aggiungere all’inizio del system‑prompt una versione esplicita, per esempio SYSTEM_PROMPT_VERSION: v3. Questo ti permette di capire perché il modello si comporta diversamente: vedi subito con quale preciso set di istruzioni sta lavorando. Se in produzione si verifica un comportamento strano, è facile capire se l’errore riguarda la versione vecchia o quella nuova del prompt.
Esempio:
tool description
### Global assistant behavior for the entire GiftGenius App (ver 3.01)
*(system-level guidelines, not user-facing text)*
system prompt text
2. Quali allucinazioni compaiono nelle ChatGPT App (sull’esempio del catalogo dei regali)
Per capire come curare, conviene dare un nome alla “malattia”. Nel contesto di un catalogo (regali, prodotti, tariffe) si incontrano più spesso questi tipi di allucinazioni.
In primo luogo, voci di catalogo inventate. L’utente chiede “un certificato digitale per l’abbonamento annuale a un servizio specifico” o un regalo molto esotico che non è presente nel tuo feed, e il modello, desideroso di essere utile, inventa con entusiasmo “Super Space Flight 3000 — volo nello spazio”, che nel database di GiftGenius non è mai esistito.
In secondo luogo, attributi inventati. Il regalo è presente a catalogo, ma il modello “abbellisce” la realtà: cambia il prezzo, il tipo di regalo (digitale vs fisico), la disponibilità di spedizione nel paese dell’utente o la validità del certificato, perché così “sembra più logico” o “suona meglio”.
In terzo luogo, azioni allucinatorie. Il modello scrive “ho già acquistato questo regalo e ho inviato il codice al tuo e‑mail, sono stati addebitati $49”, anche se il backend di GiftGenius non ha nemmeno provato a comprare nulla e nessun flusso ACP/Stripe è stato avviato.
Infine, c’è un caso combinato: lo strumento ha restituito una lista vuota (non ci sono regali con quei filtri e quel budget), e il modello, per non deludere l’utente, inventa un paio di “opzioni indicative” senza spiegare che nel catalogo non esistono.
Il nostro obiettivo è fare in modo che in queste situazioni il modello:
- ammetta onestamente che nel catalogo non c’è una corrispondenza esatta;
- non inventi nuovi regali e non modifichi i valori dei campi;
- spieghi all’utente cosa è successo e proponga un passo successivo chiaro.
E farlo non con “incantesimi” in punti a caso, ma attraverso un contratto connesso system‑prompt ↔ tools ↔ follow‑ups.
3. Livello 1: rafforziamo il system‑prompt contro le allucinazioni
Per fermare regali, attributi e azioni inventati della sezione precedente, prima rinforziamo il livello superiore — il system‑prompt: definiamo al modello la “filosofia” generale di comportamento nel catalogo.
Nella prima lezione del modulo hai già scritto un system‑prompt di base del tipo: “Sei GiftGenius, aiuti a scegliere i regali…” e hai fissato i confini di responsabilità dell’assistente e l’uso degli strumenti.
Ora aggiungiamo regole anti‑allucinazione esplicite.
La logica è questa: il system‑prompt definisce la filosofia generale del comportamento. Non conosce i dettagli di ogni strumento, ma può:
- vietare di inventare regali / prezzi / disponibilità fuori dal catalogo;
- definire il comportamento quando gli strumenti restituiscono un risultato vuoto o un errore;
- richiedere una distinzione esplicita tra i dati del catalogo dei regali e qualsiasi “conoscenza generale del modello”.
Esempio di frammento di system‑prompt (una costante TypeScript nel nostro progetto Next.js, per esempio config/systemPrompt.ts):
// config/systemPrompt.ts
export const SYSTEM_PROMPT = `
# Ruolo
Sei GiftGenius, un assistente per la scelta dei regali
basato sul catalogo dei regali della nostra applicazione.
# Dati e vincoli
- Non inventare regali che non sono nel catalogo o nelle risposte degli strumenti.
- Non inventare prezzi, disponibilità, tipo di regalo (digitale/fisico),
regioni di spedizione o altri attributi.
- Se uno strumento non ha restituito i dati necessari o si è verificato un errore,
dillo onestamente e non provare a indovinare i valori.
# Uso degli strumenti
- Usa sempre gli strumenti del catalogo dei regali per qualsiasi dato fattuale:
elenco dei regali, prezzi, tipi, disponibilità, SKU.
- Se lo strumento ha restituito un risultato vuoto, dì che con le condizioni attuali
non ci sono regali adatti e proponi di allentare i filtri
(modificare il budget, la categoria, il tipo di regalo).
`;
Qui sono importanti alcuni punti.
In primo luogo, separiamo le “conoscenze generali del modello” dai “dati dell’applicazione”. Il modello può ancora spiegare in cosa un regalo digitale differisce da uno fisico o quali occasioni sono comuni, ma qualsiasi regalo concreto, prezzo e SKU devono provenire solo dagli strumenti di GiftGenius.
In secondo luogo, descriviamo esplicitamente cosa fare in caso di errori/risposta vuota: non tacere, non “creare”, ma dire onestamente all’utente che non si è trovato nulla e proporre di modificare i parametri.
In terzo luogo, ci concentriamo non su un astratto “non avere allucinazioni”, ma su comportamenti concreti, legati al nostro dominio (catalogo dei regali e acquisto di SKU digitali/fisici).
Questo livello già aiuta molto, ma è facile “essere smentito” da una descrizione imprecisa dello strumento. Passiamo alle descrizioni degli strumenti.
4. Livello 2: descrizioni degli strumenti (tool descriptions) e schemi come parte formale del contratto
Il modello decide quando e come invocare il tuo strumento, principalmente in base a:
- nome dello strumento;
- description dello strumento;
- inputSchema / outputSchema (JSON Schema che descrive i campi).
Cioè la descrizione dello strumento (tool description) non è “documentazione per umani”, ma una parte del prompt, solo più formalizzata. E molte allucinazioni nascono proprio qui.
Immaginiamo il nostro strumento recommend_gifts, che il backend implementa come selezione di regali dal catalogo di GiftGenius.
Una cattiva variante di descrizione potrebbe essere così:
// MALE: troppo vago
const recommendGiftsTool = {
name: "recommend_gifts",
description: "Seleziona regali per l'utente",
inputSchema: {
type: "object",
properties: {
profile: { type: "string" }
}
}
};
Formalmente è tutto corretto, ma da ciò il modello non capisce:
- quali sono i confini dello strumento;
- cosa fare se i regali non vengono trovati;
- che non si possono inventare regali e prezzi al di fuori del catalogo.
Una buona descrizione fa più cose insieme: definisce chiaramente il dominio, spiega quando invocare il tool e stabilisce in modo rigido che non si possono inventare risultati.
Esempio (adattato al contratto GiftGenius con segments, budget, locale, occasion):
// config/tools.ts
export const recommendGiftsTool = {
name: "recommend_gifts",
description: `
Selezione di regali nel catalogo GiftGenius.
Usa questo strumento quando serve ottenere un elenco di regali reali
in base ai segmenti del profilo del destinatario, al budget, alla locale e all'occasione.
Lo strumento restituisce solo i regali che esistono davvero
nel catalogo GiftGenius.
NON inventare regali o i loro attributi al di fuori dei risultati di questo strumento.
Se lo strumento ha restituito una lista vuota, non inventare alternative,
ma passa al dialogo: proponi di modificare il budget, il tipo di regalo,
l'occasione o altri parametri.
`.trim(),
inputSchema: {
type: "object",
properties: {
segments: {
type: "array",
description:
"Segmenti del profilo del destinatario, per esempio ['tech', 'fitness'].",
items: { type: "string" }
},
budget: {
type: "object",
description: "Intervallo di budget per il regalo.",
properties: {
min: {
type: "number",
description: "Importo minimo, non negativo.",
minimum: 0
},
max: {
type: "number",
description: "Importo massimo, maggiore di 0.",
exclusiveMinimum: 0
},
currency: {
type: "string",
description: "Codice valuta di tre lettere, per esempio 'USD' o 'RUB'.",
minLength: 3,
maxLength: 3
}
},
required: ["min", "max", "currency"]
},
locale: {
type: "string",
description:
"Locale dell'utente (formato lingua/regione), per esempio 'ru-RU' o 'en-US'.",
minLength: 2
},
occasion: {
type: "string",
description:
"Occasione per il regalo: per esempio 'birthday', 'anniversary', 'new_year'."
}
},
required: ["segments", "budget", "locale", "occasion"]
}
};
Qui la description fa diverse cose utili.
Dice chiaramente che lo strumento funziona solo con il catalogo dei regali GiftGenius e che qualsiasi regalo concreto e prezzo deve essere preso solo dal suo risultato.
Spiega quando usare lo strumento: quando serve proprio un elenco di regali concreti per i parametri del destinatario, non una teoria generale sui regali.
Definisce il comportamento in caso di risultato vuoto: non inventare, ma passare al dialogo (che poi fisseremo nei follow‑up).
E inputSchema aiuta il modello a estrarre in modo più affidabile le entità dalla richiesta dell’utente: segmenti, budget, locale e occasione. Indicare struttura e vincoli espliciti per i campi (min, max, currency con lunghezza fissa) riduce anche la probabilità di combinazioni strane ed errori di parsing.
Si può aggiungere anche il rovescio della medaglia — non solo “quando invocare”, ma anche quando non invocare. Per esempio, se la richiesta è chiaramente teorica:
description: `
...
Non usare questo strumento se l'utente pone una domanda generale
sui regali senza chiedere una selezione per una persona specifica
(per esempio, "quali sono i regali popolari per Capodanno in generale").
In questi casi rispondi direttamente in chat.
`.trim()
Così sincronizzi la descrizione dello strumento con le regole del system‑prompt sui richiami “teorici” vs “pratici”.
5. Livello 3: i follow‑up come livello UX e di sicurezza
Anche se il system‑prompt e le descrizioni dei tools sono scritti alla perfezione, la vita non è perfetta:
- il backend può restituire un errore;
- il catalogo — una lista vuota;
- i risultati — ambigui o troppo numerosi.
Se non si definisce cosa dire dopo la chiamata del tool, il modello improvviserà: a volte bene, a volte — con fatti inventati.
Nella lezione 2 hai già visto istruzioni UX di base: come il modello annuncia l’avvio dell’App, come termina lo scenario e cosa dice all’utente “in uscita”. Ora aggiungiamo pattern di follow‑up che riducono le allucinazioni.
Questi pattern di solito sono descritti direttamente nel system‑prompt in un blocco separato, per esempio “Dialogo dopo il lavoro con gli strumenti”.
Esempio di frammento:
// continuazione di SYSTEM_PROMPT
export const SYSTEM_PROMPT = `
# ... sezioni precedenti ...
# Dialogo dopo il lavoro con gli strumenti
- Se lo strumento di selezione dei regali ha restituito una lista vuota:
1) dì onestamente che con gli attuali filtri non sono stati trovati regali adatti;
2) proponi all'utente di modificare 1–2 parametri chiave
(budget, tipo di regalo, interessi del destinatario, occasione).
- Se lo strumento ha restituito troppe opzioni:
1) scegli le 3–7 più rilevanti;
2) spiega esplicitamente in base a quali criteri le hai selezionate
(corrispondenza agli interessi, rientro nel budget, valutazione).
- Se si è verificato un errore dello strumento:
1) non inventare dati;
2) dì che c’è stato un errore tecnico e proponi
di riprovare più tardi o semplificare la richiesta.
`.trim();
In questo modo “impiantiamo” nel modello esempi di repliche di follow‑up. Le formulerà con parole sue, ma con la struttura indicata:
- constatazione del fatto (vuoto / troppi risultati / errore);
- ammissione onesta del limite;
- proposta chiara del passo successivo.
Per un catalogo di regali questo è cruciale: invece di “tutto ok, ecco tre regali”, in caso di risultato vuoto il modello dirà qualcosa del genere:
«Con le condizioni attuali (regalo digitale sullo spazio fino a $5 con consegna solo negli USA) nel nostro catalogo non c’è nulla. Vuoi che provi ad aumentare il budget o a proporre altre categorie?»
E fai attenzione: questo non è codice dello strumento, ma istruzioni nel prompt che definiscono l’UX atteso.
6. Mettiamo tutto insieme: l’evoluzione del nostro GiftGenius
Vediamo una mini‑evoluzione della nostra applicazione e riduciamo gradualmente il livello di allucinazioni.
Versione iniziale: dove tutto si rompe
Supponiamo di avere un system‑prompt molto minimalista:
export const SYSTEM_PROMPT = `
Sei un assistente per la scelta dei regali.
Aiuta l'utente a trovare idee adatte.
`;
Lo strumento era descritto così:
export const recommendGiftsTool = {
name: "recommend_gifts",
description: "Seleziona regali per l'utente",
inputSchema: { type: "object" }
};
Nessuna istruzione di follow‑up.
Cosa accadrà in pratica:
- se l’utente chiede “un regalo digitale per un amico gamer fino a $10” e nel database con tali filtri non c’è nulla, il modello può:
- o non invocare affatto il tool e inventare regali di sana pianta;
- oppure invocare il tool, ottenere una lista vuota, ma non dirlo e inventare opzioni;
- se il backend restituisce un errore, il modello può pensare che “qualcosa ci dovrà pur essere” e iniziare a indovinare.
Così nasce la situazione classica: in chat — una risposta impeccabile, nel database — niente di simile.
Nuova versione del system‑prompt
R riscriviamo il system‑prompt tenendo conto dei tre livelli di difesa. Una parte l’hai già vista sopra, ora lo componiamo per intero:
// config/systemPrompt.ts
export const SYSTEM_PROMPT = `
# Ruolo
Sei GiftGenius, un assistente per la scelta dei regali
basato sul catalogo dei regali della nostra applicazione.
# Area di responsabilità
- Il tuo compito è aiutare l'utente a scegliere regali adatti
dal catalogo, spiegando pro e contro delle opzioni.
- Non fare promesse di acquisto effettivo o invio del regalo —
tu aiuti solo a selezionare e confrontare le opzioni.
L'acquisto e la consegna del codice/link li effettua il backend dopo l'esplicito consenso dell'utente.
# Dati e vincoli
- Non inventare regali che non sono nel catalogo o nelle risposte degli strumenti.
- Non inventare prezzi, tipo di regalo, disponibilità o regioni di spedizione.
- Se uno strumento non ha restituito dati o si è verificato un errore,
non provare a indovinare: informane l'utente.
# Uso degli strumenti
- Usa gli strumenti del catalogo dei regali (per esempio, profile_to_segments,
recommend_gifts, get_gift) per qualsiasi dato fattuale
(elenco dei regali, prezzi, tipi, SKU, descrizioni).
- Rispondi direttamente (senza strumenti) se la domanda è teorica
e non richiede la selezione di un regalo specifico.
# Dialogo dopo il lavoro con gli strumenti
- In caso di risultato vuoto: spiega onestamente che non è stato trovato nulla
con le condizioni attuali e proponi di modificare 1–2 parametri.
- In caso di troppi risultati: scegli 3–7 opzioni più adatte
e spiega i criteri di scelta.
- In caso di errore dello strumento: non inventare dati, scusati per il problema
e proponi di riprovare o semplificare la richiesta.
`.trim();
Ora il modello sa con chiarezza:
- dove è un consulente per i regali e dove c’è il “back‑office” (che sta dietro gli strumenti);
- quali dati esattamente non può inventare;
- come comportarsi nei casi tipici non ideali.
Nuova description e schema per recommend_gifts
Abbiamo rinforzato il system prompt, ora rifiniamo il tool e prepariamo la versione finale della sua descrizione — sulla base delle idee della sezione 4.
// config/tools.ts
export const recommendGiftsTool = {
name: "recommend_gifts",
description: `
Selezione di regali nel catalogo GiftGenius.
Usa questo strumento quando serve:
- ottenere un elenco di regali reali con prezzi aggiornati, tipo
(digital/physical) e tag;
- restringere la scelta per segmenti di interesse, budget, locale e occasione.
NON USARE lo strumento:
- se l'utente pone una domanda teorica generale sui regali
senza chiedere una selezione per una persona specifica;
- per inventare regali che non sono nel catalogo.
Se il risultato è vuoto, NON inventare regali da solo,
ma restituisci il controllo al dialogo (segui le istruzioni del system‑prompt).
`.trim(),
inputSchema: {
type: "object",
properties: {
segments: {
type: "array",
description:
"Segmenti del profilo del destinatario: per esempio, 'tech', 'sport', 'books'.",
items: { type: "string" }
},
budget: {
type: "object",
description:
"Intervallo di budget per il regalo nella valuta dell'utente (min/max).",
properties: {
min: { type: "number", minimum: 0 },
max: { type: "number", exclusiveMinimum: 0 },
currency: {
type: "string",
minLength: 3,
maxLength: 3,
description: "Codice valuta ISO 4217, per esempio 'USD' o 'RUB'."
}
},
required: ["min", "max", "currency"]
},
locale: {
type: "string",
description: "Locale dell'utente, per esempio 'ru-RU' o 'en-US'."
},
occasion: {
type: "string",
description:
"Occasione per il regalo: 'birthday', 'anniversary', 'new_year', ecc."
}
},
required: ["segments", "budget", "locale", "occasion"]
}
};
Qui ci sono alcune sfumature.
Colleghiamo esplicitamente il comportamento dello strumento al system‑prompt: la frase “segui le istruzioni del system‑prompt” ricorda al modello che “risultato vuoto = conversazione onesta, non creatività”.
Stabiliamo condizioni negative (“non usare…”, “non inventare…”), che, in pratica, sono importanti quanto le descrizioni positive.
Rendiamo inputSchema semanticamente ricco: descrizioni e vincoli ben fatti aiutano il modello a mappare correttamente le richieste ai campi e a “sbagliare” meno già prima della chiamata dello strumento.
Pattern di follow‑up nel codice del widget e nel formato della risposta
Oltre alle istruzioni testuali abbiamo un’altra leva — il formato di risposta dello strumento. Attraverso di esso possiamo anche suggerire al modello cosa è successo e ridurre lo spazio per la fantasia.
Formalmente i follow‑up sono definiti nel testo del system‑prompt, ma nel widget Next.js puoi inoltre normalizzare il ToolOutput, per semplificare la vita del modello e ridurre il margine di invenzione.
Per esempio, concordiamo che il backend per recommend_gifts restituisca sempre:
// tipo di risposta dello strumento sul backend
export type RecommendGiftsResult = {
items: Array<{
id: string;
title: string;
price: number;
currency: "USD" | "EUR" | "RUB";
tags: ("digital" | "physical" | "education" | "fitness" | "tech")[];
}>;
// campo che il backend compila per indicare esplicitamente al modello cosa è successo
status: "ok" | "empty" | "error";
errorMessage?: string;
};
Il widget può visualizzare tutto in modo gradevole e il modello — basarsi su status quando formula la risposta. Nell’Apps SDK spesso restituisci alla modello il ToolOutput come oggetto JSON, e lui vede questo campo.
Nel system‑prompt puoi aggiungere un piccolo blocco:
# Interpretazione dello status dello strumento
- Se status = "empty": vedi la sezione "Dialogo dopo il lavoro con gli strumenti" e
non inventare regali.
- Se status = "error": comunica l'errore tecnico e non provare a indovinare
il contenuto del catalogo.
Sì, il modello avrebbe potuto anche capirlo da solo, ma un’istruzione esplicita riduce la probabilità di “indovinare” basandosi su supposizioni.
7. Pratica: miglioriamo la tua App
Per evitare l’impressione “bello sulle slide”, descriviamo un esercizio concreto che puoi fare con la tua attuale App (nel nostro caso — GiftGenius). Facciamo un piccolo refactoring sui tre livelli di difesa: system‑prompt, descrizioni degli strumenti e gestione dei risultati.
Per prima cosa, a livello di system‑prompt, prendi il tuo system‑prompt della prima lezione e trova la parte in cui si descrivono l’area di responsabilità e l’uso degli strumenti. Aggiungi:
- il divieto di inventare entità al di fuori del catalogo/database (regali, SKU, prezzi);
- regole per il caso di risultato vuoto ed errore dello strumento;
- una sezione “Dialogo dopo il lavoro con gli strumenti” con 2–3 scenari (vuoto, troppi, errore).
In secondo luogo, a livello delle descrizioni dei tools, apri la descrizione dello strumento chiave (nel tuo caso può essere recommend_gifts, search_gifts, search_tariffs, calculate_quote, non importa). Riscrivi la description in modo che:
- dica esplicitamente che lo strumento lavora solo con la tua fonte dati (catalogo dei regali, delle tariffe, ecc.);
- spieghi quando è necessario e quando no;
- contenga vincoli negativi espliciti: “non inventare…”, “non usare per…”.
In terzo luogo, a livello della struttura della risposta dello strumento, se nella risposta dello strumento non c’è ancora un campo che descrive esplicitamente lo stato (status, resultType, hasMore) — aggiungilo al tipo sul backend e nel ToolOutput. Poi, nel system‑prompt, scrivi come il modello deve interpretare questo status nel dialogo.
Infine, prova un paio di richieste in Dev Mode, incluse quelle in cui i risultati sono volutamente vuoti o al limite. Fai attenzione a se il modello ha smesso di inventare entità e a quanto onestamente spiega all’utente i limiti.
Nella prossima lezione formalizzerai tali richieste in un golden prompt set e le trasformerai in un artefatto di test ripetibile, ma per ora è importante che tu senta a mano la differenza.
8. Errori tipici nel contrastare le allucinazioni tramite prompt e strumenti
Errore n. 1: una frase magica “non avere allucinazioni” nel system‑prompt.
Lo sviluppatore scrive alla fine del prompt: “Non inventare informazioni” — e considera il compito risolto. In pratica il modello continua a inventare, perché le descrizioni degli strumenti e i follow‑up non gli forniscono un comportamento alternativo. Senza regole specifiche su “cosa fare invece di inventare” (riconoscere il risultato vuoto, proporre di modificare i filtri, segnalare l’errore) questa frase aiuta ben poco.
Errore n. 2: contraddizione tra system‑prompt e description dello strumento.
Nel system‑prompt dici: “Non inventare regali che non sono nel catalogo”, e nella descrizione dello strumento — “Seleziona regali adatti e, se non trovi nulla, puoi proporre opzioni simili a tua discrezione”. Di conseguenza il modello oscilla tra due fonti di verità e, purtroppo, vince quella più specifica (di solito la description dello strumento). Bisogna che entrambi i livelli dicano la stessa cosa: se le opzioni simili sono ammesse, va formalizzato (e va spiegato all’utente che non sono corrispondenze esatte).
Errore n. 3: descrizioni degli strumenti troppo vaghe.
Una descrizione del tipo “Strumento che aiuta l’utente a risolvere problemi” non dà al modello quasi nessuna informazione sui confini dello strumento. In tal caso potrebbe non usarlo affatto oppure attivarlo per qualsiasi motivo — e poi “completare” i dati quando lo strumento ha restituito poco o nulla. Una buona description deve essere discriminativa: dire chiaramente cosa fa lo strumento e quando non va invocato.
Errore n. 4: assenza di una strategia per risultati vuoti ed errori.
Lo sviluppatore realizza con cura un backend che restituisce { items: [], status: "empty" }, ma non spiega da nessuna parte al modello cosa significa. Il risultato è che il modello vede un array vuoto e decide: “beh, probabilmente devo proporre qualcosa dalla conoscenza generale”. Nel system‑prompt manca una sezione che spiega come interpretare tali status e cosa dire all’utente. Eppure aggiungere un paio di regole chiare per risultato vuoto/errore porta a un enorme miglioramento della qualità.
Errore n. 5: tentare di “curare” le allucinazioni solo a livello di codice del widget.
A volte si vorrebbe demandare tutto al frontend: “se la lista è vuota — mostrerò un placeholder e non farò vedere all’utente la risposta testuale del modello”. Questo può attenuare un po’ l’UX, ma il modello continua comunque a credere in entità inventate e a comportarsi allo stesso modo nelle battute successive. L’approccio corretto è cambiare prima le istruzioni (system‑prompt, descrizioni degli strumenti, follow‑up), e solo dopo completare con protezioni nell’interfaccia.
Errore n. 6: ignorare l’influenza di metadati e schemi sul comportamento del modello.
Alcuni sviluppatori percepiscono JSON Schema e le descrizioni dei campi come “solo per form e validazione”. In realtà, per ChatGPT sono una parte importante del prompt: da queste descrizioni il modello capisce quali parametri deve estrarre dalla richiesta e com’è una risposta corretta. Descrizioni deboli o incoerenti dei campi (description, enum) aumentano la probabilità di errori e indirettamente provocano allucinazioni.
Errore n. 7: divieti troppo rigidi senza alternative.
Capita che il prompt diventi un elenco di “non fare questo, non fare quello”, ma da nessuna parte si dice cosa fare nei casi difficili. Per esempio, abbiamo vietato di inventare regali e ci siamo limitati solo al catalogo, ma non abbiamo detto nulla sulle domande teoriche. Alla fine il modello a volte risponde “non lo so”, anche se potrebbe utilmente spiegare principi generali per la scelta dei regali. Cerca sempre di non solo vietare, ma anche aprire percorsi consentiti: “se non puoi trovare un regalo nel catalogo — dillo onestamente e proponi come modificare la richiesta” o “se la richiesta è teorica — rispondi direttamente, senza strumenti”.
GO TO FULL VERSION