
Полная версия:
ИИ без мифов
Шесть полей. Вход — что именно прикладывается: файл, таблица, пять примеров, прошлогодняя версия. Шаги — порядок операций, если он важен: сначала отфильтровать недоступных, потом закрывать ячейки, потом проверять ограничения. Выход — формат и объём. Критерий — условия приёмки, лучше числовые. Кто проверяет — имя и время, которое на это отводится. Что запрещено — границы, за которые модель не имеет права выходить.
Заполненная карточка для расписания выглядит так.
{
"задача": "Составить недельное расписание: 7 дней x 3 позиции = 21 смена",
"вход": ["staff.csv: 19 строк, колонки name, zones, days_available, max_shifts, min_rest_h, contract_limits",
"slots.csv: 21 строка, колонки day, position"],
"шаги": ["исключить недоступных в этот день", "закрыть позиции по совпадению зоны",
"проверить три ограничения", "вывести таблицу"],
"выход": "таблица: day, position, name + строка проверки по каждой позиции",
"критерий": ["21/21 смен закрыто", "у каждого <= 5 смен", "между сменами >= 11 часов"],
"кто_проверяет": "Мира, пятница, 15 минут",
"запрещено": ["менять список имён", "придумывать ограничения, которых нет в staff.csv",
"сокращать смены", "ставить человека в зону, которой нет в его zones"]
}
Два поля делают почти всю работу, и оба обычно пропускают. «Запрещено» отменяет фантазию в той части, где она дороже всего: модель не имеет права править входные данные, чтобы решение сошлось. «Кто проверяет» превращает проверку из намерения в расписание — с именем и минутами.
Есть и побочный эффект, который замечают все, кто довёл карточку до конца: часть задач умирает на этапе заполнения. Если в поле «приёмка» нечего написать, кроме «чтобы мне понравилось», задача не готова — и модель тут ни при чём. Это относится и к задачам, которые вы никогда не отдадите машине: карточка на них всё равно полезна, потому что описывает работу.
Если вы новичок: как объяснить задачу, чтобы вас поняли
Представьте, что вы просите стажёра, который никогда не был в вашей отрасли, но очень старается. Он не знает слов «стандартная смена» и «наш обычный клиент». Он понятия не имеет, что для вас очевидно.
- Скажите, что должно получиться на выходе: таблица, список, письмо, пять пунктов. Формат — первое, что нужно назвать.
- Скажите, что даёте: «вот файл, вот прошлая версия, вот правила». Если данных нет, модель придумает их.
- Скажите, что нельзя: не менять цифры, не добавлять факты, не сокращать имена.
- Скажите, как вы поймёте, что годится: «все двадцать одна строка заполнены», «не длиннее одной страницы».
- Один запрос — одна работа. Если в просьбе три разных дела, разделите её на три.
Это не особый приём, а обычная постановка задачи. Стажёру вы объясняете то же самое, и по тем же причинам.
Какие задачи ложатся на модель, а какие нет
Есть короткий список глаголов, которые ложатся почти всегда: сжать, переформатировать, сменить тон, сравнить две версии, извлечь поля, разложить по категориям, перевести, придумать N вариантов, отсортировать по заданному критерию, найти противоречия, переписать под конкретную аудиторию, собрать план по каркасу.
И есть список того, что не ложится: посчитать точную сумму, узнать факт, появившийся после обучения, понять мотивы конкретного человека, взять на себя ответственность за решение, выбрать лучший вариант, когда критерия нет.
Разница между списками одна и её полезно проговорить: модель сильна там, где работа уже кем-то сделана в виде текста и её надо преобразовать. Она слаба там, где нужно добавить знание, которого на входе нет.
Отдельно стоит сказать про задачи, которые только выглядят одной. «Сделай отчёт по продажам за квартал» — это три работы: извлечь числа из выгрузки, сравнить с прошлым кварталом, написать вывод на страницу. У каждой свой результат и своя цена ошибки. В одном запросе они смешиваются, и модель делает ту часть, которую умеет лучше, — пишет складный вывод на выдуманных числах.
Правило деления простое: если части можно проверить по отдельности, их нужно и ставить по отдельности. Три запроса, три выхода, три проверки — и на каждом шаге видно, где именно появилась ошибка. Один большой запрос даёт один большой ответ, в котором искать причину ошибки почти так же дорого, как делать работу заново.
Задача
Данные
Результат
Приёмка
Разобрать 200 анкет конкурса
анкеты + правила конкурса
таблица противоречий
каждое противоречие с цитатой
Ответить на 40 писем клиентов
письма + база ответов
40 черновиков
ни одного факта вне базы
Свести три версии договора
три файла
список расхождений
каждая строка с номером пункта
Подготовить отчёт по продажам
выгрузка + шаблон прошлого месяца
таблица и вывод на страницу
цифры совпадают с выгрузкой
Составить программу обучения
описание роли + список навыков
8 модулей с целями
каждый модуль проверяем за 10 минут
Проверка перед стартом — четыре вопроса подряд. Если ответ на первый — «нет», дальше идти не нужно.
1. Работа сводится к преобразованию текста, который у меня есть? Если нет — нужен другой инструмент: поиск, база, калькулятор, человек.
2. Могу ли я назвать критерий приёмки в трёх условиях? Если нет — сначала пишется критерий, потом запрос.
3. Есть ли у меня данные в явном виде — файл, таблица, примеры? Если только «в голове», сначала выгружаю: без этого шага модель будет додумывать.
4. Проверка займёт меньше времени, чем работа руками? Если нет — задача не стоит автоматизации, даже если технически решается.
Дерево короче: если работа — преобразование имеющегося текста и у вас есть три условия приёмки, отдавайте модели с проверкой. Если нужен новый факт, точное число или решение с ценой ошибки — модели отдаётся только подготовка материала, а решение остаётся человеку. Если критерий приёмки не формулируется вовсе — задача не поставлена, и никакая модель этого не исправит.
Данные: четыре уровня, на которых работает модель
Один и тот же вопрос можно решить на четырёх разных уровнях, и они различаются не качеством, а ценой и сроком.
Корпус. Всё, что модель видела при обучении. Это общие знания человечества, усреднённые. Доступно всем, стоит ноль, обновляется раз в несколько месяцев и не содержит вашей внутренней информации.
Контекст. То, что вы положили в запрос. Единственный уровень, который вы контролируете полностью: файл, таблица, три прошлых письма, выдержка из регламента. Работает сразу, стоит копейки, ограничен размером окна.
Поиск по вашим документам (RAG). Модель сначала ищет фрагменты в вашей базе, потом отвечает по найденному. Подробно — в главе 9. Нужен, когда документов больше, чем помещается в запрос, и когда они меняются каждый день.
Дообучение (fine-tuning). Вы доучиваете модель на своих примерах, чтобы она стабильно воспроизводила ваш стиль или формат. Дорого, долго, требует сотен чистых примеров. Подробно — в главе 6.
Практическое правило: начинайте с контекста. Девять из десяти задач, для которых ищут «свою модель», решаются приложенным файлом и тремя примерами. Дообучение имеет смысл, когда нужен стиль или формат, а не знания, и когда примеров набралось хотя бы несколько сотен.
Что при этом забывают положить в данные. Прошлую версию документа — она задаёт структуру лучше любого описания формата. Три примера «вход — желаемый выход», включая один плохой, который надо переделать. Правила в явном виде, даже те, что кажутся очевидными: «сокращения не расшифровываем», «имена не переводим», «итог округляем до целого». И границы применимости: до какого размера файла всё это работает и что делать, когда он больше.
Шесть правил, записанных один раз, экономят больше, чем любая настройка модели. Они переиспользуются во всех следующих запросах и переживают смену версии — в отличие от приёмов, которые работали в конкретном интерфейсе прошлой весной.
Критерий приёмки: формат плюс критерий плюс шкала
Критерий пишется в три слоя. Формат — что физически должно быть: таблица с колонками, список из пяти пунктов, письмо до 120 слов. Критерий — что делает содержимое правильным: все строки заполнены, ни одного числа не из головы модели, каждое утверждение с цитатой. Шкала — как сравнивать варианты, если их несколько: «оцени каждый по трём условиям и покажи, какой нарушен».
Плохой критерий
Почему не работает
Рабочая замена
«Сделай красиво»
«красиво» живёт только в вашей голове
«Заголовок до 60 знаков, три абзаца, без прилагательных»
«Чтобы было понятно»
понятно кому — не сказано
«Поймёт человек без юридического образования за 60 секунд»
«Как в прошлый раз»
модель не помнит прошлый раз
«Как в файле template.docx, структура и порядок разделов те же»
«Качественно и профессионально»
нечего проверять
«Все факты из приложенного отчёта, ни одного нового числа»
«Учти все нюансы»
означает «сделай хорошо» другими словами
«Отдельно перечисли: сроки, штрафы, условия расторжения»
Проверка критерия простая: покажите его человеку, который не видел вашу задачу, и спросите, сможет ли он отличить хороший результат от плохого. Если не сможет — критерий не готов.
Шкала нужна там, где вариантов несколько. Работают два способа. Порог — «принимаю, если выполнены все три условия, иначе отклоняю целиком»; он хорош для рутины, где нужен ноль брака. Сравнение — «сгенерируй три варианта, оцени каждый по трём условиям, покажи, какое нарушено, и предложи один»; он хорош для текстов, где важен выбор, а не единственно верный ответ. Смешивать их нельзя: если вы просите три варианта, у вас должен быть способ выбрать, иначе выбор сделает модель, а критерий останется вашим.
Верификация — это и есть проверка выхода по независимому правилу или источнику, а не по ощущению «нравится». Дешёвая верификация выглядит скучно: пересчитать число строк, найти цитату поиском по документу, сверить три даты с оригиналом. Дорогая — читать всё заново. Разница между ними — это и есть разница между работающим процессом и ритуалом.
Сериализация — превращение ответа в строгий формат (JSON, CSV, таблица с фиксированными колонками), который принимает программа или таблица без перечитывания. Она экономит не время модели, а ваше: результат в формате проверяется механически, результат в свободном тексте — только чтением.
Под капотом: параметры ответа и почему формат важнее вежливости
Параметры ответа — настройки генерации, которые вы или продукт задаёте перед запросом. Температура управляет разбросом: при низкой модели разрешено выбирать почти всегда самое вероятное продолжение, при высокой — заметно менее вероятное. Предел длины обрезает ответ, и обрезка почти всегда попадает в середину таблицы, а не в конец. Стоп-последовательности останавливают генерацию на нужном маркере, например на закрывающей скобке JSON.
Для задач с приёмкой температура около нуля и явный формат дают воспроизводимость: два запуска на одних данных дают почти одинаковый выход, и расхождение можно объяснить, а не гадать. Для задач «придумай десять вариантов названия» высокая температура полезна: разброс — это и есть работа.
Отдельно про формат. Когда вы просите «таблицу с колонками день, позиция, имя», модель генерирует разделители и заголовки теми же токенами, что и содержание. Ошибка в одном разделителе ломает разбор всей таблицы. Поэтому в инженерных задачах формат задают схемой (structured outputs) — модель обязана вернуть поля по объявленной структуре, и выход проверяется автоматически. Разметку и синтаксис разбирает глава 8.
Почему конкретика убирает фантазию
Техническая цель, которую вы достигаете, разделяя задачу, данные, результат и приёмку, — уменьшать энтропию, то есть меру неопределённости на выходе. Модель на каждом шаге выбирает следующий фрагмент из распределения вероятностей. Чем шире распределение, тем больше разных продолжений она может выдать на один и тот же запрос.
Каждая деталь постановки это распределение сужает. «Сделай расписание» оставляет тысячи допустимых продолжений. «Закрой двадцать одну ячейку, вот девятнадцать строк с ограничениями, у каждого не больше пяти смен» оставляет десятки — и почти все они правильные.
Отсюда три следствия, которые видно в любой практике. Конкретика снижает разброс не потому, что модель «лучше понимает», а потому, что у неё меньше свободы. Примеры работают сильнее инструкций: два-три образца «вход — желаемый выход» сужают распределение резче, чем абзац объяснений. И наоборот: чем менее определённы данные, тем увереннее модель заполняет пустоты — уверенность тона не связана с правильностью, об этом подробно в главе 7.
Есть и обратная сторона, о которой честно стоит сказать. Слишком узкая постановка экономит время модели и отнимает ваше: карточка на двадцать строк пишется дольше, чем разовая работа руками. Поэтому полную карточку доводят до конца для задач, которые повторяются хотя бы раз в месяц, а для разовых хватает трёх полей — вход, выход, приёмка.
Под капотом: откуда берётся разброс на одних и тех же данных
Модель не хранит ответ, она строит его заново при каждом запуске. Даже при температуре около нуля выбор между почти равновероятными продолжениями может качнуться из-за длины контекста, порядка абзацев и мелочей в форматировании. Плюс сам контекст имеет значение: чем длиннее вход, тем слабее внимание к его середине, поэтому правила лучше держать в начале и в конце, а не в середине простыни.
Практический вывод для постановки: одни и те же данные, поданные таблицей с явными колонками, дают заметно более устойчивый выход, чем те же данные, пересказанные абзацем. Дело не в «понятности» для модели, а в том, что структура уменьшает число допустимых прочтений входа.
Отсюда же приём, который экономит часы: попросите модель сначала перечислить, что она поняла из ваших данных, и только потом делать работу. Расхождение в этом перечислении — самый дешёвый способ поймать ошибку постановки до того, как она размножится на двадцать строк результата.
До / После: «сделай расписание»
До. «Составь расписание смен для моей пекарни на следующую неделю. У меня 19 сотрудников, нужно закрыть пекарню и витрину. Сделай хорошо, чтобы всем было удобно».
Что происходит: модель придумывает и состав сотрудников, и их доступность, и правила. В ответе появляются имена, которых нет, ограничения, которых не было, и бодрый комментарий про баланс. Проверить нечего: критерия нет, данных нет, формат — свободный текст.
После. «Ты — администратор, который составляет график для пекарни и ресторана. Задача: закрыть 21 смену на следующую неделю — 7 дней, 3 позиции: пекарь, витрина, касса. Данные: staff.csv — 19 строк, колонки name, zones, days_available, max_shifts, min_rest_h, contract_limits; slots.csv — 21 строка с колонками day, position. Правила: человек ставится только в зону из своего zones; не больше max_shifts смен; между сменами не меньше min_rest_h часов. Запрещено: менять список имён, добавлять ограничения, которых нет в файле, оставлять пустые ячейки. Формат вывода: таблица day, position, name, затем строка проверки по каждой позиции. В конце — три условия приёмки с фактическим результатом: 21/21, max_shifts ok/нарушено, min_rest ok/нарушено. Если какая-то ячейка не закрывается по правилам — не придумывай человека, напиши „нет решения“ и объясни, какое ограничение мешает».
Что изменилось, по пунктам.
1. Появился вход в виде файлов со схемой. Модель больше не выбирает, кого из девятнадцати взять, и не додумывает доступность.
2. Правила стали проверяемыми. «Не больше пяти смен» можно посчитать, «чтобы всем было удобно» — нельзя.
3. Появился запрет на подгонку. Без него модель правит данные, чтобы решение сошлось, и вы получаете аккуратную таблицу с неверными входными данными.
4. Появился формат и встроенная проверка. Три условия печатаются в конце ответа, и пятнадцать минут сверки превращаются в тридцать секунд чтения.
5. Появился выход для тупика: «нет решения» вместо выдуманного человека. Это самое дешёвое изменение во всём запросе и самое недооценённое.
Обратите внимание, чего в новом запросе нет: ни одного прилагательного о качестве, ни просьбы постараться, ни объяснений, зачем это нужно. Всё оставшееся — проверяемые условия. Поэтому такой запрос переиспользуется через месяц без изменений: он описывает работу, а не настроение дня.
И ещё одно отличие, которое легко пропустить. Новый запрос длиннее, но не потому, что в нём больше вежливости: он длиннее за счёт данных и запретов. Длина сама по себе ничего не улучшает. Улучшает количество проверяемых условий на сотню слов — и здесь их примерно в десять раз больше.
Красные флаги: задачи, которые нельзя формализовать
- Вы не можете назвать три условия, по которым примете результат. Значит, задача не поставлена, и любой ответ будет «вроде неплохо».
- Критерий звучит как «чтобы понравилось руководству». Вкус нельзя проверить, а значит, нельзя и перепоручить.
- Модель просят «оценить человека», «понять клиента», «предсказать решение совета». Мотивы конкретных людей не выводятся из текста, если этого текста у вас нет.
- Ни один файл не приложен, а в задаче есть ваши внутренние правила, цены или имена. Модель заполнит пустоты средним по корпусу, и вы этого не заметите.
- Проверка занимает больше времени, чем работа руками. Тогда вы автоматизируете не работу, а своё недоверие.
- Результат уходит наружу без человека: клиенту, регулятору, в подписанный отчёт. Цена ошибки платится пачкой, а не по одной.
Что сделать сегодня
1. Заполните карточку задачи на одну работу этой недели. Шесть полей: вход, шаги, выход, критерий, кто проверяет, что запрещено. Результат: один лист на одну задачу. Измерение: если поле «критерий» пустое дольше пяти минут — задача не готова, начните с него, а не с запроса.
2. Перепишите критерий приёмки в три слоя — формат, критерий, шкала. Результат: три строки, каждая проверяема без вас. Измерение: покажите критерий человеку, который не видел задачу; если он не может отличить хороший выход от плохого, переписывайте.
3. Отдельно выпишите список запретов. Результат: 3–5 строк «нельзя менять», «нельзя добавлять», «нельзя сокращать». Измерение: прогоните прошлый запрос с этим блоком и без него; считайте число выдуманных правил и пропущенных полей, цель — ноль.
4. Задайте два уровня данных: контекст (файл в запросе) и примеры (2–3 образца «вход — желаемый выход»). Результат: один запрос, собранный по карточке. Измерение: сравните с прежним ответом по трём условиям приёмки; если формат поплыл, добавьте пример, а не абзац объяснений.
5. Замерьте время: «до» — как вы делали эту работу руками, «после» — запрос плюс проверка. Результат: два числа. Измерение: если разница меньше 20 %, проверка съедает весь выигрыш, и задачу надо либо упростить, либо вернуть человеку.
Формула из этой главы возвращается дальше четырежды: в главе 6 — про то, откуда берутся данные и где кончаются возможности модели; в главе 8 — про то, как эта постановка превращается в текст запроса; в главе 13 — про то, как собрать из карточки рабочий сценарий за полчаса; в главе 14 — про то, как измерить качество и стоимость получившегося. Матрица вердиктов «сразу / с проверкой / нельзя» из главы 1 — это тот же каркас, только с другой стороны: там вы решали, кому отдать работу, здесь — как её описать, чтобы её можно было принять.
Живой слой. Обновляемые шаблоны, чек-листы и разборы под текущие версии моделей: github.com/ai-bez-mifov/book#ch04 — QR-код на вклейке и в электронной версии.
ЧАСТЬ II. Как это работает без формул
Глава 5. Модель — это не база знаний, а функция предсказания
Паспорт главы. Обещание: увидеть в модели один механизм — предсказание следующего фрагмента — и вывести из него, когда она надёжна, когда врёт уверенно и во что обходится каждый ответ. Время чтения: 15 минут. Результат: два режима, разложенные по вашим задачам, порог включения режима рассуждений и посчитанная стоимость одного типового запроса — по формуле, а не «примерно».
В 01:10 по берлинскому времени Айла смотрит на красный CI — систему непрерывной сборки, которая гоняет тесты на каждый коммит. Деплой встал на третьем шаге из семи: тест, который восемь лет проверял разбор ответа платёжного провайдера, падает с KeyError: 'status'.
Файл billing_router.py — 1 400 строк, восемь лет истории, 38 тестов и 44 % покрытия. Айла попросила модель: «Перепиши весь файл целиком, код устарел, сделай чисто и современно». Ответ пришёл через 50 секунд: 900 строк, аккуратные импорты, docstring (строка документации) у каждого метода, обработка ошибок в каждом втором блоке.
Код запускался. Семнадцать тестов из тридцати восьми упали. Три обработчика — таймаут, частичный ответ, повторное списание — исчезли вместе с ретраями. В файле появился вызов requests.post, которого в проекте нет три года, и эндпоинт /v2/refund, которого нет у провайдера.
Ни одна строка в ответе не выглядела выдуманной. В этом и состоит главное свойство модели: у неё нет отдельного режима «вспомнить» и отдельного «придумать». Есть один механизм, и он одинаково уверенно выдаёт и то, что было в обучающих текстах, и то, чего не было никогда.
Кейс: «перепиши весь файл» и 89 сэкономленных часов
billing_router — внутренний сервис разбора ответов платёжного провайдера: 14 000 заказов в сутки, четыре типа событий, три валюты. Восемь лет назад его написали за две недели, с тех пор правили одиннадцать раз, каждый раз «быстро, до релиза». Оценка миграции на новую версию внутреннего HTTP-клиента, где убрали синхронную обёртку, а ретраи переехали в middleware — промежуточный слой обработки запросов: 120 часов, один разработчик, три недели календарно.
Цена задержки была известна заранее. Старая версия клиента требовала ручного патча безопасности раз в месяц: шесть часов инженера и $700 на внешнюю проверку. Окно миграции закрывалось в конце квартала.
Первая попытка заняла две строки промпта и пятьдесят секунд ожидания. Модель выдала 900 строк, файл стал короче на треть, и это был самый опасный сигнал: «стало чище» не значит «стало верно». Три часа ушло на ревью. Из них сорок минут — на поиск того, чего в новом файле нет: исчезнувшие обработчики не видны, их отсутствие ничем не выдаёт себя. Ещё шесть тестов падали из-за переименованных публичных функций: parse_response стал parse_payment_response, а вызывали его два других сервиса, которые в промпте не упоминались.
Вторая попытка была умнее и провалилась иначе. Айла разбила файл на пять частей по 250–300 строк и причесала каждую отдельно. Каждая часть прошла ревью. На стыках обнаружилось шесть несовместимостей: два разных формата ошибок, две независимые реализации ретраев, три способа логирования и поле amount, которое в одном куске было числом, а в другом строкой. Интеграция заняла четыре дня — почти столько же, сколько заняла бы миграция руками.
Две неудачные попытки обошлись примерно в $2 450: три часа ревью и четыре дня интеграции по ставке $70 в час. Это не цена технологии, а цена постановки: работа была сделана дважды, потому что первый запрос описывал намерение, а не работу.
Правильный подход отличался не формулировкой, а подготовкой. До первого запроса Айла сделала четыре вещи.
Прогнала 38 существующих тестов и дописала 12 новых — на таймаут, частичный ответ и повторное списание. Тесты стали контрактом: то, что нельзя сломать, теперь проверялось машиной, а не глазом.
Описала контракт: публичные сигнатуры не меняются, внутренний клиент не заменяется на сторонний, схема ошибок остаётся прежней, на вход идёт функция, а не файл, ответ — патч не длиннее 120 строк.
Разложила миграцию на одиннадцать задач и отметила четыре, где шагов много: восстановление логики ретраев, разбор противоречий в спецификации провайдера, порядок миграции двух связанных сервисов, отладка таймаута, который воспроизводился раз в двести запросов.

