Prompt engineering в цифрах: что меняет ответ
60 тикетов, те же слова в 6 порядках и точность от 26,7 % до 85,0 %. Затем 4 интернет-трюка — с погрешностями.
На этой странице
Вот тикет в поддержку и четыре очереди, куда он может попасть.
The label on the parcel has my old surname on it.
-> billing / technical / shipping / accountЧтобы направить его, в prompt нужны три вещи: определения очередей, сам тикет и инструкция выбрать одну очередь. Три блока. Их можно расположить в шести порядках, и во всех шести блоки содержат ровно одни и те же символы.
На шестидесяти тикетах с известными ответами эти шесть порядков дают от 26,7 % до 55,0 %. Перенесите те же два блока из пользовательской реплики в системную, не меняя ни слова, — и та же модель получает 76,7 %. Оберните тикет в XML-подобный тег — и результат доходит до 85,0 %.
В модели ничего не изменилось. В задаче ничего не изменилось. Не было переписано ни одного слова. Размах в пятьдесят восемь пунктов возник из-за расположения одного и того же текста.
Именно поэтому существует эта глава — и именно поэтому эта тема больше всех в области заражена карго-культом. Эффекты реальны и велики, поэтому каждый анекдот кажется подтверждённым; и они нестабильны между моделями и задачами, а значит, большая часть советов так и остаётся анекдотами. Поэтому у этой главы есть одно правило, и всё в ней подчинено ему:
prompt нужно измерять, а не обсуждать. Четыре варианта на двадцати кейсах не различают вообще ничего.
prompt — это всё состояние
Ссылка на раздел: prompt — это всё состояниеПеред измерениями — один факт, который тихо объясняет половину дальнейшего.
У модели нет памяти. Между двумя вызовами она ничего не сохраняет — ни ваш прошлый вопрос, ни свой прошлый ответ, ни файл, который вы прикрепили, ни сам факт, что вы уже спрашивали её дважды. Каждый вызов начинается с пустой машины, и единственное, что эта машина знает, — последовательность tokens, которую вы ей только что передали.
То, что в чат-интерфейсе выглядит как память, — это ваш клиент, который заново отправляет всю беседу, каждую реплику, с самого начала. Модель снова читает всё с нуля, каждый раз. Глава 13 измерила, во что обходится это повторное чтение в forward pass; глава 16 превращает это в строку счёта. Здесь важнее следствие для дизайна: prompt — это не сообщение системе, у которой есть состояние. Он и есть состояние.
Это снимает целое семейство заблуждений. «Модель забыла, что я ей сказал» обычно означает, что это ей никогда не отправляли. «Она проигнорировала мою раннюю инструкцию» обычно означает, что инструкция выпала из окна, когда историю обрезали. «В production она повела себя иначе» обычно означает, что production собирает другой prompt, не тот, который вы тестировали. Ни одно из этого не является проблемой модели, и ничто из этого не исправляется переформулировкой.
Утверждение «этот prompt лучше» — это утверждение о распределении, а распределение нельзя увидеть по одному output. Нужно скучное: кейсы с известными ответами, N вариантов и интервал.
harness — это пятьдесят строк TypeScript с той же формой, что и клиент из главы 14: запрос, deadline, немного concurrency, подсчёт. Он снова появляется в главе 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 — объединены в одно пользовательское сообщение. Все шесть перестановок, побайтово идентичное содержимое, по шестьдесят кейсов на каждую.
| порядок трёх блоков | правильно | точность, 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 пункта, и интервалы не перекрываются, так что это не история про шум. Поскольку каждый вариант оценивается на тех же шестидесяти объектах, более точный вопрос — парный: среди кейсов, где два варианта расходятся, насколько перекошен расклад? Переход от худшего порядка к лучшему перевернул 21 кейс в правильную сторону и 4 в неправильную — точная парная вероятность 0,0009.3
Читайте таблицу по её форме, а не по победителю. Две лучшие строки обе заканчиваются тикетом; две худшие либо хоронят инструкцию в середине, либо ставят её после данных. Это то же явление, которое Liu et al. назвали Lost in the Middle: материал по краям prompt используется надёжнее, чем материал в центре.4 Глава 16 оценивает стоимость окна, а глава 24 измеряет эффект как следует на длине, где середина схлопывается описанным образом, а восстановление в самом конце уже не появляется. Здесь практическое правило выходит само: задача сверху, данные снизу, ничего важного в середине.
Теперь перенесём те же слова между репликами. Глава 11 установила, что chat template — не украшение вокруг модели, а её часть: <|im_start|>system и <|im_start|>user — реальные tokens, которые модель видела миллионы раз во время fine-tuning, именно в этих позициях. Значит, должно иметь значение, по какую сторону этих маркеров оказывается ваша инструкция, — и оно имеет:
| где находятся те же слова | правильно | точность, 95 % Wilson |
|---|---|---|
| правила и инструкция в системной реплике, только тикет в пользовательской | 46/60 | 76,7 % [64,6, 85,6] |
| правила в системной реплике, инструкция и тикет в пользовательской | 44/60 | 73,3 % [61,0, 82,9] |
| правила и инструкция в системной реплике, инструкция повторена после тикета | 42/60 | 70,0 % [57,5, 80,1] |
| все три блока в одной пользовательской реплике | 33/60 | 55,0 % [42,5, 66,9] |
Перенос правил и инструкции через границу template дал 21,7 пункта — 19 кейсов выиграно, 6 проиграно, парная вероятность 0,0146 — без изменения ни одного символа. Это конкретный ответ на вопрос system prompt против user prompt: это не два способа сказать одно и то же. Это две разные token-позиции в структуре, на которой модель обучали, и системная позиция — место для инструкций, применимых ко всей беседе.
Обратите внимание и на третью строку. Повторить инструкцию после тикета — широко рекомендуемый трюк — оказалось хуже, чем сказать её один раз. На этой модели, на этой задаче, сказать дважды было хуже, чем сказать один раз.
Разделители и статистический урок внутри них
Ссылка на раздел: Разделители и статистический урок внутри нихТот же 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 для его собственной точности. Широкий, если у вас не сотни кейсов. Это число вы показываете тому, кто решает, можно ли shipping.
B лучше A? Парный тест по кейсам, где они расходятся. Намного чувствительнее, потому что общая сложность набора сокращается. Это число нужно, чтобы выбрать между двумя кандидатами.
Общий вывод — модели сильно и непредсказуемо чувствительны к форматированию без семантического содержания — не нов. Sclar et al. меняли только разделители, пробелы и регистр в десятках задач и обнаружили разбросы точности, достаточные, чтобы перевернуть опубликованные рейтинги моделей.5 Практическое следствие не «используйте XML-теги». Оно в том, что форматирование — это hyperparameter, его ничего не стоит перебрать, и любое сравнение двух моделей с фиксированным форматом сравнивает форматы не меньше, чем модели.
Сколько примеров на самом деле достаточно
Ссылка на раздел: Сколько примеров на самом деле достаточноIn-context learning — когда модели показывают рабочие примеры в prompt и она обобщает их без обновления weights — это способность, сделавшая GPT-3 знаменитой.6 Практический вопрос никогда не в том, работает ли это. Вопрос в том, за сколько примеров платить.
Примеры добавляются как реальные предыдущие реплики, чередуя 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Два хорошо выбранных примера лучше восьми небрежно выбранных. Если ваши примеры взяты с верхушки таблицы, именно эту переменную нужно перебрать до добавления новых.
Один раз переберите порядок, а затем заморозьте его
Ссылка на раздел: Один раз переберите порядок, а затем заморозьте егоЭто бесплатно, это реальный эффект, и, в отличие от большей части этой главы, для проверки не нужна перепись текста.
Проверьте баланс классов
Ссылка на раздел: Проверьте баланс классовЧетыре примера с одной и той же меткой учат модель метке, а не задаче. Схлопывание этой модели к очереди, указанной последней, — тот же сбой в другом костюме.
Четыре предложения из интернета
Ссылка на раздел: Четыре предложения из интернетаТеперь фольклор. Каждое из них — одно предложение, добавленное в начало 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, — и при этом десять из шестидесяти ответов изменились, пять в каждую сторону. Итоговая статистика была идентичной, а поведение — нет. Если ваша оценка — одно число на маленьком наборе, изменение, переписывающее шестую часть output, может выглядеть как изменение, не сделавшее ничего, и вы отгрузите его, веря, что оно было бесплатным.
А затем угроза — единственное предложение, которое сдвинуло стрелку, причём на 35 пунктов вниз, перевернув 24 кейса из правильных в неправильные. Это не артефакт округления; это другое поведение модели. Урок не в том, что «никогда не угрожайте модели». Урок в том, что эмоциональная рамка не инертна. Она сдвигает распределение, иногда сильно, в направлении, которое никто не предскажет по чтению предложения, — именно поэтому её нужно измерять, а не рассуждать о ней.
Оговорка, которую эта глава вам должна: эти пять предложений проверялись на одной небольшой модели и одной задаче. Некоторые имеют опубликованную поддержку в других местах — «take a deep breath» вышло из статьи, которая искала инструкции с высокими оценками, а не придумывала их, и это другое, более сильное утверждение, чем то, что затем разошлось по блогам.8 Обобщаются не предложения. Обобщается то, что список, выживший в блог-постах, и список, выживший в измерении, — два разных списка, и единственный способ понять, какой у вас в руках, — запустить бенч.
Почему «не» не работает
Ссылка на раздел: Почему «не» не работаетПравило, которое повторяют все, — говорите, чего хотите, а не чего не хотите — при обычном отсутствии числа. Вот число. Одно и то же требование к формату, записанное тремя способами, при свободной генерации модели, чтобы можно было наблюдать соблюдение:
| как записано правило формата | 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. Модель выбирает следующий token из распределения, обусловленного всем, что было до него, а запрет помещает запрещённую вещь внутрь этого conditioning. Оператора отрицания нет; есть context, в котором слово теперь появилось.
Это можно измерить напрямую. Возьмите baseline prompt и добавьте одну строку: Do not use the shipping queue for software problems. Затем смотрите только на сорок пять тикетов, которые не являются shipping-тикетами:
выбран 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-технику,910 затем как нечто обученное через проверяемые 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 на вызов и отсутствие измеримой выгоды. Неопределённость целиком на стороне пользы. Счёт определён.
Неудачная цепочка поучительнее удачной. На просьбу рассуждать о «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, — а затем ответила на вопрос классификации пятьюстами символами нерелевантного reasoning в собственном context. Chain of thought помогает в задачах с промежуточным состоянием, которое стоит вычислять: арифметика, multi-hop lookups, удовлетворение ограничений. У маршрутизации одного предложения в одну из четырёх корзин нет промежуточного состояния. Цепочке нечего удерживать, поэтому она лишь добавляет правдоподобный текст, через который затем должно пройти финальное решение.
Два практических следствия. Во-первых, для модели, обученной рассуждать, — RLVR-моделей главы 12 — инструкция хуже избыточности: она может заменить длинную цепочку, которую модель произвела бы сама, короткой, prompt-образной. А выборка нескольких цепочек и голосование, чем занимается self-consistency,11 не спасают задачу, где не о чем спорить: это умножает стоимость на число samples, чтобы разбивать ничьи, которых нет. Глава 12 измерила этот trade там, где он применим. Во-вторых, заметьте, чего стоил сам сравнительный каркас. Принудительный ответ в строке Final queue: снизил вариант без reasoning с 76,7 % до 61,7 %. Пятнадцать пунктов, заплаченные за сопоставимость двух вариантов. Структура, существующая ради вашего удобства, тоже не бесплатна.
Тот же вызов, дважды
Ссылка на раздел: Тот же вызов, дваждыПоследнее измерение, потому что именно это спрашивают все после первого неожиданного результата. Шестьдесят prompts, greedy decoding, повторные запуски:
- Один и тот же вызов, повторённый при полной фиксации всего, вернул побитово идентичные вероятности. Детерминированно.
- Тот же вызов, сбатченный с разными соседями — batch sizes 1, 4, 12, 30 и 60, — вернул вероятности, отличающиеся до 0,0128. Выбранная метка не изменилась ни разу, в 0 из 60 кейсов.
Метка выжила, потому что у неё был запас: по шестидесяти кейсам самый узкий разрыв между двумя верхними очередями был 0,0459, в три с половиной раза больше drift. Стабильность не была свойством алгоритма. Это был margin, а margins заканчиваются. Глава 17 объясняет арифметическую причину и разбирает ручки sampling, которые расширяют и сужают эти разрывы. Причина поместить это здесь в том, что оно ограничивает смысл любого измерения prompt: бенч измеряет систему, воспроизводимую только в пределах допуска, и разница в два пункта между вариантами в плохой день находится внутри этого допуска.
Хватит спорить — начинайте искать
Ссылка на раздел: Хватит спорить — начинайте искатьВсё выше — человек выбирает вариант, машина его оценивает. Очевидный следующий шаг — позволить машине выбирать и варианты.
APE делает именно это: модель предлагает кандидатные инструкции, их оценивают на отложенных примерах, лучшие выживают.8 Инструкции, которые она находит, часто такие, какие человек никогда бы не написал, — в этом и смысл: поиск идёт по тому, что набирает score, а не по тому, что звучит профессионально.
DSPy идёт дальше и как идея полезнее для продукта.12 Вы объявляете, что каждый шаг pipeline принимает и возвращает, а framework компилирует это в prompts, выбирая demonstrations и оптимизируя инструкции под вашу метрику. Меняете модель — перекомпилируете, а не переписываете. prompt перестаёт быть source code, который кто-то вручную подкручивает, и становится артефактом, сгенерированным против метрики, каким ему и следовало быть с самого начала.
Ни APE, ни DSPy не убирают необходимость в бенче. Оба делают его единственным, что вам нужно, потому что optimiser без метрики ничего не оптимизирует.
Остаётся дисциплина. Prompts должны жить в version control, в файлах, рядом с кодом, который их отправляет, — а не в строке базы данных, которую кто-то отредактировал во вторник. Им нужен идентификатор версии, сохранённый рядом с каждым output, который они произвели, иначе в день регрессии вы не узнаете, что изменилось. Им нужен бенч в continuous integration, потому что prompt — единственная часть вашей системы, которую вендор может молча инвалидировать, развернув новую модель. И им нужны кейсы: не сотня хитрых, а просто скучные двадцать, которые ломались в прошлом квартале, сохранённые навсегда. Бенч — это deliverable. prompt — его побочный продукт.
Куда дальше
Ссылка на раздел: Куда дальшеВсё в этой главе измерялось в точности. У каждого из этих вариантов есть и цена.
System prompt, который дал 21,7 пункта, отправляется на каждом вызове, всегда. Два примера, которые дали семь пунктов, отправляются на каждом вызове, всегда. Шестнадцать, которые дали двенадцать, отправляются на каждом вызове, всегда, и они примерно в десять раз длиннее вопроса, который пользователь на самом деле задал. Chain of thought, который не дал ничего, произвёл девяносто восемь дополнительных tokens на запрос, а output tokens — дорогой вид.
Ничего из этого не видно в таблице точностей, и всё это видно в счёте.
Глава 16 — о единице, в которой эти решения на самом деле номинированы. token как единица биллинга, context window как budget, а не память, почему разговор в сорок реплик стоит намного больше, чем сорок первых реплик, за что prompt caching платит и не платит, и почему порядок вашего prompt решает, будет ли cache hit вообще, — что оказывается второй, полностью экономической причиной ставить стабильный материал первым, а переменный последним.
Источники и метод
Ссылка на раздел: Источники и методБенч и все таблицы были получены с Qwen/Qwen2.5-0.5B-Instruct при greedy decoding, поэтому они воспроизводятся точно. Документация Hugging Face по chat templates — референс для того, во что на самом деле разворачиваются template markers из главы 11, и для факта, что модель, поставляемая с неправильным template, — реальный и повторяющийся сбой. Для позиционных и форматных эффектов в production scale, а не laboratory scale, первичные источники — цитаты выше; руководства вендоров по prompting полезны своими примерами, но их стоит читать, помня, что ни одно из них не публикует интервал.
Сноски
Ссылка на раздел: Сноски-
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, а также почему ротация в бенче этой главы не опциональна. ↩
-
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). Здесь цитируется ради позиционного эффекта; на длине измеряется в главе 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). Автоматический prompt engineering через предложения и 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). ↩