Dev48
ЯЗЫК
  • О нас
  • Услуги
  • Индустрии
  • Технологии
  • Статьи
  • Контакты
Забронировать звонок
    Главная/Статьи/Ispolzovanie parallelnyh vyzovov instrumentov dlya uskoreniya agentnogo poiska v
Dev48

© 2026 · All rights reserved.

Использование параллельных вызовов инструментов для ускорения агентного поиска в 4 раза

Источник: Relace

Использование параллельных вызовов инструментов для ускорения агентного поиска в 4 раза

Источник: Relace

Today we're releasing Fast Agentic Search (FAS), a code-specific subagent trained with RL to search through codebases for files relevant to a user request.

25 сентября 2026 г.

Сегодня мы выпускаем Fast Agentic Search (FAS) — специализированный агент для работы с кодом, обученный с помощью обучения с подкреплением (RL) для поиска файлов в кодовых базах, соответствующих запросу пользователя.

FAS использует многошаговое рассуждение и параллельное выполнение инструментов view, grep и bash для одновременного исследования нескольких цепочек файлов. В конце он вызывает инструмент report_back, чтобы упаковать результаты поиска в минимальный набор файлов, которые основной агент может использовать в качестве контекста для реализации желаемых изменений.

Это первый продукт в нашей линейке небольших агентов, совместно оптимизированных с инфраструктурой. Вы можете запустить FAS в любом репозитории Relace с помощью команды relace.repo.search(repoId, { query });, которая использует нашу готовую агентную обвязку, предназначенную для обработки параллельных вызовов инструментов с низкими накладными расходами. Мы также предоставляем публичную конечную точку, которую вы можете использовать для вызова модели из вашей собственной агентной инфраструктуры.

В этом блоге мы подробно расскажем о том, как мы обучали модель FAS, вдохновленную моделью SWE-grep от Cognition.

RAG против агентного поиска

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

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

Однако по мере расширения контекстных окон и улучшения способностей моделей к многошаговому рассуждению ограничения RAG стали более очевидными. Даже при использовании специализированных моделей эмбеддинга/ранжирования для кода получить все релевантные файлы за один проход сложно.

Команда Claude Code под руководством Бориса Черного первой полностью отошла от стандартной настройки RAG, внедрив то, что они назвали агентным поиском. Вместо использования отдельной системы для подбора контекста модель сама находит нужный контекст в кодовой базе, используя инструменты командной строки view и grep.

Команда обнаружила, что это улучшило производительность, но с определенным компромиссом:

Ценой задержки и токенов вы получаете действительно отличный поиск.

Ценой задержки и токенов вы получаете действительно отличный поиск.

Если вы пробовали Claude Code, вы, вероятно, поняли, почему. Модель работает последовательно, методично рассуждая о том, какие разделы кодовой базы являются релевантными.

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

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

Изоляция задачи поиска

Конечно, специализированная модель, такая как FAS, полезна только в том случае, если вы можете действительно отделить поиск от остальной части задачи агентного программирования.

Чтобы измерить эту возможность разделения, мы использовали агент программирования для решения набора из ~1200 задач по программированию и искали первый вызов инструмента, не связанный с поиском, в каждой трассировке, например, инструмент редактирования файла или какой-либо bash-скрипт для тестирования.

Мы обнаружили, что в среднем поиск составляет 56,6% от всех токенов, потребляемых моделью на протяжении всей трассировки.

Многие токены, встречающиеся во время поиска, также оказываются нерелевантными. Оформление сбора контекста как отдельной задачи с этапами поиск --> фильтрация --> отчет предотвращает загрязнение контекста.

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

Построение среды RL

До появления FAS мы обучали модели только с использованием контролируемого дообучения (SFT) на наборах данных, состоящих из пар «вход-выход» чрезвычайно высокого качества.

Это было полностью «вне политики» (off-policy), то есть данные, которые мы собирали, не были взяты из базовой модели, которую мы обучали.

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

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

Для обучения FAS мы решили, что необходимо создать конвейер обучения с подкреплением «в рамках политики» (on-policy). Вот как мы настроили среду:

Определение примера поиска

Для FAS каждая точка данных состоит из начального состояния репозитория, хранящегося как Relace Repo, вместе с задачей программирования, определенной промптом пользователя.

Мы собираем эти пары «репозиторий/промпт» из (1) партнерств по данным с компаниями, занимающимися разработкой приложений через промпты, и (2) пулл-реквестов, полученных из открытых репозиториев GitHub.

Преимущество (1) заключается в том, что данные берутся непосредственно из распределения, которое мы ожидаем увидеть в продакшене для наших клиентов. Недостаток в том, что нам нужно синтетически создавать «золотой стандарт» (ground truth).

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

В случае (2) ситуация обратная. Мы можем создать безупречный «золотой стандарт», взяв файлы, фактически отредактированные разработчиками в пулл-реквесте. Однако мы используем LLM для перевода истории комментариев пулл-реквеста в реалистичный, полный промпт пользователя, описывающий задачу. Для этого набора данных у нас нет аналога «просмотренных» файлов.

Агентная обвязка

Мы запускаем FAS внутри фиксированной агентной обвязки, которая предоставляет небольшой специализированный набор инструментов.

Обвязка оснащает базовую модель пятью инструментами: view_file, view_directory, grep_search, bash и report_back.

Промпт инструктирует модель исследовать репозиторий с помощью этих инструментов, а затем вернуть результаты через инструмент report_back в структурированном формате:

Каждый путь к файлу соответствует списку диапазонов строк [начало, конец], которые имеют отношение к задаче.

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

Мы подробно описываем полную обвязку и промпт здесь.

Функция вознаграждения

Основываясь на литературе по обучению моделей для глубоких исследований, мы решили оценивать производительность модели FAS с использованием F-меры инструмента report back, то есть гармонического среднего точности и полноты.

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

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

Для данных GitHub (2) в качестве эталона у нас есть только отредактированные файлы. Модель может правильно определить релевантные справочные файлы, которые не были отредактированы, но они будут помечены как ложноположительные результаты. Чтобы учесть эту несовершенную истину, мы используем \(F_2\)-меру, чтобы придать полноте (recall) в 2 раза больший вес, чем точности (precision):

$$A_2 = \frac{5 P_h R_h}{4 P_h + R_h}$$

где \(P_h\) и \(R_h\) — «жесткие» точность и полнота, вычисленные по отредактированным файлам. Это снижает значимость точности, поскольку мы ожидаем, что некоторые ложноположительные результаты на самом деле верны.

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

$$A_1 = \frac{2 P_s R_h}{P_s + R_h}$$

где \(P_s\) — точность, вычисленная по просмотренным файлам, а \(R_h\) — полнота по отредактированным файлам. Это позволяет избежать штрафов за правильные предсказания, которые также были просмотрены в процессе исследования.

Второй критический компонент — штраф за параллелизм. Хотя базовая модель была оснащена инструкциями для параллельного вызова инструментов, она чаще выполняла поиск последовательно. Наша гипотеза заключалась в том, что мы можем распараллелить поиск с помощью 4–12 одновременных вызовов инструментов за ход и значительно сократить общее количество ходов, сохраняя при этом производительность.

Чтобы стимулировать меньшее количество ходов и при этом оставаться устойчивыми к «взлому вознаграждения» (reward hacking), мы применили штраф, который не действует при \(n \leq 4\) ходах, но линейно убывает до нуля при \(n = 24\) ходах:

$$P = \max\left(0, \frac{n_{\max} - n}{n_{\max} - n_{\min}}\right) \quad \text{где } n_{\min} = 4,\ n_{\max} = 24$$

Объединяя эти компоненты, получаем итоговое вознаграждение:

$$R = A \cdot P \quad \text{где } A = \begin{cases} A_1 & \text{на наборе данных (1)} \\ A_2 & \text{на наборе данных (2)} \end{cases}$$

Обучение модели

Настройка конвейера обучения с подкреплением с гибкостью, необходимой для задачи поиска, заняла около 1 месяца.

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

Мы строили решение на базе verl и использовали Nebius для доступа к узлам 8xH200. Обучение заняло около 1,5 дней на одном узле в течение 3 эпох на 3,2 тыс. высококачественных точек данных.

Ниже вы можете увидеть прогресс функции вознаграждения вместе с количеством ходов генерации, необходимых во время обучения:

Эмерджентное рассуждение

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

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

Однако, как только количество ходов стабилизировалось ниже \(n_{max}\), модель больше не могла извлекать дополнительное вознаграждение только за счет параллелизма. Это привело к временной остановке роста вознаграждения. После этого плато точность начала улучшаться, и вознаграждение снова выросло.

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

Это подтверждает интуицию Бориса и команды Claude Code о том, что агентный поиск превосходит RAG, потому что он многошаговый — модель может итеративно уточнять свое суждение о релевантности файлов, рассуждая об информации, собранной из других файлов.

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

Оценка модели

Для оценок, представленных на Рисунке 1, мы отложили 889 точек данных, чтобы справедливо сравнить их с другими моделями на рынке — 465 из этих точек данных поступили из набора данных (1), а 424 — из набора данных (2).

В обеих задачах мы значительно сократили количество ходов: с 20 до 5 в (1) и с 10 до 4 в (2). Это привело к более чем 4-кратному сокращению сквозной задержки в обоих случаях при сохранении аналогичной точности по сравнению с такими моделями, как Claude 4.5 Sonnet!

Поскольку задача поиска сильно зависит от префилла (prefill) с соотношением входных/выходных данных 15:1, мы обнаружили, что выходная скорость (TPS) гораздо менее важна, чем сокращение количества ходов генерации и накладных расходов агентной обвязки.

Вышеуказанные ускорения были достигнуты с использованием стандартного движка вывода, работающего на скорости ~200 TPS.

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

Эксперименты SWE-Bench

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

Мотивация

Наша цель для этих экспериментов была двоякой:

  • Сохранить или улучшить производительность агента с FAS

Сохранить или улучшить производительность агента с FAS

  • Сократить общее время генерации

Сократить общее время генерации

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

Для этого мы настроили обоих агентов на выполнение SWE-Bench verified и записали как точность, так и задержку.

Передача контекста

Перед запуском всех 500 примеров мы попробовали различные стратегии передачи между FAS и Оракулом, чтобы минимизировать дублирование усилий (повторный просмотр одних и тех же файлов) и регрессию производительности.

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

Вы можете прочитать подробнее о точных инструкциях по передаче в нашей документации.

Результаты

Ниже приведены результаты эксперимента:

Стратегия

Медианная задержка

Точность

Всего токенов

FAS + Оракул

7м 1с

71.4%

890М

Стандартный Оракул

7м 44с

72.0%

1.03Б

Интеграция FAS снижает медианную задержку на 9,3% (43 секунды) и сокращает общее использование токенов на 13,6% (140 млн токенов) при сохранении сопоставимой точности.

На первый взгляд, это улучшение кажется небольшим, учитывая, что FAS обеспечивает ~4-кратное сокращение задержки для самого поиска.

Однако мы обнаружили, что для трассировок SWE-bench начальный поиск составляет лишь ~12% от общего количества токенов во всей траектории агента. Постановки задач богаты деталями и часто прямо указывают релевантные файлы.

Это резко контрастирует с нашими 1200 реальными трассировками «vibe-coding», где пользователи дают расплывчатые инструкции, которые приводят к тому, что почти 60% трассировки занимает поиск. Мы ожидаем, что в этих производственных условиях выигрыш будет намного больше.

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

Попробуйте модель

FAS теперь доступна поверх Relace Repos с нашей оптимизированной средой для агентов. Попробуйте ее на нашей площадке и дайте нам знать, что вы думаете!

Мы также выпустили совместимую с OpenAI конечную точку как на платформе Relace, так и на OpenRouter по цене 1 доллар за миллион входных токенов и 3 доллара за миллион выходных токенов.

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

Мы нанимаем

Если вы дочитали до этого места, скорее всего, вам было интересно!

Мы нанимаем прагматичных исследователей (физика/математика/информатика/машинное обучение) и выдающихся инженеров для создания подобных моделей, на которые полагаются реальные продуктовые команды. Загляните на нашу страницу вакансий и присоединяйтесь к нам!

← Все статьи