кодло/ студия

Разбор · статья 2 из 5

Какое плечо модели нужно какой задаче

Сравниваем модели и усилия рассуждения на одинаковых задачах. Проверяем результаты прогонов и стоимость принятой работы.

13 мин чтения2404 словпо нашим артефактам

1. Вопрос: что именно мы выбираем

«Возьмём модель посильнее» не задаёт проверяемого критерия. На живом проекте изменение должно устранять конкретный дефект и сохранять проверяемое поведение. Название модели само по себе этого не гарантирует. Более долгое рассуждение тоже нужно оценивать по результату: завершённый агентный цикл может оставить красные тесты, а зелёный общий набор — пропустить исходный баг.

Плечо в нашем стенде — сочетание модели и усилия рассуждения. Например, gpt-5.6-sol/low и gpt-5.6-sol/medium — разные плечи. Их сравнивают на одной постановке, с одинаковым исходным деревом и одинаковой приёмкой. Цель лейна сформулирована в CONTEXT.md: выяснить, какое плечо нужно какой задаче, и превратить решения в контрибьют в чужие проекты.

Мы рассматриваем только предоставленные артефакты. Правила берём из CONTEXT.md, исходы пересчитываем по строкам журналов. Сводка и журнал могут расходиться. Так, контекст сообщает о пуле из 9 задач, 27 прогонах и 6 сделанных задачах; предоставленный results.jsonl содержит 47 записей, из которых только одна имеет grade.passed=true. Сводка и журнал сохранили разное состояние. Подтверждение шести решений в этом журнале — не зафиксировано. Сводная фраза его не заменяет.

2. Как устроен замер

Стенд на собственных тикетах использует fail-to-pass: решение проверяют тестами из фикс-коммита, наложенными на дерево модели. В журнале сохраняются исходный parent, эталонный fix, список tests_applied и отдельный объект grade. Так мы проверяем выполнение контракта репозитория, а не убедительность ответа. Сообщение модели «готово» не заменяет приёмку (CONTEXT.md, results.jsonl).

Для вклада в чужие проекты процедура сходная. На стадии prep готовим дерево от origin/main, постановку и относящиеся к задаче тесты. Затем baseline устанавливает, что проходит на чистом дереве и воспроизводится ли дефект. После run машинная приёмка проверяет результат, а review запускает другую копию Codex как спорщика. Открытие PR следует после приёмки; контекст описывает автоматическую цепочку «приёмка → ревью → публикация» (CONTEXT.md).

Для задачи с воспроизведением условие принятия состоит из двух частей: баг устранён, новых падений относительно базы нет. Поля acceptance.passed и acceptance.accepted означают разное. Первое описывает тестовый набор, второе — итоговую приёмку. В Hermes тестовые файлы проходили, но скрипт воспроизведения оставался красным, поэтому accepted=false (contrib.jsonl, строки 2–3).

Если отдельного воспроизведения нет, граница доказательства слабее. В LangGraph журнал прямо записывает repro.ran=false, причину «скрипта проверки нет» и основание принятия «тесты репозитория». Это подтверждает отсутствие новых падений в выбранном наборе, но не позволяет утверждать, что самостоятельный fail-to-pass сценарий задачи был выполнен (contrib.jsonl, строки 8 и 10).

Когда фикс создаёт модуль с нуля, стенд предусматривает заготовки объявлений. С ними задача начинается с другого состояния. Поэтому результаты без заготовки и с ней должны оставаться отдельными сериями: прежние ошибки компиляции нельзя складывать с новой поведенческой приёмкой в общий рейтинг (CONTEXT.md).

3. Правила честности и пересчёт журналов

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

Исчерпанный лимит означает invalid. Отказ сервиса не считается неудачной попыткой решения. В старой части results.jsonl, строки 10–37, сохранены 28 записей с сообщением You've hit your usage limit, но без явного invalid. По правилу из CONTEXT.md их исключаем из оценки способности плеча. Так мы исправляем классификацию при анализе. Сам журнал не изменяем. В строке 47 такой отказ уже помечен quota=true, invalid=true, а приёмка не запускалась.

Таблица ниже пересчитана из results.jsonl, строки 1–37. «Принято» означает только сохранённое grade.passed=true. Отсутствие ошибки лимита ещё не доказывает безупречность приёмщика.

Плечо, без заготовки Записей запусков Исключено: ошибка лимита Осталось для оценки Принято
gpt-5.6-terra / medium 13 9 4 0
gpt-5.6-sol / low 12 9 3 0
gpt-5.6-sol / medium 12 10 2 1

Новая серия считается отдельно. Источник — results.jsonl, строки 38–47; во всех этих записях присутствует непустой scaffold.

Плечо, с заготовкой Записей запусков Исключено: invalid Осталось для оценки Принято
gpt-5.6-terra / medium 4 1 3 0
gpt-5.6-sol / low 3 0 3 0
gpt-5.6-sol / medium 3 0 3 0

Тесты контрибьюта идут пофайлово. В CONTEXT.md указана причина: общий запуск создавал падения из-за протечки состояния между тестами. Для оценки учитываются новые падения относительно чистой базы. Так, у LangGraph проходят 4 проверяемых файла, ещё 4 исключены как красные на чистом дереве (contrib.jsonl, строки 8 и 10). Вердикт относится только к проверенным файлам. Это ограничение нужно указывать рядом с ним.

Запись журнала не всегда означает новый запуск. В contrib.jsonl всего 12 записей: 8 типа contrib-run, 3 ревью и один разбор отказов. Среди contrib-run есть повторная приёмка с reaccept=true, нулевыми временем и токенами. Она не была новым решением. Поэтому таблица запусков исключает её, а также отдельно показывает попытку по исчерпанному лимиту.

Плечо контрибьюта Записей запусков без reaccept Invalid Запусков для оценки Машинно принято
gpt-5.6-sol / medium 4 1 3 2
gpt-5.6-terra / medium 3 0 3 2

Источник таблицы — contrib.jsonl, строки 1–10. Дополнительная принятая повторная проверка Terra относится к Hermes, строка 6. Все 3 сохранённых ревью имеют вердикт «ОТКЛОНИТЬ»; машинная приёмка ещё не означает одобрения ревьюером или слияния в исходном проекте.

4. Экономика: стоимость принятой работы

GO_LIMITS_ECONOMY.md — снимок экономики OpenCode Go от 28.09.2026, с цифрами из документации самого провайдера. Это отдельная подписка; перенос её коэффициентов на Codex не обоснован. Месячный долларовый лимит задаётся для каждой модели. Пятичасовое окно соответствует 20% её лимита, недельное — 50%, месячное — 100%. Общий расход складывается из процентов по моделям.

Для сопоставимого окна вклад модели рассчитывается как расход, делённый на её собственный лимит. Поэтому одинаковый долларовый расход при лимите $15 занимает вчетверо большую долю, чем при $60. В источнике месячный лимит DeepSeek V4.1 Flash и MiMo указан как $60, DeepSeek V4 Flash — $30, группы дорогих моделей — $15 (GO_LIMITS_ECONOMY.md). Цена токена без этого знаменателя не описывает экономику подписки.

В том же снимке пиковые часы DeepSeek: 01:00–04:00 и 06:00–10:00 UTC по будням, то есть 08:00–11:00 и 13:00–17:00 в Новосибирске. Пиковые цены вдвое выше. У MiMo, GLM, LongCat и MiniMax надбавки не указаны (GO_LIMITS_ECONOMY.md). Расписание автономной работы влияет на расход даже при неизменном плече.

Расчёт для профиля тикета byte//run — 117K входа, 4,35M кэша, 48K выхода — даёт следующие расходы. Все значения взяты из GO_LIMITS_ECONOMY.md, раздел «Цена одной и той же работы в процентах окна»; это расчёт на одинаковом профиле, а не фактическая цена каждого запуска.

Ведущая модель / режим Расход окна на профиль
MiMo-V2.5 0,070%
DeepSeek off-peak 0,099%
DeepSeek peak 0,198%
GLM-5.3-Flash 0,287%

Источник сообщает преимущество MiMo перед DeepSeek off-peak в 1,41×. Выгода 2,4–2,7× при равной приёмке — не зафиксирована в предоставленных артефактах. Её нельзя выдавать за результат стенда. Условная логика верна: если плечо тратит в 2,4–2,7 раза меньше окна и сохраняет приёмку, фиксированный лимит позволяет выполнить соответственно больше сопоставимых задач. Но оба условия нужно измерить.

На реальных тикетах одинаковое качество подтвердилось лишь частично. REAL_TICKETS_STATUS.md описывает пробел учёта: расход микстуры записывается общей суммой, без полной разбивки по ведущей модели и советнику. Точная цена микстуры — не зафиксирована. Цена принятого решения должна учитывать неудачные попытки, повторные проверки и эскалации; одних тарифов для неё недостаточно.

5. Что показали конкретные задачи

TCK-020, класс уведомления в claude_gate. В results.jsonl, строки 1–4, Terra/medium запускалась дважды и получила одинаковый итог: 6 упавших, 3 прошедших теста. Sol/low получила такой же итог. Sol/medium прошла приёмку: 9 тестов зелёные. На этом контракте увеличение усилия помогло. Повторные успешные замеры для проверки устойчивости результата — не зафиксированы.

TCK-019, соседняя задача claude_gate. Все сохранённые плечи красные: 7, 9 и 6 падений соответственно для Terra/medium, Sol/low и Sol/medium (results.jsonl, строки 5–7). Меньшее число падений не превращает изменение в принятое. Поле build_or_collect_failed=true соседствует с конкретными итогами pytest, а tests_failed=0. Чтобы понять результат, приходится читать grade.tail. Одного сводного поля недостаточно.

Kodaro с заготовками. Для планировщика KOD-006 журнал сохраняет по 2 падения у каждого плеча; для брокера KOD-009 и слоя доступа KOD-011 — по 7. Принятых решений нет. Ответы моделей сообщают об ограничениях доступа к PostgreSQL и сокетам, но хвост машинной приёмки содержит только FAIL (results.jsonl, строки 38–46). Эти сведения требуют диагностики окружения. Причина каждого падения и исправленный повторный вердикт — не зафиксированы; объявлять все результаты ложными красными нельзя.

Hermes #129590, числовой default_assignee. На main=3294d683af обе модели меняли обработку числового идентификатора. Sol/medium и Terra/medium проходили 8 выбранных тестовых файлов, но воспроизведение отвергало выбор default вместо 2024 (contrib.jsonl, строки 2–3). Затем тот же путь патча Terra и размер 7865 байт фигурируют в принятой повторной проверке: при наличии профиля выбран 2024, при отсутствии — default (строка 6). Нового агентного запуска журнал не содержит. Хеш содержимого патча, причина первоначального расхождения и изменение кода проверочного скрипта — не зафиксированы. Повторная приёмка Sol — не зафиксирована.

DSPy #10321, допустимый seed=0. Исправление отличает None от нуля при выборе зерна. У Sol/medium и Terra/medium воспроизведение проверяет ноль, отсутствие значения и ненулевое зерно; оба результата машинно приняты, новых падений нет (contrib.jsonl, строки 4 и 7). Сохранённое ревью Sol-патча отклоняет поставку из-за теста, не включённого в видимый дифф (строка 5).

LangGraph #8880, явный признак выхода. Обе модели заменяют внутреннюю проверку на передачу exiting, обе машинно приняты, обе отклонены ревьюерами за отсутствие нового теста (contrib.jsonl, строки 8–11). Последующий rejects_analysis.md устанавливает наличие существующего поведенческого покрытия и отсутствие репозиторного требования писать новый тест на каждый рефакторинг. Формальная красная оценка ревью здесь не равна доказанной регрессии.

Отдельный стенд byte//run проверял DeepSeek и микстуру с ведущей MiMo. Это сравнение конструкций; усилие рассуждения в его таблице не зафиксировано. По REAL_TICKETS_STATUS.md итог после перепроверки такой:

Участник Прогонов Принято TCK-203: сброс лобби TCK-201: broker + ui_mockup
base: DeepSeek V4.1 Flash 2 2 PASS PASS
m-g: MiMo + советник GLM 2 1 PASS FAIL

На сбросе лобби оба решения прошли. На TCK-201 микстура прошла broker, но получила UIMOCKUPTEST FAILED fails=12 и была остановлена по таймауту 2400 секунд. Пороги визуальной проверки выставлены ниже измеренных значений без требуемого обоснования (REAL_TICKETS_STATUS.md). Дешёвую конструкцию можно рассматривать для первого типа задач; одинаковая приёмка на обоих тикетах не подтверждена.

Контрибьют также потребовал отбора площадок. small_issues.json хранит выборку чужих PR: у DSPy влиты 32 из 40, медиана времени 6,4 часа; у Agno — 25 из 40 и 10,6 часа; у lm-evaluation-harness — 25 из 40 и 49,8 часа. Это данные о работе с внешними PR. Они не гарантируют, что наш патч примут. Сводка тоже требует сверки: для vLLM JSON даёт 31 из 40 и 2,4 часа, тогда как CONTEXT.md сообщает 30 из 40 и 2,6 часа. Для чисел отбора используем JSON. Слияние измеренных здесь решений в исходных проектах — не зафиксировано.

6. Где замер врал и где доказательств не хватает

Таймаут вместо сломанного дерева. В REAL_TICKETS_STATUS.md описан ложный FAIL (parse): rc=124 означал таймаут парс-смоука на свежераспакованном дереве. Добавлена повторная попытка. Таймаут самого агента на TCK-201 остался ограничением незавершённой работы. Одинаковый код возврата нужно разбирать по месту возникновения.

Проверка написания вместо поведения. Приёмщик byte//run искал буквальную русскую строку эталонного фикса, хотя агенты назвали кейсы иначе. Проверку заменили на функциональный критерий. Для broker и ui_mockup пришлось добавить команды, действительно покрывающие тикет: общий verify_tree.sh этого не делал (REAL_TICKETS_STATUS.md).

Параллельные прогоны на общей БД. Конкретный случай, его строки журнала и перепроверенный исход в заданных источниках — не зафиксировано. Данные Kodaro подтверждают сообщения об ограничениях подключения, но не столкновение параллельных запусков. Изоляция БД остаётся пунктом проверяемой процедуры; приписывать ей наблюдавшиеся падения нельзя.

Обрыв по бюджету вывода. Подтверждённый случай — не зафиксировано. Контекст описывает дневной бюджет входных токенов, а журналы содержат ошибки лимита подписки. Ни то ни другое не устанавливает исчерпание бюджета вывода.

Дубли чужих PR. По CONTEXT.md, 7 из 8 задач ночной очереди уже закрывал чужой открытый PR. После этого появились проверки свежих PR и точечный поиск занятости issue. Отдельного поля о дубле у каждого запуска в contrib.jsonl нет: точную привязку этой сводки ко всем строкам восстановить нельзя. Такой выбор работы приводит к дублям, даже если патч проходит тесты.

Неполный дифф и лишний критерий ревью. git diff origin/main не показывал новый untracked-тест DSPy. Контекст фиксирует переход к git add -A и diff --cached, чтобы ревью видело тот же набор изменений, что патч. rejects_analysis.md уточняет: тест существовал; проблема состояла в полноте поставки. Для LangGraph ревьюеры требовали тест на приватный способ реализации, хотя существующее покрытие проверяло сохраняемое поведение. Исправлять пришлось критерий оценки, а не автоматически усложнять решение.

7. Вывод: как выбирать плечо на живом проекте

Пригодная процедура начинается с воспроизводимого контракта задачи. Затем фиксируются база, тесты, окружение и конструкция запуска. Проверяемые плечи получают одинаковую постановку и независимое чистое состояние. Лимитные отказы исключаются; дефекты приёмки разбираются отдельно от дефектов патча.

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

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

Что проверить скептику

— Пересчитать results.jsonl по строкам: отделить scaffold, проверить errors на лимит и считать принятие по grade.passed. — В contrib.jsonl разделить запуск, reaccept, ревью и разбор отказов; различить passed и accepted. — Сверить parent, fix, main, tests_applied, baseline_ts, исключённые файлы и фактическое воспроизведение. — Проверить расхождения сводок с журналами, особенно число решений и выборку vLLM. — Прочитать rejects_analysis.md: видел ли ревьюер все файлы и следовал ли правилам репозитория. — Проверить знаменатели окон в GO_LIMITS_ECONOMY.md и пробел учёта микстуры в REAL_TICKETS_STATUS.md. — Потребовать артефакты для выгоды 2,4–2,7×, общей БД, бюджета вывода и слияния: в предоставленных источниках эти результаты не зафиксированы.

Написано по артефактам студии; ссылки на файлы — имена наших исходников, они живут в репозитории, а не в вебе.