Від Zero-Shot до самоконсистентності: практична ієрархія технік формулювання запитів.
Інжиніринг запитів як драбина: zero-shot, few-shot, декомпозиція, цикли критики та запити для міркувань, з прикладом бота-підтримки та ситуаціями, коли варто використовувати звичайний код.
Джерела: Prompt Engineering for LLMs: Zero-Shot, Few-Shot, Reasoning, Decomposition & ReAct
Як тільки додаток визначив, що бачитиме модель, які документи будуть завантажені, що буде стиснуто та що залишиться поза увагою, з’являється інша проблема — формулювання самого запиту. Жоден метод наведення інструкцій не є універсально ефективним. Розумною практикою є початок з найпростішої можливої інструкції та використання прикладів чи поетапної структури лише тоді, коли завдання вимагає цього.
Наведений нижче сценарій — це асистент з підтримки клієнтів.
Початок без жодних прикладів
Запит типу „zero-shot“ описує завдання, не показуючи прикладу хорошого результату. Для асистента з підтримки це може бути однорядковий запит на узагальнення скарги, з якою його надсилають:
Summarize the following customer complaint in one sentence.
<complaint>
The package arrived three days late and the box was damaged.
</complaint>
Модель отримує завдання та нічого більше. Саме ця простота є причиною, чому варто спробувати її спочатку. Кожен елемент, доданий до запиту, має свою ціну: приклади займають місце в контексті, додаткові інструкції підвищують складність, а кожен новий елемент створює ще одну можливість для зіткнення двох правил. Якщо пряма інструкція вже забезпечує надійний результат, складна структура є ліком від хвороби, якої у когось немає.
Що відповідає хороша інструкція
Добре сформульоване описання завдання визначає чотири аспекти: дію, яку потрібно виконати, матеріал, з якого слід черпати інформацію, обмеження, які діють, та форму, яку має мати відповідь. Більш повна версія запиту виглядає так:
Task:
Summarize the customer complaint.
Source:
<complaint>
The package arrived three days late and the box was damaged.
</complaint>
Constraints:
- Use only the information in the complaint.
- Do not infer the cause of the damage.
- Use one sentence.
Output:
Return only the summary.
Це більш детально, ніж просте запитання «Підсумуйте це», проте кожен доданий рядок усуває можливі припущення. Моделі більше не потрібно замислюватися, чи варто спекулювати щодо причин, як довго продовжувати, чи доцільні коментарі. Рекомендації від постачальників великих моделей вказують на те саме: потрібно чітко сказати, що полягає завдання, яким має бути результат, які обмеження діють та який контекст має значення, замість того, щоб сподіватися, що модель це зрозуміє сама. Простіше кажучи, кожна вимога, яка має значення для застосунку, має бути описана письмово.
Конкретні цілі кращі за нечіткі
„Бути корисним“ майже не дає моделі жодної конкретної мети. „Назвіть проблему, яку описує клієнт, та узагальніть її в одному реченні“ — це дає їй чітку мету. Порівняйте два інструкції для інструменту підтримки: у слабкій пропонується просто допомогти клієнту, тоді як у сильній — вимагається визначити проблему автентифікації, про яку говорить клієнт, а також навести щонайбільше три кроки для усунення несправностей на основі наданої документації.
Це має значення, тому що модель може розвивати поставлене завдання у багатьох можливих напрямках. Нечітка мета залишає простір для того, щоб вона обрала тлумачення, відмінне від того, що мав на увазі розробник, тоді як чітка мета звужує цей простір.
Обмеження мають бути в самому завданні
Нехай асистент ніколи не вигадує рішення, якого немає в документації. Це правило продукту, тому у запиті має бути чітко зазначено: використовувати лише надану документацію, а якщо вона не охоплює питання, зазначити, що наявної інформації недостатньо. Порівняйте це з вимогою „Бути точним“, яка описує бажаний результат, але не надає вказівок щодо дій у разі невизначеності.
Ця схема є універсальною. Необхідно не лише описувати ідеальний результат; потрібно також вказати, що має робити модель, коли цей результат неможливо отримати безпечно. Це має ще більше значення пізніше, під час використання інструментів та форматування результатів.
Де достатньо підходу zero-shot
Проста інструкція зазвичай підходить, коли завдання є простим, його опис легко сформулювати словами, модель вже знає тип завдання, правила формування вихідних даних є простими, а вхідні дані не містять дивних крайніх випадків. Запит на версію продукту у повідомленні, лише номер версії, — це одне з таких завдань. Переклад речення французькою — інше. Накопичення п’яти демонстрацій у будь-якому випадку мало допомагає.
Тож перше правило оптимізації запитів є дивно консервативним: починайте з методу zero-shot та додавайте додаткові механізми лише після того, як оцінка покаже потребу.
Способи, якими zero-shot може зазнати невдачі
Повторюються кілька типів невдач.
Неоднозначність. Фраза «Зробіть це краще» не визначає критеріїв: коротше, переконливіше, точніше, формальніше? Моделі доводиться припускати. Порівняйте це з проханням переписати відповідь підтримки так, щоб вона була стислою, професійною та зрозумілою для нетехнічного клієнта, при цьому зберігаючи всі фактичні твердження. У цьому випадку обмеження значно суворіші.
Відсутній контекст. Модель не може покладатися на факти, які їй ніколи не надавалися та які вона не може отримати. Якщо запитати її, чому у клієнта зазнала невдачі автентифікація, не надавши повідомлення про помилку чи деталей системи, жодна перефразування не створить відсутніх доказів. Тут рішенням є кращий контекст, а не краща інструкція. Це очевидний момент, а також справжня межа інженерії запитів.
Суперечливі вимоги. Запит, який вимагає повного пояснення рівно у десять слів, передбачає дві речі, які неможливо виконати належним чином одночасно. Хороше проектування запитів допомагає уникнути таких конфліктів, замість того щоб покладатися на модель для їх вирішення.
Невисловлені припущення. Розробник, який пише «Узагальніть скаргу», може мав на увазі «вказати лише ті факти, які навів клієнт». У такому разі модель може надати витончене узагальнення з розумними висновками. Якщо ця різниця має значення, інструкцію потрібно сформулювати чітко. Припущення, які мають значення для системи, мають стати чіткими, читабельними для машин вимогами.
Додавання прикладів
Коли звичайна інструкція недостатня, на допомогу приходить метод кількісного навчання: включення готових прикладів виконання завдання в контекст. Класифікатор, який сортує повідомлення на категорії оплати, технічні та акаунтні, може показати кілька позначених повідомлень перед справжнім:
Task:
Classify the customer message as BILLING, TECHNICAL, or ACCOUNT.
Example 1:
"My invoice contains an unexpected charge."
→ BILLING
Example 2:
"The application crashes when I upload a file."
→ TECHNICAL
Example 3:
"I cannot reset my password."
→ ACCOUNT
Now classify:
"I was charged twice for my subscription."
На основі цих демонстрацій модель виводить правила відповідності. Це називається навчанням у контексті, оскільки модель змінює свою поведінку щодо поточного запиту, використовуючи приклади зі свого „вікна“, при цьому її базові параметри залишаються незмінними. По суті, приклади говорять: „Ось як виглядає завдання на практиці“, і вони можуть передати деталі, які важко описати прозою.
Демонстрації навчають завданню, а не лише форматуванню
Багато розробників використовують приклади з невеликою кількістю екземплярів як допомогу у форматуванні. Але вони роблять ще більше. Візьмемо приклад пари „додаток працює повільно“ з міткою TECHNICAL. Це показує формат вихідних даних, але також демонструє, як цей додаток розуміє категорію TECHNICAL. Приклади формують розуміння самого завдання у моделі.
Саме тому погані приклади є ризикованими. Несуворі мітки, випадкова упередженість чи крайні випадки, які суперечать правилам, можуть бути повторно використані моделлю.
Вибір прикладів для включення
За наявності 10 000 історичних заявок включити їх усі в запит є нереальним, тому необхідно обрати підмножину. Випадковий вибір є примітивним підходом. Кращим є свідомий вибір репрезентативних випадків:
Example 1: straightforward billing issue
Example 2: straightforward technical issue
Example 3: ambiguous issue
Example 4: boundary case
Example 5: short, poorly written request
Те, що вважається гарним вибором, залежить від завдання. Для класифікації необхідно представити основні класи та їхні межі. Для завдань форматування потрібні приклади, які демонструють бажану структуру. Завдання, що вимагають логічних міркувань, виграють від прикладів, які показують, як розбити проблему на частини або її перевірити. У кожному випадку приклад заслуговує на місце завдяки інформації, яку він несе, а не через те, що він доступний.
Скільки
Більше не означає автоматично краще. Якщо один ретельно підібраний приклад робить поведінку очевидною, ще тридцять прикладів можуть додати тисячі токенів без жодної користі та навіть ввести суперечливі закономірності. Тому для завдань з невеликою кількістю прикладів існує та сама проблема обмеженого обсягу контексту, що й у всіх інших випадках, і правильну кількість потрібно знайти шляхом тестування.
Тут інжиніринг запитів починає нагадувати експериментальну роботу. Питання вже не полягає у тому, чи звучить запит краще, а у тому, чи працює ця версія краще у репрезентативних тестових випадках. Ця зміна стає ключовою, як тільки у гру вступає оцінка.
Різноманітність прикладів
Якщо кожна демонстрація — це короткий, зрозумілий та добре написаний запит, модель може навчитися вузькій моделі поведінки, якої не дотримуються справжні користувачі. Справжні повідомлення виглядають так:
"can't login"
"I've been locked out since yesterday"
"Password reset isn't sending me anything"
"login broken after changing phone"
Усі ці описи стосуються схожих проблем, але використовують зовсім різні формулювання. Хороший набір прикладів відображає ту варіативність, яку очікує додаток. Це не означає додавання прикладів випадково; це означає навмисне охоплення значущих відмінностей.
Показ того, чого слід уникати
Для деяких завдань корисно поєднувати хороший результат із поганим, щоб модель могла побачити межу. У випадку підтримки повідомлення про запізнене отримання пакета може супроводжуватися як прийнятним, так і некоректним резюме:
Input:
"The customer says the package arrived late."
Good output:
"The customer reports that the package arrived late."
Bad output:
"The courier lost the package."
Reason:
The customer did not state that the courier lost it.
Поганий приклад вказує на межу: не слід виводити факти, які не підтримуються вхідними даними. Однак з негативними прикладами потрібно бути обережними. Той, що позначений як неправильний, може випадково навчити саме тієї поведінки, яку мав запобігти, особливо коли різниця є тонкою. Програма повинна перевіряти, чи покращують негативні приклади результати, а не просто припускати, що так і буде.
Приклади для структури
Коли складно описати формат вихідних даних, корисним є приклад. Припустимо, що асистент має відповісти трьома рядками з позначками для проблеми, доказів та дій:
Issue: ...
Evidence: ...
Action: ...
Одна працююча демонстрація миттєво утверджує цю структуру:
Input:
"The login token expired after 30 days."
Output:
Issue: Expired authentication token
Evidence: Token expiration is reported after 30 days
Action: Regenerate the authentication token
Це виправляє як шаблон контенту, так і його подання. Однак приклади не завжди є правильною відповіддю. Якщо програмному забезпеченню потрібен машинний формат JSON із гарантованою коректністю, функція форматування, обмежена схемою, може бути надійнішою, ніж надання моделі зразка.
Збереження послідовності прикладів
Запити з невеликою кількістю прикладів погано реагують на суперечності. Розгляньмо два приклади з однаковим вхідним даним „Не вдається увійти“, позначені як ACCOUNT у одному та TECHNICAL у іншому:
Example 1:
"Can't log in" → ACCOUNT
Example 2:
"Can't log in" → TECHNICAL
У моделі немає чіткого способу визначення, яке мапування є бажаним. Навіть незначні неузгодження завдають шкоди. Якщо деякі приклади використовують позначку BILLING, а інші — фразу „Проблема з оплатою“, простір результатів стає нечітким. Позначки, форматування, термінологія, рівень деталізації та спосіб обробки крайніх випадків мають бути однаковими у всіх прикладах. Демонстрації є частиною специфікації та заслуговують на таку саму увагу.
Навчання всередині контексту
Навчання в контексті — це основна ідея підходу з кількома прикладами: приклади знаходяться в поточному контексті, і поведінка моделі змінюється під впливом цієї взаємодії. Це не означає, що модель постійно засвоює їх. Якщо додаток надсилає один приклад із позначкою, а потім повідомлення від користувача про неможливість доступу до облікового запису:
Example:
"Password reset email never arrived." → ACCOUNT
User:
"I can't access my account."
Модель може використовувати демонстрацію для цього запиту. Її параметри не оновлюються, і приклад не додається до її постійних знань. Це відображає розмежування між контекстом та пам’яттю, про яке йшлося раніше. Методи, які змінюють параметри, наприклад тонке налаштування за допомогою додаткових даних для навчання, є окремим механізмом, і їх порівняння з методом запитування відбувається значно пізніше. Наразі метод запитування з кількома прикладами краще розглядати як тимчасове умовлювання завдання через контекст.
Вибір між двома підходами
Ефективний процес прийняття рішень починається з визначення того, чому результат є неправильним. Неоднозначне завдання вимагає більш чіткого формулювання. Відсутня інформація потребує кращого контексту. Коли модель ігнорує певну тонку конвенцію, тут можуть допомогти приклади. Якщо завдання вимагає точних арифметичних обчислень чи доступу до бази даних, додавання більше тексту у запит може бути зовсім неправильним рішенням.
Цей останній випадок веде до складніших ситуацій. Деякі завдання занадто складні, щоб їх можна було надійно виконати за допомогою однієї інструкції та однієї відповіді. Їх потрібно розділити на менші операції, перевірити або пов’язати з зовнішніми обчисленнями. Після певної межі завданням вже не є пошук ідеального речення; це проектування невеликої процедури, яку має дотримуватися модель.
Розгляньмо ситуацію, коли клієнт не може увійти в систему одразу після зміни пароля, і від асистента вимагають пройтися по історії, визначити ймовірну причину та написати відповідь. Це здається одним завданням. Насправді воно приховує кілька: з’ясування того, що сталося, пошук відповідних доказів, розрізнення фактів від припущень, аналіз можливих причин, вирішення, що можна безпечно порекомендувати, перевірка цієї рекомендації та написання кінцевої відповіді. Розуміння цього є вхідними дверима до декомпозиції завдань.
Розділення одного завдання на кілька
Декомпозиція замінює одну складну роботу на кілька менших, які мають чіткі межі. Замість того, щоб просити все одразу, додаток може розбити запит на етапи:
Task:
Analyze this customer support case.
Step 1:
Extract the relevant facts.
Step 2:
Identify the customer's actual problem.
Step 3:
List plausible causes supported by the evidence.
Step 4:
Select the safest supported resolution.
Step 5:
Draft the customer-facing response.
Моделі буквально не потрібне слово „Крок“. Важливо те, що розмита мета перетворюється на послідовність керованих операцій. Це особливо корисно, коли елементи мають різну природу: вилучення фактів — це завдання з обробки інформації, вибір діагнозу — це міркування, а написання повідомлення — це комунікація. Об’єднання їх у єдину недиференційовану інструкцію ускладнює керування результатом та його оцінку.
Розкладена система також пропонує більше можливостей для тестування. Якщо кінцева відповідь неправильна, можна з’ясувати, чи не виявилися проблемами вилучення фактів, постановка діагнозу чи написання відповіді. Зміна підходу полягає у тому, що запит можна структурувати як конвеєр, а не лише записувати у вигляді запитання.
Спочатку сплануйте, потім дійте
Схожа техніка полягає у тому, що від моделі вимагають скласти план перед виконанням складної задачі. Це допомагає, коли моделі потрібно вирішити, які операції необхідні, перш ніж вона зможе дати відповідь. Асистент може почати з мети та послідовного плану:
Goal:
Resolve the customer's login problem using only supported evidence.
Plan:
1. Read the latest customer message.
2. Check the relevant conversation history.
3. Identify authentication-related evidence.
4. Compare the evidence with the known troubleshooting guidance.
5. Produce a response that does not claim unsupported facts.
Планування відокремлює процес прийняття рішення щодо того, як щось вирішити, від самого процесу вирішення. Це розділення стає ще важливішим, коли залучаються інструменти, адже моделі може знадобитися зробити висновок про необхідність пошуку в базі знань, перегляду запису облікового запису чи спочатку виконання обчислень. Використання підказок дозволяє сформувати структуру роботи ще до її початку.
Це має свою ціну. Розкладання завдання на етапи збільшує довжину підказок, а коли кожен етап є окремим запитом, це також призводить до додаткових викликів моделі та затримок. П’ятиетапний процес може коштувати значно більше, ніж один виклик. Це виправдано, коли додатковий контроль та надійність компенсують цю вартість, а не тому, що більше етапів за своєю суттю кращі.
Створювати, аналізувати, коригувати
Ще один ефективний підхід дозволяє моделі ще раз переглянути свій власний проєкт відповіді. Перша відповідь не вважається остаточною; під час другого проходу вона перевіряється за конкретними критеріями. Для системи підтримки це означає скласти проєкт відповіді, а потім перевірити його за списком визначених проблем:
First:
Draft the response.
Then:
Check the draft for:
- unsupported claims,
- missing evidence,
- incorrect troubleshooting steps,
- promises the support team cannot make,
- failure to answer the customer's actual question.
Finally:
Revise the response to correct any problems.
Це працює тому, що створення та оцінка — це різні завдання. Генерація означає створення чогось правдоподібного. Перегляд існуючої відповіді дозволяє моделі шукати порушення певного переліку критеріїв. Викладення критеріїв зазвичай є ефективнішим, ніж просто просити її думати більше.
Ця схема може застосовуватися на різних рівнях складності: чернетка, перегляд, остаточна відповідь, або для більш структурованої роботи — вилучення інформації, перевірка вилученої інформації, класифікація, перевірка класифікації, генерація. Друга форма легша для виправлення помилок, оскільки кожен етап має чітко визначені вимоги.
Одна обмеженість є важливою. Модель, яку просять критикувати себе, не є самостійним джерелом істини. Якщо початкова відповідь ґрунтується на хибній припущенні, критик також може її поділити. Самокритика може покращити послідовність, але не гарантує правильності, тож при прийнятті важливих рішень варто перевіряти їх за допомогою чогось ззовні моделі: бази даних, відомих правил, розрахунків, отриманих документів чи детерміністичного коду.
Запити, які розкривають структуру міркувань
Дослідження щодо запитів типу „chain-of-thought“ показали, що наведення моделі прикладів із проміжними кроками міркувань може покращити результати у деяких багатокрокових задачах, що проявилося у покращеннях на тестах з арифметики, здорового глузду та символічних завдань. Урок інженерії є ширшим за цей вираз: складне завдання може отримати користь, якщо запит чітко визначає його проміжну структуру.
Identify the relevant facts.
Determine which facts support each possible conclusion.
Eliminate conclusions that require unsupported assumptions.
Select the conclusion supported by the evidence.
Це запитування, орієнтоване на міркування: сформулювання завдання так, щоб проміжні рішення були достатньо зрозумілими для спрямування моделі до бажаного результату. Це не зобов’язує додаток показувати користувачеві внутрішні міркування моделі. Часто кращий інтерфейс запитує про результат перевірки, а не довге пояснення. Додаток може вимагати компактного внутрішнього запису, подібного до наведеного нижче, а потім окремо створювати коротку відповідь для клієнта:
classification: password_reset_issue
evidence_supported: true
recommended_action: resend_reset_link
confidence: high
Структура міркувань та пояснення для клієнта є окремими вимогами. Розділення їх також допомагає уникнути поширеної помилки — припущення, що більш помітні міркування роблять відповідь більш надійною. Проміжні кроки також можуть містити помилки. Дослідження методу chain-of-thought prompting показали, що такі властивості демонстрацій, як їхня релевантність та порядок, мають велике значення, тому просте додавання довгих обґрунтувань не є універсальним рішенням.
Кілька спроб, потім голосування
Генерація є ймовірнісною, тому одна проблема може давати різні відповіді під час різних запусків. Метод самоконсистентності використовує це, добираючи кілька шляхів міркувань та обираючи ту відповідь, яку підтримує більшість з них, замість того щоб покладатися на один обраний шлях.
Припустимо, що система підтримки клієнтів не впевнена, чи йдеться про проблему з скиданням пароля, чи про блокування облікового запису. Замість того, щоб обрати одну класифікацію, вона може створити кілька аналізів та порівняти отримані результати.
Узгодженість все одно не є ознакою істини. Якщо модель постійно неправильно інтерпретує ситуацію, багато незалежних процесів обробки можуть дійти до однієї й тієї самої неправильної відповіді. Нестача розбіжностей свідчить про стабільність, але не є доказом правильності. Крім того, це потребує більше обчислень та спричиняє затримки, тож такий підхід є привабливим лише для завдань настільки складних, що підвищена надійність виправдовує витрати.
Де запити мають передаватися коду
Ось де проходить межа між все складнішими запитами та хорошим проектуванням системи. Уявіть собі запит на підсумок рахунку-фактури з 17 позиціями по ціні 1500 рупій кожна. Модель, ймовірно, зможе обчислити цю суму, але коли важлива точна фінансова цифра, немає причин змушувати її імітувати арифметичні операції за допомогою все довших інструкцій. Калькулятор чи звичайна програма виконують множення детерміністично.
Та сама логіка застосовується й до інших завдань:
- Дані про рахунок мають надходити з запиту до бази даних, а не з пам’яті моделі.
- Актуальні факти слід отримувати, а не згадувати з процесу навчання.
- Арифметика — це справа калькулятора чи програми.
- Перевірка схеми — це робота парсера та валідатора.
- Авторизація стосується коду додатку та правил керування доступом.
- Критичні бізнес-правила слід кодувати детерміністично, де це можливо.
Існує корисне правило: використовуйте запити для керування поведінкою мовної моделі, а також застосовуйте детерміністичне програмне забезпечення тоді, коли завдання дійсно вимагає детерміністичних обчислень чи строгого дотримання правил.
Зовнішні дії допомагають у цьому. ReAct – відомий дослідницький підхід – поєднує міркування з діями, щоб модель могла звертатися до зовнішніх джерел чи середовищ замість того, щоб покладатися лише на внутрішні знання; цей підхід довів, що така взаємодія може полегшити проблеми, такі як галюцинації та поширення помилок у деяких завданнях.
Це міст до того, що буде далі. Система підтримки спочатку була простим запитом, а тепер нагадує невелику програму. Як тільки для перевірки потрібні база даних, база знань, API чи інші зовнішні ресурси, модель більше не працює лише з текстом, і питання переходить до інженерії контексту: необхідно вирішувати не лише, які інструкції написати, а й яку інформацію має отримати модель.