
Всем привет! На связи Толя Потапов, MLE в Т-Банке. Продолжаем развивать линейку открытых моделей Gen-T. Мы делились русскоязычными семействами моделей T-Lite и T-Pro. Сегодня выпускаем модель другого класса — T-Search. Это открытый агент-ретривер для сложного многошагового поиска.
Классический RAG предполагает, что ответ находится по формулировке вопроса: один запрос — и нужный документ в топе выдачи. Но реальные вопросы часто устроены иначе: чтобы найти финальный документ, нужно узнать промежуточную сущность, не названную в вопросе, из другого источника, отсеять правдоподобные, но неверные документы и не потерять по дороге ключевой факт.
T-Search — именно такой агент. Он построен на базе Qwen3.6-35B-A3B и обучен полностью на синтетических данных, которые мы генерировали под собственный харнесс. Важная особенность: T-Search не пишет финальный ответ, а отдает ранжированный список чанков, генерацию можно доверить любой модели под требования конкретного продукта.
Вместе с моделью выкладываем в open source два бенчмарка:
-
TRuST — первый бенчмарк сложного агентского поиска на русском языке, собранный вручную;
-
SynthComp — синтетический бенчмарк в двух версиях, на русском и английском, с фиксированными индексами.
В статье расскажу, как устроен харнесс, как мы построили фабрику синтетических поисковых задач с состязательным циклом проверок, какие решения принимали на SFT- и RL-стадиях и как мерили качество.
Харнесс: как устроена обвязка агента
Качество в задачах сложного агентского поиска зависит не только от модели, но и от харнесса — обвязки, которая определяет, какие инструменты видит модель, как форматируются результаты и что происходит, когда заканчивается контекст. Одна и та же модель в разных харнессах может показывать разные цифры, поэтому харнесс мы проектировали так же внимательно, как обучали модель.
T-Search — агент-ретривер. Его задача — сбор контекста, а не написание красивого ответа. Генеративную часть мы сознательно оставляем на стороне пользователя. Требования к финальному ответу у всех разные: стиль, формат, правила цитирования, продуктовые ограничения — каждый потребитель решает это по-своему. А вот сбор контекста мало зависит от различных сценариев. Поэтому на выходе ретривер отдает не текст, а ранжированный список evidence-чанков с обоснованиями — дальше по нему можно генерировать ответ любой моделью и в любом формате.
С другой стороны, любая длинная агентская задача рано или поздно упирается в одну проблему: контекстное окно заполняется результатами вызовов инструментов, большинство из которых уже не нужны. Еще до исчерпания токенов накопленный шум начинает снижать качество работы модели — этот эффект называют context rot. Перед проектированием харнесса мы изучили, как с ним борются существующие системы:
-
Claude Code и Codex периодически суммаризуют историю с помощью LLM и заменяют ее компактным блоком;
-
MemGPT добавляет внешнюю память в отдельную базу знаний, доступную через поисковые инструменты;
-
Chroma Context-1 обучила модель редактировать контекст напрямую: инструмент prune_chunks точечно удаляет нерелевантные фрагменты без суммаризации остального.
Свой пласт решений сложился в недавних релизах открытых моделей: почти каждый репортит агентские бенчмарки с пометкой with context management: DeepSeek-V3.2 сравнивает суммаризацию переполненной траектории, удаление первых 75% истории вызовов и полный сброс контекста (Discard-all), при котором остается только исходная задача, Kimi K2.5, GLM, Qwen3.5 следуют похожим способам управления контекстом.
Самый показательный прием — Discard-all. Он прост и дает измеримый прирост на бенчмарках, но, по сути, представляет собой серию независимых попыток. Сами DeepSeek показывают, что по качеству Discard-all сопоставим с параллельным запуском N траекторий. Информация, добытая путем дорогих вызовов инструментов, теряется и добывается заново в каждом раунде. Для ретривера это особенно болезненно: его цель как раз в том, чтобы найти и сохранить правильные документы.
Суммаризация — тоже плохой вариант. Модель может сгладить оговорку, потерять отрицание или превратить слабый сигнал в уверенный факт. Для сложного агентского поиска это критично: правильный ответ часто держится на одной строке одного документа, и, если она потерялась при пересказе, цепочка фактов ломается.
Мы исходим из другой постановки. Контекстное окно у агента фиксированное и относительно небольшое по сравнению с полной длиной поиска. Раунды — это способ имитировать более длинный рабочий контекст: каждый новый раунд получает чистое окно, но стартует не с нуля, а с памяти, собранной раньше. В эту память попадают сами evidence-чанки, которые агент явно решил сохранить. Ненужные чанки агент может выборочно удалить, чтобы они не превращались в новый источник шума.
Как устроен агент. Ретривер работает раундами, внутри раунда это обычный ReAct-loop с инструментами, бюджетом около 32 000 токенов и тремя инструментами:
-
search_corpus— поиск по корпусу, возвращает чанки документов; -
save_and_advance— сохранение важных чанков и переход в новый раунд; -
finalize_ranking— завершение поиска и выдача ранжированного списка чанков.
Агент видит исходный вопрос, уже сохраненные чанки и текущее состояние покрытия задачи: какие части вопроса уже подкреплены evidence, а какие еще остаются открытыми. Дальше он сам выбирает поисковые запросы, смотрит найденные чанки и решает, что делать: искать еще, сохранить состояние и перейти в новый раунд или финализировать результат.
Когда заполнение контекста достигает 75% окна, search_corpus блокируется. У агента остается два действия: финализировать поиск или вызвать save_and_advance. В save_and_advance он явно собирает память для следующего раунда:
-
какие чанки сохранить и зачем нужен каждый;
-
какие части вопроса покрыты, какие остаются открытыми;
-
что было испробовано и какой следующий шаг имеет смысл.
Через границу раунда не проходит вся история вызовов инструментов, а нерелевантные результаты из предыдущих раундов и промежуточный шум могут быть удалены. С этого контекста и исходного вопроса начинается новый раунд.
save_and_advance или finalize_rankingБез дополнительных ограничений агент легко уходит в один из плохих режимов. Он может слишком часто сбрасывать контекст и фактически превратить раунды в Discard-all. Может, наоборот, сохранять все подряд и перенести context rot в память. А может финализировать после первой удачной находки, не закрыв остальные части вопроса. Поэтому харнесс дисциплинирует поведение в нескольких местах:
-
Не даем использовать новый раунд как дешевый сброс контекста. В текущей конфигурации агент может вызвать
save_and_advanceпосле пяти поисковых запросов и сохранить хотя бы один чанк с объяснением. Этот порог относится только к переходу между раундами: если простой вопрос решается одним запросом, агент может сразу завершить поиск черезfinalize_ranking.Таким образом, пять запросов — это защита от почти пустых сбросов контекста, а не обязательный минимум для каждой задачи.
-
Не даем завершать поиск, пока большая часть вопроса остается открытой. При сохранении или финализации модель сама перечисляет покрытые и нерешенные части задачи. Харнесс не угадывает покрытие по тексту — он проверяет переданные списки covered и unresolved. Если нерешенной остается половина или больше частей и это не последний раунд, финализация отклоняется. Суммарное количество раундов при этом у задачи ограничено, не больше 5, и на последнем раунде сохранение (инструмент
save_and_advance) отключается — агент обязан отдать лучший найденный набор, даже если часть вопроса осталась без ответа.
-
Не возвращаем уже просмотренные результаты. Харнесс фильтрует результаты, которые агент видел в текущем раунде, и не возвращает чанки, которые лежат в контексте. При этом чанки, которые встречались в прошлых раундах, но не были сохранены, могут появиться снова: если новый запрос снова приводит к тому же документу, возможно, агент преждевременно его отбросил.
-
Не разрешаем искать дважды одними словами. Если агент повторяет тот же поисковой запрос с отличием только в регистре или пробелах, харнесс отклоняет вызов. Это простая защита от бесполезного цикла: модель не может искать еще буквально по тем же словам и получать тот же результат.
Синтетические данные: как генерировали сложные поисковые задачи
Под собственный харнесс нужны собственные данные. Нам требовалась полноценная поисковая задача: вопрос, фиксированный индекс, размеченные чанки и траектория решения — с помощью тех же инструментов и в той же среде, в которых затем будет работать T-Search. Готовых датасетов с такой структурой почти нет: обычно в открытом доступе лежат либо обычные QA-пары, либо вопросы с несколькими приложенными документами, либо готовые траектории в другом харнессе. Быстро стало понятно, что весь объем тренировочных данных необходимо создавать самим — причем сразу нативно на двух языках со своими локальными индексами.
Почему сложно сгенерировать вопрос. Самый прямой подход к генерации вопроса выглядит так: дать модели доступ к поиску, запустить ее как агента и попросить исследовать корпус. Потом найти несколько связанных фактов и собрать из них вопрос (Context-1: генерация данных). Другой распространенный вариант — сначала построить граф знаний на основе индекса, а затем генерировать вопросы по его цепочкам (например, подход Tongyi). Оба подхода рабочие, но сильно зависят от модели-генератора.
Модель фронтирного уровня еще можно убедить придумать действительно сложную поисковую задачу, но нам этот путь не подходил: генерация нужна массовая, с постоянными перезапусками и сменой фильтров и стратегий отбора под тренировочный датамикс, а на фронтирной модели это неоправданно дорого. Поэтому мы сразу делали ставку на относительно небольшую локальную модель.
При этом небольшая модель с задачей в лоб не справляется. Вопрос может выглядеть убедительно — длинная формулировка, несколько условий, редкие сущности, — но для ретривера он оказывается простым. Иногда достаточно скопировать почти весь вопрос как поисковый запрос, и нужный чанк сразу появляется в top-k поисковой выдачи. Или один документ уже содержит все необходимое для ответа, хотя задача формально размечена как многошаговая. А иногда вопрос задается о чем-то, что модели и так хорошо известно, — ответить можно вообще без поиска, просто из весов. Визуальная сложность вопроса и реальная сложность поиска, который нужен для ответа, — разные вещи.
Первая итерация: генератор-исследователь. В качестве первой версии пайплайна мы адаптировали подход в духе Context-1. Агент-генератор ходил по индексу, находил несколько документов, извлекал из них связанные факты, а затем составлял вопрос и короткий ответ.
Метод оказался рабочим: на выходе получались QA с опорными документами и на таких вопросах уже можно было собирать поисковые траектории. Но довольно быстро проявилось ограничение. Большинство вопросов сводилось к одному паттерну — цепочке подсказок, в конце которой нужно назвать последнюю найденную сущность. Так можно выучить только один шаблон поведения. Кроме того, небольшой генератор часто выбирал слишком очевидные факты: вопрос выглядел многошаговым, но на практике решался с помощью одного широкого запроса или вовсе без поиска.
Таксономия: формализация вопросов. Мы проанализировали большой пул поисковых вопросов и разложили их по нескольким осям (Google Research). Нас интересовала не только тема, но и то, какое поведение требуется от поискового агента: пройти по цепочке сущностей, пересечь несколько независимых ограничений, учесть момент, собрать множество кандидатов, сравнить их или выполнить вычисление по ходу рассуждения. Отдельно учитывались форма вопроса, тип ответа, характер дистракторов — отвлекающих документов, которые похожи на нужные, но не содержат ответа, — и другие свойства.
Совместимые значения осей складывались в ячейки — конкретные сочетания вида «механика + форма + тип ответа». Перед каждой генерацией мы сэмплировали одну такую ячейку и передавали ее генератору как явное задание, а веса сэмплирования подкручивали так, чтобы покрытие оставалось равномерным. Это дало сразу два преимущества — контроль над балансом датасета и разнообразие собираемых траекторий по поисковым навыкам. Таксономия закрыла проблему разнообразия. Но вопрос все равно мог иметь короткий путь к ответу. Поэтому следующим шагом мы перенесли контроль сложности из промпта в саму структуру исходных данных.
Упрощение задачи для генератора. Вместо того чтобы просить небольшую модель самостоятельно исследовать весь индекс и искать подходящую цепочку, мы заранее подготавливали перспективный подграф документов. В такой подграф входит несколько чанков, связанных промежуточными сущностями, событиями, датами или другими ограничениями. Мы находили их по NER-разметке корпуса и статистикам индекса — частоте упоминаний сущностей и их совместной встречаемости. Особое внимание уделяли нишевым сущностям и неочевидным связям: чем менее очевидна стартовая точка, тем ниже вероятность, что ответ уже хорошо известен модели или находится путем одного общего запроса.
Факты из чанков при этом не попадали к генератору дословно. Сначала они извлекались и перефразировались, и вопрос дальше строился по промежуточному представлению, без доступа к исходным цитатам. Это защита от буквального копирования: редкая фраза, перекочевавшая из чанка в вопрос, — почти идеальный поисковый запрос. После перефразирования лексических подсказок остается меньше и поисковому агенту приходится идти по смыслу и промежуточным сущностям, а не по скопированной строке. Риск галлюцинаций при перефразировании есть, но вопрос с искаженным фактом не пройдет проверку решаемости. Если не делать перефразирование и в вопросе будет дословная цитата, такой вопрос не пройдет проверку прямым запросом в поиске. У маленькой модели склонность к цитированию оказалась сильнее склонности к искажениям, поэтому с перефразированием выход качественных вопросов оказался заметно выше.
Важным решением оказалось постепенное наращивание сложности. Композитор сначала строил относительно простой вопрос, затем добавлял еще один переход, еще одну сущность или ограничение. После каждого шага проверялось, что вопрос по-прежнему решаем, а новый чанк действительно добавляет необходимый этап поиска.
Инкрементальная композиция заметно повысила стабильность генерации на небольшой модели. Собрать хороший многошаговый вопрос сразу трудно. Гораздо надежнее строить по одному шагу за раз, постоянно проверяя промежуточный результат.
Состязательный механизм. Мы упростили задачу, но даже хороший подграф и аккуратный композитор не гарантируют честную сложность. Поэтому вокруг генератора построили замкнутый цикл проверок. Композитор создает вопрос, а следующие стадии пытаются найти способ решить его в обход изначально задуманной цепочки.
Сначала проверяется базовая решаемость: полного набора опорных чанков, выделенных генератором, должно хватать, чтобы однозначно получить ответ. Сложный, но неразрешимый вопрос для обучения бесполезен.
Затем мы проверяем, не выдает ли формулировка слишком много. Ответ и ключевые промежуточные сущности не должны быть названы напрямую или почти напрямую. Иначе вместо исследования корпуса поисковому агенту достаточно зацепиться за готовую подсказку.
Следующая проверка — широкий поисковый запрос. Мы намеренно пробуем решить задачу самым ленивым способом: подаем весь вопрос в один поисковый запрос и смотрим, не появляются ли нужные документы сразу в верхней части выдачи.
После этого проводится тест необходимости чанков. Каждый опорный чанк по очереди убирается из контекста, и мы снова проверяем решаемость. Если без какого-то чанка ответ все еще легко выводится, значит, этот чанк был декоративным и не вынудит поискового агента сделать дополнительные шаги поиска. Такие чанки удаляются из списка опорных. В финальном примере остается только минимально достаточный набор.
Наконец, на вопрос запускается полноценный поисковый агент: та же модель, что генерировала вопрос, работает уже в поисковом харнессе и пытается найти ответ. Нас интересует не только финальный ответ, но и итоговый recall траектории. Если агент справился с задачей легко, считаем, что вопрос недостаточно сложный и требует доработки. Совокупность проверок повышает уверенность в сложности вопроса, а порядок от дешевых к дорогим позволяет отсеивать слабых кандидатов без лишних затрат вычислительных ресурсов.
Результат проверок возвращается композитору: какой чанк оказался лишним, где формулировка подсказала связь, какой запрос сразу нашел ответ. Генератор на основе обратной связи исправляет задачу и снова отправляет ее на проверку.
Получается состязательный цикл: композитор строит вопрос, а остальные компоненты пайплайна ищут в нем слабые места. В датасет попадают только примеры, пережившие этот цикл. В итоге состязательный цикл пережили около 60% кандидатов: из ~67 000 сгенерированных вопросов в пуле осталось ~40 000.
Устойчивость к ретриверам. Еще один риск — обучить модель особенностям конкретного ретривера. Например, она может привыкнуть к характеру выдачи одного эмбеддера. Поэтому данные собирались в нескольких режимах. Основной объем строился на семантическом поиске, но часть траекторий мы дистиллировали с BM25 и гибридным поиском, варьируя эмбеддеры и размер выдачи поискового инструмента.
В результате каждый пример содержит не только вопрос и ответ — мы знаем, какие чанки действительно необходимы, чтобы на этот вопрос ответить. По готовым задачам мы собирали траектории сильной модели-учителя на фиксированном локальном индексе. Эти траектории стали основой для SFT, а отдельный пул задач пошел на этап RL. Главный результат стадии — не столько датасет, сколько управляемая фабрика поисковых задач.
Рецепт обучения T-Search
Модель T-Search обучалась по двухэтапному рецепту с параллельными языковыми ветками. Сначала базовая модель прошла SFT отдельно для русского и английского языков, после чего полученные чекпоинты были объединены в одну SFT-модель через DARE-мерджинг. Процедура повторилась на этапе RL: русская и английская ветки обучались независимо с последующим SLERP-мерджингом.
Раздельное обучение позволяет каждой ветке выучить свой язык без взаимной интерференции при обучении, а слияние весов — сохранить результаты каждой компоненты в одной модели. Стратегия мерджинга на каждом этапе выбиралась эмпирически с учетом поведения объединенной модели: мы статистически оценивали качество рассуждений и поиска, стабильность генерации, а также устойчивость работы в харнессе.
Стадия SFT. После генерации вопросов и сбора траекторий учителя оставалось превратить эти траектории в тренировочные данные, на которых можно обучать T-Search. Наивный вариант — взять все получившиеся траектории и обучить модель повторять их целиком. Но траектории получаются длинными, содержат тупиковые запросы и повторы. При этом два внешне похожих действия могут иметь совершенно разную ценность: один запрос открывает новую ветку поиска, другой просто еще раз приносит уже известные документы. Поэтому SFT-этап для нас начинался не с обучения, а с определения того, что именно считать хорошим поисковым поведением.
Единицей обучающего примера стал раунд. По устройству харнесса он самодостаточен: внутри есть исходный вопрос, память, серия поисков и решение, чем закончить эпизод. Так одна длинная траектория превращается в несколько компактных сэмплов с разными состояниями задачи — от старта с нуля до финализации.
Даже сильный учитель не всегда следует харнессу идеально. При этом харнесс сам отлавливает ошибочные действия, поэтому их легко пометить и исключить из подсчета loss. А вот продолжение учителя после ошибки часто содержит полезный паттерн: модель получает сигнал от среды, пересматривает решение и приходит к правильному действию — это ценные обучающие примеры, их мы оставляли. Дополнительно каждый обучающий turn проходит базовые проверки: корректно ли сформирован вызов инструмента, заполнены ли обязательные аргументы его схемы, не раздуты ли рассуждения. Зацикленные и неоправданно длинные цепочки размышлений в обучение не идут.
В начале каждого раунда мы знаем, какие чанки уже сохранены. Поэтому в конце раунда можно измерить, появилось ли что-то новое. Если после серии поисков агент сохранил новый необходимый чанк, раунд можно считать продуктивным. Если же он сделал десяток запросов, но закончил с тем же набором документов, такой эпизод вряд ли стоит добавлять в SFT. Для раундов, завершившихся вызовом save_and_advance, мы смотрели, нашел ли агент хоть что-то новое из необходимого относительно состояния на входе. Для раундов с финализацией важно, насколько полно итоговый набор покрывает размеченные чанки.
Синтетика специально создавалась без простого пути к ответу, поэтому многие вопросы трудны даже для модели-учителя и фильтр по высокому recall незаметно сместил бы датасет в сторону легких задач. Так модель не увидит поведения на действительно трудном хвосте. Траектория даже с низким recall может оставаться полезной: например, учитель правильно декомпозировал вопрос, собрал большую часть доказательств, но под конец споткнулся. Раундовая нарезка позволяет распорядиться такой траекторией аккуратно: продуктивные раунды, где агент продвигался к ответу, идут в обучение, а слабая финализация с плохим покрытием отбрасывается. Модель видит, как действовать в трудной ситуации, но не учится считать неполный результат успехом.
Естественное распределение раундов сильно несбалансированно. Простых начальных раундов обычно больше, чем хороших продолжений. Если оставить распределение как есть, модель начнет слишком охотно завершать поиск и хуже освоит длинные стратегии.
Поэтому при сборке итогового SFT-датамикса мы контролировали сразу несколько измерений одновременно:
-
номер раунда;
-
способ его завершения;
-
сложность и механику исходного вопроса;
-
полноту найденных чанков.
У массовых ячеек вроде первых раундов стоял верхний потолок, а редкие, но важные, шли в микс целиком. Например, поздние раунды, где агент все еще находит новое.
Оба SFT-датамикса после отбора данных на английском и русском языках состояли из 11 000 тренировочных примеров (8 000 уникальных вопросов). При этом четверть из них составляли сабсеты на устойчивость к ретриверам: на RL-стадию обучения мы отложили еще по 2 000 вопросов на язык из непересекающегося с SFT пула. В итоге SFT-этап повысил устойчивость работы модели в харнессе и улучшил базовые поисковые навыки.
В RL-стадии мы оптимизируем всю поисковую политику end-to-end. Модель получает вопрос и дальше действует сама: формулирует поисковые запросы, читает выдачу, решает, какие чанки сохранить через save_and_advance, и завершает траекторию вызовом finalize_ranking.
Награда устроена так, что по построению не требует ни LLM-судьи, ни сравнения текстов. Мы напрямую сопоставляем chunk_id, которые модель выдала в финальном ранжировании, с эталонными чанками из данных. Используем recall по этому множеству как основную награду. Precision и F-меру для каждой траектории тоже считаем, но как диагностику, а не как обучающий сигнал.
Основной тренировочный сигнал при этом сознательно сделан recall-oriented, и причина чисто практическая. В нашей задаче ошибки асимметричны: «не нашел нужный факт» намного хуже, чем «принес лишний документ». К этому мы пришли не сразу.
Сначала пробовали награды на базе precision/F1: они плохо ведут себя на ранних степах RL. Модель быстро выучивает консервативную стратегию: меньше ходит в поиск, раньше финализирует и получает приемлемый precision при низком покрытии вопроса. Формально награда растет, фактически поисковый агент деградирует. Поэтому основной сигнал был выбран как recall: finalize_ranking вознаграждается за найденные эталонные чанки, а лимит на число возвращаемых из нашего харнесса чанков защищает от бесконтрольного раздувания контекста.
На стороне оптимизации политики мы ушли от ванильного GRPO к GSPO. Для MoE это важно из-за несовпадения маршрутизации экспертов в средах генерации и обучения. В GSPO Importance Ratio рассчитывается на уровне последовательности, поэтому токеновые расхождения роутинга усредняются. Это позволяет отказаться от routing replay, то есть от записи и последующего воспроизведения решений роутера при расчете градиентов.
Отдельно мы проверяли CISPO, но на rollout с tool calls он работал нестабильно: в некоторых конфигурациях модель нарушала синтаксис вызовов инструментов, что приводило к снижению награды.
Итоговая рабочая схема: RL сразу на полных поисковых траекториях с вызовами инструментов, recall по эталонным чанкам как награда вместо награды за текстовый ответ и GSPO как более стабильная альтернатива GRPO/CISPO для MoE.
Бенчмарки
Основная проблема существующих search-бенчмарков заключается в том, что они оценивают модели не на зафиксированном корпусе документов, из-за чего результаты плохо сопоставимы между собой. Бенчмарков с фиксированным ограниченным корпусом немного, а их методологии местами расходятся. Отсюда возникает потребность в едином пайплайне, который оценивал бы модели в одинаковых условиях на разных корпусах и наборах данных.
В качестве основы выбрали BrowseComp-Plus с фиксированным корпусом и готовой методологией оценки. Под него адаптировали бенчмарк SealQA — его сабсет Seal-Hard и собственный фиксированный корпус. Каждый документ SealQA разбили на чанки размером 512 токенов, после чего разметили чанки на «необходимость для ответа». Задачей было определить, какие именно чанки требуются, чтобы правильно ответить на вопрос.
Оценка на бенчмарке проводилась на уровне чанков. Из набора удалили 33 вопроса, поскольку их документы либо не содержали полезной для ответа информации, либо противоречили правильному ответу.
Еще одно ограничение существующих бенчмарков в том, что они оценивают поисковые способности моделей преимущественно на английском языке, а русскоязычные аналоги отсутствуют. Это создает потребность в локализации и создании русских бенчмарков. Так получили TRuST, собранный полностью вручную, и русскоязычную версию SynthComp, сгенерированную синтетически.
Локализация BrowseComp-Plus и SealQA выполнялась по двум траекториям: перевод корпуса текстов и перевод вопросов и ответов. Пайплайн перевода опирается на строгие правила, сохраняющие именованные сущности, числа и единицы измерения, структуру и форматирование, а также стилистику оригинала. Проверка возможности дать правильный ответ по голд-текстам показала, что перевод не разрушает связку фактов: процент правильных ответов остался на уровне оригинального BrowseComp-Plus.
При этом самой по себе локализации недостаточно для полноценной русскоязычной версии задачи: перевод проверяет скорее языковую устойчивость модели, а не способность к поиску на русском языке. Если вопрос касается англоязычной сущности, ответ часто находится в англоязычных источниках или в знаниях самой модели. Даже при русскоязычной формулировке вопроса модель внутри поискового цикла все равно формирует 60—80% запросов на английском, а промпт-усиление на язык и локализация среды стабильного эффекта не дают.
TRuST-бенчмарк
Нам нужен был бенчмарк, который оценивает поиск в русскоязычном вебе, а не качество перевода. Так появился TRuST (T-Tech Russian Search Test) — бенчмарк на основе BrowseComp-Plus. Он оценивает, насколько LLM умеет искать и связывать информацию именно в русскоязычной части веба.
TRuST построен по методологиям BrowseComp и BrowseComp-Plus и представляет собой набор из 324 сложных вопросов с короткими однозначными ответами. Эти вопросы нельзя уверенно решить только за счет знаний модели или одного поверхностного запроса: для ответа нужно пройти поисковую цепочку, связать несколько источников и не попасться на правдоподобные, но неверные документы.
Важная особенность TRuST — фиксированный индекс, как в BrowseComp-Plus. В отличие от live-web-бенчмарков агент ищет не в интернете напрямую, а по заранее собранному индексу документов. Такая постановка делает оценку воспроизводимой, уменьшает зависимость от изменений поисковой выдачи и позволяет отдельно анализировать качество retrieval.
Задачи в TRuST собрали вручную с помощью 15 разметчиков. Они искали исходные факты, превращали их в вопросы, подбирали подтверждающие источники и проверяли, что ответ не находится путем простого поиска по формулировке или ее перефразированию.
Задачи собирались в разрезе двух осей: по тематике и по типу поисковой сложности. Тематическая разметка нужна, чтобы бенчмарк покрывал разные области русскоязычного веба, а типы задач — чтобы понимать, какую именно способность агента проверяет конкретный вопрос.
Всего мы выделили 8 тематик: бизнес и технологии, спорт, новости и политика, наука и академические публикации, медиа и искусство, регулирование и право, география, история и архивы.
Покрытие по тематикам позволяет не сводить оценку к одному домену: агенту приходится работать и с региональными новостями, и с официальными документами, и с культурными источниками, и с научными публикациями, и со спортивными таблицами.
Помимо тематики каждая задача относится к одному из 5 типов поисковой сложности:
-
Multihop — задачи, в которых нужно связать факты из нескольких источников;
-
Structured Evidence — ответ находится в таблицах, списках, PDF, реестрах или других структурированных документах;
-
Temporal Tracking — когда нужно учесть изменения во времени: переименования, смену статуса, должности или актуальной версии документа;
-
Entity Disambiguation — задачи, где необходимо отличить нужную сущность от однофамильцев, похожих организаций, аббревиатур или региональных совпадений;
-
Comparative Reasoning — задачи со сравнением нескольких сущностей по найденным свойствам.
Типология сложности вдохновлена подходом SealQA, где важна не только предметная область вопроса, но и структура рассуждения, необходимая для ответа.
Задачи для TRuST собирались разметчиками без профильного опыта в ML/NLP. Это было важно, потому что мы хотели получить не вопросы, сгенерированные моделью, а реальные поисковые задачи, которые человек может придумать, проверить и подтвердить источниками.
Сбор начинался с поиска сида — короткого факта или сущности, вокруг которой можно построить вопрос. Затем разметчик добавлял к нему несколько свойств так, чтобы каждое из них сужало круг кандидатов, но ни одно не раскрывало ответ напрямую. После этого формулировался вопрос с коротким однозначным ответом.
Формально процесс напоминает пайплайн генерации синтетических обучающих данных, но в TRuST все его этапы выполнялись вручную. Для полноценного бенчмарка это принципиально, поскольку ручная разметка позволяет создавать задачи, близкие к реальным поисковым вопросам, которые мог бы сформулировать человек.
Для каждой задачи фиксировались источники: финальный документ, где подтверждается ответ, и промежуточные, необходимые для прохождения поисковой цепочки. Мы специально старались использовать разные сайты: вопрос, который решается за счет одного очевидного источника вроде Википедии, плохо подходит для сложного поискового бенчмарка. После этого задача проходила проверку на сложность. Ответ не должен был находиться путем поиска вопроса целиком, его перефразирования или англоязычных запросов.
Помимо человеческой проверки мы валидировали задачу на сложность через других поисковых агентов. GPT-5.4 в трех режимах пыталась решить вопрос: из весов, с простым подходом в один запрос и через полноценный агентский поиск. Если ответ находился из весов или путем простого поиска, задача отправлялась на доработку. Для агентского режима мы определили эвристику минимального времени поиска ответа как 3 минуты, чтобы оставить только самые сложные, но решаемые примеры.
Затем источники парсились и проверялась их полнота. Если по собранным документам модель в несколько подходов не могла получить правильный ответ, задача также отправлялась на доработку.
Отдельно собирались hard negatives. Вопрос разбивался на подзапросы по методологии BrowseComp-Plus, по ним парсились SERP-результаты, из которых получались реалистичные отвлекающие документы. Такой подход позволяет проверить, умеет ли агент отличать действительно нужный источник от похожих, но неверных.
TRuST закрывает важный пробел в оценке русскоязычных поисковых LLM-агентов: он делает оценку воспроизводимой, диагностируемой и привязанной к реальным особенностям Рунета. Вместо того чтобы проверять только финальный ответ, бенчмарк позволяет смотреть на весь путь решения: какие документы агент нашел, справился ли с неоднозначными сущностями, временным контекстом и структурированными источниками.
Мы выкладываем TRuST в open source, чтобы его можно было использовать для сравнения поисковых агентов, анализа ошибок и разработки более надежных RAG/search-пайплайнов.
SynthComp-бенчмарк
Тот же пайплайн синтетики, на котором мы строили данные для обучения T-Search, позволил собрать отдельный бенчмарк — SynthComp. Это бенчмарк многошагового поиска в духе BrowseComp-Plus с двумя версиями по 395 вопросов: англоязычный SynthComp-En построен на корпусе Essential-Web, а SynthComp-Ru — на русскоязычных веб-источниках, включая FineWeb2, русскую Википедию и другие источники.
Методология синтетики дает уверенность, что вопрос действительно требует пройти размеченную многошаговую цепочку. При сборке SynthComp мы добавили к этим гарантиям еще одну независимую проверку — после отбора вопросов и формирования общего индекса. Мотивация простая: основная метрика бенчмарка — rrecall по опорным чанкам, и низкое значение должно однозначно означать, что агент пропустил нужные документы, а не нашел другой корректный путь, которого нет в разметке.
Основная идея опирается на геометрию векторного поиска. Каждый вопрос и запросы, которые агент делает в ходе его решения, задают некоторую область ближайших документов в пространстве эмбеддингов. Если области разных задач пересекаются, опорный чанк одного вопроса может случайно стать подсказкой или обходным путем для другого. Поэтому после объединения кандидатов в общий индекс мы проверяли ближайшее окружение каждого вопроса — с помощью того же поиска, что используется при оценке. Если в поисковой выдаче по его запросам появлялись опорные чанки другой задачи или альтернативные документы, позволяющие получить тот же ответ в обход размеченной цепочки, такой кандидат исключался.
Большой исходный пул позволил в итоге отобрать вопросы без обнаруженных пересечений, не жертвуя размером бенчмарка.
При этом изоляция сама по себе не означает сложность. Наоборот, слишком уникальный документ иногда легко находится по одной характерной детали. Поэтому отсутствие пересечений использовалось как обязательный фильтр, а сложность контролировалась отдельно: рядом с правильными чанками должны были оставаться дистракторы. Их мы майнили заново по той же методологии BrowseComp-Plus, которая использовалась при сборке hard negatives для TRuST. Вопросы, для которых не удалось собрать достаточно сложное окружение, в финальную версию SynthComp не попадали.
Сложность оценивалась по реальным прогонам сильного поискового агента. Мы смотрели, какую долю опорных чанков ему удалось найти, и по этому recall разделяли вопросы на три уровня. Финальный набор балансировали по механике задачи, глубине поисковой цепочки и уровню сложности. При этом мы намеренно оставляли больше вопросов из сложного хвоста: задачи, которые уверенно решают почти все сильные модели, хуже помогают различать их поисковые способности.
Отдельно мы полностью разделили SynthComp и данные, использованные на SFT- и RL-стадиях. Тексты всех вопросов бенчмарка сравнивались с тренировочными вопросами с помощью MinHash, чтобы удалить совпадения и близкие формулировки. Дополнительно исключались пересечения по объединенным наборам размеченных чанков. Так в обучение T-Search не попадали ни вопросы SynthComp, ни их близкие варианты, ни задачи, построенные на тех же наборах документов.
SynthComp-Ru добавляет к TRuST вторую, независимую ось оценки поиска на русском: постановка та же, но вопросы построены программно, а не руками разметчиков. Вывод, устойчивый на обоих бенчмарках, надежнее, чем на каждом по отдельности.
SynthComp-En играет ту же роль на английском: еще одна независимая ось оценки рядом с англоязычными бенчмарками. При этом текущий набор можно расширять: фабрика синтетики позволяет генерировать большой пул новых кандидатов, а их сложность можно откалибровать по прогонам разных моделей или других агентов. Обе версии SynthComp мы публикуем в open source вместе с фиксированными индексами.
В таблице представлены результаты измерений по перечисленным бенчмаркам с recall в качестве основной метрики.
|
Модель |
BrowseComp-Plus |
ru-BrowseComp-Plus |
SealQA |
ru-SealQA |
SynthComp |
ru-SynthComp |
TRuST |
Avg |
|
T-Search (N = 1) |
65,35 |
55,95 |
61,16 |
57,72 |
54,52 |
53,13 |
43,92 |
55,96 |
|
T-Search (N = 3) |
72,65 |
62,93 |
66,08 |
61,98 |
58,52 |
58,00 |
49,12 |
61,33 |
|
GLM 5.1 |
64,32 |
58,18 |
55,49 |
53,21 |
51,69 |
51,71 |
43,11 |
53,96 |
|
GLM 5.2 |
63,01 |
52,54 |
55,30 |
54,69 |
52,29 |
49,37 |
37,07 |
52,04 |
|
Kimi-K2.6 |
60,71 |
49,76 |
56,86 |
52,46 |
48,25 |
47,06 |
42,39 |
51,07 |
|
DeepSeek-V4-Flash |
53,27 |
46,30 |
55,70 |
51,12 |
44,83 |
45,68 |
40,40 |
48,19 |
|
Qwen3.6-27B |
56,69 |
46,81 |
54,01 |
48,95 |
46,82 |
46,99 |
38,12 |
48,34 |
|
Qwen3.6-35B-A3B |
43,66 |
38,58 |
46,07 |
43,26 |
41,82 |
43,88 |
33,53 |
41,54 |
|
gemma-4-26B-A4B-it |
35,32 |
27,51 |
45,13 |
39,.05 |
36,24 |
34,77 |
21,75 |
34,25 |
|
Qwen3.5-397B-A17B |
53,48 |
44,06 |
51,68 |
48,33 |
47,38 |
46,.91 |
38,57 |
47,20 |
|
Qwen3.5-122B-A10B |
47,81 |
40,15 |
51,57 |
44,74 |
42,11 |
42,25 |
30,55 |
42,74 |
Мы построили latency-quality-кривые для разных значений максимального количества раундов. Для измерения latency зафиксировали случайным образом по пять вопросов из каждого из семи бенчмарков — 35 вопросов суммарно. Каждый вопрос прогонялся 13 раз: первые три запуска использовались для прогрева, а оставшиеся десять —– для статистики.
Latency одного прогона считалась как wall-clock-время всего агентного цикла. Сначала тайминги усредняются по повторам одного вопроса, затем по вопросам внутри бенчмарка и наконец по всем бенчмаркам.
Для T-Search мы отдельно измеряли два режима: один прогон агента (N = 1) на вопрос и три параллельных прогона с объединением выдач через RRF и порогом top-10 (N = 3). В параллельном режиме результат готов только после завершения самой медленной из трех попыток, поэтому latency в этом случае равна максимуму из трех. Recall для тех же точек считался как обычно — на полных версиях бенчмарков.
При обучении есть риск, что модель подстроится под особенности конкретного ретривера. Чтобы проверить, что этого не произошло, мы оценили модель, используя различные ретриверы, различающиеся по типу, размеру и механизму ранжирования:
-
BM25;
-
Qwen3-Embedding-8B с LLM-реранжированием (Qwen3.6-27B в роли реранкера).
Такой набор покрывает основные оси, по которым ретриверы расходятся между собой.
|
Ретривер |
BrowseComp-Plus |
ru-BrowseComp-Plus |
SealQA |
ru-SealQA |
SynthComp |
ru-SynthComp |
TRuST |
Avg |
|
Qwen3-Embedding-8B |
65,35 |
55,95 |
61,16 |
57,72 |
54,52 |
53,13 |
43,92 |
55,96 |
|
Qwen3-Embedding-8B + LLM Reranking |
75,04 |
66,24 |
64,82 |
59,95 |
62,71 |
62,39 |
48,93 |
62,87 |
|
Qwen3-Embedding-0.6B |
51,70 |
43,71 |
56,80 |
49,53 |
54,72 |
52,27 |
36,95 |
49,38 |
|
jina-embeddings-v5-text-small-retrieval |
60,52 |
51,41 |
62,46 |
55,60 |
56,37 |
54,56 |
39,31 |
54,32 |
|
BM25 |
39,49 |
31,97 |
55,33 |
50,00 |
66,87 |
65,15 |
49,18 |
51,14 |
Устойчивость метрик при всех сетапах показывает, что модель научилась общим поисковым навыкам, а не подстроилась под конкретный эмбеддер: разброс объясняется качеством самого ретривера, а не деградацией агента.
Выводы
T-Search — открытый агент-ретривер для сложного многошагового поиска на русском языке. На семи бенчмарках сложного многошагового поиска T-Search превосходит по качеству более крупные открытые решения и значительно опережает базовую модель, а с параллельными запусками отрыв увеличивается. При этом модель не подстроилась под конкретный эмбеддер: метрики устойчивы при смене ретривера.
Как и у любого агента, у T-Search есть ограничения: модель обучена под собственный харнесс, поэтому в других обвязках качество может различаться. Рекомендуем использовать модель вместе с харнессом и валидировать поведение на своем индексе.
Модель, TRuST и SynthComp бенчмарки с фиксированными индексами уже в open source. Будем рады обратной связи: заводите issues, присылайте кейсы, где агент ломается.
Полезные ссылки:
ссылка на оригинал статьи https://habr.com/ru/articles/1060262/