Глава 6.1 — Системный дизайн для LLM-продуктов

Содержание

  1. От компонентов к продукту: чем является и не является эта глава
  2. Требования и ограничения: вопросы, предшествующие любой архитектуре
  3. Выбор базовой модели и масштаба: compute-optimal и inference-optimal
  4. Превращение базовой модели в чат-продукт: слой SFT/RLHF
  5. Обслуживание в масштабе: неотъемлемые требования
  6. Длина контекста как продуктовое решение, а не просто как способность
  7. RAG против дообучения против агентов: подбор нужного рычага под задачу
  8. Оценка как непрерывный процесс, а не как ворота перед запуском
  9. Прохождение всего цикла: разбор проектного примера
  10. Взгляд с точки зрения интервью
  11. Вопросы для самопроверки
  12. Источники

1. От компонентов к продукту: чем является и не является эта глава

Часть V завершилась тезисом, с которым легко согласиться и который легко недооценить: всё, что охватила эта книга — механизмы внимания, цели предобучения, законы масштабирования, техники выравнивания, извлечение информации, агенты, оценку, — всё равно нужно собрать во что-то, что реально обслуживает запросы, по цене, которую кто-то готов платить, так, чтобы это можно было честно измерить после запуска. Этот этап сборки — не сноска. Именно здесь происходит удивительно большая доля реальной инженерной работы с LLM, и именно здесь решения из каждой предыдущей главы начинают взаимодействовать и обмениваться компромиссами друг с другом, вместо того чтобы рассматриваться изолированно.

Эта глава намеренно не будет вводить новых техник. Здесь нет новой архитектуры, новой цели обучения, нового варианта внимания. Вместо этого задача главы — заставить проделать своего рода припоминание и синтез, который отдельные главы сделать не могут: получив конкретное продуктовое техническое задание, какой из двадцати с лишним имеющихся у вас инструментов подходит для этой работы, в каком порядке к ним обращаться и — не менее важно — какие вы сознательно не используете, потому что издержки не оправданы требованием, стоящим перед вами? Это, не случайно, также близко к форме реального собеседования по системному дизайну для позиции, связанной с LLM, старшего уровня: интервьюер редко проверяет, помните ли вы, что существует PagedAttention, — он проверяет, умеете ли вы рассуждать о том, когда это важно.

2. Требования и ограничения: вопросы, предшествующие любой архитектуре

Любой реальный проект системы начинается с вопросов, не имеющих ничего общего с трансформерами. Что представляет собой продукт? Ассистент общего назначения, бот поддержки клиентов для конкретной предметной области, ассистент для написания кода, инструмент вопросов-ответов с расширением через поиск? Кто пользователи, сколько их и как часто они отправляют запросы? Каков бюджет задержки на запрос — это синхронный ход чата, на который смотрит человек, где время до первого токена критически важно, или пакетная задача, которая может допускать минуты ожидания? Каков бюджет по стоимости, выраженный в долларах на миллион обслуженных токенов, и как этот бюджет меняется по мере роста использования? Что означает «приемлемо» для этого продукта с точки зрения фактической надёжности, тона и безопасности — у ассистента для юридических исследований и у творческого спутника для писательства почти противоположная терпимость к галлюцинациям.

Эти вопросы важны, потому что они определяют, какие части книги критически важны для конкретного дизайна, а какие нерелевантны. У малотрафикового внутреннего инструмента для сотни инженеров требования к слою обслуживания совершенно иные, чем у потребительского продукта, обслуживающего десятки миллионов ежедневных активных пользователей; у системы, которой нужно рассуждать над контрактом на несколько сотен страниц, требования к длине контекста иные, чем у той, что отвечает на короткие фактические вопросы. Первое движение опытного инженера почти никогда не заключается в том, чтобы «выбрать модель». Это фиксация этих ограничений, потому что они определяют всю форму всего, что последует далее, — и интервьюер, наблюдающий, как вы сразу переходите к архитектуре, не спросив о масштабе, задержке и стоимости, видит, что вы упустили саму суть упражнения.

3. Выбор базовой модели и масштаба: compute-optimal и inference-optimal

После того как требования зафиксированы, первое реальное инженерное решение — с какой базовой модели начинать и в каком масштабе. Материал о законах масштабирования из главы 4.3 — это инструмент, который управляет этим решением, но стоит переформулировать напряжение между вариантами в продуктовых терминах, а не только в терминах стоимости обучения. Фронтир compute-optimal в стиле Chinchilla говорит вам, при фиксированном бюджете вычислений на обучение, какой размер модели и какое количество токенов минимизируют потери на обучении. Но продукт, который будет обслуживать миллиарды запросов за свой жизненный цикл, на самом деле не хочет минимизировать потери при обучении для фиксированного бюджета обучения — он хочет минимизировать полную стоимость владения, которая определяется стоимостью инференса, а не стоимостью обучения, как только модель выходит в продакшн. Именно поэтому LLaMA и LLaMA 2 обучались именно так, как обучались: в статье о LLaMA Touvron и др. явно обучали модели меньшего размера на гораздо большем числе токенов, чем предполагал бы compute-optimal фронтир, потому что модель меньшего размера, которую дешевле обслуживать в масштабе, даже если её обучение стоило дороже в расчёте на параметр, выигрывает по совокупной стоимости жизненного цикла для широко развёртываемого продукта. Это конкретизация inference-optimal логики из главы 4.3: вычисления на обучение — это разовая стоимость, вычисления на обслуживание — это стоимость, умноженная на каждый запрос за весь развёрнутый жизненный цикл модели, и при достаточно большом масштабе развёртывания второе слагаемое полностью доминирует в арифметике.

Решение о базовой модели также имеет измерение «открытые веса против проприетарной модели», которое стоит назвать явно, потому что оно повторяется в реальных интервью. Линейка LLaMA от Meta (LLaMA, LLaMA 2 и семейство моделей LLaMA 3) представляет стратегию выпуска сильных базовых моделей с открытыми весами и предоставления экосистеме возможности их дообучать и обслуживать; линейки PaLM и Gemini от Google представляют альтернативную стратегию крупных, часто мультимодальных, тесно интегрированных проприетарных моделей, обслуживаемых через инфраструктуру одного поставщика. Ни одна из них не «правильна» в абстрактном смысле — правильный выбор для вашего продукта зависит от того, нужно ли вам контролировать собственный стек обслуживания и глубоко его кастомизировать (что склоняет к базовой модели с открытыми весами вроде LLaMA 3, которая обучалась с выбором пост-обучения и масштаба, явно нацеленным на то, чтобы сделать семейство моделей пригодным для использования во многих размерах последующего развёртывания), или же вам нужны лучшие в своём классе мультимодальные возможности уже сегодня и вы готовы зависеть от API поставщика (что склоняет к чему-то вроде Gemini). Опытный инженер должен уметь чётко сформулировать этот компромисс, а не относиться к «какой модели» как к вопросу личного предпочтения.

4. Превращение базовой модели в чат-продукт: слой SFT/RLHF

Предобученная базовая модель, каким бы удачным ни был выбор, — это не чат-продукт. Глава 4.5 объяснила почему: базовая модель обучена правдоподобно продолжать текст, а не следовать инструкциям, отказываться от небезопасных запросов или порождать конкретный разговорный регистр, который ожидают пользователи. Превращение её в продукт означает пропустить её через контролируемое дообучение (supervised fine-tuning) на парах «инструкция-ответ», а затем через некоторую форму выравнивания на основе предпочтений — RLHF в классическом виде или один из более современных подходов прямой оптимизации предпочтений, — чтобы сформировать её в сторону ответов, которые реально предпочитают человеческие оценщики. Статья о выпуске LLaMA 2 — по-настоящему полезный конкретный источник здесь, потому что она документирует этот конвейер от начала до конца для широко развёрнутой модели: предобучение, контролируемое дообучение и итеративный RLHF с использованием как моделей вознаграждения за полезность, так и за безопасность, доработанные за несколько раундов, а не за один проход.

Именно на этом этапе решается значительная часть реальной «личности» и профиля безопасности чат-продукта, и именно здесь напрямую отражаются продуктовые требования из раздела 2. Боту поддержки клиентов нужны данные для SFT и модель вознаграждения, отражающие конкретную предметную область и тон, которых хочет бизнес; ассистенту для написания кода нужны данные SFT, насыщенные кодом и транскриптами использования инструментов, а не общим разговором. Ошибка, которой стоит избегать и которую слушает интервьюер, — трактовать «мы это дообучим» как единый недифференцированный шаг: сильный ответ различает, что делает SFT (обучает формату и общему поведению) и что делает оптимизация предпочтений (формирует, какой из нескольких правдоподобных ответов предпочтителен), и признаёт, что для них требуются разные данные (размеченные демонстрации против сравнительных данных) и разные сбои, за которыми нужно следить (SFT может переобучиться на узкий стиль; RLHF может «взломать» несовершенную модель вознаграждения).

Модель вознаграждения за безопасность RLHF формирует обученное поведение базовой модели, но продакшен-система надстраивает явные, независимые guardrails (защитные ограждения) поверх, а не полагается исключительно на обученное поведение, — то же самое разделение «этап обучения против этапа инференса», которое глава 5.6 проводит для структурированного вывода, применяется здесь ровно так же напрямую и к безопасности. Слой guardrails обычно запускает лёгкий классификатор модерации — Llama Guard от Meta является широко используемым конкретным примером: модель, обученная специально классифицировать промпт или ответ по фиксированной таксономии безопасности, а не вести диалог, — над входящим запросом и над собственным выводом модели, прежде чем он дойдёт до пользователя, проверяет вывод на паттерны PII или нарушения политики и может отклонить или переписать ответ независимо от того, что был склонен сказать сам исходный вывод модели. Причина, по которой этот слой вообще существует, а не полагается исключительно на хорошо выровненную модель, — та же причина, по которой неотъемлемые требования обслуживания из раздела 5 существуют независимо от качества модели: механическая, проверяемая проверка, выполняющаяся на каждом отдельном запросе, — это жёсткая гарантия, тогда как «модель была обучена вести себя хорошо» — лишь сильная склонность, и ответ по системному дизайну должен уметь назвать guardrails собственным архитектурным слоем, а не сворачивать всю безопасность в конвейер обучения.

5. Обслуживание в масштабе: неотъемлемые требования

Как только у вас есть модель, материал главы 3.4 об эффективности обслуживания перестаёт быть опциональным фоном и становится разницей между продуктом, экономически жизнеспособным, и тем, что таковым не является. При сколько-нибудь значительном объёме трафика небольшое число техник на уровне слоя обслуживания фактически обязательны, а не являются опциональными оптимизациями. Кэширование KV (KV-caching) — базовое требование для авторегрессивной генерации вообще: без него каждый новый токен требовал бы пересчёта внимания по всему префиксу с нуля, что асимптотически расточительно до степени непригодности к выпуску. Квантование (запуск весов и активаций с пониженной точностью, обычно int8 или 4 бита для весов) близко к обязательному в масштабе, потому что оно напрямую сокращает объём памяти и часто вычислительную стоимость на запрос, как правило, ценой небольших и тщательно измеряемых потерь качества. Непрерывное батчирование (continuous batching) — динамическое добавление и удаление отдельных запросов из батча вместо ожидания завершения фиксированного батча целиком — это то, что делает обслуживание экономически эффективным при реальном, пульсирующем, переменной длины трафике, поскольку иначе небольшое число длинных запросов застопорило бы весь статический батч коротких. Кэширование промптов (prompt caching) — четвёртое неотъемлемое требование для любого продукта с общим, повторяющимся префиксом между запросами: системный промпт, длинный набор few-shot примеров, извлечённый документ, включаемый в каждый ход диалога, — вместо повторного прогона вычислительно тяжёлого прохода prefill (глава 3.4) по этому идентичному префиксу на каждом отдельном запросе, записи KV-кэша, которые производит префикс, кэшируются один раз и переиспользуются в каждом запросе, разделяющем этот префикс, — платя за prefill один раз, а не на каждый запрос. Для продукта, где каждый запрос разделяет длинный, дорогой в обработке системный промпт, это часто самая рычаговая оптимизация стоимости из доступных, именно потому, что она устраняет повторяющуюся работу, а не просто удешевляет ту же самую работу.

Каноническое открытое решение этой проблемы обслуживания — vLLM, построенный вокруг PagedAttention (Kwon и др., SOSP 2023), которое подробно рассматривалось в главе 3.4 и здесь стоит упомянуть лишь как перекрёстную ссылку, а не выводить заново: он рассматривает KV-кэш как набор страниц фиксированного размера, управляемых так, как операционная система управляет виртуальной памятью, что устраняет фрагментацию и избыточное выделение памяти, от которых страдает наивное управление KV-кэшем, и это техника, наиболее непосредственно ответственная за то, что высокопроизводительное, высококонкурентное обслуживание LLM стало практически осуществимым за пределами проприетарной инфраструктуры. В зависимости от масштаба продукта и чувствительности к стоимости материал главы 3.3 о смесях экспертов (mixture-of-experts) также становится актуальным здесь по другой причине: MoE позволяет увеличить общее число параметров модели — а вместе с ним и её способность хранить знания и обрабатывать разнообразные типы запросов — без пропорционального увеличения вычислительной стоимости прямого прохода, поскольку на каждый токен активируется лишь подмножество экспертов. Для продукта, обслуживающего чрезвычайно широкое и гетерогенное распределение запросов в очень большом масштабе, этот аргумент «мощность на вычисление» может перевесить дополнительную сложность обслуживания, связанную с маршрутизацией и размещением экспертов; для более узкого, менее масштабного продукта эта сложность обычно того не стоит, и это как раз то суждение, которое ответ по системному дизайну должен делать явным, а не тянуться к MoE рефлекторно.

6. Длина контекста как продуктовое решение, а не просто как способность

То, сколько контекста нужно продукту, — это вопрос требований с реальными архитектурными последствиями, а не просто число, которое нужно максимизировать. Главы 3.1 и 3.2 объяснили, почему квадратичная стоимость наивного внимания по длине последовательности (сложность $O(n^2)$ по длине контекста $n$) делает очень длинные контексты дорогими, и рассмотрели различные техники — разреженные и линейные варианты внимания, схемы позиционного кодирования, разработанные для экстраполяции за пределы длины обучения, и стратегии скользящего окна и чанкинга, используемые на практике, — которые делают более длинный эффективный контекст осуществимым. В системном дизайне этот материал проявляется в виде прямого вопроса: действительно ли этому продукту нужно 100 тыс.+ токенов контекста, или ему просто нужно так ощущаться?

Это разные инженерные задачи с разной ценой. Продукту для анализа юридических документов действительно нужно охватывать очень длинные документы вниманием, и техники длинного контекста из глав 3.1 и 3.2 здесь критически важны. Чат-боту поддержки клиентов, который создаёт впечатление, что «помнит» длинную историю разговора, обычно не нужна модель с буквально огромным окном контекста — ему нужен слой извлечения или суммаризации, который сохраняет реально релевантные недавние ходы диалога и сжимает или отбрасывает остальное, прежде чем оно вообще достигнет контекста модели. Смешение этих двух вещей — распространённая ошибка дизайна: обращение к самой дорогой доступной модели с длинным контекстом, когда реальное требование можно удовлетворить гораздо дешевле с помощью хорошего управления контекстом, — это как раз та вынужденная ошибка, которую сильный ответ по системному дизайну избегает, снова спрашивая, каково реальное требование, прежде чем выбирать инструмент.

7. RAG против дообучения против агентов: подбор нужного рычага под задачу

Глава 5.2 установила генерацию с расширением через поиск (RAG), а глава 5.4 — агентов и использование инструментов; при проектировании системы нужно решить для конкретного продукта, какой из этих подходов — если вообще какой-либо — применим, и это одна из наиболее часто неправильно отвечаемых частей реальных интервью. Различающий вопрос — какой именно разрыв вы пытаетесь закрыть. Если знание модели устарело или в нём отсутствуют предметно-специфические факты, но её общее рассуждение и следование инструкциям уже адекватны, RAG почти всегда правильный первый рычаг: индекс дешевле обновлять, чем переобучать модель, он приходит с естественным следом происхождения для цитирования, и он деградирует более плавно (неудачное извлечение даёт неверный, но объяснимый ответ, тогда как пробел знаний, встроенный в веса, даёт уверенную галлюцинацию без видимой причины). Дообучение — правильный рычаг, когда разрыв поведенческий, а не фактический — модель знает релевантные факты, но выдаёт их в неправильном формате, тоне или стиле рассуждения для продукта, — поскольку RAG не может научить модель рассуждать или писать иначе, а только даёт ей другие факты для рассуждения и письма.

Агенты и использование инструментов из главы 5.4 — правильный рычаг, когда задача действительно требует многошагового взаимодействия с внешним миром — вызовов API, исполнения кода, выполнения многоходового плана, где поздние шаги зависят от результатов ранних, — а не единственного хорошо информированного ответа. Ошибка, на которую стоит явно указать в ответе на интервью, — это обращение к агентной архитектуре по умолчанию, потому что она звучит наиболее изощрённо: единственный вызов с хорошим извлечением, хорошим промптом, за один ход дешевле, быстрее и надёжнее, чем агентный цикл, всякий раз когда задача на самом деле не требует итеративного взаимодействия с внешним состоянием, и материал главы 5.4 об издержках надёжности при выполнении долгосрочных агентных задач — это именно причина не перебарщивать с агентной сложностью там, где справился бы более простой паттерн.

8. Оценка как непрерывный процесс, а не как ворота перед запуском

Глава 5.5 показала, что оценка — это не то, что делается один раз перед запуском и затем забывается; в реальном продукте она должна выполняться непрерывно, до и после каждого изменения, используя как офлайн-, так и онлайн-сигналы. Офлайн-оценка — наборы бенчмарков, отложенные тестовые выборки, оценка LLM-как-судья — это то, что используется перед выпуском изменения, чтобы дёшево и быстро отловить регрессии, но глава 5.5 явно указала, что производительность на бенчмарке и реальная надёжность — не одно и то же, и модель, улучшившаяся на бенчмарке, всё ещё может деградировать на реальном распределении трафика вашего продукта. Онлайн-оценка — то, что отлавливает этот разрыв: A/B-тестирование изменений на реальном пользовательском трафике, отслеживание продуктовых метрик (выполнение задачи, удовлетворённость пользователей по их собственным отчётам, частота эскалаций или жалоб, удержание), а не только метрик уровня модели (перплексия, точность на бенчмарке), и инструментирование для конкретных сбоев, важных именно для этого продукта, — частоты галлюцинаций на предметно-специфических фактах, частоты отказов на безобидных запросах, перцентилей задержки при реальной нагрузке, а не синтетической.

Проектный вывод состоит в том, что для выпущенного LLM-продукта инфраструктуру оценки нужно строить одновременно с самим продуктом, а не прикручивать её позже. Это означает логирование каждого взаимодействия в объёме, достаточном для реконструкции произошедшего, размеченную или оценённую судьёй выборку продакшн-трафика, регулярно просматриваемую, и механизм отката или постепенного развёртывания, чтобы регрессия, обнаруженная онлайн-метриками, не должна была ждать следующего полного цикла релиза для исправления. Это также место, где сильный ответ на интервью выделяется: более слабый ответ говорит «мы оценим это на стандартных бенчмарках перед запуском», более сильный описывает конкретный онлайн- и офлайн-цикл оценки, который продолжает работать после запуска, потому что именно это на самом деле отлавливает важные в продакшне регрессии.

9. Прохождение всего цикла: разбор проектного примера

Конкретно: предположим, техническое задание таково — «спроектировать чат-ассистент общего назначения, рассчитанный на обслуживание порядка десяти миллионов ежедневных активных пользователей, с бюджетом задержки менее секунды до первого токена, требованием отвечать на вопросы о событиях после статической отсечки обучения и жёстким требованием избегать уверенно сфабрикованных ответов на фактические запросы». Разбирая сначала требования: это достаточно высокий трафик, чтобы стоимость обслуживания на токен доминировала в дизайне, задержка достаточно жёсткая, чтобы время до первого токена и стриминг имели значение, а требования свежести и отсутствия галлюцинаций указывают напрямую на извлечение, а не на чистое параметрическое знание.

Отсюда выбор базовой модели следует inference-optimal логике из раздела 3: учитывая огромный объём запросов, модель меньшего размера, обученная на большем числе токенов, чем предполагает чисто compute-optimal фронтир, очень вероятно правильный выбор, в духе проектных решений линейки LLaMA, потому что стоимость обслуживания доминирует над стоимостью жизненного цикла в этом масштабе, — и если важна глубокая кастомизация стека обслуживания и конвейера дообучения, базовая модель с открытыми весами вроде LLaMA 3 — обоснованная отправная точка по сравнению с закрытой альтернативой только через API. Эта базовая модель затем проходит через SFT и оптимизацию предпочтений (раздел 4), становясь пригодной для использования чат-моделью с подходящим тоном и профилем безопасности для потребительского продукта. Учитывая требования свежести и отсутствия галлюцинаций, RAG (раздел 7) становится близким к обязательному, а не опциональным: слой извлечения по непрерывно обновляемому индексу решает как проблему устаревания, так и даёт требованию избегания галлюцинаций конкретный механизм — ответы, привязанные к извлечённым фрагментам с цитированием, а не опора исключительно на параметрическую память, — тогда как одно дообучение вообще не затронуло бы требование свежести. Учитывая, что это ассистент общего назначения, а не узкий продукт для вызова API, полноценный агентный цикл, вероятно, не путь по умолчанию для каждого запроса — он добавил бы задержку и поверхность отказов, которые бюджет задержки для десяти миллионов пользователей не может легко переварить, — но лёгкая способность использования инструментов (для чего-то вроде вычислений в стиле калькулятора или явного инструмента поиска-с-цитированием) — разумная золотая середина, согласующаяся с материалом главы 5.4 о соответствии агентной сложности реальным требованиям задачи.

На стороне обслуживания при таком объёме трафика KV-кэширование, квантование и непрерывное батчирование (раздел 5) просто необходимы, и что-то из семейства PagedAttention/vLLM — разумный вариант по умолчанию, а не самодельная альтернатива, именно потому что это хорошо проверенный открытый ответ ровно на эту проблему. Стоит обосновать это грубыми числами, а не оставлять «стоимость обслуживания доминирует» абстрактным утверждением: эффективно обслуживаемые модели с открытыми весами такого размерного класса обходятся по сырым вычислениям порядка от доли цента до нескольких центов за тысячу выходных токенов, что звучит тривиально на один запрос, но, помноженное на десять миллионов пользователей в день, каждый из которых обменивается хотя бы скромной горсткой сообщений, легко складывается в счёт за обслуживание в десятки тысяч долларов в день: если расписать явно, 10 000 000 пользователей × ~10 сообщений в день × ~300 выходных токенов на сообщение × ~$0,002 за тысячу токенов дают порядка $60 000 в день, — именно тот масштаб, на котором техники из раздела 5 перестают быть приятным дополнением и становятся разницей между жизнеспособной юнит-экономикой и невыпускаемым продуктом. Требование субсекундного времени до первого токена — столь же конкретное ограничение: при таком объёме трафика это по сути бюджет задержки prefill (глава 3.4) на то, сколько бы ни занимал извлечённый и закэшированный контекст, — именно поэтому кэширование промптов и inference-optimal (а не максимально compute-optimal) базовая модель имеют значение здесь конкретно, а не просто KV-кэширование в абстракции. Стоит ли MoE дополнительной сложности, зависит от широты распределения запросов: по-настоящему универсальный ассистент, обрабатывающий крайне гетерогенную смесь типов запросов, — более правдоподобный кандидат на выгоду от MoE «мощность на вычисление», чем узкопрофильный продукт. Длину контекста следует подбирать под то, что реально нужно продукту, — рабочий контекст чат-ассистента определяется недавними ходами диалога и извлечёнными фрагментами, а не огромным статическим окном, так что умеренная длина контекста с хорошим извлечением и суммаризацией, вероятно, более экономически эффективна, чем максимизация сырого размера окна. И, наконец, ничто из этого не выходит в продакшн без цикла оценки из раздела 8, встроенного с первого дня: офлайн-наборы регрессионных тестов, блокирующие любое изменение модели или промпта, и онлайн-метрики — частота галлюцинаций на выборке реального трафика, оценённой судьёй, перцентили задержки при продакшн-нагрузке, сигналы удовлетворённости пользователей и эскалаций — работающие непрерывно после запуска, потому что это единственный способ узнать, действительно ли изменение, хорошо выглядевшее в офлайне, хорошо для людей, использующих продукт.

Обратите внимание, что этот разбор на самом деле сделал: он не ввёл ни одной новой техники. Он взял компромисс compute-vs-inference-optimal из главы 4.3, конвейер SFT/RLHF из главы 4.5, техники обслуживания из главы 3.4, аргумент о мощности MoE из главы 3.3, компромиссы длинного контекста из глав 3.1 и 3.2, различия RAG-против-дообучения-против-агентов из глав 5.2 и 5.4 и дисциплину непрерывной оценки из главы 5.5 — и заставил их взаимодействовать при одном конкретном наборе ограничений. Это и есть реальный навык, который проверяет собеседование по системному дизайну старшего уровня, и это, не случайно, реальный навык, который требуется на работе: не знание того, что эти техники существуют, а знание того, какие из них действительно требует конкретный набор требований, и умение чётко сказать, почему остальные здесь не применимы. Но даже самый тщательно собранный дизайн такого рода опирается на допущение, которое стоит назвать прямо: что если каждый компонент сделан правильно, в сумме это даёт систему, которая надёжно работает при каждом обращении. Именно это допущение всё ещё проверяет остальная часть области.

10. Взгляд с точки зрения интервью

«Спроектируйте ассистента для написания кода, который должен работать со всей крупной кодовой базой, а не только с текущим файлом. Расскажите о своём подходе.» Сильный ответ начинает с требований: что функционально требует «работа со всей кодовой базой» — разрешение перекрёстных ссылок между файлами, осведомлённость о соглашениях проекта, многофайловые правки? Затем он явно рассуждает о контексте: кодовая база обычно намного больше любого практического окна контекста, так что это проблема извлечения (индексировать кодовую базу, извлекать релевантные файлы/функции/символы по запросу), а не проблема сырой длины контекста, проводя то же различие RAG-против-длинного-контекста, что и в разделе 6. Стоит отметить, что ассистенту для написания кода правдоподобно нужно агентное использование инструментов (запуск тестов, применение многофайловых диффов, вызов линтера) согласно главе 5.4, и что оценка здесь не может быть чисто офлайн-бенчмарками — нужны онлайн-сигналы вроде того, действительно ли сгенерированные диффы компилируются и проходят тесты, а не просто выглядят ли они правдоподобно.

«Офлайн-баллы бенчмарков вашего продукта улучшились после обновления модели, но пользователи жалуются больше. Что вы делаете?» Сильный ответ немедленно распознаёт это как разрыв главы 5.5 между производительностью на бенчмарке и реальной надёжностью и предлагает конкретный диагностический путь: проверить, соответствует ли распределение бенчмарка реальному распределению продакшн-трафика, сопоставить конкретные категории жалоб с инструментированными типами сбоев (галлюцинации, тон, частота отказов, задержка) и относиться к онлайн-метрикам как к истине в последней инстанции над офлайновыми, пока не доказано обратное, — потому что офлайн-набор по построению может проверять лишь то, для чего он был создан.

«Когда стоит выбирать MoE, а не просто обучить меньшую плотную модель?» Сильный ответ формулирует реальный компромисс из главы 3.3 в продуктовых терминах: MoE покупает параметрическую мощность — полезную для широкого, гетерогенного распределения запросов, где разные «виды» знания выигрывают от разных экспертов, — без пропорционального увеличения вычислений на токен, но это заметно увеличивает сложность инфраструктуры обслуживания (маршрутизация экспертов, балансировка нагрузки между экспертами, более сложное батчирование). Для узкопрофильного продукта с однородным распределением запросов эта сложность обычно не окупается, и меньшая плотная модель — более обоснованный выбор.

«Расскажите, как бы вы выбирали между дообучением и RAG для бота поддержки клиентов, который постоянно даёт устаревшие ответы о политике компании.» Сильный ответ сначала диагностирует тип сбоя: устаревшие ответы — это проблема свежести/фактов, а не поведенческая, что согласно разделу 7 указывает прямо на RAG по актуальному индексу политик, а не на дообучение, поскольку дообучение запекает факты в веса, которые снова устареют при следующем изменении политики, тогда как индекс извлечения можно обновить в момент изменения политики без переобучения чего-либо.

«В какой момент память KV-кэша становится узким местом и что с этим делать?» Сильный ответ связывает это с материалом главы 3.4: память KV-кэша растёт с длиной последовательности, размером батча и числом слоёв/голов — конкретно, размер кэша в байтах приблизительно равен $2 \times L \times H \times d_{head} \times S \times B \times \text{байт\_на\_элемент}$, где $L$ — число слоёв, $H$ — число голов, $d_{head}$ — размерность на голову, $S$ — длина последовательности, $B$ — размер батча, а множитель 2 отражает хранение и ключей, и значений, — и при высокой конкурентности с длинными контекстами она может доминировать над весами модели в потреблении памяти GPU; практические ответы — квантование кэша, использование техник вроде multi-query или grouped-query внимания для сокращения размера кэша на токен, и использование постраничного, несмежного выделения кэша (PagedAttention) для избежания потерь из-за фрагментации, а не просто выделение большего объёма памяти как решения по умолчанию.

11. Вопросы для самопроверки

  1. Почему inference-optimal размер модели для широко развёртываемого продукта обычно отличается от compute-optimal размера в стиле Chinchilla, и какую стоимость минимизирует каждый из них?
  2. Какие конкретные продуктовые требования подтолкнули бы вас к базовой модели с открытыми весами вроде LLaMA 3, а не к закрытой модели вроде Gemini?
  3. Назовите три техники уровня обслуживания, переходящие от «желательно иметь» к «фактически обязательны» по мере роста объёма запросов, и объясните, что ломается без каждой из них.
  4. Учитывая жалобу продукта «модель даёт устаревшие факты», разберите, почему RAG обычно правильный первый рычаг, а не дообучение, и опишите сценарий, в котором дообучение было бы лучшим ответом.
  5. Почему продукт, который, кажется, требует очень длинного окна контекста, может на самом деле лучше обслуживаться хорошим извлечением или суммаризацией, чем действительно большой длиной контекста?
  6. В чём разница между тем, что каждый из SFT и оптимизации предпочтений (RLHF или аналог) вносит при превращении базовой модели в чат-продукт?
  7. Почему улучшение офлайн-бенчмарка недостаточно доказательство того, что обновление модели безопасно полностью развернуть, и что бы вы проверили перед тем, как ему довериться?

12. Источники

  • Touvron, H., Lavril, T., Izacard, G., et al. (2023). LLaMA: Open and Efficient Foundation Language Models. arXiv:2302.13971. https://arxiv.org/abs/2302.13971
  • Touvron, H., Martin, L., Stone, K., et al. (2023). Llama 2: Open Foundation and Fine-Tuned Chat Models. arXiv:2307.09288. https://arxiv.org/abs/2307.09288
  • Grattafiori, A., Dubey, A., Jauhri, A., et al. (2024, Meta). The Llama 3 Herd of Models. arXiv:2407.21783. https://arxiv.org/abs/2407.21783
  • Chowdhery, A., Narang, S., Devlin, J., et al. (2022, Google). PaLM: Scaling Language Modeling with Pathways. JMLR 2023. arXiv:2204.02311. https://arxiv.org/abs/2204.02311
  • Gemini Team, Google DeepMind (2023). Gemini: A Family of Highly Capable Multimodal Models. arXiv:2312.11805. https://arxiv.org/abs/2312.11805
  • Kwon, W., Li, Z., Zhuang, S., et al. (2023). Efficient Memory Management for Large Language Model Serving with PagedAttention (vLLM). SOSP 2023. arXiv:2309.06180. https://arxiv.org/abs/2309.06180
  • Inan, H., Upasani, K., Chi, J., et al. (2023, Meta). Llama Guard: LLM-based Input-Output Safeguard for Human-AI Conversations. arXiv:2312.06674. https://arxiv.org/abs/2312.06674

Тест для самопроверки

Проверьте понимание главы с помощью короткого теста — вопросы по теории и небольшие расчёты.

Почему Meta обучала модели LLaMA меньшего размера, чем предполагал бы Chinchilla compute-optimal размер, но на большем числе токенов?

Объяснение: Вычисления на обучение — разовая стоимость; вычисления на обслуживание умножаются на каждый запрос за весь развёрнутый жизненный цикл модели — в масштабе второе слагаемое доминирует.

Согласно этой главе, что должно быть первым шагом в любом реальном системном дизайне LLM, прежде чем выбирать модель или архитектуру?

Объяснение: Эти ограничения определяют, какие части набора инструментов несущие для конкретного дизайна — интервьюер, видящий, что вы сразу переходите к архитектуре, видит, что вы упускаете суть упражнения.

Согласно рекомендациям главы о RAG против дообучения, какой рычаг правильно применить в первую очередь, когда знания модели устарели или в них не хватает специфичных для домена фактов, но рассуждение и следование инструкциям уже адекватны?

Объяснение: Дообучение — правильный рычаг, когда разрыв поведенческий (неверный формат/тон/стиль), а не фактический — RAG не может научить модель рассуждать или писать иначе.

Почему улучшения на офлайн-бенчмарках сами по себе недостаточное доказательство того, что обновление модели безопасно полностью выкатывать?

Объяснение: Именно поэтому нужно онлайн A/B-тестирование на реальном трафике с отслеживанием продуктовых метрик, чтобы поймать то, что не ловят офлайн-наборы.

Обслуживание стоит 2 доллара за миллион выходных токенов. Средний ответ — 500 токенов. Какова стоимость одного ответа в долларах? (Округлите до 4 знаков после запятой.)

Объяснение: 500 токенов × (2 доллара / 1 000 000 токенов) = 0.001 доллара.

Продукт обслуживает 10 миллионов ежедневных активных пользователей, каждый в среднем отправляет 3 запроса в день, каждый запрос стоит 0.001 доллара в обслуживании. Какова общая ежедневная стоимость обслуживания в долларах?

Объяснение: 10 000 000 × 3 × 0.001 доллара = 30 000 долларов в день.

Один GPU может обслуживать 50 запросов в секунду при целевом бюджете задержки. Сколько GPU нужно, чтобы выдержать пиковую нагрузку в 2000 запросов в секунду?

Объяснение: 2000 / 50 = 40 GPU.

KV-кэш одного запроса занимает 200 МБ. Сколько всего памяти под KV-кэш нужно, чтобы обслуживать 128 одновременных запросов, в ГБ (1 ГБ = 1024 МБ)?

Объяснение: 200 МБ × 128 = 25 600 МБ. Поскольку 1 ГБ = 1024 МБ, это 25 600 / 1024 = 25.0 ГБ.