TRL documentation
Интеграция Harbor для обучения LLM с использованием сред
Интеграция Harbor для обучения LLM с использованием сред
Harbor — это фреймворк для выполнения агентных задач в песочницах. Он разделяет задачу (инструкция + образ песочницы + верификатор), harness/агента (интерфейс инструментов + цикл) и песочницу (docker, e2b, daytona, gke, …), позволяя свободно комбинировать их. Это делает его естественным выбором для RL: один и тот же набор задач можно обучать с различными интерфейсами инструментов на любом предпочитаемом бэкенде песочницы.
В этом руководстве описано, как интегрировать Harbor с TRL. Саму Harbor см. в документации Harbor.
Интеграция находится в
trl.experimental.harborи доступна через дополнительный пакетtrl[harbor](импортируется лениво — пользователи, не использующие её, не несут никаких затрат).
Когда использовать окружения Harbor
GRPOTrainer поддерживает обучение на основе сред через слот environment_factory — см. OpenEnv для общего контракта. Используйте Harbor, если хотите обучать модель на наборе задач Harbor: это древовидная структура каталогов с задачами, каждая из которых представляет собой автономный песочный контейнер и верификатор (например, набор задач для агента по анализу данных, где модель исследует файлы в песочнице и записывает ответ, который проверяет оценщик).
Установка
pip install trl[harbor]
Harbor управляет генерацией через vLLM и использует
environment_factory, для которого требуютсяvllmиtransformers>=5.2.0.pip install vllm
Это устанавливает фреймворк harbor (Python >= 3.12). Интеграция импортирует harbor лениво и запускает его в процессе, поэтому пользователи, не использующие trl.experimental.harbor, не затрагиваются.
Песочница (sandbox backend) также должна быть установлена и доступна во время обучения. Harbor хранит облачные бэкенды за своими дополнительными пакетами (extras), поэтому установите тот, который вы планируете использовать, и предоставьте его учётные данные:
pip install "harbor[e2b]" # E2B cloud sandbox -> environment_type="e2b", needs E2B_API_KEY
# docker backend (environment_type="docker", Harbor's default) just needs a reachable Docker daemonБыстрый старт
HarborSpec подключает один набор задач Harbor к трём слотам тренера TRL — train_dataset, environment_factory, reward_funcs — за счёт свойств, которые соответствуют этим именам аргументов один к одному:
from trl import GRPOConfig, GRPOTrainer
from trl.experimental.harbor import HarborSpec
spec = HarborSpec("AdithyaSK/data_agent_rl_environment_train", agent="bash", num_tasks=64)
trainer = GRPOTrainer(
model="Qwen/Qwen3-4B",
args=GRPOConfig(
num_generations=8,
max_steps=50,
max_tool_calling_iterations=25,
log_completions=True,
),
train_dataset=spec.train_dataset,
environment_factory=spec.environment_factory,
reward_funcs=spec.reward_funcs,
)
trainer.train()Под капотом HarborSpec выполняет три действия, отложенные до первого обращения:
spec.train_dataset: разрешает набор задач в локальные каталоги задач (при необходимости скачивая датасет HF) и создаётdatasets.Datasetсprompt(пустым — инструкция окружения добавляется приreset),task_dir,task_index, а также с колонками метаданных изtask.tomlдля каждой задачи.spec.environment_factory: возвращает вызываемый объект без аргументов, создающий новый экземпляр HarborEnv для каждого rollout. При вызовеreset(task_dir)запускается песочница Harbor для задачи и возвращается её инструкция; методы инструментов выполняют команды внутри песочницы;env.rewardзапускает верификатор один раз после завершения rollout.spec.reward_funcs: итоговая награда, которая считывает скаляр Harbor verifier для каждого rollout.
Набор данных
dataset — это либо идентификатор репозитория датасета Hugging Face, содержащего дерево задач Harbor, либо локальный путь, включающий поддерево tasks/. Каждая задача представляет собой каталог:
tasks/<task_id>/
├── instruction.md # the task prompt (returned by reset)
├── task.toml # config + metadata (gold answer, difficulty, ...)
├── environment/ # Dockerfile (+ any pre-agent data hooks)
└── tests/ # test.sh / grader → writes the rewardВыберите подмножество с помощью num_tasks или indices (взаимоисключающие параметры):
spec = HarborSpec("AdithyaSK/data_agent_rl_environment_train", num_tasks=10) # first 10
spec = HarborSpec("AdithyaSK/data_agent_rl_environment_train", indices=[0, 5, 13]) # specificАгенты: внешние и установленные
Harbor поддерживает два способа, которыми агент выполняет задачу, и это различие определяет, что можно обучать с помощью RL:
- Внешние агенты работают вне песочницы и сами управляют циклом, отправляя команды в контейнер через интерфейс окружения Harbor («как правило, выполняя bash-команды с помощью метода
exec»). Агент принимает решение о каждом действии и интерпретирует каждый результат; песочница лишь выполняет команды. - Установленные агенты устанавливаются в образ контейнера и выполняются в нём как автономный подпроцесс без графического интерфейса (наследуют
BaseInstalledAgent). Harbor запускает агента внутри песочницы, а затем анализирует его файл траектории (populate_context_post_run); агент работает автономно, используя собственную инференс-логику.
Интеграция TRL использует паттерн внешнего агента, и на данный момент поддерживается только он. Обучение с подкреплением требует, чтобы тренер управлял развёрткой по ходу каждого хода: обучаемая модель политики генерирует каждый ход, а TRL захватывает её токены и лог-вероятности и применяет маску среды — именно то, что обеспечивает environment_factory поверх «чёрного ящика» rollout_func. Установленный агент непрозрачен для этого процесса: он работает внутри контейнера со своей моделью и выдаёт траекторию только постфактум, поэтому у тренера нет токенов политики или лог-вероятностей для оптимизации, а обучаемая модель никогда не вызывается. Таким образом, HarborEnv является внешним агентом: его методы инструментов exec выполняются в песочнице, но цикл и обучаемая модель остаются в TRL.
Выбор базового агента (harness)
Базовый агент — это каркас, определяющий, какие методы инструментов предоставляет среда и как агент отправляет запросы. Выберите его с помощью agent=:
HarborSpec(dataset, agent="bash") # built-in single-bash-tool harness
HarborSpec(dataset, agent="my_pkg.harnesses:JupyterEnv") # import path to your HarborEnv subclass
HarborSpec(dataset, agent="path/to/harness.py:JupyterEnv") # file path to your HarborEnv subclass
HarborSpec(dataset, agent=MyHarborEnv) # a HarborEnv subclass directlyВстроенный "bash" harness (HarborBashEnv) предоставляет один инструмент bash и отправляет ответ, записывая его в /workdir/answer.txt. Два более функциональных harnessa поставляются в качестве примеров — каждый в отдельной папке с README, перечисляющим его инструменты, — в examples/grpo_harbor/harnesses/:
jupyter/(JupyterEnv) — ядро Python с состоянием (переменные сохраняются между ячейками) + инструмент для работы с оболочкой.terminal_notes/(TerminalNotesEnv) — 6 shell-инструментов (включая фоновые процессы) + набор из 4 инструментов для постоянного ведения заметок.
HarborSpec(dataset, agent="examples/grpo_harbor/harnesses/jupyter/env.py:JupyterEnv")
HarborSpec(dataset, agent="examples/grpo_harbor/harnesses/terminal_notes/env.py:TerminalNotesEnv")Чтобы написать собственный harness, создайте подкласс HarborEnv и добавьте методы инструментов — каждый публичный метод становится инструментом (TRL обнаруживает их с помощью inspect.getmembers), поэтому каждому методу нужна типизированная сигнатура и docstring (используется для построения схемы инструмента). Вспомогательные методы начинайте с подчёркивания. Используйте self._exec(cmd) для выполнения shell-команд в песочнице, а PROMPT_SUFFIX задайте, чтобы добавить инструкции harness к задаче:
from trl.experimental.harbor import HarborEnv
class GrepEnv(HarborEnv):
PROMPT_SUFFIX = "\n\nUse `grep` and `read_file`. Submit by writing /workdir/answer.txt."
def grep(self, pattern: str, path: str) -> str:
"""Search for `pattern` under `path`.
Args:
pattern: The regex to search for.
path: The file or directory to search.
"""
return self._exec(f"grep -rn {pattern!r} {path!r}")Песочный бэкенд
environment_type передаётся напрямую в Harbor (TRL не выполняет его проверку):
HarborSpec(dataset, environment_type="e2b") # cloud sandbox (offloads provisioning), needs E2B_API_KEY
HarborSpec(dataset, environment_type="docker") # default; needs a local Docker daemone2b рекомендуется для обучения на кластере: в облачную песочницу переходит только environment.exec, поэтому GPU остаются выделенными под политику, и можно запускать множество rollouts одновременно.
Функции вознаграждения
spec.reward_funcs по умолчанию использует вознаграждение за результат — для каждого rollout он считывает скаляр Harbor verifier (env.reward), который вычисляется один раз после rollout путём запуска верификатора tests/ задачи в песочнице. Для пользовательского вознаграждения напишите обычную функцию вознаграждения TRL:
def my_reward(environments, **kwargs) -> list[float]:
return [env.reward for env in environments]API
класс trl.experimental.harbor.HarborSpec
< source >( dataset: stragent: str | type[HarborEnv] = 'bash'environment_type: str = 'docker'num_tasks: int | None = Noneindices: list[int] | None = Noneinclude_metadata: bool = True )
Параметры
- dataset (
str) — Идентификатор репозитория датасета Hugging Face, содержащего дерево задач Harbor (например,"AdithyaSK/data_agent_rl_environment_train"), или локальный путь к каталогу, содержащему поддеревоtasks/. Каждая задача представляет собой каталог сinstruction.md/task.toml/environment//tests/. - agent (
strилиtype, необязательный, по умолчанию"bash") — Базовый агент / каркас, то есть набор инструментов, который предоставляет окружение. Одно из: встроенное имя ("bash"), путь импорта"package.module:ClassName", путь к файлу"path/to/file.py:ClassName"или непосредственно подкласс HarborEnv. - environment_type (
str, необязательный, по умолчанию"docker") — Бэкенд песочницы Harbor, передаваемый в Harbor (поддерживает всё, что поддерживает Harbor —"docker","e2b","daytona","gke","modal","runloop", …). Здесь не проверяется; проверку выполняет Harbor."docker"— это значение по умолчанию в самом Harbor; выберите"e2b", чтобы перенести работу песочницы в облако. - num_tasks (
int, необязательный) — Ограничение на количество задач, загружаемых в набор данных.Noneиспользует все задачи в дереве. - indices (
list[int], необязательный) — Конкретные индексы задач (в отсортированном списке задач). Взаимоисключается сnum_tasks. - include_metadata (
bool, необязательный, по умолчаниюTrue) — Добавляет метаданные изtask.tomlдля каждой задачи (gold_answer, difficulty, …) в строки набора данных.
Единый объект спецификации, который подключает набор задач Harbor к тренеру TRL.
класс trl.experimental.harbor.HarborEnv
< source >( environment_type: str = 'docker' )
Базовое окружение TRL, работающее на базе песочницы Harbor и верификатора.
Подклассы определяют методы инструментов (обвязку). Жизненный цикл, который TRL управляет для каждого rollout: reset(task_dir) (запуск песочницы задачи, возврат её инструкции) -> методы инструментов (выполнение команд в песочнице) -> reward (однократный запуск верификатора, лениво, после rollout).
Обёртка с единственным инструментом bash; отправьте ответ, записав его в /workdir/answer.txt.
Выполните команду оболочки в песочнице и верните её объединённый вывод stdout+stderr. Оболочка не сохраняет состояние между вызовами. Используйте её для просмотра файлов (ls, head, cat), запуска Python (python3 -c "...") и отправки ответа (echo -n "<value>" > /workdir/answer.txt).
Ограничения
- Интеграция находится в
trl.experimental— API могут измениться. УстановитеTRL_EXPERIMENTAL_SILENCE=1, чтобы отключить предупреждение в логах CI. - Асинхронный клиент песочницы Harbor привязан к одному циклу событий, поэтому каждый env синхронно выполняет start/exec/verify в собственном цикле; в результате provisioning песочниц в рамках генерационной партии происходит последовательно (облачные бэкенды, такие как
e2b, снижают стоимость на каждую песочницу). - Один объект
HarborSpecописывает один набор задач и один harness; обучение на нескольких наборах задач пока не поддерживается.