Всегда было интересно, как AI Overview в гугле работает так быстро, и тут наткнулся на статью https://research.google/blog/looking-back-at-speculative-decoding/
Оказалось, что они используют технику speculative decoding
В обычном сетапе тяжелая llm генерирует токен за токеном, что может быть слишком долго/дорого. Однако, некоторые токены предсказать довольно просто:
• частые слова вроде the, is, of, and, ...
• цифры / имена, которые уже были в контексте
• повторяющиеся связки слов
И идея заключается в том, что а давайте сначала пробовать сгенерировать несколько токенов более легковесной моделью, далее большая модель их батчево проверит, и если ок, то оставит, если не ок — сгенерит сама
Вместо:
Будем делать:
И если small и large модели работают "похожим образом", то это может дать серьезный буст в скорости генерации, так как мы будем часто оставлять те токены, которые предложила легковесная модель и не будем тратить ресурсы на генерацию с помощью тяжелой модели
Btw похожая техника используется в Cursor https://cursor.com/blog/instant-apply
Оказалось, что они используют технику speculative decoding
В обычном сетапе тяжелая llm генерирует токен за токеном, что может быть слишком долго/дорого. Однако, некоторые токены предсказать довольно просто:
• частые слова вроде the, is, of, and, ...
• цифры / имена, которые уже были в контексте
• повторяющиеся связки слов
И идея заключается в том, что а давайте сначала пробовать сгенерировать несколько токенов более легковесной моделью, далее большая модель их батчево проверит, и если ок, то оставит, если не ок — сгенерит сама
Вместо:
large model:
context → T1
context+T1 → T2
context+T1+T2 → T3
...
Будем делать:
small model:
context → T1
context+T1 → T2
context+T1+T2 → T3
large model:
проверяет context+T1+T2+T3
ок → оставляем
не ок → large генерит сама
И если small и large модели работают "похожим образом", то это может дать серьезный буст в скорости генерации, так как мы будем часто оставлять те токены, которые предложила легковесная модель и не будем тратить ресурсы на генерацию с помощью тяжелой модели
Btw похожая техника используется в Cursor https://cursor.com/blog/instant-apply
Google Research
Looking back at speculative decoding
Speculative decoding has proven to be an effective technique for faster and cheaper inference from LLMs without compromising quality. It has also proven to be an effective paradigm for a range of optimization techniques.
1🔥40👍22💅2
Несколько способов дождаться результата асинхронной задачи
Сетап:
1. Клиент отправляет какой-то запрос
2. Джоба ставится в очередь задач
3. Клиент получает jobId
4. Клиент хочет дождаться результата
Поллинг
Самый простой с точки зрения бэкенда способ, нужна всего лишь апишка, которая по jobId вернет актуальный статус
И клиент в эту апишку долбится с некоторой периодичностью
Лонг поллинг
Более сложный, но более удобный для клиента вариант: клиент делает один запрос, сервер ждёт, пока задача завершится (или истечет таймаут), и возвращает результат
Как такое реализовать?
Идея 1: ожидание в потоке обработки
Сделать просто, но есть несколько очевидных минусов:
• Блочится поток обработки. В классической thread-per-request модели это быстро приведет к тому, что все request-threads будут заняты ожиданием. Для легковесных го(-ко)рутин проблема сильно менее критична:)
• Можем замучать базу кучей точечных запросов
Идея 2: асинхронное ожидание
Давайте попробуем решить сразу обе проблемы — не занимать поток обработки, и не мучать базу кучей запросов. Сделать это можно так:
1. На уровне контроллера отдаем фьючу и сразу освобождаем поток
Соединение остаётся открытым, но поток обработки запроса освобождается сразу
2. Появляется отдельный компонент, который
• позволяет зарегистрировать ожидание задачи
• держит in-memory структуру вида Map<JobId, Future> задач, которых клиенты ожидают
• батчево поллит базу по набору JobId
• по готовности — завершает все связанные фьючи
Таким образом, ожидание не держит request-thread и в базу идет контролируемый батч-запрос раз в какой-то промежуток времени
—
Альтернативы: вебсокеты, SSE, коллбэки
Пишите в комментах, что из этого используете, и какие еще знаете варианты реализации
Сетап:
1. Клиент отправляет какой-то запрос
2. Джоба ставится в очередь задач
3. Клиент получает jobId
4. Клиент хочет дождаться результата
Поллинг
Самый простой с точки зрения бэкенда способ, нужна всего лишь апишка, которая по jobId вернет актуальный статус
И клиент в эту апишку долбится с некоторой периодичностью
client -> server: jobId = 123
client <- server: status = running
...
client -> server: jobId = 123
client <- server: status = running
...
client -> server: jobId = 123
client <- server: status = done
Лонг поллинг
Более сложный, но более удобный для клиента вариант: клиент делает один запрос, сервер ждёт, пока задача завершится (или истечет таймаут), и возвращает результат
client -> server: jobId = 123
...
client <- server: status = done
Как такое реализовать?
Идея 1: ожидание в потоке обработки
fun await(id: JobId): JobResult {
while (true) {
val result = jobService.get(id)
if (result.status != RUNNING) {
return result
}
Thread.sleep(1000)
}
}
Сделать просто, но есть несколько очевидных минусов:
• Блочится поток обработки. В классической thread-per-request модели это быстро приведет к тому, что все request-threads будут заняты ожиданием. Для легковесных го(-ко)рутин проблема сильно менее критична:)
• Можем замучать базу кучей точечных запросов
Идея 2: асинхронное ожидание
Давайте попробуем решить сразу обе проблемы — не занимать поток обработки, и не мучать базу кучей запросов. Сделать это можно так:
1. На уровне контроллера отдаем фьючу и сразу освобождаем поток
fun await(id: JobId): DeferredResult<JobResult> {
val dr = DeferredResult<JobResult>()
val future = jobWaitService.register(id)
future.whenComplete { result, _ ->
dr.setResult(result)
}
return dr
}
Соединение остаётся открытым, но поток обработки запроса освобождается сразу
2. Появляется отдельный компонент, который
• позволяет зарегистрировать ожидание задачи
• держит in-memory структуру вида Map<JobId, Future> задач, которых клиенты ожидают
• батчево поллит базу по набору JobId
• по готовности — завершает все связанные фьючи
Таким образом, ожидание не держит request-thread и в базу идет контролируемый батч-запрос раз в какой-то промежуток времени
—
Альтернативы: вебсокеты, SSE, коллбэки
Пишите в комментах, что из этого используете, и какие еще знаете варианты реализации
🔥25👍8💅2
Про Стратоплан и менеджмент pt.4
Таки осилил основную часть курса "Руководитель отдела", были три занятия про
• Целеполагание и реализацию стратегии
• Найм и развитие ключевых сотрудников
• Системный people-management
Первое занятие
Достаточное лайтовое. Ключевая мысль: есть perfomance goals, есть development goals
• perfomance goals обычно "SMART-уются" и влияют на ближайшее вознаграждение. Пример: увеличить метрику X на Y п.п. до ближайшего perfomance review
• development goals — наоборот: их обычно сложно измерить, и нацелены на развитие на будущее. Пример: улучшить софты
При этом development goals можно достигать по разному. Например, к улучшению софтов можно подходить разными путями: можно бить в публичные выступления, можно бить в решение конфликтов и т.п.
И то, каким путем достигается цель, это и есть стратегия — т.е. некоторый вектор приложения сил
И для декомпозиции таких целей предлагается фреймворк GOSPA (Goals, Objectives, Strategies, Plans, and Activities). Btw, по этому фреймворку бывает удобно описать какие-то личные цели, не касающиеся работы
Второе занятие
В основном дается некоторая база про найм и развитие: портрет кандидата, матрицы компетенций и т.д.
При этом запомнились несколько интересных мыслей
В найме тимлидов очень важно много времени уделять мэтчу с корпоративной культурой. И делать это можно, задавая вопросы не "какие результаты ты получил на прошлой работе?", а "как ты их получил?"
Почему это важно? Один тимлид может выжигать команду, заставлять овертаймить, и таким образом давать результат. Второй может очень мягко идти в долгосрочную мотивацию. И парадоксально — и то, и то может быть как ок, так и не ок в рамках определенной корп культуры
И очень неплохо такое вскрывать помогают проективные вопросы. Это работает так: задается какой-то общий вопрос типа "как думаешь, почему люди обычно увольняются?". И вопрос вроде бы про "всех", но человек скорее всего начнет говорить про себя, через призму своего опыта
Третье занятие
Про системный people-management. Мое любимое, так как немного сдвинуло парадигму мышления
Ключевая мысль: поведение людей — рациональный ответ на структуру системы. И если поведение не нравится, то проблема почти всегда в системе, а не в людях
Как это работает? Во всех компаниях есть вещи, которые явно не прописаны, но которые определяют, как работает система:
• кто по факту принимает решения?
• кто имеет право-вето?
• как на самом деле реагируют на ошибки?
• за что на самом деле поощряют и продвигают?
И каждый руководитель дает своим сотрудникам эти сигналы, зачастую усиливая сигналы руководителя сверху. Пример:
• CTO: проект X нужно выполнить к дд.мм.ГГГГ! Если что то пойдет не так, виноватых найдем и накажем!
• Рук отдела/TL: ошибаться опасно, нужно жестче контролировать разработчиков
• Разработчик: сделаю ровно то, что просят. Жду новую постановку задачи. Если будут делать ровно то, что скажут, то меня не накажут
В итоге из-за сигнала сверху что ошибаться нельзя, получили безынициативных разработчиков
И чтобы менять систему, очень важно уметь замечать такие сигналы. Далее в занятии даются практики, которые помогают раздебажить систему, и понять, а как ее менять. Где точка наиболее эффективного приложения сил
—
Как-то так! Еще осталось досмотреть несколько занятий из курса "основа" — это 4 больших воркшопа, посвященных общим руководительским навыкам, не привязанным к конкретной роли. Про это будет еще 1 или 2 поста
Пишите в комментах с чем согласны/не согласны, что показалось интересным
Таки осилил основную часть курса "Руководитель отдела", были три занятия про
• Целеполагание и реализацию стратегии
• Найм и развитие ключевых сотрудников
• Системный people-management
Первое занятие
Достаточное лайтовое. Ключевая мысль: есть perfomance goals, есть development goals
• perfomance goals обычно "SMART-уются" и влияют на ближайшее вознаграждение. Пример: увеличить метрику X на Y п.п. до ближайшего perfomance review
• development goals — наоборот: их обычно сложно измерить, и нацелены на развитие на будущее. Пример: улучшить софты
При этом development goals можно достигать по разному. Например, к улучшению софтов можно подходить разными путями: можно бить в публичные выступления, можно бить в решение конфликтов и т.п.
И то, каким путем достигается цель, это и есть стратегия — т.е. некоторый вектор приложения сил
И для декомпозиции таких целей предлагается фреймворк GOSPA (Goals, Objectives, Strategies, Plans, and Activities). Btw, по этому фреймворку бывает удобно описать какие-то личные цели, не касающиеся работы
Второе занятие
В основном дается некоторая база про найм и развитие: портрет кандидата, матрицы компетенций и т.д.
При этом запомнились несколько интересных мыслей
В найме тимлидов очень важно много времени уделять мэтчу с корпоративной культурой. И делать это можно, задавая вопросы не "какие результаты ты получил на прошлой работе?", а "как ты их получил?"
Почему это важно? Один тимлид может выжигать команду, заставлять овертаймить, и таким образом давать результат. Второй может очень мягко идти в долгосрочную мотивацию. И парадоксально — и то, и то может быть как ок, так и не ок в рамках определенной корп культуры
И очень неплохо такое вскрывать помогают проективные вопросы. Это работает так: задается какой-то общий вопрос типа "как думаешь, почему люди обычно увольняются?". И вопрос вроде бы про "всех", но человек скорее всего начнет говорить про себя, через призму своего опыта
Третье занятие
Про системный people-management. Мое любимое, так как немного сдвинуло парадигму мышления
Ключевая мысль: поведение людей — рациональный ответ на структуру системы. И если поведение не нравится, то проблема почти всегда в системе, а не в людях
Как это работает? Во всех компаниях есть вещи, которые явно не прописаны, но которые определяют, как работает система:
• кто по факту принимает решения?
• кто имеет право-вето?
• как на самом деле реагируют на ошибки?
• за что на самом деле поощряют и продвигают?
И каждый руководитель дает своим сотрудникам эти сигналы, зачастую усиливая сигналы руководителя сверху. Пример:
• CTO: проект X нужно выполнить к дд.мм.ГГГГ! Если что то пойдет не так, виноватых найдем и накажем!
• Рук отдела/TL: ошибаться опасно, нужно жестче контролировать разработчиков
• Разработчик: сделаю ровно то, что просят. Жду новую постановку задачи. Если будут делать ровно то, что скажут, то меня не накажут
В итоге из-за сигнала сверху что ошибаться нельзя, получили безынициативных разработчиков
И чтобы менять систему, очень важно уметь замечать такие сигналы. Далее в занятии даются практики, которые помогают раздебажить систему, и понять, а как ее менять. Где точка наиболее эффективного приложения сил
—
Как-то так! Еще осталось досмотреть несколько занятий из курса "основа" — это 4 больших воркшопа, посвященных общим руководительским навыкам, не привязанным к конкретной роли. Про это будет еще 1 или 2 поста
Пишите в комментах с чем согласны/не согласны, что показалось интересным
🔥45👍20🙏4 2💅1
Написал небольшую статейку с примерами про Schema Guided Reasoning — полезный и частоиспользуемый паттерн при разработке агентов
https://telegra.ph/SGR-Schema-Guided-Reasoning-02-21
Приятного чтения!
https://telegra.ph/SGR-Schema-Guided-Reasoning-02-21
Приятного чтения!
Telegraph
SGR (Schema Guided Reasoning)
По умолчанию LLM отдают произвольный текст. Иногда это удобно, но иногда хочется строгий структурированный вывод. Например, в задачах классификации Structured Output Строгий вывод делается благодаря Structured Output 1. Задается JSON-схема ответа
🔥30👍2
AI ускоряет разработчиков. Почему фичи начинают шипаться дольше?
В свете последних событий с массовым использованием ИИ-ассистентов вижу интересную картину:
Объяснить этот феномен может закон Литтла
• WIP — сколько фич одновременно в работе у команды
• Throughput — сколько фич полноценно завершает команда за единицу времени
• Cycle Time — сколько времени занимает полноценно сделать одну фичу
Что происходит с AI
Чтобы полноценно сделать фичу, нужна совместная работа дискавери, дизайна, бэка, фронта, QA
Cursor увеличивает локальную скорость написания кода
И получаем примерно следующую картину:
С WIP разобрались. Но что насчет Throughput? Кажется, что если Cursor ускоряет индивидуальных разработчиков, то должен ускорять и всю команду целиком
Но есть нюансы:
• Если боттлнек — не разработка, то ускорение разработки сделает только хуже для команды в целом
• Из-за роста WIP получаем безумное количество context switching
И в реальности получаем, что эффект от ускорения индивидуальных разработчиков невелируется, и Throughput либо не меняется, либо становится хуже
Если подытожить:
• WIP растет
• Throughput либо не меняется, либо ухудшается
• Согласно закону Литтла Cycle Time сильно вырастает
—
Какое минимальное действие можно сделать, чтобы этого избежать? На мой взгляд — это WIP-лимиты на уровне фичей
Т.е. команда одновременно работает не более чем над N фичами
И если условный бэк сделал все по своей части, он не берет (N + 1)-ую фичу в работу, а вместо этого
• либо идет исправлять техдолг
• либо в идеале идет помогать текущему узкому месту в команде, например QA
Поскольку все основные негативные эффекты с замедлением команды связаны с ростом WIP и переключениями контекста, WIP-лимиты помогут это нивелировать, и обратить ускорение разработки на пользу команды
Пишите ваше мнение в комментариях!
👍 — AI-ассистенты ускоряют работу моей команды
🔥 — замедляют
В свете последних событий с массовым использованием ИИ-ассистентов вижу интересную картину:
Разрабы начинают юзать Cursor →
Код пишется быстрее →
Фичи в проде появляются медленнее
Объяснить этот феномен может закон Литтла
Cycle Time = WIP / Throughput
• WIP — сколько фич одновременно в работе у команды
• Throughput — сколько фич полноценно завершает команда за единицу времени
• Cycle Time — сколько времени занимает полноценно сделать одну фичу
Что происходит с AI
Чтобы полноценно сделать фичу, нужна совместная работа дискавери, дизайна, бэка, фронта, QA
Cursor увеличивает локальную скорость написания кода
И получаем примерно следующую картину:
Бэк быстро сделал свою часть фичи →
Бэк берет следующую фичу →
Очередь перед фронтом и QA растет →
WIP растет
С WIP разобрались. Но что насчет Throughput? Кажется, что если Cursor ускоряет индивидуальных разработчиков, то должен ускорять и всю команду целиком
Но есть нюансы:
• Если боттлнек — не разработка, то ускорение разработки сделает только хуже для команды в целом
• Из-за роста WIP получаем безумное количество context switching
И в реальности получаем, что эффект от ускорения индивидуальных разработчиков невелируется, и Throughput либо не меняется, либо становится хуже
Если подытожить:
• WIP растет
• Throughput либо не меняется, либо ухудшается
• Согласно закону Литтла Cycle Time сильно вырастает
—
Какое минимальное действие можно сделать, чтобы этого избежать? На мой взгляд — это WIP-лимиты на уровне фичей
Т.е. команда одновременно работает не более чем над N фичами
И если условный бэк сделал все по своей части, он не берет (N + 1)-ую фичу в работу, а вместо этого
• либо идет исправлять техдолг
• либо в идеале идет помогать текущему узкому месту в команде, например QA
Поскольку все основные негативные эффекты с замедлением команды связаны с ростом WIP и переключениями контекста, WIP-лимиты помогут это нивелировать, и обратить ускорение разработки на пользу команды
Пишите ваше мнение в комментариях!
👍 — AI-ассистенты ускоряют работу моей команды
🔥 — замедляют
👍102🔥32🤔23💅3
Где может потеряться "exactly-once"
Представим классическую схему — два сервиса интегрированы через брокер:
Хочется обеспечить exactly-once обработку на всей цепочке
Что может пойти не так?
producer → broker
Продюсер записал сообщение в брокер → брокер отправляет ack → сеть сбойнула → продюсер ретраит → в брокере дубликат
Как обычно решается: зачастую общий механизм выглядит так, что каждый продюсер отправляет сообщения с монотонно-возрастающим sequenceNumber (в рамках данного продюсера), а брокер дедуплицирует по (producerId, sequenceNumber). Т.е. если от данного producerId пришло сообщение с sequenceNumber меньшим или равным, чем уже записано, то брокер его дискардит
Конкретная реализация зависит от брокера: например у кафки и нашего яндексового logbroker механизмы чуть разные
broker → consumer → side effect
Консюмер обработал сообщение → не успел закомитить offset → упал → после восстановления обрабатывает то же самое сообщение
Как обычно решается: у каждого сообщения есть уникальный идентификатор + обработка внутри консюмера идемпотентна по уникальному идентификатору сообщения
Например, консюмер может хранить идентификаторы обработанных сообщений в своей БД и выполнять дедупликацию перед применением бизнес-логики (например, через insert ... on conflict do nothing в транзакции с бизнес логикой). Если сообщение уже было обработано, повторная обработка пропускается, и применение сообщения к системе становится идемпотентным
Однако если обработка включает side effect во внешнюю систему, то для сохранения exactly-once внешняя система тоже должна поддерживать идемпотентность
—
Поэтому важно понимать: в большинстве случаев под капотом “exactly-once” — это at-least-once доставка + идемпотентная обработка на каждом стыке. Физически сообщения могут обрабатываться несколько раз, но система спроектирована так, что итоговое состояние меняется ровно один раз
Представим классическую схему — два сервиса интегрированы через брокер:
producer → broker → consumer → side effect
Хочется обеспечить exactly-once обработку на всей цепочке
Что может пойти не так?
producer → broker
Продюсер записал сообщение в брокер → брокер отправляет ack → сеть сбойнула → продюсер ретраит → в брокере дубликат
Как обычно решается: зачастую общий механизм выглядит так, что каждый продюсер отправляет сообщения с монотонно-возрастающим sequenceNumber (в рамках данного продюсера), а брокер дедуплицирует по (producerId, sequenceNumber). Т.е. если от данного producerId пришло сообщение с sequenceNumber меньшим или равным, чем уже записано, то брокер его дискардит
Конкретная реализация зависит от брокера: например у кафки и нашего яндексового logbroker механизмы чуть разные
broker → consumer → side effect
Консюмер обработал сообщение → не успел закомитить offset → упал → после восстановления обрабатывает то же самое сообщение
Как обычно решается: у каждого сообщения есть уникальный идентификатор + обработка внутри консюмера идемпотентна по уникальному идентификатору сообщения
Например, консюмер может хранить идентификаторы обработанных сообщений в своей БД и выполнять дедупликацию перед применением бизнес-логики (например, через insert ... on conflict do nothing в транзакции с бизнес логикой). Если сообщение уже было обработано, повторная обработка пропускается, и применение сообщения к системе становится идемпотентным
Однако если обработка включает side effect во внешнюю систему, то для сохранения exactly-once внешняя система тоже должна поддерживать идемпотентность
—
Поэтому важно понимать: в большинстве случаев под капотом “exactly-once” — это at-least-once доставка + идемпотентная обработка на каждом стыке. Физически сообщения могут обрабатываться несколько раз, но система спроектирована так, что итоговое состояние меняется ровно один раз
👍71🔥18🤔4💅3 3
Почему загрузить разработчиков на 100% — плохая идея
Иногда в управлении командой есть очень соблазнительная мысль — давайте полностью загрузим каждого разраба, и тогда команда будет работать эффективно. На практике это часто дает обратный эффект
Занятость людей ≠ движение работы
Цель команды — протолкнуть фичу до прода. Проталкивание обычно включает в себя разработку → кодревью → тестирование → выкатку на прод
Пример, что происходит, когда все загружены на 100%. Начало спринта:
• Разработчик 1 делает фичу А
• Разработчик 2 делает фичу B
• QA тестирует предыдущую фичу C
Разработка фичи A завершена, требуется ревью. Но разработчик 2 загружен. Чтобы не просиживать, разработчик 1 берет следующую фичу D:
• разработчик 1 делает фичу А (ждет ревью)
• разработчик 1 делает фичу D
• разработчик 2 делает фичу B
• QA тестирует предыдущую фичу C
На следующий день аналогичная ситуация случается со вторым разработчиком. При этом QA до сих пор тестирует фичу С, так как фича оказалась большой и сложной
• разработчик 1 делает фичу А (поревьюено, ждет QA)
• разработчик 1 делает фичу D
• разработчик 2 делает фичу B (ждет ревью)
• разработчик 2 делает фичу E
• QA тестирует предыдущую фичу С
Спустя несколько дней получаем:
• растущую очередь перед кодревью
• растущую очередь перед QA
• кучу незавершенной работы
Незавершенная работа ⇒ раздутый WIP ⇒ огромный Cycle Time ⇒ фичи в проде появляются очень медленно
Ситуация выше описывается Теорией Ограничений — нет смысла усиливать ту часть производства, которая не является узким местом. Потому что это будет приводить к раздуванию очереди перед узким местом, и как следствие, повышению времени цикла
Что с AI?
Может возникнуть мысль что с AI-ассистентами проблема выше неактуальна, так как
• бэкендер может написать немного фронта
• фронт может сам поправить контракт апишки
• разрабы могут сильно помогать QA
Пункты выше действительно ослабляют проблему 100% загрузки, потому что люди становятся более "кросс-функциональными". Но тут есть важный нюанс — AI не отменяет закон очередей. Он просто делает границы между ролями чуть более размытыми
Поэтому очень важно использовать AI правильно — не генерить кучу незавершенки, а помогать разгружать узкое место. Об этом писал в одном из предыдущих постов
—
Пишите в комментах, если сталкивались с желанием загрузить всех на 100%, и что из этого вышло:)
P.S.: те 10% девушек, которые читают этот канал, с праздником вас!
Иногда в управлении командой есть очень соблазнительная мысль — давайте полностью загрузим каждого разраба, и тогда команда будет работать эффективно. На практике это часто дает обратный эффект
Занятость людей ≠ движение работы
Цель команды — протолкнуть фичу до прода. Проталкивание обычно включает в себя разработку → кодревью → тестирование → выкатку на прод
Пример, что происходит, когда все загружены на 100%. Начало спринта:
• Разработчик 1 делает фичу А
• Разработчик 2 делает фичу B
• QA тестирует предыдущую фичу C
Разработка фичи A завершена, требуется ревью. Но разработчик 2 загружен. Чтобы не просиживать, разработчик 1 берет следующую фичу D:
• разработчик 1 делает фичу А (ждет ревью)
• разработчик 1 делает фичу D
• разработчик 2 делает фичу B
• QA тестирует предыдущую фичу C
На следующий день аналогичная ситуация случается со вторым разработчиком. При этом QA до сих пор тестирует фичу С, так как фича оказалась большой и сложной
• разработчик 1 делает фичу А (поревьюено, ждет QA)
• разработчик 1 делает фичу D
• разработчик 2 делает фичу B (ждет ревью)
• разработчик 2 делает фичу E
• QA тестирует предыдущую фичу С
Спустя несколько дней получаем:
• растущую очередь перед кодревью
• растущую очередь перед QA
• кучу незавершенной работы
Незавершенная работа ⇒ раздутый WIP ⇒ огромный Cycle Time ⇒ фичи в проде появляются очень медленно
Ситуация выше описывается Теорией Ограничений — нет смысла усиливать ту часть производства, которая не является узким местом. Потому что это будет приводить к раздуванию очереди перед узким местом, и как следствие, повышению времени цикла
Что с AI?
Может возникнуть мысль что с AI-ассистентами проблема выше неактуальна, так как
• бэкендер может написать немного фронта
• фронт может сам поправить контракт апишки
• разрабы могут сильно помогать QA
Пункты выше действительно ослабляют проблему 100% загрузки, потому что люди становятся более "кросс-функциональными". Но тут есть важный нюанс — AI не отменяет закон очередей. Он просто делает границы между ролями чуть более размытыми
Поэтому очень важно использовать AI правильно — не генерить кучу незавершенки, а помогать разгружать узкое место. Об этом писал в одном из предыдущих постов
—
Пишите в комментах, если сталкивались с желанием загрузить всех на 100%, и что из этого вышло:)
P.S.: те 10% девушек, которые читают этот канал, с праздником вас!
👍49💅18🔥9🙏1 1
random thought
Привычные аргументы насчет гексагоналки/clean arch выглядят так:
+: высокая тестируемость
+: понятная структура проекта
-: много бойлерплейта
-: много абстракций
-: высокий порог входа
Но если вспомнить, что сейчас большинство кода пишется агентами, которым как раз нужна
• высокая тестируемость
• понятная структура проекта
При этом для агентов не проблема
• написать бойлерплейт
• осознать абстракции
мэтч?
Привычные аргументы насчет гексагоналки/clean arch выглядят так:
+: высокая тестируемость
+: понятная структура проекта
-: много бойлерплейта
-: много абстракций
-: высокий порог входа
Но если вспомнить, что сейчас большинство кода пишется агентами, которым как раз нужна
• высокая тестируемость
• понятная структура проекта
При этом для агентов не проблема
• написать бойлерплейт
• осознать абстракции
мэтч?
👍67🤔9💅4😁2
Про Стратоплан и менеджмент (итог)
Я уже как ~месяц назад закончил обучение в Стратоплане на руководителя отдела https://stratoplan-school.com/head/
Обучение весьма удачно совпало с новой зоной ответственностью на работе, поэтому многое удалось попробовать на практике. Если меня попросить топ выводов/мыслей, в которых убедился на собственном опыте, я бы ответил так:
• Не хочешь внезапных разочарований (в т.ч. от себя) — явно проговаривай ожидания
• Регулярное обеспечение прозрачности таки действительно рождает доверие (как и наоборот)
• Эффективность каждого конкретного человека по отдельности ≠ эффективность команды
• Если проблемы со всеми людьми одновременно, то скорее всего проблемы не с людьми)
—
Еще на первом занятии упоминалось, что задача рук-ля отдела — строить систему, и в целом курс действительно направлен на то, чтобы абстрагироваться от решения локальных проблем, и решать их на уровне всей системы
Поэтому я думаю, обучение точно будет полезно:
• тимлидам, у которых начала разрастаться команда, и "уследить за всеми" уже стало как-то нереально
• M2 руководителям, которые не понимают, что происходит
Если у вас только-только появилась команда, то скорее всего будет полезнее тимлидское обучение
Подробности про обучение писал в постах
• раз
• два
• три
• четыре
• пять
Если интересно пообщаться лично и поспрашивать подробности, можно писать в личку, всем отвечу!
Я уже как ~месяц назад закончил обучение в Стратоплане на руководителя отдела https://stratoplan-school.com/head/
Обучение весьма удачно совпало с новой зоной ответственностью на работе, поэтому многое удалось попробовать на практике. Если меня попросить топ выводов/мыслей, в которых убедился на собственном опыте, я бы ответил так:
• Не хочешь внезапных разочарований (в т.ч. от себя) — явно проговаривай ожидания
• Регулярное обеспечение прозрачности таки действительно рождает доверие (как и наоборот)
• Эффективность каждого конкретного человека по отдельности ≠ эффективность команды
• Если проблемы со всеми людьми одновременно, то скорее всего проблемы не с людьми)
—
Еще на первом занятии упоминалось, что задача рук-ля отдела — строить систему, и в целом курс действительно направлен на то, чтобы абстрагироваться от решения локальных проблем, и решать их на уровне всей системы
Поэтому я думаю, обучение точно будет полезно:
• тимлидам, у которых начала разрастаться команда, и "уследить за всеми" уже стало как-то нереально
• M2 руководителям, которые не понимают, что происходит
Если у вас только-только появилась команда, то скорее всего будет полезнее тимлидское обучение
Подробности про обучение писал в постах
• раз
• два
• три
• четыре
• пять
Если интересно пообщаться лично и поспрашивать подробности, можно писать в личку, всем отвечу!
stratoplan-school
Руководитель отдела. Управление подразделениями без компромиссов
Фундаментальная трансформация. Глубокое погружение, формирование управленческого стиля и интеграция AI в каждый процесс.
1🔥33👍24
Какой у вас Cycle Time в команде?
Время от взятия в работу до выкатки в прод типичной продуктовой задачи
Время от взятия в работу до выкатки в прод типичной продуктовой задачи
Anonymous Poll
3%
< 1 дня
12%
1-3 дней
19%
4-6 дней
34%
7-14 дней
32%
14+ дней
yet another random thought
Внезапное место, где хорошо раскрылись принципы функционального программирования — LLM агенты
Агенты в большинстве своем устроены так:
• LLM — функция без сайд эффектов (string -> string)
• Все сайд-эффекты инкапсулированы в тулах
• LLM сама ничего не вызывает. А просто возвращает агенту, какие тулы нужно вызвать
А это и есть реализация паттерна
• functional core (LLM)
• imperative shell (Агент)
И в целом никто не запрещает перенять эти принципы для продакшн кода. Чистая бизнес логика — это супер-простое юнит тестирование и простота поддержки
Внезапное место, где хорошо раскрылись принципы функционального программирования — LLM агенты
Агенты в большинстве своем устроены так:
• LLM — функция без сайд эффектов (string -> string)
• Все сайд-эффекты инкапсулированы в тулах
• LLM сама ничего не вызывает. А просто возвращает агенту, какие тулы нужно вызвать
А это и есть реализация паттерна
• functional core (LLM)
• imperative shell (Агент)
И в целом никто не запрещает перенять эти принципы для продакшн кода. Чистая бизнес логика — это супер-простое юнит тестирование и простота поддержки
💅28👍18✍3 2🙏1
Хотел написать пост не про эйай но получилось как обычно
Обзор на книжечку Agentic design patterns, которая оказалась скачана на телефон во время 8ми часового полета
Несмотря на многословность и не очень прикрытую рекламу гугловых инструментов (книга от инженера из гугла), она дает хорошее понимание, как из ллмки - функции, которая просто предсказывает следующий токен, набором инженерных решений получаются крутые инструменты типа claude code
Рассказываются основные паттерны, которые устоялись за последние пару лет разработки агентских систем
Базовые:
• prompt chaining — пайплайн из вызова ллмок, где результаты передаются по цепочке
• rouing — ллмка решает, куда дальше идти в воркфлоу
• parallelization — кусочки, которые можно распаралеллить, параллелим. Например, сбор данных из разных систем
• reflection — первая ллмка отвечает, вторая оценивает ответ, дает фидбек первой, первая корректирует ответ
• planning — вместо "реши сложную задачу" сначала просим ллмку сформулировать план. Далее выполняем набор более простых задачек
• reasoning techniques — chain-of-thoughts, tree-of-thoughts, ReAct и несколько других
Как достучаться до внешнего мира:
• tool use — обычный тул колинг: ллмке даются спеки тулов, а она отвечает, что и с какими аргументами нужно вызвать для продолжения работы
• mcp — простой небольшой рассказ что это, что такое mcp client, mcp server
• rag — ретривим релевантную информацию из базы знаний перед ответом
Память:
• memory management — про short term memory (на уровне одного чата) и long term memory (глобальная память)
• learning and adaptations — прикольная глава про то, как сделать так, чтобы агент автономно (или полуавтономно) обучался и не повторял тех же ошибок
Как не допустить говна:
• exception handling and recovery — просто глава-напоминание о том, что внешние системы могут лежать/агент можно не справляться с задачей, и это надо как-то уметь обрабатывать
• human in the loop — зовем человека, когда делаем рисковое действие
• guardrails — ллмке как на вход, так и на выход поступает примерно что угодно, поэтому хорошо бы добавлять явные проверки/валидации, что запрос/ответ приемлем
Системы из нескольких агентов:
• multi-agent — есть несколько агентов, заточенных под свои узкие области, которые друг другу дают задачи. Зачастую есть отдельный агент-оркестратор
• A2A — гугловый протокол взаимодействия между агентами в распределенных системах
Всякое разное около самих агентов:
• evaluation and monitoring — какие есть способы мониторить агентов и их качество
Примеров оч много (даже слишком), поэтому читается легко
7/10
Обзор на книжечку Agentic design patterns, которая оказалась скачана на телефон во время 8ми часового полета
Несмотря на многословность и не очень прикрытую рекламу гугловых инструментов (книга от инженера из гугла), она дает хорошее понимание, как из ллмки - функции, которая просто предсказывает следующий токен, набором инженерных решений получаются крутые инструменты типа claude code
Рассказываются основные паттерны, которые устоялись за последние пару лет разработки агентских систем
Базовые:
• prompt chaining — пайплайн из вызова ллмок, где результаты передаются по цепочке
• rouing — ллмка решает, куда дальше идти в воркфлоу
• parallelization — кусочки, которые можно распаралеллить, параллелим. Например, сбор данных из разных систем
• reflection — первая ллмка отвечает, вторая оценивает ответ, дает фидбек первой, первая корректирует ответ
• planning — вместо "реши сложную задачу" сначала просим ллмку сформулировать план. Далее выполняем набор более простых задачек
• reasoning techniques — chain-of-thoughts, tree-of-thoughts, ReAct и несколько других
Как достучаться до внешнего мира:
• tool use — обычный тул колинг: ллмке даются спеки тулов, а она отвечает, что и с какими аргументами нужно вызвать для продолжения работы
• mcp — простой небольшой рассказ что это, что такое mcp client, mcp server
• rag — ретривим релевантную информацию из базы знаний перед ответом
Память:
• memory management — про short term memory (на уровне одного чата) и long term memory (глобальная память)
• learning and adaptations — прикольная глава про то, как сделать так, чтобы агент автономно (или полуавтономно) обучался и не повторял тех же ошибок
Как не допустить говна:
• exception handling and recovery — просто глава-напоминание о том, что внешние системы могут лежать/агент можно не справляться с задачей, и это надо как-то уметь обрабатывать
• human in the loop — зовем человека, когда делаем рисковое действие
• guardrails — ллмке как на вход, так и на выход поступает примерно что угодно, поэтому хорошо бы добавлять явные проверки/валидации, что запрос/ответ приемлем
Системы из нескольких агентов:
• multi-agent — есть несколько агентов, заточенных под свои узкие области, которые друг другу дают задачи. Зачастую есть отдельный агент-оркестратор
• A2A — гугловый протокол взаимодействия между агентами в распределенных системах
Всякое разное около самих агентов:
• evaluation and monitoring — какие есть способы мониторить агентов и их качество
Примеров оч много (даже слишком), поэтому читается легко
7/10
🔥36😁3👍2💅2
Хочешь долгого выполнения задач — нагрузи всех подзавязку
В теории массового обслуживания есть очень простая и удобная модель M/M/1:
Есть бесконечный поток задач, один узел обслуживания и очередь перед ним
Где:
• поток задач описывается Пуассоновским процессом
• время обслуживания описывается экспоненциальным распределением
Интересно вот что: если взять
• λ — скорость прихода задач
• μ — скорость обработки
• ρ = λ / μ — утилизация
• W — среднее время в системе
То получается, что
• W = 1 / (μ - λ)
(proof)
И если переписать через утилизацию:
• W = 1 / μ(1 - ρ)
То есть среднее время нахождения задачи в системе растет гиперболически относительно утилизации. Возьмем простой пример: μ = 1 задача / день
И по формуле выше получаем такое среднее время нахождения задачи в системе W:
Такое происходит из-за того, что задачи поступают в систему неравномерно. Поэтому если обработчик загружен под 100%, то любая неравномерность приводит к скоплению очереди, и как следствие, взрыву времени ожидания
Например, при переходе 95% -> 99% утилизация выросла всего на 4п.п., при этом среднее время ожидания скакнуло с 20 дней до 100 дней
На произвольные распределения этот эффект обобщается формулой Кингмана
—
Какой из этого можно сделать практичный вывод? Не хочешь внезапных задержек — оставляй исполнителям задач некоторый запас капасити
Например, разработчик загружен на 100%, он сидит, работает себе, а потом ему прилетают 3 пулреквеста на ревью. И 3 задачи встанут, потому что у разработчика нет капасити на то, чтобы их поревьюить. Ну и в такой ситуации обычно начинают браться в работу новые задачи, начинает раздуваться WIP, и проявляться прочие спецэффекты, описанные в этом посте
В теории массового обслуживания есть очень простая и удобная модель M/M/1:
Есть бесконечный поток задач, один узел обслуживания и очередь перед ним
поток задач -> очередь -> узел обслуживания
Где:
• поток задач описывается Пуассоновским процессом
• время обслуживания описывается экспоненциальным распределением
Интересно вот что: если взять
• λ — скорость прихода задач
• μ — скорость обработки
• ρ = λ / μ — утилизация
• W — среднее время в системе
То получается, что
• W = 1 / (μ - λ)
(proof)
И если переписать через утилизацию:
• W = 1 / μ(1 - ρ)
То есть среднее время нахождения задачи в системе растет гиперболически относительно утилизации. Возьмем простой пример: μ = 1 задача / день
И по формуле выше получаем такое среднее время нахождения задачи в системе W:
50% utilization -> 2 дня
80% utilization -> 5 дней
90% utilization -> 10 дней
95% utilization -> 20 дней
99% utilization -> 100 дней
Такое происходит из-за того, что задачи поступают в систему неравномерно. Поэтому если обработчик загружен под 100%, то любая неравномерность приводит к скоплению очереди, и как следствие, взрыву времени ожидания
Например, при переходе 95% -> 99% утилизация выросла всего на 4п.п., при этом среднее время ожидания скакнуло с 20 дней до 100 дней
На произвольные распределения этот эффект обобщается формулой Кингмана
—
Какой из этого можно сделать практичный вывод? Не хочешь внезапных задержек — оставляй исполнителям задач некоторый запас капасити
Например, разработчик загружен на 100%, он сидит, работает себе, а потом ему прилетают 3 пулреквеста на ревью. И 3 задачи встанут, потому что у разработчика нет капасити на то, чтобы их поревьюить. Ну и в такой ситуации обычно начинают браться в работу новые задачи, начинает раздуваться WIP, и проявляться прочие спецэффекты, описанные в этом посте
👍59😁3🤔2
Как сделать карьерный рост чуть приятнее
Чем выше роль, тем меньше работа про сами задачи и тем больше — про людей. Всегда кто-то что-то требует, кто-то не согласен, кто-то аккуратно тянет одеяло на себя. Кто-то заходит в разговор так, что выходишь после него с ощущением, будто из тебя высосали всю энергию
Но, на самом деле, в таких сложных разговорах у разных людей одни и те же паттерны — тебя уводят от сути разговора, тебя пытаются ставить в оправдывающуюся позицию, разговор о предмете обсуждения подменяется разговором о личности и так далее
Нормально это осознать помог курс от ребят из SSL, который я проходил аж в 2024 (и до сих пор считаю одним из лучших вложений)
Один из тренеров курса — Миша Ромашов, который параллельно преподает переговоры в ВШЭ и лидит одно из направлений в Сбере. Миша ведет свой тг канал, где рассказывает интересные кейсы из практики:
• Про эмоции
• Про чужую картину мира
• Про конфликты без права сепарации
Если у вас в работе много сложных коммуникаций — рекомендую
Чем выше роль, тем меньше работа про сами задачи и тем больше — про людей. Всегда кто-то что-то требует, кто-то не согласен, кто-то аккуратно тянет одеяло на себя. Кто-то заходит в разговор так, что выходишь после него с ощущением, будто из тебя высосали всю энергию
Но, на самом деле, в таких сложных разговорах у разных людей одни и те же паттерны — тебя уводят от сути разговора, тебя пытаются ставить в оправдывающуюся позицию, разговор о предмете обсуждения подменяется разговором о личности и так далее
Нормально это осознать помог курс от ребят из SSL, который я проходил аж в 2024 (и до сих пор считаю одним из лучших вложений)
Один из тренеров курса — Миша Ромашов, который параллельно преподает переговоры в ВШЭ и лидит одно из направлений в Сбере. Миша ведет свой тг канал, где рассказывает интересные кейсы из практики:
• Про эмоции
• Про чужую картину мира
• Про конфликты без права сепарации
Если у вас в работе много сложных коммуникаций — рекомендую
Telegram
Осознанные коммуникации | Ромашов Михаил
Канал про осознанную коммуникацию от тренера по переговорам Soft Skills Lab, преподавателя НИУ ВШЭ и Сколково на программе MOOVE.
👉🏻 По вопросам: @Mikhail_Romashov
👉🏻 Клуб по переговорам: @sslpractice
👉🏻 По вопросам: @Mikhail_Romashov
👉🏻 Клуб по переговорам: @sslpractice
💅9😁5👍2
Разработка фичей без достаточной экспертизы в системе зачастую превращается в набор "локально-оптимальных" решений: здесь добавили ифчик, здесь протянули новую зависимость, здесь скопипастили похожий код, здесь обошли существующую точку расширения
Каждое такое решение обычно выглядит норм в моменте — оно закрывает задачу, проходит тесты, не выглядит совсем плохо на ревью
Проблема начинается, когда такие решения последовательно наслаиваются друг на друга. Это приводит к architecture drift: фактическая архитектура системы постепенно отклоняется от той, которая была задумана
С агентской разработкой принципы те же — если у агента нет достаточного контекста о системе, он будет стараться делать минимальные локальные изменения, которые приведут к решению задачи. Только с агентами это все происходит быстрее
Главная проблема в том, что самая полезная архитектурная экспертиза обычно живет не в документации, а в головах людей, которые годами работали с системой. Они держат огромный набор фактов о том, почему сделано так, как это развивать, как точно делать не надо и т.д.
И честно говоря, я пока не видел чтобы такая экспертиза была в достаточной степени оцифрована — всегда остается много вещей, которые живут только в чьей-то голове. В таком сетапе агенты всегда будут медленно тянуть архитектуру куда-то в сторону (зачастую не самую хорошую)
А как вы боретесь с этим явлением?
Каждое такое решение обычно выглядит норм в моменте — оно закрывает задачу, проходит тесты, не выглядит совсем плохо на ревью
Проблема начинается, когда такие решения последовательно наслаиваются друг на друга. Это приводит к architecture drift: фактическая архитектура системы постепенно отклоняется от той, которая была задумана
С агентской разработкой принципы те же — если у агента нет достаточного контекста о системе, он будет стараться делать минимальные локальные изменения, которые приведут к решению задачи. Только с агентами это все происходит быстрее
Главная проблема в том, что самая полезная архитектурная экспертиза обычно живет не в документации, а в головах людей, которые годами работали с системой. Они держат огромный набор фактов о том, почему сделано так, как это развивать, как точно делать не надо и т.д.
И честно говоря, я пока не видел чтобы такая экспертиза была в достаточной степени оцифрована — всегда остается много вещей, которые живут только в чьей-то голове. В таком сетапе агенты всегда будут медленно тянуть архитектуру куда-то в сторону (зачастую не самую хорошую)
А как вы боретесь с этим явлением?
👍36💅2
Очень грубо инженеров можно классифицировать на два типа:
1. Те, кто работает с техническими проблемами проактивно:
• Увидел плавное повышение cpu usage на БД => раздебажил из-за чего, добавил нужных индексов, предотвратил инцидент
• Увидел, что новая функциональность в модуль добавляется очень странным образом => инициировал и довел до конца рефакторинг, благодаря этому крупный проект сошелся в срок
• Сделал удобные алерты, что позволило видеть проблему раньше пользователей и предотвращать инциденты
2. Те, кто работает с техническими проблемами реактивно:
• TTM фичей вырос в два раза, постоянные баги => только тогда начинаем рефакторинг
• Количество инцидентов стало совсем неприемлемым => только тогда инициируем проект по стабилизации
(да, не существует чистых типов 1 и 2, это всегда спектр, и всегда нужно уметь работать в обоих режимах)
Но в чем неприятный парадокс — признание за технический вклад в основном получают люди, работающие во втором режиме
Почему так происходит? Потому что для наблюдателей есть прозрачная логическая цепочка: что-то сломалось, конкретный человек это починил, он молодец
Если же чинить проблемы проактивно, то со стороны может показаться, мол ничего особенного, все так и должно работать — фичи делаются быстро, система работает стабильно
Поэтому очень важно для всех опрозрачивать эту логическую цепочку: "что бы произошло, если бы мы не сделали эту техническую доработку". Да, это сложно. Но оно того стоит
Хороший руководитель безумно ценит людей, которые самостоятельно предупреждают проблемы. И задача руководителя — помочь опрозрачить такой вклад сотрудника для остальных
1. Те, кто работает с техническими проблемами проактивно:
• Увидел плавное повышение cpu usage на БД => раздебажил из-за чего, добавил нужных индексов, предотвратил инцидент
• Увидел, что новая функциональность в модуль добавляется очень странным образом => инициировал и довел до конца рефакторинг, благодаря этому крупный проект сошелся в срок
• Сделал удобные алерты, что позволило видеть проблему раньше пользователей и предотвращать инциденты
2. Те, кто работает с техническими проблемами реактивно:
• TTM фичей вырос в два раза, постоянные баги => только тогда начинаем рефакторинг
• Количество инцидентов стало совсем неприемлемым => только тогда инициируем проект по стабилизации
(да, не существует чистых типов 1 и 2, это всегда спектр, и всегда нужно уметь работать в обоих режимах)
Но в чем неприятный парадокс — признание за технический вклад в основном получают люди, работающие во втором режиме
Почему так происходит? Потому что для наблюдателей есть прозрачная логическая цепочка: что-то сломалось, конкретный человек это починил, он молодец
Если же чинить проблемы проактивно, то со стороны может показаться, мол ничего особенного, все так и должно работать — фичи делаются быстро, система работает стабильно
Поэтому очень важно для всех опрозрачивать эту логическую цепочку: "что бы произошло, если бы мы не сделали эту техническую доработку". Да, это сложно. Но оно того стоит
Хороший руководитель безумно ценит людей, которые самостоятельно предупреждают проблемы. И задача руководителя — помочь опрозрачить такой вклад сотрудника для остальных
👍85🔥12🤔5