Prompt engineering у цифрах: що змінює output
60 тікетів, ті самі слова в шести порядках і точність від 26,7 % до 85,0 %. Чотири інтернет-трюки — з error bars для кожного.
На цій сторінці
Ось тікет підтримки й чотири черги, куди його можна спрямувати.
The label on the parcel has my old surname on it.
-> billing / technical / shipping / accountЩоб маршрутизувати його, у prompt потрібні три речі: визначення черг, тікет і інструкція вибрати одну. Три блоки. Є шість порядків, у яких їх можна розмістити, і в усіх шести блоки містять рівно ті самі символи.
На шістдесяти тікетах із відомими відповідями ці шість порядків дають результат від 26,7 % до 55,0 %. Перенесіть ті самі два блоки з user turn у system turn, не змінивши жодного слова, — і та сама модель набирає 76,7 %. Обгорніть тікет у тег у стилі XML — і результат доходить до 85,0 %.
У моделі нічого не змінилося. У задачі нічого не змінилося. Не було переписано жодного слова. Розмах у п’ятдесят вісім пунктів виник лише через упорядкування того самого тексту.
Саме тому цей розділ існує, і саме тому це найзараженіша cargo-cult тема в галузі. Ефекти реальні й великі, тому кожен анекдот здається підтвердженим; і вони нестабільні між моделями та задачами, а отже більшість порад так і лишається анекдотом. Тож у цього розділу є одне правило, і все в ньому підпорядковано цьому правилу:
Prompt треба вимірювати, а не обговорювати. Чотири варіанти на двадцяти кейсах не відрізняють нічого.
Prompt — це весь стан
Посилання на розділ: Prompt — це весь станПеред вимірюваннями — один факт, який тихо пояснює половину подальшого.
У моделі немає пам’яті. Між двома викликами вона нічого не зберігає — ні ваше останнє запитання, ні власну останню відповідь, ні файл, який ви прикріпили, ні факт, що ви вже питали її двічі. Кожен виклик стартує з порожньої машини, і єдине, що ця машина знає, — це послідовність tokens, яку ви щойно їй передали.
Те, що в інтерфейсі чату виглядає як пам’ять, — це ваш клієнт, який щоразу заново надсилає всю розмову, кожен turn, від самого початку. Модель щоразу перечитує все з нуля. Розділ 13 виміряв, скільки коштує це перечитування у forward pass; Розділ 16 перетворює це на рядок у рахунку. Тут важливий наслідок для дизайну: prompt — це не повідомлення системі, яка має стан. Він і є станом.
Це знімає цілу родину непорозумінь. «Модель забула, що я їй сказав» зазвичай означає, що це ніколи не було надіслано. «Вона проігнорувала мою попередню інструкцію» зазвичай означає, що інструкція випала з window, коли історію обрізали. «У production вона поводилася інакше» зазвичай означає, що production збирає інший prompt, ніж той, який ви тестували. Жодне з цього не є проблемою моделі, і жодне не виправляється переформулюванням.
Твердження «цей prompt кращий» — це твердження про розподіл, а розподіл не видно з одного output. Потрібне щось нудне: кейси з відомими відповідями, N варіантів і інтервал.
harness — це п’ятдесят рядків TypeScript тієї самої форми, що й клієнт із Розділу 14: запит, дедлайн, трохи конкурентності, підрахунок. Він знову з’являється в Розділі 19, щоб оцінити retriever, і в Розділі 29 як golden set.
export type Case = { input: string; expected: string };
export type Variant = { name: string; build: (c: Case) => ChatMessage[] };
async function pooled<T, R>(xs: T[], n: number, f: (x: T) => Promise<R>) {
const out: R[] = new Array(xs.length);
let i = 0;
await Promise.all(
Array.from({ length: n }, async () => {
while (i < xs.length) {
const k = i++;
out[k] = await f(xs[k]);
}
}),
);
return out;
}
export async function runVariant(v: Variant, cases: Case[], concurrency = 6) {
const hits = await pooled(cases, concurrency, async (c) => {
const answer = await complete(v.build(c));
return answer.trim().toLowerCase() === c.expected;
});
return { name: v.name, hits, k: hits.filter(Boolean).length, n: cases.length };
}Число, яке повертається, — це не результат. Ось результат:
/** 95 % Wilson score interval for a proportion. Chapter 4 derives it. */
export function wilson(k: number, n: number, z = 1.96) {
const p = k / n;
const d = 1 + (z * z) / n;
const centre = (p + (z * z) / (2 * n)) / d;
const half = (z * Math.sqrt((p * (1 - p)) / n + (z * z) / (4 * n * n))) / d;
return [Math.max(0, centre - half), Math.min(1, centre + half)] as const;
}Розділ 4 навів аргумент, а цей розділ його інкасує. Сімнадцять правильних із двадцяти — це 85 %, а його 95 % інтервал іде від 64 % до 95 %. Варіант із результатом 13 із 20 — 65 %, що здається явно гіршим, — має інтервал від 43 % до 82 %. Ці два інтервали перекриваються майже по всій довжині. Двадцять кейсів не можуть відрізнити хороший prompt від посереднього, а більшість опублікованих порад щодо prompt було валідовано на меншій кількості.
Шістдесят кейсів, саме стільки використано в цьому розділі, — це все ще небагато. Цього досить, щоб побачити великі ефекти, і достатньо чесно, щоб визнати, коли дрібні ефекти не видно, — і нижче це доведеться визнати кілька разів.
Позиція: ті самі слова, шість порядків
Посилання на розділ: Позиція: ті самі слова, шість порядківТри блоки — правила R, тікет T, інструкція I — склеєні в одне user message. Усі шість перестановок, байтово ідентичний вміст, по шістдесят кейсів кожна.
| порядок трьох блоків | правильно | точність, 95 % Wilson |
|---|---|---|
| правила, інструкція, тікет | 33/60 | 55,0 % [42,5, 66,9] |
| правила, тікет, інструкція | 30/60 | 50,0 % [37,7, 62,3] |
| тікет, правила, інструкція | 22/60 | 36,7 % [25,6, 49,3] |
| інструкція, тікет, правила | 21/60 | 35,0 % [24,2, 47,6] |
| інструкція, правила, тікет | 17/60 | 28,3 % [18,5, 40,8] |
| тікет, інструкція, правила | 16/60 | 26,7 % [17,1, 39,0] |
Від найкращого до найгіршого — 28,3 пункта, і інтервали не перекриваються, тож це не історія про шум. Оскільки кожну гілку оцінено на тих самих шістдесяти items, гостріше запитання — парне: серед кейсів, де дві гілки не погоджуються, наскільки перекошений розподіл? Перехід від найгіршого порядку до найкращого перевернув 21 кейс у правильний бік і 4 у неправильний — точна парна ймовірність 0,0009.3
Читайте таблицю за її формою, а не за переможцем. Два найкращі рядки обидва закінчуються тікетом; два найгірші або ховають інструкцію посередині, або тягнуть її після даних. Це те саме явище, яке Liu et al. назвали Lost in the Middle: матеріал на краях prompt використовується надійніше, ніж матеріал у центрі.4 Розділ 16 рахує ціну window, а Розділ 24 вимірює ефект як слід на довжині, де середина провалюється, як описано, а відновлення в самому кінці не повторюється. Тут практичне правило випадає саме: задача згори, дані знизу, нічого важливого посередині.
Тепер перенесіть ті самі слова між turns. Розділ 11 встановив, що chat template — це не декорація навколо моделі, а частина моделі: <|im_start|>system і <|im_start|>user — реальні tokens, які модель бачила мільйони разів під час fine-tuning, саме в цих позиціях. Тож має значення, по який бік цих маркерів опиниться ваша інструкція, — і воно має:
| де живуть ті самі слова | правильно | точність, 95 % Wilson |
|---|---|---|
| правила й інструкція в system turn, лише тікет у user turn | 46/60 | 76,7 % [64,6, 85,6] |
| правила в system turn, інструкція й тікет у user turn | 44/60 | 73,3 % [61,0, 82,9] |
| правила й інструкція в system turn, інструкція повторена після тікета | 42/60 | 70,0 % [57,5, 80,1] |
| усі три блоки в одному user turn | 33/60 | 55,0 % [42,5, 66,9] |
Перенесення правил і інструкції через межу template дало 21,7 пункта — 19 кейсів здобуто, 6 втрачено, парна ймовірність 0,0146 — без зміни жодного символу. Це конкретна відповідь на system prompt проти user prompt: це не два способи сказати те саме. Це дві різні token positions у структурі, на якій навчали модель, і system position — місце для інструкцій, що застосовуються до всієї розмови.
Зверніть увагу і на третій рядок. Повторення інструкції після тікета — широко рекомендований трюк — спрацювало гірше, ніж одноразове формулювання. На цій моделі, у цій задачі, сказати двічі було гірше, ніж сказати один раз.
Розділювачі й статистичний урок, захований у них
Посилання на розділ: Розділювачі й статистичний урок, захований у нихТой самий prompt, найкраще розміщення, шістдесят кейсів. Змінюється лише те, що оточує текст тікета.
| як обмежено тікет | правильно | точність, 95 % Wilson |
|---|---|---|
| тег у стилі XML | 51/60 | 85,0 % [73,9, 91,9] |
| нічого | 48/60 | 80,0 % [68,2, 88,2] |
| заголовок Markdown | 47/60 | 78,3 % [66,4, 86,9] |
мітка, Ticket: | 46/60 | 76,7 % [64,6, 85,6] |
| hash fences | 45/60 | 75,0 % [62,8, 84,2] |
| triple backticks | 44/60 | 73,3 % [61,0, 82,9] |
| подвійні лапки | 40/60 | 66,7 % [54,1, 77,3] |
Вісімнадцять пунктів розмаху від пунктуації. Але подивіться на два крайні інтервали: [73,9, 91,9] і [54,1, 77,3]. Вони перекриваються. За грубим прочитанням — порівняти error bars, і якщо вони торкаються, нічого не казати — ця таблиця взагалі нічого не доводить.
Грубе прочитання тут неправильне, і зрозуміти чому важливіше за таблицю. Кожен варіант оцінювали на тих самих шістдесяти тікетах, тож два вимірювання не є незалежними вибірками; вони парні. Більша частина ширини кожного інтервалу походить із джерела невизначеності, спільного для обох гілок, — чи репрезентативні ці шістдесят тікетів, — і це джерело скасовується, коли ви порівнюєте їх між собою. Поставте натомість парне запитання, і відповідь буде різкою: перехід від подвійних лапок до XML-тега перевернув 12 кейсів у правильний бік і 1 у неправильний, парна ймовірність 0,0034. Це реальна різниця.
А потім той самий тест здуває заголовок. XML-тег переміг просту мітку Ticket: на 8,3 пункта — саме це число блог поставив би в заголовок. Парно: 6 здобуто, 1 втрачено, ймовірність 0,1250. Не встановлено. Сім кейсів — ось на чому тримається те знамените покращення.
Отже, є два запитання з двома різними інструментами, і їхнє змішування — це спосіб, яким поради щодо prompt помиляються в обох напрямах одночасно:
Наскільки хороший цей prompt? Інтервал Wilson на його власній точності. Широкий, якщо у вас не сотні кейсів. Це число ви звітуєте тому, хто вирішує, чи ship.
Чи B кращий за A? Парний тест на кейсах, де вони не погоджуються. Набагато чутливіший, бо спільна складність набору скасовується. Це число ви використовуєте, щоб вибрати між двома кандидатами.
Загальний висновок — що моделі сильно й непередбачувано чутливі до форматування, яке не несе семантичного змісту, — не новий. Sclar et al. змінювали лише розділювачі, пробіли й регістр у десятках задач і знайшли розмахи точності, достатні, щоб перевернути опубліковані рейтинги моделей.5 Практичний наслідок — не «використовуйте XML-теги». А те, що форматування — це hyperparameter, його нічого не коштує перебрати, і будь-яке порівняння двох моделей, яке фіксує один формат, порівнює формати не менше, ніж моделі.
Скільки прикладів насправді достатньо
Посилання на розділ: Скільки прикладів насправді достатньоIn-context learning — показати моделі відпрацьовані приклади в prompt і змусити її узагальнити з них без жодного оновлення weights — це здатність, яка зробила GPT-3 знаменитою.6 Практичне питання ніколи не в тому, чи це працює. Воно в тому, за скільки прикладів варто платити.
Приклади заходять як справжні попередні turns, чергуючи user і assistant, бо саме на такій структурі навчався template. Кожен k запускали з п’ятьма різними випадковими вибірками з окремого пулу шістнадцяти розмічених тікетів:
| приклади | середня точність | найгірша й найкраща вибірка | розмах між вибірками |
|---|---|---|---|
| 0 | 76,7 % | — | — |
| 1 | 78,7 % | 78,3 – 80,0 % | 1,7 пункта |
| 2 | 83,7 % | 80,0 – 86,7 % | 6,7 пункта |
| 4 | 81,7 % | 78,3 – 86,7 % | 8,3 пункта |
| 8 | 83,7 % | 78,3 – 88,3 % | 10,0 пункта |
| 16 | 89,3 % | 85,0 – 93,3 % | 8,3 пункта |
Два приклади дали сім пунктів. Наступні шість прикладів не дали нічого вимірюваного — 83,7, потім 81,7, потім 83,7, послідовність блукає всередині власного шуму. Шістнадцять дали ще п’ять із половиною. Крива — не плавне зростання; це крок, плато й крок.
Найважливіший стовпець — останній. На k = 8 те, які саме вісім прикладів ви випадково вибрали, зрушило точність на 10 пунктів — більше, ніж увесь виграш від переходу з двох прикладів до восьми. А нижній рядок — найгостріша версія цього: на k = 16 пул вичерпано, тож усі п’ять запусків містять рівно ті самі шістнадцять прикладів, відрізняючись лише порядком появи. Сам лише порядок зрушив точність на 8,3 пункта.
Це результат, про який повідомили Lu et al., і він виживає всюди, де його шукали: порядок прикладів — справжній hyperparameter з ефектами, порівнянними з кількістю прикладів.7 Тож чесна порада щодо few-shot prompting — не число. Вона така:
Починайте з нуля й додавайте приклади лише проти вимірювання
Посилання на розділ: Починайте з нуля й додавайте приклади лише проти вимірюванняПерші два зазвичай того варті. Далі ви вгадуєте, а це вгадування коштує tokens у кожному окремому виклику до кінця життя продукту.
Вважайте добір частиною prompt
Посилання на розділ: Вважайте добір частиною promptДва добре вибрані приклади б’ють вісім недбало вибраних. Якщо ваші приклади взято з верхівки spreadsheet, це змінна, яку слід перебрати перед додаванням нових.
Переберіть порядок один раз, а потім зафіксуйте його
Посилання на розділ: Переберіть порядок один раз, а потім зафіксуйте йогоЦе безкоштовно, це реальний ефект, і на відміну від більшості цього розділу, щоб спробувати, не потрібне переписування.
Перевірте баланс класів
Посилання на розділ: Перевірте баланс класівЧотири приклади з однаковою міткою вчать модель мітки, а не задачі. Провал цієї моделі до тієї черги, яка була вказана останньою, — той самий збій в іншому костюмі.
Чотири речення з інтернету
Посилання на розділ: Чотири речення з інтернетуТепер фольклор. Кожне з них — одне речення, додане на початок system prompt, який в іншому ідентичний, на тих самих шістдесяти кейсах.
| речення, додане до system prompt | правильно | точність, 95 % Wilson | парно проти baseline |
|---|---|---|---|
| нічого не додано | 46/60 | 76,7 % [64,6, 85,6] | — |
| «Take a deep breath and work on this problem carefully.» | 47/60 | 78,3 % [66,4, 86,9] | +4 / −3, p = 1,000 |
| «This is very important to my career.» | 46/60 | 76,7 % [64,6, 85,6] | +5 / −5, p = 1,000 |
| «You are a world-class customer support operations expert with twenty years of experience.» | 42/60 | 70,0 % [57,5, 80,1] | +3 / −7, p = 0,344 |
| «I will tip you $200 if you answer correctly.» | 41/60 | 68,3 % [55,8, 78,7] | +1 / −6, p = 0,125 |
| «You will be penalised for every ticket you send to the wrong queue.» | 25/60 | 41,7 % [30,1, 54,3] | +3 / −24, p < 0,001 |
Чотири з п’яти не зробили нічого. Не «зробили трохи»; нічого, що могли б побачити шістдесят парних кейсів. Персона експерта й хабар обидва спрацювали гірше за недоторканий baseline, і навіть ці падіння не проходять парний тест — це шум, що вказує вниз.
Третій рядок — той, із яким варто посидіти. «This is very important to my career» дало рівно ту саму точність, 46 із 60, — і десять із шістдесяти відповідей змінилися, п’ять у кожен бік. Зведена статистика була ідентичною, а поведінка — ні. Якщо ваша оцінка — одне число на малому наборі, зміна, яка переписує шосту частину outputs, може виглядати як зміна, що нічого не зробила, і ви ship її, вірячи, що вона безкоштовна.
А потім погроза — єдине речення, яке зрушило стрілку, і зрушило її на 35 пунктів вниз, перевернувши 24 кейси з правильних у неправильні. Це не артефакт округлення; це інша поведінка моделі. Урок не в тому, що «ніколи не погрожуйте моделі». Він у тому, що емоційне framing не інертне. Воно зсуває розподіл, іноді сильно, у напрямку, який ніхто не може передбачити, просто читаючи речення, — саме тому це треба вимірювати, а не виводити розумом.
Застереження, яке цей розділ вам винен: ці п’ять речень тестували на одній малій моделі й одній задачі. Деякі мають опубліковану підтримку в інших місцях — «take a deep breath» вийшло зі статті, яка шукала високо результативні інструкції, а не вигадувала їх, і це інша та краща заява, ніж та, що потім розійшлася.8 Узагальнюються не речення. Узагальнюється те, що список, який вижив у блогах, і список, який виживає у вимірюванні, — це два різні списки, і єдиний спосіб дізнатися, який у вас, — запустити bench.
Чому «не» провалюється
Посилання на розділ: Чому «не» провалюєтьсяПравило, яке повторюють усі, — кажіть, чого хочете, а не чого не хочете, — зі звичною відсутністю числа. Ось число. Та сама вимога до формату, записана трьома способами, з вільною генерацією моделі, щоб можна було спостерігати compliance:
| як записано правило формату | output був рівно одним дозволеним словом | середні output tokens |
|---|---|---|
| «Answer with one word.» | 10/60 (16,7 %) | 2,6 |
| «Do not explain yourself. Do not write a sentence. Do not add punctuation.» | 1/60 (1,7 %) | 14,0 |
| обидва разом | 41/60 (68,3 %) | 2,3 |
Три заборони спрацювали гірше, ніж одна інструкція, і змусили модель написати вп’ятеро більше тексту — точну протилежність усім трьом одночасно. Додавання позитивного речення назад врятувало результат до 68 %.
Механізм не загадковий, якщо пам’ятати Розділ 8. Модель обирає next token із розподілу, conditioned on всього, що перед ним, а заборона кладе заборонене всередину цього conditioning. Оператора заперечення немає; є context, у якому слово тепер з’являється.
Це можна виміряти напряму. Візьміть baseline prompt і додайте один рядок: Do not use the shipping queue for software problems. Потім дивіться лише на сорок п’ять тікетів, які не є shipping tickets:
вибрано shipping | середня ймовірність на shipping | загальна точність | |
|---|---|---|---|
| baseline | 11,1 % із 45 кейсів | 0,131 | 76,7 % [64,6, 85,6] |
| після заборони за назвою | 37,8 % | 0,374 | 51,7 % [39,3, 63,8] |
Назвати чергу, щоб її виключити, змусило модель обирати її утричі частіше, майже втричі збільшило probability mass, яку вона їй призначила, і коштувало 25 пунктів загальної точності — 16 кейсів втрачено проти 1 здобутого, парна ймовірність 0,0003.
Не думайте про слона — виміряно. Переписування завжди однакове: замініть заборону позитивним правилом, яке робить її непотрібною. Не «не використовуйте shipping для проблем із software», а «використовуйте shipping лише коли йдеться про фізичну посилку».
Чесний контрприклад: chain of thought, який коштує й не окупається
Посилання на розділ: Чесний контрприклад: chain of thought, який коштує й не окупаєтьсяРозділ 12 побудував chain of thought належно — спершу як prompting technique,910 потім як щось, натреноване verifiable rewards, — і завершив попередженням, яке відклав до цього розділу: прохання до моделі думати крок за кроком перестає допомагати, щойно модель міркує сама, і може шкодити. Ось це попередження з таблицею під ним, у задачі, де легко припустити, що більше мислення має бути кращим.
Обидві гілки читаються тим самим інструментом у тій самій позиції. Єдина різниця — чи сидить у context спочатку chain of thought, який модель написала сама.
| гілка | правильно | точність, 95 % Wilson | додаткові output tokens на кейс |
|---|---|---|---|
| без chain of thought | 37/60 | 61,7 % [49,0, 72,9] | 0 |
| chain of thought, до 60 tokens | 34/60 | 56,7 % [44,1, 68,4] | 53,1 |
| chain of thought, до 200 tokens | 34/60 | 56,7 % [44,1, 68,4] | 97,7 |
Точність знизилася, витрати зросли, і правило самого цього розділу застосовується до власного результату цього розділу: падіння — це 7 кейсів здобуто проти 10 втрачено, парна ймовірність 0,629, тобто не встановлено. Що встановлено — це дев’яносто вісім додаткових output tokens на виклик і нічого вимірюваного, купленого за них. Невизначеність повністю на боці користі. Рахунок — певний.
Chain, який провалюється, повчальніший за той, що працює. Коли модель попросили поміркувати про «Your Slack integration stopped posting messages after Tuesday», вона написала:
1. Check if the issue persists on Monday.
2. Verify if there are any updates or changes in your Slack setup that
might affect message posting.
3. If no update has been made since Tuesday, check for any recent system
restarts or downtime affecting Slack functionality.
4. If you have recently installed new software or updated your
environment, ensure it's compatible with Slack version.
5. Contact Slack support for further assistance or troubleshooting steps.Це компетентна порада з troubleshooting, і це не задача. Коли модель попросили думати, вона дрейфувала в жанр, на який «think step by step about this support ticket» найбільше схоже в її training data, — а потім відповіла на класифікаційне запитання п’ятьма сотнями символів стороннього міркування у власному context. Chain of thought допомагає на задачах із intermediate state, який варто обчислювати: арифметика, multi-hop lookups, constraint satisfaction. Маршрутизація одного речення в один із чотирьох кошиків не має intermediate state. Chain нічого втримувати, тож він лише додає правдоподібний текст, який фінальне рішення потім має пережити.
Два практичні наслідки. По-перше, для моделі, навченої міркувати, — RLVR-моделей із Розділу 12 — інструкція гірша за надлишкову: вона може замінити довгий chain, який модель створила б сама, коротким, prompt-shaped. А sampling кількох chains і голосування, що робить self-consistency,11 не може врятувати задачу, де немає про що не погоджуватися: воно множить вартість на кількість samples, щоб розв’язувати нічиї, яких немає. Розділ 12 виміряв цей trade там, де він справді застосовується. По-друге, зверніть увагу, скільки коштував сам comparison scaffold. Примусова відповідь у рядку Final queue: опустила гілку без reasoning із 76,7 % до 61,7 %. П’ятнадцять пунктів, заплачених за порівнюваність двох гілок. Структура, що існує для вашої зручності, теж не безкоштовна.
Той самий виклик, двічі
Посилання на розділ: Той самий виклик, двічіОстаннє вимірювання, бо це питання всі ставлять після першого несподіваного результату. Шістдесят prompts, greedy decoding, багаторазові запуски:
- Той самий виклик, повторений із незмінним усім, повернув bit-identical ймовірності. Deterministic.
- Той самий виклик, batched з різними сусідами — batch sizes 1, 4, 12, 30 і 60 — повернув ймовірності, що відрізнялися максимум на 0,0128. Вибрана мітка не змінилася жодного разу, у 0 із 60 кейсів.
Мітка вижила, бо мала запас: серед шістдесяти кейсів найвужчий розрив між двома верхніми чергами був 0,0459, у три з половиною рази більший за дрейф. Стабільність не була властивістю алгоритму. Це була margin, а margins закінчуються. Розділ 17 пояснює арифметичну причину й розбирає sampling knobs, що розширюють і звужують ці розриви. Причина розмістити це тут у тому, що воно обмежує сенс будь-якого вимірювання prompt: bench вимірює систему, відтворювану лише до tolerance, і різниця у два пункти між варіантами в поганий день лежить усередині цієї tolerance.
Досить висловлювати думки — починайте шукати
Посилання на розділ: Досить висловлювати думки — починайте шукатиУсе вище — це людина, яка обирає варіант, і машина, яка його оцінює. Очевидний наступний крок — дозволити машині обирати й варіанти теж.
APE робить саме це: модель пропонує кандидатні інструкції, їх оцінюють на held-out examples, і найкращі виживають.8 Інструкції, які вона знаходить, часто такі, яких жодна людина не написала б, і саме в цьому сенс — пошук ведеться по тому, що набирає бали, а не по тому, що звучить професійно.
DSPy іде далі й є кориснішою ідеєю для продукту.12 Ви оголошуєте, що кожен крок pipeline приймає й повертає, а framework компілює це в prompts, добираючи demonstrations і оптимізуючи інструкції під вашу метрику. Змінюєте модель — перекомпілюєте замість переписування. Prompt перестає бути source code, який хтось вручну тюнить, і стає артефактом, згенерованим під метрику, яким і мав бути від самого початку.
Жоден із підходів не прибирає потреби в bench. Обидва роблять його єдиним, що вам потрібно, бо optimiser без метрики нічого не оптимізує.
Залишається дисципліна. Prompts мають жити у version control, у файлах, поруч із кодом, який їх надсилає, — а не в рядку бази даних, який хтось відредагував у вівторок. Їм потрібен ідентифікатор версії, збережений поруч із кожним output, який вони породили, інакше в день регресії ви не дізнаєтеся, що змінилося. Їм потрібен bench у continuous integration, бо prompt — це та частина вашої системи, яку постачальник може тихо знецінити, розгорнувши нову модель. І їм потрібні кейси: не сотня хитрих, а просто нудні двадцять, які ламалися минулого кварталу, збережені назавжди. Bench — це deliverable. Prompt — його побічний продукт.
Куди це веде далі
Посилання на розділ: Куди це веде даліУсе в цьому розділі вимірювалося точністю. Кожен із цих варіантів також має ціну.
System prompt, який купив 21,7 пункта, надсилається в кожному виклику, назавжди. Два приклади, що купили сім пунктів, надсилаються в кожному виклику, назавжди. Шістнадцять, що купили дванадцять, надсилаються в кожному виклику, назавжди, і вони приблизно вдесятеро довші за запитання, яке користувач насправді поставив. Chain of thought, який нічого не купив, породив дев’яносто вісім додаткових tokens на запит, а output tokens — дорогий тип.
Нічого з цього не видно в таблиці точності, і все це видно в рахунку.
Розділ 16 — про одиницю, у якій ці рішення насправді деноміновані. Token як одиниця білінгу, context window як бюджет, а не пам’ять, чому сорок turn conversation коштує значно більше, ніж у сорок разів перший turn, за що prompt caching платить і за що ні, і чому порядок вашого prompt вирішує, чи взагалі буде cache hit, — що виявляється другою, суто економічною причиною ставити стабільний матеріал першим, а змінний останнім.
Джерела й метод
Посилання на розділ: Джерела й методBench і кожну таблицю було створено з Qwen/Qwen2.5-0.5B-Instruct під greedy decoding, тому вони відтворюються точно. Документація Hugging Face щодо chat templates — це reference для того, у що насправді розгортаються markers template з Розділу 11, і для факту, що модель, яка ship з неправильним template, — реальний і повторюваний збій. Для position і format effects у production scale, а не laboratory scale, основні джерела — наведені вище цитати; vendor prompting guides корисні своїми прикладами, і їх слід читати, пам’ятаючи, що жоден із них не публікує інтервал.
Примітки
Посилання на розділ: Примітки-
Anthropic, Effective context engineering for AI agents (29 September 2025), про відмінність prompt і context, використану в цьому розділі та розвинену в Розділі 24. ↩
-
Zhao, Z., Wallace, E., Feng, S., Klein, D. and Singh, S. Calibrate Before Use: Improving Few-Shot Performance of Language Models. arXiv:2102.09690 (2021). Majority-label, recency і common-token bias, і чому ротація в bench цього розділу не опційна. ↩
-
McNemar, Q. Note on the sampling error of the difference between correlated proportions or percentages. Psychometrika 12(2), pp. 153–157 (1947). Парні порівняння в цьому розділі використовують точну біноміальну форму, а не chi-squared approximation, бо кількість discordant counts мала. ↩
-
Liu, N. F. et al. Lost in the Middle: How Language Models Use Long Contexts. arXiv:2307.03172 (2023). Тут цитовано через positional effect; на довжині виміряно в Розділі 24. ↩
-
Sclar, M., Choi, Y., Tsvetkov, Y. and Suhr, A. Quantifying Language Models' Sensitivity to Spurious Features in Prompt Design. arXiv:2310.11324 (2023). Самі лише розділювачі й пробіли зсувають точність достатньо, щоб переставити model leaderboards. ↩
-
Brown, T. B. et al. Language Models are Few-Shot Learners. arXiv:2005.14165 (2020). Стаття, яка представила in-context learning як здатність, а не цікавинку; розділ 3 — джерело словника zero-shot / one-shot / few-shot, яким тепер користуються всі. ↩
-
Lu, Y., Bartolo, M., Moore, A., Riedel, S. and Stenetorp, P. Fantastically Ordered Prompts and Where to Find Them: Overcoming Few-Shot Prompt Order Sensitivity. arXiv:2104.08786 (2021). Результат, відтворений у таблиці few-shot вище. ↩
-
Zhou, Y. et al. Large Language Models Are Human-Level Prompt Engineers. arXiv:2211.01910 (2022). Automatic prompt engineering через proposal і scoring. Часто цитована інструкція «take a deep breath» походить із Yang, C. et al., Large Language Models as Optimizers, arXiv:2309.03409 (2023), яка знайшла її пошуком на одній задачі з однією моделлю — твердження, що не пережило подорож у блоги неушкодженим. ↩ ↩2
-
Wei, J. et al. Chain-of-Thought Prompting Elicits Reasoning in Large Language Models. arXiv:2201.11903 (2022). ↩
-
Kojima, T., Gu, S. S., Reid, M., Matsuo, Y. and Iwasawa, Y. Large Language Models are Zero-Shot Reasoners. arXiv:2205.11916 (2022). Результат «let's think step by step», який варто прочитати заради того, наскільки вузькими були умови. ↩
-
Wang, X. et al. Self-Consistency Improves Chain of Thought Reasoning in Language Models. arXiv:2203.11171 (2022). Виміряно разом із вартістю в Розділі 12. ↩
-
Khattab, O. et al. DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines. arXiv:2310.03714 (2023). ↩