Как создать маршрутизатор моделей в Harness

Источник: LangChain

Как создать маршрутизатор моделей в Harness

Источник: LangChain

Как мы встроили маршрутизатор моделей в Open SWE, что позволило сократить медианную стоимость выполнения задачи по программированию на 64% без заметного снижения качества, и как создать такой же для себя.

•Обновлено: 2 октября 2026 г.

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

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

Мы недавно столкнулись с этой проблемой в LangChain, когда наши ежемесячные расходы на агента по написанию кода начали быстро расти. Услышав те же опасения от клиентов, мы решили создать эффективный маршрутизатор моделей для Open SWE, нашего агента для написания кода с открытым исходным кодом. По сравнению с нашим предыдущим базовым уровнем, где всегда использовалась топовая передовая модель, это сократило медианную стоимость одного потока на 64% без измеримого изменения качества. В этой статье рассказывается, как мы создали маршрутизатор, что мы узнали и как вы можете начать внедрять маршрутизацию моделей в своих агентов.

Шаг 1: понимание задач

Нашим испытательным стендом был Open SWE, который наши инженеры используют в Slack и веб-интерфейсе, чтобы задавать вопросы о наших кодовых базах и запрашивать изменения в коде. Прежде чем создавать маршрутизатор, нам нужно было понять типы задач, для которых разработчики используют Open SWE. Мы извлекли данные на уровне потоков из трассировок LangSmith: виды поступающих запросов, а также стоимость и количество итераций каждого потока (как приблизительные показатели сложности). Мы провели исследование в LangSmith Custom Apps с помощью небольшого интерфейса, построенного непосредственно поверх трассировок Open SWE.

Мы взяли неделю интерактивных потоков и классифицировали каждый из них по типу задачи с помощью классификатора LLM. LangSmith Insights также может выполнять такую группировку по вашим трассировкам. Изменения в коде преобладали: новые функции (22%) и исправление ошибок (17%) были двумя крупнейшими группами, за ними следовали тесты или холостые запуски (16%). Категории представляют собой эвристики, основанные на заголовке и метаданных каждого потока.

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

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

На момент сбора данных все потоки Open SWE направлялись через топовую передовую модель. Приведенные выше данные показали, что многие задачи, которые обрабатывал Open SWE, возможно, не требуют передового интеллекта, учитывая диапазон сложности.

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

Шаг 2: понимание моделей

Индекс интеллекта Artificial Analysis оценивает модели по общему набору задач и сообщает стоимость выполнения одной задачи, поэтому вы можете построить их все на одной кривой зависимости интеллекта от стоимости. Граница Парето — это набор моделей, которые являются самыми дешевыми и самыми умными.

Мы выбрали три модели вдоль этой кривой, каждая из которых имеет разный баланс стоимости, скорости и интеллекта:

  • Быстрая: GLM-5.3-Flash (xhigh)
  • Сбалансированная: GPT-5.6 Sol (medium)
  • Производительная: GPT-6 Astra (low)

Мы выбрали модели от разных провайдеров, а быстрый уровень — это открытая модель. GLM-5.3-Flash находится на границе Парето рядом с закрытыми моделями, что является еще одним признаком того, что открытые модели преодолели этот порог. LangChain является агностиком к моделям, с общим интерфейсом модели, который работает одинаково у всех провайдеров, поэтому, когда появляется лучшая модель, ее замена — это изменение одной строки в маршрутизаторе.

Шаг 3: создание маршрутизатора в harness

Имея карту сочетания задач и три выбранных уровня, нам нужно сопоставить задачи с моделями, считывая каждый входящий запрос и отправляя его на самый дешевый уровень, способный успешно его решить. В LangChain это решение естественным образом вписывается в промежуточное ПО (middleware), которое может менять модель, вызываемую агентом, не меняя ничего другого в агенте (см. динамический выбор модели).

Маршрутизатор в Open SWE запускается при получении первого сообщения от пользователя в потоке. Он состоит из трех частей:

  • Базовый промпт: сообщает классификатору его задачу: выбрать наименее дорогую модель, способную выполнить задачу.
  • Критерии для каждого уровня: краткое описание на простом языке того, какую работу должен выполнять каждый уровень.
  • Модель-классификатор: считывает запрос и выбирает уровень в соответствии с критериями и промптом.

Общий бенчмарк — это только отправная точка. Напишите критерии для каждого уровня, основываясь на двух источниках: вашем собственном анализе задач и том, в чем, по словам каждого провайдера, его модели лучше всего справляются. Мы объединили разбивку задач из шага 1 с руководствами провайдеров для GPT-5.6 Sol, GPT-6 Astra и GLM-5.3-Flash, чтобы написать базовый промпт и критерии для каждого уровня.

Эти критерии написаны для набора задач Open SWE, поэтому маршрутизатор глубоко связан с задачами, которые обрабатывает Open SWE. Вот почему он должен находиться в harness, который уже обладает контекстом конкретной задачи агента (его промптом, инструментами и знаниями предметной области), чего нет у общего шлюза.

Наша первая версия использовала LLM со структурированным выводом, с промптом, содержащим запрос пользователя. Теперь классификатор работает на Jev, недавно выпущенной модели принятия решений, что сделало классификацию почти в 50 раз быстрее. Посмотрите, как мы это сделали в статье «Создание Harness с Jev».

Маршрутизатор выбирает модель один раз, в начале каждого потока, и эта модель используется для всего потока. Естественное возражение: что, если поток меняет тему или сложность на лету? Хотя это не рассматривается в данном простом дизайне маршрутизатора, мы освещаем маршрутизацию на лету в разделе «Что дальше» ниже.

Шаг 4: отслеживание результатов задач

Ценность маршрутизатора заключается в снижении затрат, но только если качество не ухудшается. Маршрутизатор должен правильно делать две вещи: выбранная модель должна быть способна выполнить задачу, и это должна быть самая дешевая и быстрая модель, которая может это сделать. Это означает, что вам нужен способ отслеживания результатов задач. Есть два способа сделать это:

  • Автономные оценки (offline evals) запускают маршрутизатор на фиксированном наборе данных, чтобы вы могли безопасно и повторяемо сравнивать версии. Подвох заключается в наборе данных: он должен быть похож на ваш реальный трафик и оцениваться по тому, что важно для ваших пользователей. Для агента по написанию кода это означает качество PR и возможность проверки, которые трудно оценить в автономном режиме.
  • A/B-тестирование разделяет «живые» потоки между маршрутизатором и базовой моделью, сравнивая их по метрике успеха, которую можно измерить для каждого потока. «Живой» трафик естественным образом представляет собой репрезентативный набор данных, но недостаток заключается в том, что пользователи могут столкнуться с потенциально неоптимальным маршрутизатором.

Мы провели A/B-тесты с двумя сигналами результатов:

  • Объединенные PR (Merged PRs): Open SWE теперь записывает каждый открытый PR и информацию о том, был ли он объединен или закрыт. Количество объединенных PR на поток стало нашей основной метрикой успеха.
  • Отзывы пользователей: мы добавили кнопки «палец вверх» и «палец вниз» в Open SWE, чтобы пользователи могли оценивать любой поток, включая вопросы, которые не приводят к созданию PR. Каждая оценка регистрируется как отзыв в трассировке LangSmith для данного потока.

Мы отслеживали оба показателя в пользовательском приложении LangSmith. Объединенные PR оказались более сильным сигналом. Отзывов было мало, так как оценивается лишь небольшая часть потоков, но именно из них мы узнали об ошибках маршрутизации, подобных тем, что приведены в первом тесте ниже.

Эксперимент

Наш первый A/B-тест сравнивал маршрутизатор с использованием нашей самой мощной модели: половина потоков проходила через маршрутизатор, а половина всегда использовала GPT-6 Astra, всего было протестировано 973 потока.

Качество заметно не изменилось. 29,2% маршрутизируемых потоков завершились объединенным PR против 27,3% в контрольной группе (p = 0,49). Показатели открытия PR также остались на прежнем уровне (38,9% против 39,6%, p = 0,82).

Стоимость значительно снизилась. Медианная стоимость маршрутизируемого потока составила $0,94 против $2,61 в контрольной группе, что на 64% меньше. Среднее значение снизилось на 42%, а p90 — на 37%, так что экономия не была обусловлена лишь несколькими дешевыми выбросами.

Большинству запросов не требовалась самая мощная модель. Из маршрутизируемых потоков 56% были направлены на сбалансированную модель, 34% — на быструю, и только 10% — на производительную. Лестница затрат между уровнями крутая: медианная стоимость потока составила $0,097 на быстрой модели, $1,50 на сбалансированной и $2,88 на производительной, что дает 30-кратный разброс.

Отзывы пользователей указывали на то же самое. Когда простой запрос выполнялся на GPT-6 Astra, инженеры прямо указывали на перерасход комментариями вроде: «слишком дорого для этого запроса» и «этот запрос не должен был быть направлен на производительную модель».

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

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

Что дальше

Эта реализация маршрутизатора моделей является доказательством концепции, которая служит основой для создания оптимального маршрутизатора. Вот несколько областей, которые мы могли бы изучить для улучшения:

  • Бенчмаркинг маршрутизатора на DeepSWE или других бенчмарках кодирования, чтобы мы могли оценивать решения по маршрутизации относительно контролируемой базы, а не полагаться только на A/B-тестирование на рабочем трафике.
  • Выбор модели для субагентов. Сейчас субагенты выбирают свою модель независимо от маршрутизатора. Маршрутизация субагентов, особенно в долгосрочных задачах, также может сократить расходы.
  • Перемаршрутизация в середине потока. Когда новое сообщение достаточно сильно отличается от предыдущих, например, вопрос, который превращается в исправление ошибки, смена модели может окупиться. Стоимость заключается в кэше промптов: переключение моделей сбрасывает его, поэтому новая модель повторно считывает поток по полной цене. Для асинхронных агентов эти затраты часто незначительны, поскольку кэш часто истекает в любом случае между действиями человека, когда TTL короткий (например, 5 минут).
  • Уточнение критериев маршрутизации с помощью дополнительных сигналов, таких как анализ настроений пользователей в трассировках: поиск потоков, где пользователи разочарованы, что может означать, что для задачи требовалась более мощная модель.

С чего начать

Если вы добавляете маршрутизацию в своего собственного агента, вот с чего мы бы начали:

  • Поймите задачи. Ваши трассировки содержат реальную запись того, что требуется от вашего агента, а LangSmith Insights помогает вам находить в них закономерности, чтобы вы могли увидеть структуру задач перед выбором уровней.
  • Поймите модели. Выберите несколько моделей вдоль кривой «стоимость-интеллект», опираясь на современные бенчмарки. Интерфейс моделей LangChain работает с разными провайдерами, поэтому вы можете менять модели в любое время без необходимости перепроектировать свое приложение.
  • Создайте маршрутизатор в системе. Относитесь к маршрутизации как к проектированию контекста, аналогично классическому проектированию признаков: решите, какую информацию должен видеть маршрутизатор, чтобы принять наилучшее решение о соответствии модели с учетом домена вашего агента.
  • Отслеживайте результаты задач. Установите показатели успеха перед маршрутизацией: оценки, онлайн-оценщики или отзывы пользователей о трассировках. Если создание набора данных для оценки слишком дорого или сложно, хорошо работает A/B-тестирование на «живом» трафике.

Правильная модель для задачи постоянно меняется, так как новые модели, включая модели с открытыми весами, продолжают появляться на передовой. Поскольку LangChain не зависит от конкретных моделей, использование этих достижений означает смену уровня, а не перестройку вашего агента.

Чтобы добавить маршрутизацию в своего агента, вы можете воспользоваться нашим недавно выпущенным промежуточным ПО для маршрутизации моделей. Предоставьте ему свой базовый промпт, уровни моделей и критерии для каждого из них, и он будет выбирать модель в начале каждого потока. Мы будем рады вашим отзывам в X или на GitHub LangChain issues.

Дополнительная литература

  • Open SWE на GitHub
  • Создание системы с Jev
  • Документация по промежуточному ПО для маршрутизации моделей
  • Документация по наблюдаемости LangSmith
  • Документация по оценке LangSmith
  • Пользовательские приложения LangSmith
  • Регистрация отзывов пользователей в LangSmith
  • Индекс искусственного интеллекта Artificial Analysis

Благодарности

Спасибо Мейсону Догерти, Кевину Фрэнку и Харрисону Чейзу за их вдумчивые отзывы об этой статье. Также спасибо команде OpenSWE, которая поддержала этот эксперимент!

О чём эта статья

Что-то непонятно? Спросите по статье — объясню простыми словами.

Не хотите разбираться сами? Мы поможем.

Ещё в разделе «AI и машинное обучение»

Все →

Ещё от LangChain