● HABR WEEKLY DIGEST · AI / AGENTS / LLM

AI-статьи недели с Хабра

Разборы, рецепты и инструменты по LLM и агентам, которые можно применить: о чём статья — что главное — что попробовать за вечер.

🗓 окно 2026-08-17 — 2026-08-24 ⚡ статей: 10 👀 на заметку: 4 📡 отсканировано: 343
📝 О чём пишут на этой неделе

Три самых прикладных текста недели — про свой контур: шлюз LiteLLM на арендованном VPS, локальный агент на Ollama и личная рабочая система из markdown-файлов, которую агент собирает по готовому промпту. Второй сквозной сюжет — измерения, и он неожиданно объединяет очень разные статьи. RAG врёт уверенно, и поймать это можно только на размеченном наборе вопросов; кэш префикса может вообще не работать, пока не посмотришь разбивку по типам токенов; MMLU может «не расти» из-за формы замера, а не из-за данных. Формулировка из прод-кейса про свой инференс подходит ко всей неделе: диагностика стоит дешевле любой оптимизации и должна идти раньше неё.

Главные статьи недели

01

Свой LLM-шлюз на VPS: один адрес, виртуальные ключи и видимый счёт за токены

✍ Алексей Яковенко Хабр ⏱ ≈37 мин Искусственный интеллект DevOps llm
О чём

Туториал на вечер: как поднять на зарубежном VPS собственный OpenAI-совместимый endpoint. Контур состоит из двух половин — LiteLLM управляет официальными API-ключами, OmniRoute подключает подписочную авторизацию ChatGPT и Claude. Вторая половина требует платной подписки, а вот слой LiteLLM отделяется и собирается сам по себе: приложения перестают знать ключи провайдеров, а расход становится виден по каждому проекту. Переключение клиента показано на curl и конфигах CLI-агентов, примера на SDK в статье нет.

🔑 Главное
  • LiteLLM Proxy встаёт между приложением и провайдерами: приложение шлёт обычный OpenAI-совместимый запрос на https://свой-домен/v1, а маршрут, ключ и модель выбирает шлюз. Имя модели можно сделать своим алиасом вроде main-coder и позже подменить модель за ним, не трогая код клиентов.
  • Docker-compose из статьи поднимает два контейнера: ghcr.io/berriai/litellm:main-stable с портом 127.0.0.1:4000:4000 и healthcheck на /health/liveliness, плюс postgres:16-alpine с проверкой через pg_isready. Наружу порт не торчит — к нему ходит только nginx.
  • В nginx обязательны proxy_buffering off и proxy_read_timeout 3600s. Без первого nginx копит куски потокового ответа вместо того, чтобы сразу отдавать их клиенту.
  • LITELLM_SALT_KEY нельзя менять после добавления моделей: им шифруются учётные данные провайдеров в базе, и после замены сохранённые токены перестанут расшифровываться.
  • Виртуальный ключ выпускается в веб-интерфейсе с ограничением по модели, бюджетом и сроком действия. После первого же запроса в разделе Usage появляются модель, число токенов, задержка и стоимость.
  • Автор сам очерчивает границу схемы: подписка через OmniRoute не превращается в официальный API-ключ, лимиты и правила провайдера остаются в силе, а для публичного прода нужны официальные ключи.
⚡ Попробовать за вечер
  • Собрать только слой LiteLLM: docker compose up -d с образом ghcr.io/berriai/litellm:main-stable и postgres:16-alpine, спрятать порт 4000 за nginx с proxy_buffering off и выпустить сертификат командой certbot --nginx.
  • В разделе Models → Add Model подключить один свой ключ провайдера, дать модели короткий публичный алиас и выпустить под него виртуальный ключ с бюджетом.
  • Перевести одно своё приложение с прямого ключа провайдера на адрес шлюза и этот алиас.
  • Метрика: приложение больше не хранит ключ провайдера, а в разделе Usage по вашему виртуальному ключу видны модель, токены, задержка и стоимость каждого запроса.
Раздел Usage в веб-интерфейсе LiteLLM: трата по виртуальным ключам, имена моделей и разбивка по провайдеру из статьи
На картинке: раздел Usage после первых запросов — трата по виртуальным ключам, публичные имена моделей и разбивка по провайдеру: 4 успешных запроса, 317 токенов через openai.
02

Локальный агент на своей GPU: где Ollama молча возвращает пустой ответ

✍ Станислав Погоржельский Хабр ⏱ ≈33 мин Искусственный интеллект ollama llm inference
О чём

Разбор одного вечера, за который автор поймал двенадцать ошибок: gpt-oss:20b в Ollama, агентная платформа OpenClaw и карта на 24 ГБ. Ценность не в облаке, где всё это стоит, а в конфиге и в умении читать отказы, которые выглядят как поломка модели, хотя ломается транспорт. Отдельно полезен разбор того, как агент имитирует выполненную работу — и как это ловить.

🔑 Главное
  • Главная развилка — "api": "ollama" и baseUrl без /v1. С суффиксом платформа уходит в OpenAI-совместимый режим, gpt-oss возвращает пустой ответ, а в логах не появляется ни одной ошибки.
  • contextWindow у платформы и num_ctx у модели надо держать синхронными (у автора оба 65 536). Иначе платформа набьёт промпт до своего лимита, а Ollama примет меньше и обрежет контекст.
  • Значения keep_alive в 15 и 10 минут оказались малы: модель выгружалась прямо посреди работы, и следующий запрос получал паузу на 20–30 секунд на чтение весов с диска. Обеим моделям нужно 60m.
  • Арифметика памяти считается по сумме весов и кешей всех резидентных моделей. При окне 64k две модели занимают 22,4 ГБ из 24 — и только если KV-кеш сжат в q8_0 парой OLLAMA_FLASH_ATTENTION=1 и OLLAMA_KV_CACHE_TYPE=q8_0: квантование кеша работает лишь при включённом flash attention.
  • Практический предел модели на 20 млрд параметров — шесть последовательных вызовов инструментов. На восьми-девяти агент начинает обрываться на середине, а пустая сессия съедает 18% окна в 65 536 токенов ещё до первого слова пользователя.
  • При сообщении «Context overflow» не спешите увеличивать окно: три числа из лога gateway показали, что 20 000 токенов забрал внутренний резерв платформы, которого нет в конфиге.
⚡ Попробовать за вечер
  • Поставить ollama, вытянуть gpt-oss:20b и в конфиге провайдера выставить "api": "ollama", baseUrl без /v1 и одинаковые contextWindow и num_ctx.
  • Через systemctl edit ollama добавить OLLAMA_FLASH_ATTENTION=1 и OLLAMA_KV_CACHE_TYPE=q8_0, поднять keep_alive до 60m и перезапустить сервис — без перезапуска переменные не применятся, а статус останется зелёным.
  • Проверить всю цепочку одной командой openclaw infer model run --model ollama/gpt-oss:20b --prompt "ok".
  • Метрика: nvidia-smi --query-gpu=memory.used,memory.total показывает запас до 24 ГБ при обеих резидентных моделях, а результат работы скилла проверяйте через ls и cat в терминале, а не по отчёту агента.
Ответ агента с придуманным листингом каталога против реального вывода ls и cat в терминале из статьи
На картинке: сверху агент рапортует, что файл создан, и показывает вывод ls -la; снизу тот же каталог в терминале, где cat отвечает «No such file or directory».
03

Личный контур в markdown: агент ведёт журнал и собирает отчёт к 1:1

✍ Роман Авдонин Хабр ⏱ ≈14 мин Искусственный интеллект obsidian kanban
О чём

Head of QA собрал рабочий контур из Claude Code, Obsidian и пачки markdown-файлов: он рассказывает ассистенту, чем занимался, а тот раскладывает это по журналу, канбан-доске и заметкам о людях. Читать стоит ради последнего раздела — там лежит промпт целиком, который берёт у вас интервью и собирает такой же контур под вашу роль. Ни Obsidian, ни плагин Kanban денег не стоят, а сам промпт работает и в Cursor, и в Codex.

🔑 Главное
  • Память системы — обычные markdown-файлы, а не контекст чата: новая сессия начинает с чтения карты заметок и продолжает работу. Поэтому контур переносится между Claude Code, Cursor, Codex и Qwen Code без пересказов.
  • Формат строки журнала жёсткий: - HH:MM | что сделано прозой #тег @статус {note: контекст} со словарём статусов @done, @progress, @blocked, @idea, @meeting, @decision, записанным в README. Конвенция переживает и смену модели, и смену чата.
  • Доска — файл Tasks/Task Board.md с фронтматтером kanban-plugin: board, приоритетами #p1..#p3, дедлайнами @{YYYY-MM-DD} и JSON с цветами тегов. Карточки не удаляются: они переезжают в «Готово» с итогом или в «Не будет выполнено» с причиной, и каждый переезд подписывается курсивом с датой.
  • Отчёт к 1:1 автор раньше собирал по чатам час-полтора перед созвоном. Теперь его готовит рутина к утру понедельника: в Claude Code она заводится через /schedule и сохраняется файлом SKILL.md.
  • За два месяца ставки поменялись местами. Граф связей в Obsidian оказался красивой игрушкой, Google-таблица с целями — рудиментом, а алмазом стала канбан-доска, на которую автор изначально вообще не рассчитывал.
  • Честная цена: подписки за $20 не хватило — автор упёрся в пятичасовой лимит Opus, когда перенёс около 80% старых заметок. И рутины работают, только пока приложение открыто.
⚡ Попробовать за вечер
  • Открыть Claude Code (подойдут и Cursor, и Codex) в пустой папке и вставить целиком промпт из раздела «Промт, который соберёт такой же контур вам».
  • Ответить на интервью из 8–12 вопросов про роль, главную боль, отчётность вверх и то, где сейчас живут задачи, и дождаться плана — промпт обязывает агента спросить «ок» до сборки.
  • Поставить в Obsidian community-плагин Kanban (автор mgmeyers) и открыть собранный Tasks/Task Board.md.
  • Метрика: доска рендерится колонками, а не текстом, все вики-ссылки ведут в существующие заметки, а через неделю отчёт к 1:1 собирается из журнала, а не из переписки в чатах.
Схема контура: человек → Claude → цели, канбан-доска и журнал → память в markdown → отчёт к 1:1 и копилка достижений из статьи
На картинке: схема контура — рассказ человека попадает к Claude, тот раскладывает его по целям, доске и журналу, всё стекается в память из markdown-файлов, а две рутины по расписанию собирают отчёт к 1:1 и копилку достижений.
04

RAG ломается тихо: сначала тестовый набор, потом чанки и реранкеры

✍ Лев Рябов Хабр ⏱ ≈8 мин Искусственный интеллект rag pgvector
О чём

Фронтенд-разработчик собрал RAG поверх 62 книг по античной истории (примерно 46 000 чанков) и проверил каждое проектное решение на фиксированном наборе из 135 вопросов — включая решения, которые не сработали. Ценность статьи не в архитектуре, а в демонстрации того, что отказ RAG выглядит не как ошибка поиска, а как уверенная выдумка. Готового eval-харнесса в тексте нет: формат разметки и раннер придётся написать самому.

🔑 Главное
  • Бейзлайн из туториалов — чанки по 500 токенов и топ-5 — дал recall@5 = 35,2%. Примерно для двух вопросов из трёх нужный фрагмент вообще не доходил до модели, и модель всё равно отвечала: гладко, тем же уверенным тоном, что и при удачном извлечении.
  • Самый сильный рычаг — модель эмбеддингов. Замена дефолтного BGE-M3 на qwen3-embedding-8b подняла recall@5 с 35% до 53%, то есть изменением одной строки конфига. Сильнее всего выросла проблемная категория «синонимы» — на 41,7 пункта.
  • Второй рычаг — что лежит в чанке, а не сколько в нём токенов. Название книги и путь заголовков в начале чанка дали +18,2 пункта recall@5 на самой слабой категории: вопросах, требующих синтеза по всему разделу.
  • Что не сработало: гибридный поиск BM25 плюс векторы дал побайтово тот же результат, что и чисто векторный. Из пяти реранкеров бейзлайн обошёл только самый дорогой хостинговый — примерно на 1,7 пункта ценой платной зависимости в каждом запросе. Автор его выкинул.
  • Отказ надо проектировать и тестировать как полноценную фичу, и у промпта здесь есть потолок: пять версий промпта скользили вдоль одной кривой компромиссов, а смена модели-генератора подняла долю честных отказов на вопросах-ловушках с 73% до 100%. Итог системы — 0% ложных отказов и 96% честных.
  • Весь стек — PostgreSQL с pgvector, хостинговый API эмбеддингов и около 200 строк TypeScript. Извлечение — обычный SELECT ... ORDER BY embedding <=> $1 LIMIT 10, где <=> сортирует по косинусному расстоянию.
⚡ Попробовать за вечер
  • Написать 30–50 реальных вопросов по своему корпусу — таких, какие задают пользователи, а не таких, ответы на которые удобно лежат в документах, — и для каждого зафиксировать документ и фрагмент с ответом.
  • Добавить к ним 5–10 вопросов-ловушек, ответа на которые в корпусе нет. Самый злой тип ловушки — вопрос про источник, который в корпусе упомянут, но не содержится.
  • Прогнать текущий пайплайн как есть и посчитать recall@k чистым кодом, без LLM-судьи, — до того как трогать чанкинг, реранкер или фреймворк.
  • Метрика: две цифры порознь и обе в CI как обычные интеграционные тесты — доля вопросов, где размеченный фрагмент попал в топ-k, и доля честных отказов на ловушках при нуле ложных отказов.
05

Deep Agents: файловая система, навыки и субагенты одним вызовом поверх LangGraph

✍ Сергей Тращенков Хабр ⏱ ≈22 мин Искусственный интеллект langgraph агенты
О чём

Разбор открытой обвязки Deep Agents: что она добавляет над create_agent() из LangChain и как из одного вызова получить агента с файловой системой, оболочкой, планировщиком, памятью и субагентами. В конце — сквозной пример sales-analyst с ноутбуком в открытом репозитории. Важная оговорка: весь запуск в статье завязан на ключ GigaChat API и профиль deepagents-gigachat, независимость обвязки от модели только декларируется.

🔑 Главное
  • create_deep_agent() внутри вызывает тот же create_agent() и надстраивает над его циклом готовый стек middleware: файловые инструменты, write_todos, память, навыки, субагенты. Специализируют такого агента не кодом, а содержимым среды.
  • Выгрузка длинных результатов работает автоматически: когда результат инструмента переваливает tool_token_limit_before_evict (по умолчанию 20 тыс. токенов), тело уходит файлом в /large_tool_results/<tool_call_id>, а в контексте остаются превью из первых и последних пяти строк и путь к файлу.
  • Навыки раскрываются постепенно: в системном промпте живёт только индекс — имя, описание и путь к SKILL.md, — а полная инструкция подтягивается обычным read_file, когда навык действительно понадобился. Отдельного инструмента для этого нет.
  • LocalShellBackend(root_dir=..., virtual_mode=True) ограничивает файловые инструменты корнем папки: пути с .. и ~ отклоняются. А вот execute так не ограничить — команды оболочки выполняются на вашей машине со всеми правами пользователя, поэтому в эксплуатации нужен sandbox-бэкенд.
  • Порядок middleware в стеке важен: before_* выполняются сверху вниз, after_* — в обратном порядке, а wrap_* вкладываются луковицей. Самые внешние проверки ставят в начало списка.
  • Смотреть трассы можно без проприетарного LangSmith: локальный Arize Phoenix поднимает UI и коллектор одной командой phoenix serve на порту 6006.
⚡ Попробовать за вечер
  • Поставить pip install "deepagents>=0.6.7" langchain-gigachat deepagents-gigachat, поднять phoenix serve и подключить трассировку через phoenix.otel.register.
  • Повторить пример sales-analyst на своём CSV: create_deep_agent с LocalShellBackend(root_dir="workspace", virtual_mode=True) и задачей «разберись в структуре данных, напиши analyze.py, запусти его и оформи report.md».
  • Положить в workspace/skills/ две папки-навыка — нужный и заведомо лишний — и посмотреть в трассе, какой из них агент откроет по короткому описанию.
  • Метрика: execute дошёл до exit code 0, в workspace/ лежат настоящие analyze.py и report.md, скрипт перезапускается руками и даёт те же цифры, что в отчёте, а в дереве спанов Phoenix видно токены каждого шага.
Дерево спанов прогона Deep Agents в Arize Phoenix с middleware, вызовами инструментов и счётчиками токенов из статьи
На картинке: тот же прогон в Phoenix — middleware вокруг каждого шага, вызовы read_file и write_file и токены каждого обращения к модели (9 622 и 12 995) при общей задержке 1 м 8 с.
06

JS-песочница вместо десятка инструментов: код как способ звать tools

✍ Станислав Чистяков Хабр ⏱ ≈18 мин Искусственный интеллект ии-агенты context-engineering
О чём

Про то, как один инструмент «выполни JavaScript» заменяет самописные calculator, sum_payments и percentile, а в LangChain тот же приём вырастает в programmatic tool calling: инструменты вызывает не модель, а написанный ею скрипт. Начинается с примера, который повторяется в LM Studio за пять минут, и заканчивается разбором правил безопасности. Команды установки langchain_quickjs в статье нет, а параметр ptc= показан двумя несовместимыми способами — сверяйтесь с исходниками.

🔑 Главное
  • В LM Studio из коробки есть плагин js-code-sandbox с единственным инструментом run_javascript. Без инструментов модель отвечает датой, застрявшей в ней при обучении; с ним — сама решает написать скрипт и считает, например, третий четверг после ближайшего полнолуния.
  • Дефолты интерпретатора langchain_quickjs: timeout=5.0 секунды на вызов, memory_limit=64 MB, mode="thread". Скрипт может зависнуть или съесть память, но не прочитает ~/.ssh, не отправит архив наружу и не удалит данные на диске.
  • В режиме PTC инструменты пробрасываются внутрь JavaScript с переименованием в camelCase: get_current_datetime становится tools.getCurrentDatetime(...). Сами вызовы по-прежнему делает harness, скрипт только просит их выполнить и обрабатывает ответы.
  • Арифметика контекста говорит сама за себя: в классическом ReAct-цикле вопрос про десять клиентов даёт один поиск плюс четыре вызова на каждого, то есть больше сорока tool-результатов в истории, и все они лежат там до конца разговора. С PTC модель видит только объект из return.
  • Ловушка безопасности: LangChain игнорирует interruptOn для вызовов из скрипта — подтверждения запрашиваются только на прямые вызовы модели. Отсюда прямое правило: в PTC-allowlist отдавать читающие инструменты, пишущие оставлять обычными вызовами, а число PTC-вызовов ограничивать через maxPtcCalls.
  • PTC не окупается на одиночном чтении файла или одном запросе к API. Он выигрывает там, где между несколькими вызовами есть повторяемая логика, с которой скрипт справляется лучше рассуждений модели.
⚡ Попробовать за вечер
  • Включить в LM Studio плагин js-code-sandbox с инструментом run_javascript и прогнать свой типовой расчётный запрос — с датами, перцентилями или фильтрацией JSON, пришедшего из другого инструмента.
  • В своём LangChain-агенте заменить самописные tools вида calculator и percentile на один CodeInterpreterMiddleware(timeout=5.0, memory_limit=64*1024*1024).
  • Собрать PTC-allowlist только из читающих инструментов и поставить потолок maxPtcCalls, а пишущие оставить обычными вызовами под interruptOn.
  • Метрика: число tool-результатов в истории на один вопрос пользователя и суммарные токены до и после — вместо четырёх десятков JSON-ответов в контексте должен остаться один объект из return.
Окно LM Studio: модель вызывает run_javascript и считает третий четверг после ближайшего полнолуния из статьи
На картинке: LM Studio с плагином js-code-sandbox — на вопрос про третий четверг после полнолуния модель вызывает run_javascript и отвечает 17 сентября 2026 года с разбором по шагам.
07

48 часов записей в вики на 47 статей: схема, которая не даёт модели выдумывать

✍ Тимур Цедик Хабр ⏱ ≈4 мин Open source structured output whisper
О чём

Кейс с открытым кодом: конвейер превращает 48 часов видеозаписей курса в Obsidian-вики, где каждое утверждение в двух кликах от минуты записи. Переносится отсюда не код, а три правила схемы, которые заставляют модель молчать вместо того, чтобы выдумывать. Самой схемы и промпта в тексте нет — за ними придётся идти в репозиторий.

🔑 Главное
  • Наружу уходит ровно один вызов — извлечение знаний из чанка. Транскрибация локальная, whisper-medium на Apple Silicon, и вся LLM-обработка 48 часов записей обошлась примерно в четыре доллара токенов OpenAI.
  • Чанки режутся окнами по 10 минут с перехлёстом в 2 минуты, чтобы мысль, разрезанная границей окна, целиком попала хотя бы в одно из соседних. Если на входе транскрипт без таймкодов, окна считаются в словах, а поля времени остаются пустыми: фейковых таймстампов конвейер не ставит даже ради красоты ссылок.
  • Схема с strict: true требует source — запись, чанк, начало и конец — у каждой единицы знания и при этом разрешает вернуть пустые массивы. Вывод автора прямой: модель, которой запрещено отвечать «ничего», начинает выдумывать; модель, которой разрешено, — перестаёт.
  • Ценз на входе в статьи: из 353 чанков извлеклось 1543 темы, порог «минимум два независимых чанка» оставил 47 статей. Потом автор снизил порог до одного — для личной библиотеки полнота оказалась дороже строгости, а строгий фильтр остался ручкой в CLI.
  • Ссылки под конвоем с двух сторон: при генерации модель получает белый список существующих заголовков, при сборке vault каждая ссылка перепроверяется. Неизвестные не выбрасываются, а уходят в индекс Unlinked Mentions — готовую очередь кандидатов на следующие статьи, отсортированную частотой упоминаний.
  • Каждая стадия пишет результат на диск и узнаёт уже сделанное, поэтому упавший прогон продолжается с того же места; телеметрия прогонов пишется в JSONL.
⚡ Попробовать за вечер
  • Взять свой корпус записей и прогнать его через media-to-wiki-convertor (MIT, Python) или повторить схему у себя: окна по 10 минут с перехлёстом в 2 минуты.
  • В JSON-схему извлечения добавить обязательное поле source с записью, чанком и границами по времени — и явно разрешить пустой массив как легальный ответ.
  • Порог «тема становится статьёй с двух независимых чанков» вынести параметром CLI, а не зашивать константой.
  • Метрика: доля утверждений в готовых статьях, у которых source ведёт в реальный таймкод, и стоимость токенов на час записи.
Граф собранной вики: 47 статей с подписанными темами и серые точки отложенных тем вокруг из статьи
На картинке: граф собранной вики — 47 статей с подписями вроде Agentic loop и Tool calling, а серые точки вокруг — 1495 отложенных тем в индексе Unlinked Mentions.
08

Тест-кейсы от LLM: как не купить ложное покрытие

✍ kirakirap Хабр ⏱ ≈16 мин Тестирование IT-систем мутационное тестирование автотесты
О чём

Разбор про то, где именно ломается генерация тест-кейсов: модель добавляет правдоподобный шаг «Нажать кнопку „Отменить“» и вызов метода cancelEmailChange(), которых в продукте нет, а ревьюер принимает выдумку за техническую деталь. Полезны две вещи, которые можно унести сразу: рабочий шаблон запроса и чек-лист приёмки из десяти вопросов. Шаблон написан под сценарий смены email — на свой метод его придётся переносить руками, а рекламный хвост курсов в конце просто пролистайте.

🔑 Главное
  • Промпт устроен так, чтобы можно было проверить происхождение каждого кейса: правила перечислены явным списком, для каждого кейса требуется ссылка на проверяемое правило или риск, а пробелы уходят отдельным списком вопросов. Ограничение в конце прямое: «Не придумывай интерфейс, сообщения и правила, которых нет в описании».
  • Покрытие кода не оценивает качество проверки: тест может выполнить всю функцию и проверить только то, что она что-то вернула. Ловит это мутационное тестирование — инструмент вроде Stryker инвертирует условие или меняет оператор, и если тесты остались зелёными, они не заметили поломку.
  • Сгенерированные тесты чаще оказываются нестабильными. В исследовании 2026 года на SAP HANA, DuckDB, MySQL и SQLite в 63% разобранных вручную случаев причиной была зависимость от порядка элементов, который система не гарантирует. Модель ещё и копирует нестабильность из примеров, которые ей дали на вход.
  • Цифры промышленного TestGen-LLM на Reels и Stories: 75% сгенерированных тестов собирались, 57% стабильно проходили и только 25% увеличивали покрытие. Из прошедших фильтр рекомендаций инженеры приняли 73%.
  • Генерировать надо небольшими пачками по типу риска: сначала основной поток, потом границы, ошибки и переходы состояний. Если первые десять тестов построены на неверном предположении, чинить остальные девяносто дороже, чем поправить входные данные.
  • Проверка делится надвое. Сначала техническая — собирается ли код, стабильно ли проходит, не зависит ли результат от порядка запуска и времени. И только потом смысловая — откуда взят ожидаемый результат, какое требование закрывает кейс, не дублирует ли он существующую проверку.
⚡ Попробовать за вечер
  • Взять один свой API-метод и собрать под него запрос по шаблону из статьи: правила явным списком, для каждого кейса — ссылка на правило или риск, а пробелы отдельным списком вопросов вместо додуманных ожидаемых результатов.
  • Прогнать полученное через чек-лист из десяти вопросов приёмки: откуда взят ожидаемый результат, не придумала ли модель часть продукта, падает ли тест, если намеренно сломать проверяемое условие.
  • Натравить на набор мутационное тестирование — Stryker или его аналог для вашего языка.
  • Метрика: не число кейсов и не покрытие кода, а доля убитых мутантов и доля кейсов, чей ожидаемый результат выведен из требования, а не из текущей реализации.
09

Свой инференс на 25 разработчиков: кэш префикса решает больше, чем выбор модели

✍ Павел Куваев Хабр ⏱ ≈16 мин IT-инфраструктура vllm prefix caching
О чём

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

🔑 Главное
  • --enable-prefix-caching для гибридных и MoE-архитектур не включается автоматически, а до vLLM 0.27.1 для этой связки не работал вовсе. Явный флаг поднял долю попаданий в кэш с 0% до 96,9%, а латентность на повторном префиксе упала с 31,9 с до 0,24 с.
  • Цифру автор сверяет с двух независимых сторон: биллинг шлюза даёт 96,9%, собственные счётчики движка за период аптайма — 97,3%. Сходятся — значит, меряют одно и то же.
  • Разбивка по типам токенов вскрыла перекос вход/выход 452:1. Средний шаг агента тащит около 123 700 токенов контекста, из них примерно 119 800 читается из кэша и лишь 3 900 обрабатывается реально, а на выходе — 274 токена. Бенчмарки, меряющие токены в секунду на генерации, описывают 0,2% реального трафика.
  • Латентность надо смотреть распределением, а не средним: медиана времени до первого токена 0,43 с против среднего 1,4 с. Среднее тянет вверх хвост из девятнадцати запросов с холодным стартом на 20–40 секунд.
  • Потолок стенда не в вычислениях, а в KV-пуле: при среднем контексте около 124 000 токенов и пуле в 1 032 910 токенов одновременно помещается восемь-девять запросов с полным контекстом. При этом сам рост пула с 497 000 токенов дали --kv-cache-dtype fp8 и апгрейд версии, а не кэш префикса.
  • Две грабли на память: VLLM_USE_DEEP_GEMM=0 лечит падение DeepGEMM на sm120 с FP8-чекпоинтами, а занижение --max-model-len памяти не освободило вообще, зато вдвое урезало контекст.
  • Главный урок сформулирован в конце: шлюз с разбивкой по типам токенов надо было ставить первым делом. Пока была одна цифра «токенов потрачено», команда чинила вслепую и не знала, что кэш не работает.
⚡ Попробовать за вечер
  • Проверить, работает ли кэш префикса на вашей конкретной архитектуре в вашей версии движка: выставить --enable-prefix-caching явным флагом и найти в статистике строку cache read.
  • Сверить долю попаданий с двух сторон — по кумулятивным счётчикам движка и по биллингу шлюза; цифры должны сойтись.
  • Заменить в своём отчёте о латентности среднее на медиану и перцентили, а потребление за неделю разбить по типам токенов.
  • Метрика: доля попаданий в кэш совпадает по движку и по шлюзу, отношение входных токенов к выходным посчитано (у авторов 452:1), и видно, какая часть входа реально обрабатывается, а не читается из кэша.
10

MMLU не растёт? Проверьте форму замера, а не данные

✍ Матвей Сапрыкин Хабр ⏱ ≈18 мин Машинное обучение llm-модели Big Data
О чём

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

🔑 Главное
  • Один и тот же MMLU меряется как минимум тремя способами: MCF с вариантами A/B/C/D прямо в промпте (task mmlu), CF без вариантов со сравнением log-likelihood полных ответов (task mmlu_continuation) и generative с жадным декодингом (mmlu_generative).
  • В прогонах команды CF даёт полезный сигнал в начале обучения, но рано выходит на плато, а MCF стартует позже — рядом с уровнем случайного угадывания — и продолжает расти до конца decay-фазы. Поэтому дальше они мерили сразу в двух формах.
  • Диагностики важнее loss: max attention-логит и число намертво занулившихся параметров ловят расхождение за тысячи шагов до того, как оно дойдёт до кривой loss, — а на кривой чинить уже поздно.
  • Ablation по XSA это показывает наглядно. Чистая формула разогнала max-логит примерно до 90, и запуск остановили. Вариант head_gate дал формально лучший loss 2,541, но убивал головы: num-zeros рос ступеньками ровно по 2048 (это hidden size, то есть целая строка весов одной головы), и к 50 тыс. шагов насчитали около тринадцати мёртвых голов из 448. Выбрали λ_h — логит рядом с baseline, loss близкий, num-zeros не растёт.
  • Инфраструктурная грабля на всякий случай: на источниках свыше 2 млрд документов сборка индекса Megatron падала с segfault, потому что счётчик документов упирался в переполнение int32. Такие датасеты пришлось резать на части.
⚡ Попробовать за вечер
  • Добавить в свой eval-конфиг lm-evaluation-harness обе задачи — mmlu и mmlu_continuation — и перемерить последние чекпоинты в обеих формах.
  • Свести обе кривые на один график и посмотреть, где они расходятся и какая из них выходит на плато раньше.
  • Добавить в трейнинг-луп логирование max attention-логита и числа занулившихся параметров — хук придётся написать самому, в статье его нет.
  • Метрика: если CF выходит на плато раньше, а MCF продолжает расти, прошлый вывод «MMLU не растёт» был артефактом формата замера. Отдельно проверьте, успевают ли обе диагностики дать сигнал раньше всплеска loss.
График: кривые mmlu и mmlu_continuation на одном прогоне расходятся — CF рано выходит на плато, MCF продолжает расти из статьи
На картинке: один прогон, две формы замера — mmlu_continuation (зелёная) уходит на плато около 0,35, а mmlu (синяя) стартует у 0,245 и к концу доходит примерно до 0,50.
💬

На что обратить внимание

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

💻 Развёртка по --n-cpu-moe: параметр не монотонный

✍ Sergey ProshchaevХабр⏱ ≈14 мин

Опубликованная развёртка владельца RTX 5090: 54 токена в секунду при значении 20, дальше 64,5 при 16, 69,4 при 12 — и обвал до 27,5 ещё на шаг ниже. Край не подписан, в него просто въезжаешь, поэтому значение подбирают под свою модель, карту, объём RAM и контекст. Но статья даёт одну иллюстративную команду llama-server — без сборки llama.cpp, без источника GGUF и без методики раздельного замера префилла и декодирования.

Читать ↗

🚀 Спекулятивное декодирование на топ-16 кандидатов

✍ Антон ВасильевХабр⏱ ≈6 мин

DFlash 2 хранит на каждую позицию топ-16 кандидатов вместо жадного Top-1: верный токен на первой позиции блока попадает в 99,5% случаев против 85,4%, а средняя длина принятия на GSM8K растёт с 5,02 до 5,46. Команды запуска даны для SGLang, vLLM и llama.cpp, но флаг --speculative-num-steps для DFLASH указан не тот, требований к видеопамяти нет, а «+2M параметров» относится только к селектору, а не к самому драфтеру.

Читать ↗

🤖 VLA на гуманоиде: 836 мс от кадра до движения

✍ Арсентий ГусевХабр⏱ ≈27 мин

Постадийная раскладка задержки на Jetson Orin NX 16 GB в профиле 25 Вт: захват 22 мс, энкодер зрения 490 мс, модуль действий на четыре шага denoise 144 мс, постобработка 12 мс. Главная мысль переносится за пределы робототехники: бюджет считают против горизонта исполнения, а не предсказания — при восьми исполняемых шагах и шаге 50 мс это 400 мс, и 748 мс расчёта не влезают почти вдвое. Итоговая таблица рычагов — расчётная цель, а не замер: у половины строк стоит «прогона нет».

Читать ↗

🖼 Портрет, похожий на вас: промпт-«identity card»

✍ Паша МоляновХабр⏱ ≈8 мин

Приём против усреднения: вместо приложенного референса модели отдают текстовое описание, а стабильные черты внешности выносят в отдельную «карточку личности» — этот промпт приведён целиком и копируется. Финальная инструкция прямо запрещает делать человека стройнее, выше и атлетичнее, чем на загруженных фото. На эксперименты у автора ушло около $200, нужен платный ChatGPT с режимом Thinking, а блок описания референса в статье оборван на «И так далее».

Читать ↗
🎯

Мой план на эту неделю

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

Поднять: LiteLLM в docker compose на своём поддомене, выпустить виртуальный ключ с бюджетом и перевести на него один рабочий скрипт
до четверга
Замерить: написать 30 вопросов по рабочему корпусу с разметкой фрагментов плюс 5 ловушек и снять recall@5 текущего пайплайна как есть
до пятницы
Прогнать: sales-analyst на своём CSV под Phoenix и посмотреть в дереве спанов, какой шаг съедает токены
в выходные
#

Метаданные

сгенерировано 2026-08-24T19:50:37Z
окно 2026-08-17 — 2026-08-24 (7 дней)
отсканировано / в дайджест 343 / 14
источник постраничный API Хабра (хабы: Искусственный интеллект, Машинное обучение, Обработка естественного языка; плюс топ недели, срез из 100 верхних статей)
пропущенные ленты нет — все четыре ленты закрыли окно
×
Открыть статью