惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hugging Face - Blog
Hugging Face - Blog
D
DataBreaches.Net
A
About on SuperTechFans
D
Docker
腾讯CDC
Google DeepMind News
Google DeepMind News
Hacker News - Newest:
Hacker News - Newest: "LLM"
W
WeLiveSecurity
Forbes - Security
Forbes - Security
S
Security @ Cisco Blogs
V
Vulnerabilities – Threatpost
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
I
InfoQ
P
Privacy International News Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Application and Cybersecurity Blog
Application and Cybersecurity Blog
aimingoo的专栏
aimingoo的专栏
C
Cyber Attacks, Cyber Crime and Cyber Security
S
Secure Thoughts
Stack Overflow Blog
Stack Overflow Blog
T
Tenable Blog
T
Threatpost
P
Proofpoint News Feed
博客园 - 司徒正美
Microsoft Security Blog
Microsoft Security Blog
N
News and Events Feed by Topic
Apple Machine Learning Research
Apple Machine Learning Research
云风的 BLOG
云风的 BLOG
GbyAI
GbyAI
Hacker News: Ask HN
Hacker News: Ask HN
B
Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Microsoft Azure Blog
Microsoft Azure Blog
F
Fortinet All Blogs
Project Zero
Project Zero
Help Net Security
Help Net Security
WordPress大学
WordPress大学
F
Full Disclosure
博客园 - 三生石上(FineUI控件)
O
OpenAI News
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
H
Heimdal Security Blog
Security Latest
Security Latest
T
Tor Project blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
Cisco Talos Blog
Cisco Talos Blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Система авто-оценки качества вебинаров на Claude Code за неделю
Дмитрий Волошин · 2026-06-22 · via Все публикации подряд на Хабре

Средний

15 мин

3

TL;DR

  • Методисты вручную пересматривали вебинары - не масштабируется. Собрал конвейер: видео → локальная расшифровка (whisper.cpp на Apple M4) → LLM-судья по рубрике с цитатами → SQLite → письмо и дашборд. Боевое ядро заработало примерно за неделю.

  • Главное в LLM-судье - не промпт, а методика: рубрика как данные (YAML, который правят методисты), калибровка под живых экспертов и честность про пределы текста.

  • Claude Code тут - быстрый дисциплинированный джун: ускоряет «как написать» в разы, но надежность, идемпотентность и гардрейлы надо прямо навязывать.

  • Самый полезный результат - отрицательный: эксперимент с локальной заменой судьи закрыл за вечер вопрос, на который иначе ушли бы недели.

Это моя четвертая статья про работу с Claude Code на боевых проектах - после темпераментного джуна, документационного долга и сквозной аналитики. И снова она не про «ИИ все написал сам», а про то, как из агента вытащить поддерживаемый прод. Объектом автоматизации в этот раз выступает моя компания - Otus.ru.

Задача: почему «спроси GPT, хорош ли вебинар» не работает

В моей школе сотни технических вебинаров в неделю: Java, Linux, DDD, сети, базы данных. Длина - около двух часов, четверть времени - разбор домашних заданий. Качество этих занятий кто-то должен оценивать: соответствует ли методике, держит ли структуру, понятно ли объясняет, доводит ли до итогов. Делают это методисты - вручную, пересматривая записи. Это очень плохо масштабируется: методистов мало, занятий много, и оценка получается неравномерной (устал, отвлекся, у разных людей разная планка).

Очевидное решение - «прогнать через LLM» - разваливается на первом же шаге, как только начинаешь относиться к задаче серьезно:

  • Нужна не оценка «нравится / не нравится», а структурированный вердикт по рубрике. Методисты смотрят занятие по конкретным критериям в конкретном порядке. Балл «7 из 10» без разбивки бесполезен - его нельзя оспорить, нельзя улучшить, нельзя свести в динамику.

  • Нужны доказательства. Оценщику не верят на слово - ни человеку, ни модели. На каждый балл нужна цитата из занятия с тайм-кодом: «вот здесь преподаватель поставил цель», «вот здесь увел в сторону на 20 минут». Без привязки к доказательной базе LLM-судья - это генератор правдоподобных, но непроверяемых приговоров.

  • Нужна калибровка под живых оценщиков. Система ценна ровно настолько, насколько ее баллы совпадают с тем, как поставил бы методист. Иначе это просто еще одно мнение, которому никто не доверяет.

  • Контур данных. В записях - персональные данные (голоса, имена, иногда лица). По требованиям их нельзя гонять через внешние сервисы за пределами РФ. Это сразу режет половину «удобных» вариантов и определяет архитектуру.

  • Источник скуп. Платформа, где лежат видео, отдает только сам файл: ни готовой расшифровки, ни чата, ни таймингов. То есть все, что нужно для оценки, придется добывать самому.

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

Как это было устроено: один инженер и агент

Я писал это в паре с Claude Code. Чтобы из этой пары вышел поддерживаемый прод, а не гора сгенерированного кода, я с самого начала навязал несколько правил.

  • Спецификация и документы - раньше кода. Каждый кусок начинался с того, что мы фиксировали задачу, ограничения и критерии приемки текстом. Агент неплохо пишет код, но плохо угадывает намерение - поэтому намерение надо записать.

  • Работа спринтами с журналом решений. Каждое архитектурное решение - отдельная запись с обоснованием и сквозным номером, на который потом можно сослаться. Отложенное - в бэклог явным пунктом, а не «потом разберемся». Это звучит как бюрократия, но именно это не дает агенту (и мне) забыть, почему месяц назад мы сделали вот так.

  • Жесткие правила как гардрейлы. Часть решений я зашил как нерушимые: запросы к боевой базе - только на чтение, ограниченно, с оценкой тяжести и моим согласованием; любое изменение оценочной логики - отдельно и с пересудом (повторным прогоном судьи по уже оцененным занятиям - дальше объясню, почему это дорого); содержимое занятий не уходит из контура.

  • Definition of Done с демо-доказательством. Спринт закрыт не когда агент написал «готово», а когда есть запуск/запрос/экран, показывающий данные. «Готово» без доказательства не принимается - это сняло целый класс галлюцинаций вида «я добавил обработку, все работает» (нет, не работает).

  • Ревизия. Если решение оказалось неверным, мы не переписываем его задним числом, а дописываем постскриптум: «тогда думали так, по факту вышло иначе». История ошибок ценна тем, что к ней возвращаешься, когда наступаешь на те же грабли.

Дальше пару слов и картинка про проект, а еще про работу правил: где агент хотел сделать лажу, где правило заставило его остановиться и согласовать, где мы измерили и оказалось что все не так.

Пайплайн: от видео до оценки

Сквозная схема получилась такой:

видеоплатформа (только файл)
   │  скачать
   ▼
whisper.cpp на Apple M4         ← расшифровка локально, в контуре, бесплатно
   │  сегменты с тайм-кодами
   ▼
обогащение из БД школы          ← курс / преподаватель / методист / программа (только чтение)
   │
   ▼
LLM-судья (РФ-контур)           ← покритериальная оценка + цитаты-доказательства
   │
   ▼
SQLite (расшифровки, версии методики, покритериальные баллы)
   │
   ├──► письмо-сводка методистам
   └──► статический дашборд (по методисту, динамика, экран занятия)

Несколько решений тут осознанные, а не «так получилось».

  • Расшифровка - локально, на Apple M4, через whisper.cpp. Это и про контур (данные не покидают машину - как и хотелось по ПДн), и про деньги (бесплатно), и про скорость: на M4 получается около 20-кратной скорости относительно реального времени, то есть двухчасовое занятие расшифровывается за несколько минут, а за ночь машина перемалывает порядка сотни занятий. Облачное распознавание было бы и платным, и вне контура, поэтому не рассматривалось всерьез.

  • Хранилище - SQLite, не «сразу PostgreSQL на проде». На старте важнее было гонять итерации, а не настраивать инфраструктуру. Схема при этом сразу спроектирована так, чтобы переезд на PostgreSQL был механическим - сменить драйвер и строку подключения, а не переписывать схему и запросы. Это типичный случай, где агент по умолчанию тянет «давай сразу по-взрослому», а правильный ход - сознательно начать с простого.

  • Дашборд - статика. Генератор превращает базу в один JSON-бандл, фронт - ванильный JS, который считает срезы на клиенте. Никакого бэкенда под дашборд: меньше движущихся частей, проще деплой, нечему падать ночью.

Стоит отдельно сказать, как сильно всю архитектуру продиктовал контур данных - это куда конкретнее, чем «ПДн нельзя наружу». Он сделал расшифровку локальной (часовое видео с голосами людей в облако не отправить, значит whisper на своей машине) и сузил выбор судьи до того, что доступно в контуре, а не лучшего на рынке. Качество судьи я выбирал из «лучшего из разрешенного», и это нормально: требования бывают важнее бенчмарков.

Как вообще измерить «качество занятия»: методика и пределы текста

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

Критерии берутся из того, как люди реально смотрят

Мы не выдумывали критерии из головы. Мы сняли их с того, как методист реально смотрит запись: сначала открытие (поздоровался, обозначил тему), потом постановка цели, потом раскрытие материала, понятность, баланс теории и практики, вовлечение аудитории, итоги, разбор домашнего задания. Это превратилось в рубрику - настроечный YAML, который методисты правят без меня и без кода:

criteria:
  - key: goal
    title: Постановка цели занятия
    weight: 1.0
    levels:
      1: Цель не обозначена, занятие начинается с материала
      3: Цель названа формально, без связи с пользой для слушателя
      5: Цель ясна, привязана к результату, к ней возвращаются в итогах
  - key: duration
    title: Длительность
    type: metric          # считается из чисел, без модели
    bands: { good: [105, 135], warn_short: 90, warn_long: 150 }

Тут два важных момента сразу. Во-первых, методика - данные, а не код: чтобы поменять формулировку критерия или вес, не нужен разработчик и деплой. Во-вторых, не все критерии отдаются модели - длительность это число, ее считает код по полосам, а не «как думает LLM». Знать, что считать детерминированно, а что отдавать модели - половина зрелости такой системы.

Калибровка - это спор с экспертом

Методика прошла несколько версий, и каждое изменение - не «улучшили промпт», а правка с причиной от методистов. Несколько примеров, которые хорошо показывают, насколько неочевидна задача:

  • Убрали «опоздание». Изначально был критерий «преподаватель не опоздал». Оказалось, запись комнаты часто включают до начала занятия - и «тишина в начале» означает не опоздание, а ранний старт (это, наоборот, хорошо). По записи опоздание корректно не определить в принципе. Критерий убрали, время до первой речи перестали трактовать как опоздание.

  • «Презентация ДЗ» - только там, где ДЗ выдают. Домашнее задание презентуется примерно в четверти занятий (у тех, после которых его дают). Вешать этот критерий на все занятия - значит штрафовать лекцию за отсутствие того, чего там и не должно быть. Критерий стал условным - появляется только при метке «ДЗ».

  • Длительность: сначала ввели, потом убрали из штрафа. Логично было подсветить «слишком короткое / слишком длинное». Но заказчик пояснил: большинство занятий и так около двух часов, это норма, а не повод снижать балл. Зашитую метрику оставили как информационную, но из оценки убрали. Это решение я зафиксировал, а потом, когда методика для другого потока потребовала вернуть длительность баллом, дописал постскриптум со ссылкой на старое решение - чтобы было видно, что мы не «передумали молча», а развернули осознанно.

Смысл вместо маркеров

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

Лечится это не одним приемом, а связкой: подробные описания уровней в рубрике (что значит балл 1, 3, 5 на конкретных примерах), явные негативные примеры в промпте («формальное упоминание темы - это не постановка цели»), и калибровка на спорных занятиях вместе с методистами. Это самая «ручная» часть всей работы и единственная, где агент почти не помогает: он отлично перебирает формулировки промпта, но решить, совпала ли оценка с методистом, может только человек, который посмотрел занятие. Здесь узкое место - не код и не модель, а доступ к экспертному суждению.

Важное: про пределы текста

Главный принцип, к которому мы пришли: не выдумывать метрики, которые сигнал не тянет. Расшифровка - это текст. Текст много чего не содержит, и притворяться, что содержит, - худшее, что можно сделать с доверием к системе.

  • «Работа с вопросами аудитории» - исключили, а не штрафуем. Вопросы идут в чате, которого источник не отдает. Штрафовать за то, что физически не можешь измерить, нечестно. Поэтому критерий помечен как «пропустить, если нет данных», а не «снизить балл».

  • «Энергия и уверенность» - убрали. По тексту расшифровки подачу и энергетику надежно не определить. Модель будет уверенно галлюцинировать тут оценку, и она будет шумом.

  • «Доля речи преподавателя» - убрали как фейковую метрику. Без диаризации (разделения голосов) мы не знаем, кто говорит. Считать «долю речи» по недиаризованной расшифровке - значит выводить красивое число из ничего. Такие метрики опаснее отсутствия метрики: они выглядят объективно и вводят в заблуждение.

И так далее. Почему этот раздел важен? Потому, что понять, чего твой сигнал не может, и не делать вид, что может, - путь к успеху внедрения. Когда баллы начали сходиться с методистскими, доверие появилось не от «магии ИИ», а от того, что система не отсуживала лишнего.

Дисциплина изменений: правка методики - это миграция

И последнее, чутка инженерное. Любая правка оценочной логики - это не «поменяли строчку». Это пересуд всего массива (деньги на повторные вызовы судьи) и сдвиг вердикта по всему проду (вчера занятие было «желтым», сегодня стало «красным» - и методист спросит, почему). Поэтому я зашил правило: изменение методики обязательно сопровождается снимком «до/после» на контрольной выборке занятий, а сами правки копятся в новую версию и применяются одним пересудом, а не по каждому замечанию отдельно. По сути я отношусь к методике как к схеме базы: менять можно, но это миграция, и она требует регрессии. Агенту это правило особенно полезно - без него он бодро «улучшал бы критерий» и молча перекраивал весь прод.

LLM как судья

Теперь, когда понятно, что мы измеряем, - как заставить модель измерять это надежно.

Судья - YandexGPT. Но провайдер тут вторичен; интереснее обвязка, которая превращает «болтливую модель» в воспроизводимый оценочный движок.

Контракт вывода - строгий JSON, который валидируется. Модель не пишет эссе. Она обязана вернуть по каждому критерию балл, обоснование и цитаты:

{
  "summary": "Четкая цель, сильная практика, но итоги скомканы",
  "criteria": [
    {
      "key": "goal",
      "score": 5,
      "rationale": "Цель названа на 2-й минуте и проверена в финале",
      "evidence": {
        "positive": [{ "quote": "сегодня научимся ловить дедлоки в проде" }],
        "negative": []
      }
    }
  ]
}

Ответ валидируется: те ли ключи, в той ли шкале баллы, есть ли обязательные поля. Не прошло - повтор. Это снимает классическую боль «модель вернула почти то, но не совсем».

Цитаты привязываются к тайм-кодам. Модель цитирует фрагмент, а отдельный шаг находит этот фрагмент в расшифровке по сегментам и проставляет время. В дашборде это превращается в кликабельное «за 12:30: „…“». Именно это делает оценку проверяемой: методист не верит баллу - он смотрит цитату и решает сам.

Тут есть неочевидная тонкость, на которой я споткнулся. Модель почти никогда не цитирует дословно. Она слегка перефразирует, меняет порядок слов, выкидывает «э-э» и повторы. Поэтому точный поиск подстроки в расшифровке проваливается на большинстве цитат, и тайм-код не находится. Пришлось делать нечеткое сопоставление: скользить по сегментам расшифровки и искать максимальное перекрытие по словам (по сути token-overlap), а не точное совпадение. Это подняло долю привязанных цитат с примерно половины до девяти из десяти. Мелкая на словах деталь, но без нее половина доказательств в дашборде была бы без тайм-кода, то есть наполовину бесполезна. Хороший пример того, как «модель вернула цитату» и «цитату удалось показать методисту в плеере» - две очень разные степени готовности.

Воспроизводимость - насколько ее дает облачный судья. Разнобой между прогонами убивает любой спор на «а у меня вышло иначе». Temperature я ставлю в 0 - это убирает основную долю разброса, и на практике два прогона одного занятия у меня сходились покритериально. Но строгого детерминизма облачный LLM не гарантирует в принципе (серверный батчинг, недетерминизм инференса): temperature 0 снижает разброс, а не обнуляет его. Поэтому воспроизводимость я не предполагаю, а проверяю - периодическим повтором контрольной выборки, а не верой в флаг.

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

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

На выходе - зоны 🔴 / 🟡 / 🟢 (красная / желтая / зеленая), покритериальная таблица и цитаты. Методист открывает занятие и видит не «6.8», а из чего это сложилось и где это в записи.

И тут важно замкнуть петлю - оценка ценна, только если ее кто-то использует. Вывод доходит до методиста двумя путями. Ночью уходит письмо-сводка: сколько занятий оценено, кто в красной зоне, у кого что просело - чтобы с утра было видно, куда смотреть в первую очередь. А дашборд - для разбора: выбираешь методиста, его занятия, динамику по неделям, проваливаешься в конкретное занятие с таблицей и цитатами в плеере. Смысл не в том, чтобы заменить методиста, а в том, чтобы он смотрел не вслепую, а адресно - туда, где система подсветила проблему, с готовыми тайм-кодами, а не перематывая запись. Настоящая метрика успеха тут не «точность модели», а сэкономленные часы живого человека и то, что ни одно слабое занятие не проходит мимо.

Что не взлетело

Самое ценное в любом таком проекте - не то, что заработало, а то, что нет. Здесь про грабли.

  • Петля-галлюцинация whisper. На одном занятии расшифровка выдала титр «Корректор А. Кулакова» несколько тысяч раз подряд - модель зациклилась на участке тишины. Лечится двумя вещами: отключением переноса контекста между окнами (флаг, который рвет петлю) и детектором речи (VAD), который вырезает не-речь и устраняет саму первопричину - модели не на чем залипать. До фикса начало занятия превращалось в «Редактор субтитров…», после - в реальную речь. Если строите расшифровку для продакшна - закладывайтесь на это сразу.

  • Асинхронный режим судьи оказался не дешевле. По документации асинхронный (батчевый) вызов LLM должен был выйти процентов на 50 дешевле синхронного - заманчиво для ночного прогона. Я зафиксировал решение «идем в async ради экономии». А потом свел фактический биллинг: эффективная ставка совпала в обоих режимах, экономии ноль. Вернулся на синхронный (быстрее, та же цена), async оставил опцией. Это ровно тот случай, под который и заводится честная ревизия: не стираешь старое решение, а дописываешь «по факту биллинга - не дешевле».

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

Мы с агентом поставили эксперимент прямо в процессе - честный, на том же классе железа (Apple M4, 16 ГБ). Конвейер тот же, менялся только LLM-вызов: вместо облачного судьи - локальная модель через ollama. Сравнивали покритериально с уже имеющимися оценками облачного судьи. Результат:

Что

Итог на 16 ГБ

Модель 14B

не влезает: вес + контекст уходят в своп (10+ ГБ), первый же урок упал на трэшинге

Модель 7B, скорость

~8 токенов/с → около 3.6 минуты на занятие

Модель 7B, согласие

overall-расхождение в среднем ~0.55 балла, зоны совпали 2 из 4

Модель 7B, смещение

в 3 из 4 случаев ставила выше облачного судьи (мягче)

Про выборку: это несколько десятков занятий, быстрый скрин, а не замер смещения. Но вывод однозначный. На 16 ГБ помещается только 7-8B; она и медленная (на историческом массиве это месяцы), и устойчиво расходится с откалиброванным под методистов судьей, причем в сторону завышения, то есть ломает ту самую калибровку, ради которой все и затевалось. На шкале с узкими полосами зон расхождение в полбалла регулярно переворачивает вердикт. Контур данных тут локалку не блокирует - наоборот, был бы за нее; уперлось в железо и качество модели.

Поэтому остаемся пока на облачном судье. А возврат к идее имеет смысл только при двух условиях сразу: больше памяти (чтобы крутить 14-32B) и дообучение/калибровка локальной модели на эталоне методистов. То есть отдельный проект с RAG по полной программе. Этот эксперимент занял несколько часов. Ради таких развилок и стоит уметь быстро ставить измеримые эксперименты - и тут пара с агентом особенно хороша: «подними локальную модель, прогони на 25 занятиях, сравни с облачным, сведи таблицу» - все же это вечер, а не спринт.

Дисциплина агента

Теперь про работу в паре с Claude Code на инфраструктуре, где цена ошибки выше, чем в коде.

  • Идемпотентность везде. Любой шаг можно запустить повторно без вреда: расшифровано - пропускаем, отсужено - пропускаем, выгружено - перезаписываем. Это не педантизм: ночной прогон может упасть на середине, и повтор не должен ни дублировать, ни тратить деньги судьи заново.

  • Деплой только с боевой машины. Дашборд собирается из локальной базы. Если запустить деплой с машины разработки, прод затрется бандлом из дев-данных. Это написано большими буквами и в коде, и в правилах - именно потому, что такую ошибку легко сделать «на автомате», и агент ее сделать тоже норовил.

  • Найденный баг с уборкой временных файлов. Хороший пример того, как «работает» не равно «работает надежно». Скачанное видео и промежуточный аудиофайл удалялись после расшифровки - но удаление стояло последней строкой блока, который при любой ошибке (сбой скачивания, конвертации, расшифровки) прерывался до этой строки. То есть успешные занятия чистились, а сбойные - оставались на диске, плюс копились логи. На сервере это тихо росло бы месяцами. Починили так, чтобы уборка срабатывала и при успехе, и при сбое, плюс финальное подметание осиротевших файлов. Мелочь, но именно из таких мелочей складывается разница между демо и продом - и именно их агент пропускает, если смотреть только в «проходит ли happy path».

  • Ревизия как культура. Постскриптумы оказались важнее, чем казалось. Когда работаешь быстро и в паре с агентом, решения накапливаются лавиной, и соблазн «причесать историю» огромен. Но именно лог ошибок (async не дешевле; нарезка занижала баллы; локальная модель не тянет) - самое ценное, что остается. К нему возвращаешься, когда через месяц рука сама тянется сделать ту же ошибку.

Цифры и итог

Что получилось в сухом остатке (и это, конечно, MVP):

  • Расшифровка: локально на Apple M4, около 20× реального времени, порядка сотни занятий за ночь, бесплатно, в контуре.

  • Оценка: покритериальная, с цитатами и тайм-кодами, стабильная между прогонами (temperature 0, с оговоркой про облачный недетерминизм выше), около 11-12 рублей на занятие по облачному судье.

  • Методика: настроечный YAML, который правят методисты; несколько версий, каждая правка - с обоснованием и пересудом; снимок до/после как регрессия.

  • Хранение и отчетность: SQLite (с заделом под PostgreSQL), статический дашборд, ночное письмо-сводка методистам.

  • Контур: содержимое занятий не покидает машину; к боевой базе - только чтение, ограниченно и с согласованием.

И главное по теме статьи: сквозной рабочий конвейер собрался примерно за неделю, потому что большую часть «механической» работы (обвязка, парсеры, генераторы, скрипты прогона) делал агент, а я тратил время на то, что агент делать не должен: решения, ограничения, согласования с методистами, оценку компромиссов. Это, кажется, и есть правильное разделение труда.

Выводы про agentic-разработку прод-систем

Несколько вещей, которые я для себя зафиксировал, и которые, возможно, пригодятся вам.

  • Agentic-кодинг силен там, где намерение уже ясно, а работа механическая. Написать парсер, обвязать API, собрать генератор, поставить эксперимент по четкому ТЗ - агент делает это в разы быстрее меня и почти без ошибок. Узкое место смещается с «написать» на «решить, что писать».

  • Надежность и необратимое - под присмотром. Идемпотентность, обратимость деплоя, уборку за собой, поведение при сбое агент по умолчанию не пишет - он выдает happy path. Все, что про «а если упало» и «а если запустили дважды», надо требовать явно и проверять отдельно.

  • Гардрейлы важнее подсказок. Самое полезное, что я сделал, - не лучшие промпты, а жесткие правила: к проду только на чтение и с согласованием; правка оценочной логики - с пересудом и регрессией; данные не покидают контур. Агент их соблюдал, потому что они записаны там, где он их видит, и спасали от целого класса дорогих ошибок.

  • Документируй решения и ошибки, не только код. Журнал решений и честные постскриптумы - не бюрократия, а память проекта, который движется слишком быстро, чтобы держать все в голове. Лог ошибок ценнее причесанного README.

  • И самое неожиданное - дисциплина измерять. Пара с агентом так дешево ставит эксперименты, что грех этим не пользоваться. Вопрос «а нельзя ли судью увести локально?» закрылся за вечер измеримым отрицательным результатом вместо месяца догадок. Если можете превратить спор в эксперимент - превращайте; с быстрым агентом порог входа в эксперимент почти исчезает.

Роль человека во всем этом не уменьшилась - она сместилась. Меньше «писать строчки», больше «решать, что строить, где остановиться, чему верить и что измерить». А это, по мне, куда более интересная работа.


Дмитрий Волошин, сооснователь и генеральный директор OTUS, основатель Клуба менторов, основатель Школы бизнеса Ninox. Заметки про управление, найм и фаундерский опыт: t.me/coffee_notes