Как собрать хорошие траектории для обучения LLM-агента
- Введение
- Что такое траектория в агентах
- Пример корректного и ошибочного tool call
- SFT: что это, какие данные нужны и почему этого недостаточно
- Пример SFT-траектории
- Alignment: как выучить стратегию, а не только формат ответа
- Какие
- Какие
- Пример пары
- Пример, когда инструмент не нужен
- Откуда брать данные для SFT и alignment
- Рабочий конвейер сбора
- Контроль качества до обучения
- Стартовый план по объёму данных
- Типичные ошибки при сборе траекторий
- Заключение
Введение
LLM-агенты полезны там, где модель не просто пишет текст, а выбирает действие: вызвать API, найти данные, проверить результат или сразу ответить пользователю. Поэтому качество агента зависит не только от самой модели, но и от того, какие примеры поведения мы показываем ей на обучении.
Для обучения обычной LLM часто хватает пар вопрос -> ответ. Для агента этого мало. Он должен уметь работать по шагам:
- Понять задачу.
- Решить, нужен ли инструмент.
- Правильно его вызвать.
- Обработать ответ.
- По завершении выполнения задачи выдать финальный ответ.
Что такое траектория в агентах
Траектория — это полный путь решения одной задачи, а не один финальный ответ.
Минимальный состав траектории:
user_request— просьба пользователя.decision— решение, нужен лиtool_callи почему.tool_call— вызов инструмента в корректном JSON по вашей схеме.observation— реальный ответ инструмента.next_stepилиfinal_answer— вызов следующего инструмента или финальный ответ.
Пример корректного и ошибочного tool call
Допустим, по вашей схеме у get_weather обязательные поля: city и date.
Ошибочно (нет обязательного поля city, используется city_name):
{
"tool": "get_weather",
"args": {
"city_name": "Moscow",
"date":"tomorrow"
}
}
Корректно:
{
"tool": "get_weather",
"args": {
"city": "Moscow",
"date": "tomorrow"
}
}
SFT: что это, какие данные нужны и почему этого недостаточно
SFT (Supervised Fine-Tuning) — этап, где мы учим модель на правильных примерах. То есть показываем, как должна выглядеть хорошая траектория, и модель учится повторять этот паттерн.
Что нужно для SFT:
- корректные траектории из реальных логов;
- синтетические траектории от более сильной модели-учителя;
- примеры с ошибками API и примеры, где инструмент вообще не нужен.
Модель-учитель — более сильная LLM, которая генерирует кандидаты траекторий; затем мы фильтруем их автовалидацией и выборочной ручной проверкой.
Что обычно даёт SFT:
- модель лучше держит формат;
- реже ломает JSON;
- чаще корректно заполняет аргументы вызовов.
Почему SFT недостаточно:
- модель может быть формально аккуратной, но выбирать плохую стратегию;
- частые проблемы:
- лишние вопросы,
- лишние вызовы,
- неправильный выбор инструмента.
Именно поэтому после SFT нужен этап alignment.
Пример SFT-траектории
Запрос: «Покажи погоду в Казани на завтра»
Шаг 1: decision -> нужен tool_call к погодному API
Шаг 2: tool_call -> get_weather(city="Kazan", date="tomorrow")
Шаг 3: observation -> {temp: 12, condition: "rain"}
Шаг 4: final_answer -> «Завтра в Казани около +12 и дождь»
Alignment: как выучить стратегию, а не только формат ответа
Alignment — этап, где мы учим модель выбирать более полезное поведение для конкретной исходной задачи.
Один из популярных методов такого обучения — DPO (Direct Preference Optimization). Он использует два варианта решения одной задачи: хороший и плохой. Во время обучения считается вероятность двух траекторий. Функция потерь устроена так, чтобы модель повышала относительную вероятность хорошей траектории и снижала — плохой, при этом не уходила слишком далеко от базовой reference-модели.
То есть модель не просто читает пары и запоминает, что хорошо, а что — плохо. Мы обновляем её параметры так, чтобы при аналогичном контексте она чаще выбирала стратегию, похожую на chosen, а не на rejected.
Более подробно механику можно изучить в статье:
Для DPO обычно готовят пары chosen/rejected для одной и той же задачи, контекста и набора инструментов:
chosen— лучший вариант траектории;rejected— худший вариант для того же запроса.
В такой паре меняется только качество стратегии: chosen ведёт к цели, rejected содержит конкретную ошибку.
Какие chosen примеры нужны
- задача реально решена до конца;
- нет лишних шагов;
- инструмент выбран по делу;
- есть корректные случаи без tool call.
Какие rejected примеры нужны
- лишние уточнения от LLM, когда данных уже достаточно;
- выдуманные аргументы API;
- нерелевантный инструмент;
- зацикливание вызовов;
- ошибочный JSON.
Пример пары chosen/rejected
Запрос: «Сколько стоит подписка X в 2026 году?»
chosen: вызвать get_pricing(plan="X"), получить цену, дать короткий ответ.
rejected: сначала задать лишний вопрос, затем вызвать get_user_profile, и только потом идти в pricing.
Почему
rejectedхуже: он добавляет лишний вопрос и вызывает нерелевантный инструмент. Пользователь ждёт цену подписки, а его профиль для этой задачи не нужен.
Пример, когда инструмент не нужен
Запрос: «Сократи этот черновик письма до трёх предложений: ...»
Доступные инструменты: send_email, search_docs.
Правильное действие: переписать текст сразу, без send_email и поиска.
Такой пример важен — агент не должен вызывать инструмент только потому, что инструмент доступен.
Откуда брать данные для SFT и alignment
У SFT и alignment разные цели, поэтому данные для них тоже отличаются.
| Этап | Что собираем | Зачем |
|---|---|---|
| SFT | одиночные правильные траектории | научить модель держать формат, вызывать инструменты по схеме и завершать задачу |
| Alignment | пары chosen/rejected для одного запроса | научить модель выбирать более полезную стратегию, когда формально возможны разные варианты поведения |
Источники, которые используют на практике:
- логи реальных задач с очисткой персональных данных;
- синтетика из документации или через модель-учитель;
- публичные датасеты как стартовый источник, например, Gorilla/APIBench.
Перед сбором негативных примеров полезно зафиксировать два термина.
On-policy rollout — прогон текущей версии агента на наборе задач. Мы смотрим не на выдуманные ошибки, а на то, как агент реально ошибается сейчас: где задаёт лишние вопросы, выбирает не тот инструмент или неправильно заполняет аргументы.
Hard negatives — плохие примеры, которые внешне похожи на правильные, но содержат важную ошибку. Например, агент вызывает правильный инструмент, но передаёт неверный идентификатор тарифа. Такой негатив полезнее слишком очевидной ошибки, потому что учит модель различать близкие варианты.
Как получать хорошие негативы (rejected):
- прогоняем текущую модель на задачах и собираем её естественные ошибки;
- берём хороший пример и намеренно ломаем выбор инструмента или аргументы;
- добавляем hard negatives для частых ошибок и ошибок, которые сильно портят результат;
- все ошибки из проведённого замера качества сначала фильтруем и группируем, и только потом добавляем в новый датасет.
Рабочий конвейер сбора
Порядок важен: сначала нужно зафиксировать, что агент вообще имеет право вызывать и в каком формате. После этого можно собирать задачи, генерировать траектории, проверять их и собирать пары для alignment. Если менять схему инструментов уже после генерации данных, часть траекторий быстро станет бесполезной.
- Фиксируем контракт инструментов: имена, обязательные поля, форматы аргументов и типы ошибок. Это и есть schema-first подход: данные собираются под уже известную схему.
- Собираем набор задач по различным доменам и уровням сложности.
- Генерируем траектории с помощью модели-учителя и отдельно прогоняем текущую модель на тех же задачах.
- Применяем автовалидацию:
- JSON валиден,
- вызов исполним,
- аргументы проходят схему и доменные ограничения,
- выбор инструмента соответствует задаче по заранее заданной рубрике,
- задача реально доведена до результата.
- Строим пары
chosen/rejectedпо правилам маппинга. В паре должны совпадать запрос пользователя, доступные инструменты и исходный контекст. Меняется только решение агента: например, выбор инструмента, наличие лишнего вопроса или аргументы вызова. - Делаем человеческую проверку на 5-10% примеров. В эту выборку обязательно добавляем спорные случаи по выбору инструмента и качеству пары.
- Проверяем покрытие по доменам, инструментам, no-tool кейсам и типам ошибок.
- Версионируем датасет по домену, инструментам и типу ошибки.
Контроль качества до обучения
Перед обучением фиксируем стартовые метрики, целевые пороги и покрытие датасета.
Метрики:
- доля валидного JSON;
- доля исполнимых вызовов инструмента;
- доля корректных кейсов «инструмент не нужен»;
- доля пар ‘chosen/rejected’, где различие реально смысловое.
Покрытие:
- основные домены продукта;
- все критичные инструменты;
- частые типы ошибок;
- сценарии, где инструмент не нужен.
Первые две метрики обычно проверяются автоматически. Корректность no-tool кейсов и смысловое различие в парах лучше проверять через рубрику и выборочную ручную разметку. Полностью автоматическая проверка здесь часто пропускает спорные случаи.
Стартовый план по объёму данных
Ориентиры для первого цикла подойдут для сравнительно узкого агентского сценария: один продуктовый домен, примерно 5-15 инструментов, понятные правила вызова API и не слишком длинные многошаговые задачи.
- 300-500 вручную проверенных траекторий;
- 5k-20k синтетических траекторий после фильтрации;
- 1k-5k пар
chosen/rejectedпод ваши частые ошибки; - еженедельный цикл: замер качества -> новые hard negatives -> обновление версии датасета.
Это не универсальная норма. Конкретные числа зависят от:
- количества инструментов;
- сложности сценариев;
- размера и базового качества модели;
- бюджета на ручную проверку и разметку;
- требуемой точности в проде.
Типичные ошибки при сборе траекторий
- В
chosenпопадают траектории с лишними шагами. На практике модель начинает чаще задавать ненужные вопросы и делать лишние вызовы, даже когда ответ можно дать сразу. rejectedслишком слабые и почти не учат модель. В обучении контраст выглядит понятным, но реальные сложные ошибки остаются без исправления.- Мало примеров, где инструмент не нужен. Агент начинает вызывать API просто потому, что оно доступно, и ухудшает простые текстовые задачи.
- Нет обратной связи из результатов замеров в новую версию датасета. Одни и те же ошибки повторяются из цикла в цикл, потому что датасет не обновляется под реальные провалы модели.
Заключение
В агентских задачах SFT помогает научить модель формату и базовым правилам tool call. Но рост качества чаще приходит не от простого увеличения объёма SFT-данных, а от системного сбора, проверки и обновления alignment-данных.
Хороший датасет для агента должен показывать не только правильный JSON, но и правильную стратегию: когда вызывать инструмент, когда не вызывать, как обработать ответ и когда остановиться.

