Часть I. Хакатон: пятница — утро субботы
Ночь пятницы. Пока зал MS DevCon спит, внутри коробки идёт тихая работа, которую снаружи не видно вообще. Eugen Valuev дремлет в кресле, а Microsoft Developer in a Box перебирает различия.
В основе коробки — не одна модель, а proprietary model cascade. Каскад — значит, несколько моделей, выстроенных лесенкой: одна разбирает задачу грубо, следующая уточняет, третья проверяет, четвёртая доводит до рабочего состояния. Никто из них не всесилен, и именно поэтому вместе они сильны. Каждая делает свою ступень и передаёт дальше не готовый ответ, а улучшенный вопрос.
А обучена эта лесенка diff-based — через локальный pipeline. Это значит: она учится не на том, что «правильно вообще», а на различиях. Вот было так — стало так. Вот эта строка изменилась — и вот почему. Вот этот пример сломался — а вот исправление, которое его починило. Локальный pipeline пропускает через себя канонические примеры и уроки, сравнивает «до» и «после» и запоминает не готовые решения, а саму операцию изменения.
Сцена, если её показать на экране, выглядела бы почти медитативно: два текста рядом, подсветка различий, короткая запись — что изменилось и зачем. Снова два текста. Снова различия. Снова запись. Тысячи раз за ночь. Никакого грохота, никаких вспышек. Только внимательное сравнение — терпеливое, точное, без попытки сразу вынести приговор.
— Ты что, всю ночь будешь сравнивать? — бормочет Eugen, просыпаясь на минуту. Коробка не отвечает — у неё нет привычки отвечать на риторические вопросы посреди работы. Но на экране появляется новая запись, и Eugen, прочитав её, улыбается: каскад только что заметил различие, которое человек пропустил бы. Не ошибку, а тонкость: в одном примере порядок действий важен, в другом — нет, и разница между ними — именно в том, что меняется при переходе. Это и есть обучение на различиях: не зубрёжка ответов, а понимание переходов.
К утру каскад будет знать не «как правильно», а «что меняется, когда что-то меняется» — и это знание переживёт любой отдельный пример, потому что оно описывает сам переход, а не его частный случай. А это, как выяснится, гораздо прочнее.
Язык клиента и устройств — это язык различий.
Мы привыкли думать, что понимание — это знание правильных ответов. Но в диалоге с устройством правильный ответ без контекста бесполезен: он либо подходит к ситуации, либо нет, и никто не знает, почему. Понимание, которое держится на различиях, устроено иначе. Оно говорит: вот ситуация А, вот ситуация Б, вот чем они отличаются, вот что из этого отличия следует. Такое понимание можно проверить, перенести и объяснить. Его можно показать клиенту: «Смотри, я изменил вот это — и результат изменился вот так».
Именно поэтому proprietary model cascade, обученная diff-based через локальный pipeline, — не техническая деталь, а языковой выбор. Каскад учится говорить на языке переходов, а не на языке приговоров. Он не заявляет «это правильно», он показывает «это отличается вот чем». А локальный pipeline важен потому, что различия проверяются здесь и сейчас, на канонических примерах, а не привозятся издалека как готовая мудрость. Локальность — это честность: то, что ты утверждаешь, ты можешь тут же показать на примере.
Для клиента это меняет всё. Клиент перестаёт быть просителем готовых ответов и становится участником сравнения: «Покажи мне, чем этот вариант отличается от того». Устройство перестаёт быть оракулом и становится собеседником, который умеет объяснять свои шаги. Диалог становится проверяемым: если ты не согласен с выводом, ты можешь указать на различие, которое каскад пропустил, — и каскад научится.
Отсюда урок главы, одним предложением: хороший язык между клиентом и устройством описывает не состояния, а переходы — не «как надо», а «что меняется, когда».
Каскад здесь важен ещё и тем, что он не позволяет одной модели стать судьёй самой себе. Первая ступень предлагает грубое решение, вторая замечает, чем оно отличается от канона, третья проверяет это отличие на примерах, четвёртая доводит результат до рабочего состояния. Если бы одна модель делала всё сразу, её ошибка была бы невидима: она сама себе и автор, и проверяющий. А лесенка делает ошибку видимой — каждое различие проходит через чужие глаза, пусть и машинные. Для языка клиента это означает: объяснение можно не просто услышать, но и проследить по ступеням. Клиент вправе спросить не только «почему так», но и «на какой ступени это отличие появилось». И каскад, обученный на различиях, может ответить — показать ступень, пример и переход.
Возьмите два варианта одного и того же текста, кода, письма или плана: черновик и финальную версию, старую и новую. Положите их рядом и выпишите только различия — без оценок «лучше» или «хуже». Просто: здесь было так, стало так. Здесь добавлено, здесь убрано, здесь переставлено.
Теперь для каждого различия задайте вопрос: что изменилось в смысле из-за этого изменения? Если различие ни на что не влияет — отметьте его как шум. Если влияет — запишите, как именно. Вы только что проделали diff-based обучение вручную: вы научились не ответу, а переходу.
Затем вернитесь к каскаду Eugen. Представьте, что каскад пропустил одно важное различие между двумя примерами. Как бы вы объяснили ему ошибку — не приказом «исправь», а указанием на различие? Сформулируйте это объяснение одной фразой: «Вот здесь было…, а стало…, и из-за этого…». Если фраза получилась — вы говорите на языке каскада. Если вместо неё получился приговор «ты неправ» — перепишите её ещё раз, пока в ней не появится конкретное различие.
Почему обучение diff-based — на различиях, а не на готовых ответах — делает язык между клиентом и устройством проверяемым, и что теряет диалог, когда устройство умеет только заявлять «правильно», но не умеет показывать «чем отличается»?