1. Вступ
Іноді на курсах із prompt‑інжинірингу показують «магічне заклинання»:
«Не вигадуй фактів і кажи “я не знаю”, якщо немає інформації.»
На жаль (або, якщо подивитися інакше, на щастя), для ChatGPT App це не працює як срібна куля. Причина проста: модель бачить не лише ваш system‑prompt, а й:
- список інструментів із їхніми описами та схемами;
- результати роботи цих інструментів;
- історію діалогу, зокрема попередні follow‑up‑и.
Якщо ці три шари — system‑prompt, описи tools, патерни follow‑up‑ів — суперечать один одному або просто «просідають», модель починає поводитися як типовий джуніор‑розробник: дуже старається, але час від часу вигадує зайве.
У межах курсу ви працюватимете з ідеєю «трирівневого захисту від галюцинацій» (defense in depth):
- рівень 1 — глобальні правила в system‑prompt;
- рівень 2 — локальні обмеження у визначенні кожного інструмента;
- рівень 3 — обробка помилок, порожніх результатів і follow‑up‑ів.
У цій лекції ви зведете всі три рівні в один узгоджений контракт для нашого навчального застосунку GiftGenius.
Інсайт
У новій архітектурі ChatGPT Apps поле для system‑prompt зникло — формально його більше немає. Але це не означає, що вам треба відмовлятися від глобальних інструкцій для моделі. Є простий прийом: для ChatGPT описи інструментів — це такий самий промпт‑текст, як і класичний system. Саме через них можна повернути повноцінну «прошивку» застосунку.
Створіть службовий інструмент, наприклад about або about_app. Він не призначений для частих викликів, зате його description модель читає нарівні з описами інших інструментів. Тож у цей опис можна вбудувати повний system‑prompt.
Практичне правило: розміщуйте system‑prompt після короткого технічного опису самого інструмента. Тоді на старті модель отримує ваш system‑prompt у «чистому» вигляді й застосовує його до всього подальшого діалогу та викликів tools.
Щоб спростити супровід, раджу на початку system‑prompt додавати явну версію, наприклад SYSTEM_PROMPT_VERSION: v3. Так ви легко зрозумієте, чому модель поводиться інакше: одразу видно, за яким набором інструкцій вона працює. Якщо в продакшені зʼявляється дивна поведінка, простіше перевірити, чи це проблема старої версії промпта, чи нової.
Приклад:
tool description
### Global assistant behavior for the entire GiftGenius App (ver 3.01)
*(system-level guidelines, not user-facing text)*
system prompt text
2. Які галюцинації бувають у ChatGPT App (на прикладі каталогу подарунків)
Щоб розуміти, чим лікувати, корисно спершу назвати хворобу. У контексті каталогу (подарунки, товари, тарифи) найчастіше трапляються такі типи галюцинацій.
По‑перше, вигадані позиції каталогу. Користувач просить «цифровий сертифікат на річну підписку на конкретний сервіс» або дуже екзотичний подарунок, якого у вашому фіді немає. А модель, прагнучи бути корисною, охоче вигадує «Super Space Flight 3000 — політ у космос», якого в базі GiftGenius ніколи не існувало.
По‑друге, вигадані атрибути. Подарунок у каталозі є, але модель «прикрашає» реальність: змінює ціну, тип подарунка (цифровий vs фізичний), наявність доставки в країну користувача або строк дії сертифіката. Бо так «логічніше» чи «звучить краще».
По‑третє, галюцинаторні дії. Модель пише: «Я вже купив цей подарунок і надіслав код на вашу електронну пошту, з картки списано $49», хоча ваш бекенд GiftGenius навіть не намагався нічого купувати й жоден ACP/Stripe‑процес не запускався.
Нарешті, є комбінований випадок: інструмент повернув порожній список (немає подарунків під такі фільтри й бюджет), а модель, щоб не засмучувати користувача, вигадує кілька «приблизних варіантів» і не пояснює, що в каталозі їх немає.
Наше завдання — зробити так, щоб у цих ситуаціях модель:
- чесно визнавала, що у каталозі немає точного збігу;
- не вигадувала нові подарунки й не змінювала значення полів;
- пояснювала користувачу, що саме сталося, і пропонувала зрозумілий наступний крок.
І що важливо: робити це не за рахунок «заклинань» у довільних місцях, а через повʼязаний контракт system‑prompt ↔ tools ↔ follow‑ups.
3. Рівень 1: посилюємо system‑prompt проти галюцинацій
Щоб зупинити вигадані подарунки, атрибути й дії з попереднього розділу, спершу посилимо верхній шар — system‑prompt. Тобто задамо моделі загальну «філософію» поведінки в каталозі.
У першій лекції модуля ви вже написали базовий system‑prompt на кшталт: «Ти — GiftGenius, допомагаєш добирати подарунки…». Там само ви зафіксували межі відповідальності асистента та правила роботи з інструментами.
Тепер додамо до нього явні антигалюцинаційні правила.
Логіка проста: system‑prompt задає загальну філософію поведінки. Він не знає деталей кожного інструмента, зате може:
- заборонити вигадувати подарунки, ціни та наявність поза каталогом;
- прописати поведінку, якщо інструменти повернули порожній результат або помилку;
- вимагати чіткого розрізнення між даними з каталогу подарунків і будь‑якими «загальними знаннями моделі».
Приклад фрагмента system‑prompt (TypeScript‑константа в нашому Next.js‑проєкті, наприклад config/systemPrompt.ts):
// config/systemPrompt.ts
export const SYSTEM_PROMPT = `
# Роль
Ти — GiftGenius, асистент з добору подарунків
на основі каталогу подарунків нашого застосунку.
# Дані та обмеження
- Не вигадуй подарунки, яких немає в каталозі або у відповідях інструментів.
- Не вигадуй ціни, наявність, тип подарунка (цифровий/фізичний),
регіони доставки чи інші атрибути.
- Якщо інструмент не повернув потрібних даних або сталася помилка,
чесно повідомляй про це і не намагайся вгадувати значення.
# Робота з інструментами
- Завжди використовуй інструменти каталогу подарунків для будь-яких фактичних даних:
списку подарунків, цін, типів, доступності, SKU.
- Якщо інструмент повернув порожній результат, скажи, що за поточних умов
відповідних подарунків немає, і запропонуй варіанти послабити фільтри
(змінити бюджет, категорію, тип подарунка).
`;
Тут важливо кілька моментів.
По‑перше, ми розділяємо «загальні знання моделі» й «дані застосунку». Модель усе ще може пояснити, чим цифровий подарунок відрізняється від фізичного або які бувають приводи. Але будь‑які конкретні подарунки, ціни та SKU мають надходити лише з інструментів GiftGenius.
По‑друге, ми прямо описуємо, що робити у випадку помилок або порожньої відповіді. Не мовчати й не «креативити», а чесно сказати користувачу, що нічого не знайшлося, і запропонувати змінити параметри.
По‑третє, ми зосереджуємося не на абстрактному «не галюцинуй», а на конкретних типах поведінки, привʼязаних до нашого домену (каталог подарунків і купівля цифрових або фізичних SKU).
Цей шар сам по собі вже дуже допомагає. Але його легко «перебити» неакуратним описом інструмента. Тож переходимо до tool descriptions.
4. Рівень 2: описи інструментів (tool descriptions) і схеми як формальна частина контракту
Модель вирішує, коли і як викликати ваш інструмент, насамперед за:
- назвою інструмента;
- description інструмента;
- inputSchema / outputSchema (JSON Schema, що описує поля).
Тобто опис інструмента (tool description) — це не документація «для людей», а така сама частина промпта, тільки більш формалізована. І чимало галюцинацій народжується саме тут.
Уявімо наш інструмент recommend_gifts, який бекенд реалізує як добір подарунків із каталогу GiftGenius.
Поганий варіант опису міг би виглядати так:
// ПОГАНО: надто розпливчасто
const recommendGiftsTool = {
name: "recommend_gifts",
description: "Підбирає подарунки для користувача",
inputSchema: {
type: "object",
properties: {
profile: { type: "string" }
}
}
};
Формально все коректно, але з такого опису модель не розуміє:
- де межі інструмента;
- що робити, якщо подарунків не знайдено;
- що не можна вигадувати подарунки й ціни поза каталогом.
Хороший опис робить кілька речей одночасно: чітко задає домен, пояснює, коли викликати tool, і жорстко фіксує, що не можна вигадувати результати.
Приклад (адаптований під контракт GiftGenius із segments, budget, locale, occasion):
// config/tools.ts
export const recommendGiftsTool = {
name: "recommend_gifts",
description: `
Добір подарунків у каталозі GiftGenius.
Використовуй цей інструмент, коли потрібно отримати список реальних подарунків
за сегментами профілю отримувача, бюджетом, локаллю та приводом.
Інструмент повертає тільки ті подарунки, які реально є
в каталозі GiftGenius.
НЕ вигадуй подарунки та їх атрибути поза результатами цього інструмента.
Якщо інструмент повернув порожній список, не вигадуй альтернатив,
а переходь до діалогу: запропонуй змінити бюджет, тип подарунка,
привід або інші параметри.
`.trim(),
inputSchema: {
type: "object",
properties: {
segments: {
type: "array",
description:
"Сегменти профілю отримувача, наприклад ['tech', 'fitness'].",
items: { type: "string" }
},
budget: {
type: "object",
description: "Діапазон бюджету на подарунок.",
properties: {
min: {
type: "number",
description: "Мінімальна сума, невід’ємна.",
minimum: 0
},
max: {
type: "number",
description: "Максимальна сума, більша за 0.",
exclusiveMinimum: 0
},
currency: {
type: "string",
description: "Трилітерний код валюти, наприклад 'USD' або 'UAH'.",
minLength: 3,
maxLength: 3
}
},
required: ["min", "max", "currency"]
},
locale: {
type: "string",
description:
"Локаль користувача (формат мови/регіону), наприклад 'uk-UA' або 'en-US'.",
minLength: 2
},
occasion: {
type: "string",
description:
"Привід для подарунка: наприклад 'birthday', 'anniversary', 'new_year'."
}
},
required: ["segments", "budget", "locale", "occasion"]
}
};
Тут description робить кілька корисних речей.
По‑перше, він прямо каже, що інструмент працює лише з каталогом подарунків GiftGenius. А отже, будь‑які конкретні подарунки та ціни потрібно брати тільки з його результату.
По‑друге, він пояснює, коли використовувати інструмент: коли вам потрібен саме список конкретних подарунків за параметрами отримувача, а не загальна теорія про подарунки.
По‑третє, він задає поведінку за порожнього результату: не вигадувати, а переходити до діалогу (те, що потім ми зафіксуємо у follow‑up‑ах).
А inputSchema допомагає моделі надійніше витягати сутності з користувацького запиту: сегменти, бюджет, локаль і привід. Явна структура та обмеження полів (min, max, currency із фіксованою довжиною) теж знижують імовірність дивних комбінацій і помилок під час парсингу.
За потреби можна додати й «зворотний бік»: не лише «коли викликати», а й коли не викликати. Наприклад, якщо запит явно теоретичний:
description: `
...
Не використовуй цей інструмент, якщо користувач ставить загальне питання
про подарунки без запиту на добір для конкретної людини
(наприклад, "які бувають популярні подарунки на Новий рік загалом").
У таких випадках відповідай сам у чаті.
`.trim()
Так ви синхронізуєте опис інструмента з правилами з system‑prompt про «теоретичні» та «практичні» запити.
5. Рівень 3: follow‑ups як UX‑ та safety‑шар
Навіть якщо system‑prompt і описи tools написані ідеально, у реальності все одно трапляються збої:
- бекенд може повернути помилку;
- каталог може повернути порожній список;
- результати можуть бути неоднозначними або надто численними.
Якщо не прописати, що саме казати після виклику tool, модель почне імпровізувати. Іноді це спрацює добре, а іноді призведе до вигаданих фактів.
У лекції 2 ви вже бачили базові UX‑інструкції: як модель анонсує запуск застосунку, як завершує сценарій і що говорить користувачу «на виході». Тепер додамо до цього патерни follow‑up‑ів, які знижують ризик галюцинацій.
Такі патерни зазвичай описують прямо в system‑prompt окремим блоком — наприклад, «Діалог після роботи з інструментами».
Приклад фрагмента:
// продовження SYSTEM_PROMPT
export const SYSTEM_PROMPT = `
# ... попередні секції ...
# Діалог після роботи з інструментами
- Якщо інструмент добору подарунків повернув порожній список:
1) чесно скажи, що за поточних фільтрів відповідних подарунків не знайдено;
2) запропонуй користувачу змінити 1–2 ключові параметри
(бюджет, тип подарунка, інтереси отримувача, привід).
- Якщо інструмент повернув надто багато варіантів:
1) обери 3–7 найбільш релевантних;
2) явно скажи, за якими критеріями ти їх відібрав
(збіг за інтересами, попадання в бюджет, рейтинг).
- Якщо сталася помилка інструмента:
1) не вигадуй дані;
2) скажи, що сталася технічна помилка, і запропонуй
спробувати пізніше або спростити запит.
`.trim();
Так ми «прошиваємо» в модель приблизні follow‑up‑репліки. Вона сформулює їх своїми словами, але збереже задану структуру:
- констатація факту (порожньо / багато / помилка);
- чесне визнання обмеження;
- акуратна пропозиція наступного кроку.
Для каталогу подарунків це критично: замість «усе гаразд, ось вам три подарунки» у випадку порожнього результату модель скаже щось на кшталт:
«За вашими поточними умовами (цифровий подарунок про космос до $5 з доставкою тільки в США) у нашому каталозі нічого немає. Хочете, я спробую розширити бюджет або запропоную інші категорії?»
Зверніть увагу: це вже не код інструмента, а інструкції в промпті, які задають очікуваний UX.
6. Пов’язуємо все разом: еволюція нашого GiftGenius
Розгляньмо мініеволюцію нашого застосунку й крок за кроком зменшимо рівень галюцинацій.
Початкова версія: де все ламається
Припустімо, у нас був дуже мінімалістичний system‑prompt:
export const SYSTEM_PROMPT = `
Ти — помічник із добору подарунків.
Допомагай користувачу знаходити підхожі ідеї.
`;
А інструмент було описано так:
export const recommendGiftsTool = {
name: "recommend_gifts",
description: "Підбирає подарунки для користувача",
inputSchema: { type: "object" }
};
І — жодних інструкцій для follow‑up‑ів.
Що відбуватиметься на практиці:
- якщо користувач попросить «цифровий подарунок другові‑геймеру до $10», а в базі під такі фільтри нічого немає, модель може:
- або взагалі не викликати tool і вигадати подарунки «з голови»;
- або викликати tool, отримати порожній список, але не сказати про це й натомість запропонувати вигадані варіанти;
- якщо бекенд поверне помилку, модель може вирішити, що «щось та має бути», і почати вгадувати.
Так і виникає класична ситуація: у чаті — гарна відповідь, у базі — нічого схожого.
Нова версія system‑prompt
Перепишемо system‑prompt, врахувавши три рівні захисту. Частину ви вже бачили вище — тепер зберемо все докупи:
// config/systemPrompt.ts
export const SYSTEM_PROMPT = `
# Роль
Ти — GiftGenius, асистент з добору подарунків
на основі каталогу подарунків нашого застосунку.
# Зона відповідальності
- Твоє завдання — допомогти користувачу обрати відповідні подарунки
з каталогу, пояснюючи плюси й мінуси варіантів.
- Не давай обіцянок щодо фактичної купівлі або відправлення подарунка —
ти лише допомагаєш підібрати й порівняти варіанти.
Купівлю та видачу коду/посилання виконує backend після явної згоди користувача.
# Дані та обмеження
- Не вигадуй подарунки, яких немає в каталозі або у відповідях інструментів.
- Не вигадуй ціни, тип подарунка, наявність або регіони доставки.
- Якщо інструмент не повернув даних або сталася помилка,
не намагайся вгадувати, а повідом про це.
# Робота з інструментами
- Використовуй інструменти каталогу подарунків (наприклад, profile_to_segments,
recommend_gifts, get_gift) для будь-яких фактичних даних
(список подарунків, ціни, типи, SKU, описи).
- Відповідай сам (без інструментів), якщо питання теоретичне
і не вимагає добору конкретного подарунка.
# Діалог після роботи з інструментами
- За порожнього результату: чесно поясни, що нічого не знайдено
за поточних умов, і запропонуй змінити 1–2 параметри.
- За великої кількості варіантів: обери 3–7 найбільш придатних
і поясни критерії вибору.
- За помилки інструмента: не вигадуй дані, вибачся за збій
і запропонуй спробувати ще раз або спростити запит.
`.trim();
Тепер модель чітко розуміє:
- де вона консультант із подарунків, а де «бек‑офіс» (він у нас за інструментами);
- які саме дані не можна вигадувати;
- як поводитися в типових неідеальних ситуаціях.
Новий description і схема для recommend_gifts
Системний промпт ми посилили. Тепер наведімо лад в описі інструмента й зберімо фінальну версію на основі ідей із розділу 4.
// config/tools.ts
export const recommendGiftsTool = {
name: "recommend_gifts",
description: `
Добір подарунків у каталозі GiftGenius.
Використовуй цей інструмент, коли потрібно:
- отримати список реальних подарунків з актуальними цінами, типом
(digital/physical) і тегами;
- звузити вибір за сегментами інтересів, бюджетом, локаллю та приводом.
НЕ ВИКОРИСТОВУЙ інструмент:
- якщо користувач ставить загальне теоретичне питання про подарунки
без запиту на добір для конкретної людини;
- для вигадування подарунків, яких немає в каталозі.
Якщо результат порожній, НЕ вигадуй подарунки самостійно,
а поверни керування в діалог (дотримуйся інструкцій system-prompt).
`.trim(),
inputSchema: {
type: "object",
properties: {
segments: {
type: "array",
description:
"Сегменти профілю отримувача: наприклад, 'tech', 'sport', 'books'.",
items: { type: "string" }
},
budget: {
type: "object",
description:
"Діапазон бюджету на подарунок у валюті користувача (min/max).",
properties: {
min: { type: "number", minimum: 0 },
max: { type: "number", exclusiveMinimum: 0 },
currency: {
type: "string",
minLength: 3,
maxLength: 3,
description: "Код валюти ISO 4217, наприклад 'USD' або 'UAH'."
}
},
required: ["min", "max", "currency"]
},
locale: {
type: "string",
description: "Локаль користувача, наприклад 'uk-UA' або 'en-US'."
},
occasion: {
type: "string",
description:
"Привід для подарунка: 'birthday', 'anniversary', 'new_year' тощо."
}
},
required: ["segments", "budget", "locale", "occasion"]
}
};
Тут є кілька нюансів.
По‑перше, ми прямо повʼязуємо поведінку інструмента з system‑prompt. Фраза «дотримуйся інструкцій system‑prompt» нагадує моделі: «порожній результат = чесна розмова, а не креатив».
По‑друге, ми задаємо негативні умови («не використовуй…», «не вигадуй…»). Як показує практика, це не менш важливо, ніж позитивний опис.
По‑третє, ми робимо inputSchema семантично насиченою: нормальні описи й обмеження допомагають моделі правильно зіставляти запити з полями та рідше «помилятися» ще до виклику інструмента.
Патерни follow‑up‑ів у коді віджета та у форматі відповіді
Окрім текстових інструкцій, у нас є ще один важіль — формат відповіді інструмента. Через нього ми теж можемо підказати моделі, що сталося, і звузити поле для фантазії.
Формально follow‑up‑и задаються текстом у system‑prompt. Але у вашому Next.js‑віджеті ви можете додатково нормалізувати ToolOutput, щоб полегшити життя моделі й зменшити простір для домислів.
Наприклад, домовмося, що бекенд для recommend_gifts завжди повертає:
// тип відповіді інструмента на бекенді
export type RecommendGiftsResult = {
items: Array<{
id: string;
title: string;
price: number;
currency: "USD" | "EUR" | "UAH";
tags: ("digital" | "physical" | "education" | "fitness" | "tech")[];
}>;
// поле, яке backend заповнює, щоб явно сказати моделі, що сталося
status: "ok" | "empty" | "error";
errorMessage?: string;
};
Віджет може відображати це «красиво», а модель — спиратися на status під час формування відповіді. В Apps SDK ви часто повертаєте ToolOutput моделі як JSON‑обʼєкт, і вона бачить це поле.
У system‑prompt можна додати невеликий блок:
# Інтерпретація статусу інструмента
- Якщо status = "empty": дивись розділ "Діалог після роботи з інструментами" і
не вигадуй подарунки.
- Якщо status = "error": повідом про технічну помилку і не намагайся вгадувати
вміст каталогу.
Так, модель і без цього могла б здогадатися. Але явна інструкція знижує шанс «вгадувань» на основі припущень.
7. Практика: допрацьовуємо свій App
Щоб не залишалося відчуття «це гарно виглядає на слайдах», зафіксуймо конкретну вправу, яку ви можете виконати зі своїм поточним застосунком (у нашому випадку — GiftGenius). Зробіть невеликий рефакторинг за трьома рівнями захисту: system‑prompt, описи інструментів і обробка результатів.
По‑перше, на рівні system‑prompt візьміть ваш system‑prompt з першої лекції. Знайдіть у ньому місце, де описано зону відповідальності й роботу з інструментами, і додайте туди:
- заборону вигадувати сутності поза каталогом або базою (подарунки, SKU, ціни);
- правила на випадок порожнього результату та помилки інструмента;
- розділ «Діалог після роботи з інструментами» з 2–3 сценаріями (порожньо, багато, помилка).
По‑друге, на рівні описів tools відкрийте опис ключового інструмента (у вас це може бути recommend_gifts, search_gifts, search_tariffs, calculate_quote — неважливо). Перепишіть description так, щоб він:
- прямо вказував, що інструмент працює лише з вашим джерелом даних (каталог подарунків, тарифів тощо);
- пояснював, коли він потрібен, а коли — ні;
- містив явні негативні обмеження: «не вигадуй…», «не використовуй для…».
По‑третє, на рівні структури відповіді інструмента: якщо у відповіді ще немає поля, яке явно описує статус (status, resultType, hasMore), додайте його в тип на бекенді та в ToolOutput. Після цього в system‑prompt пропишіть, як модель має інтерпретувати цей статус у діалозі.
Насамкінець проганяйте кілька запитів у Dev Mode — зокрема такі, де результати наперед порожні або «граничні». Подивіться, чи перестала модель вигадувати сутності й наскільки чесно вона пояснює користувачу обмеження.
У наступній лекції ви формалізуєте такі запити в так званий golden prompt set і перетворите це на відтворюваний тестовий артефакт. А поки для нас важливо, щоб ви власноруч відчули різницю.
8. Типові помилки під час боротьби з галюцинаціями через промпти та інструменти
Помилка №1: одна «чарівна фраза» «не галюцинуй» у system‑prompt.
Розробник пише наприкінці промпта: «Не вигадуй інформацію» — і вважає завдання розвʼязаним. На практиці модель продовжує вигадувати, бо описи інструментів і follow‑up‑и не дають їй альтернативної поведінки. Без конкретних правил «що робити замість вигадування» (визнати порожній результат, запропонувати змінити фільтри, повідомити про помилку) така фраза майже не допомагає.
Помилка №2: суперечність між system‑prompt і description інструмента.
У system‑prompt ви кажете: «Не вигадуй подарунки, яких немає в каталозі», а в описі інструмента — «Підбирає відповідні подарунки, а якщо не знайшов — може запропонувати схожі варіанти на свій розсуд». У підсумку модель метається між двома джерелами правди, і перемагає (на жаль) конкретніше — зазвичай description інструмента. Потрібно, щоб обидва шари говорили одне й те саме. Якщо «схожі варіанти» допустимі, це теж варто формалізувати — і обовʼязково пояснювати користувачу, що це не точний збіг.
Помилка №3: надто розпливчасті описи інструментів.
Опис на кшталт «Інструмент, який допомагає користувачу розвʼязувати завдання» майже нічого не говорить моделі про межі інструмента. У такому разі вона або взагалі не використовуватиме його, або викликатиме з будь‑якого приводу. А потім «домислюватиме» дані, коли інструмент повернув мало або нічого. Хороший description має бути дискримінативним: прямо говорити, що робить інструмент і коли його не треба викликати.
Помилка №4: відсутність стратегії для порожніх і помилкових результатів.
Розробник дбайливо пише бекенд, який повертає { items: [], status: "empty" }, але ніде не пояснює моделі, що це означає. У результаті модель бачить порожній масив і вирішує: «мабуть, треба запропонувати щось із загальних знань». У system‑prompt бракує розділу, який пояснює, як інтерпретувати такі статуси і що говорити користувачу. Водночас кілька чітких правил для порожнього або помилкового результату дають дуже помітний приріст якості.
Помилка №5: спроба «лікувати» галюцинації лише на рівні коду віджета.
Іноді хочеться перекласти все на фронтенд: «якщо список порожній — покажу заглушку й не дам користувачу побачити текстову відповідь моделі». Це може трохи помʼякшити UX, але сама модель при цьому й далі «вірить» у вигадані сутності та так само поводиться в наступних репліках. Правильний підхід — спершу змінювати інструкції (system‑prompt, описи інструментів, follow‑up‑и), а вже потім доповнювати це захистами в UI.
Помилка №6: ігнорування впливу метаданих і схем на поведінку моделі.
Дехто сприймає JSON Schema та описи полів як «суто для форми й валідації». Насправді для ChatGPT це важлива частина промпта: за цими описами модель розуміє, які параметри потрібно витягнути із запиту і як виглядає коректна відповідь. Слабкі або неузгоджені описи полів (description, enum) підвищують шанс помилок і опосередковано провокують галюцинації.
Помилка №7: надто жорсткі заборони без альтернатив.
Буває, що промпт перетворюється на суцільний список «не роби того, не роби цього», але ніде не сказано, що робити у складних випадках. Наприклад, ми заборонили вигадувати подарунки й обмежилися лише каталогом, але нічого не сказали про теоретичні питання. У результаті модель інколи відповідає «я не знаю», хоча могла б корисно пояснити загальні принципи вибору подарунків. Намагайтеся не лише забороняти, а й відкривати дозволені шляхи: «якщо не можеш знайти подарунок у каталозі — чесно скажи про це і запропонуй, як можна змінити запит» або «якщо запит теоретичний — відповідай сам, без інструментів».
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ