TRL documentation
Integração do Harbor para Treinamento de LLMs com Ambientes
Integração do Harbor para Treinamento de LLMs com Ambientes
Harbor é um framework para executar tarefas agênticas em sandboxes. Ele desacopla uma tarefa (instrução + imagem de sandbox + verificador), um harness/agent (a superfície de ferramentas + loop) e uma sandbox (docker, e2b, daytona, gke, …) para que possam ser combinados livremente. Isso o torna uma escolha natural para RL: o mesmo conjunto de tarefas pode ser treinado com diferentes superfícies de ferramentas, em qualquer backend de sandbox que você preferir.
Este guia aborda como integrar o Harbor com o TRL. Para o próprio Harbor, consulte a documentação do Harbor.
A integração está em
trl.experimental.harbore é controlada pelo extratrl[harbor](importação preguiçosa — não usuários não pagam nada).
Quando usar ambientes Harbor
O GRPOTrainer suporta treinamento baseado em ambientes por meio do slot environment_factory — consulte OpenEnv para o contrato geral. Use o Harbor quando quiser treinar contra uma suíte de tarefas do Harbor: uma árvore de diretórios de tarefas, cada uma sendo um sandbox + verificador autossuficiente (por exemplo, uma suíte de agentes de análise de dados em que o modelo explora arquivos em um sandbox e escreve uma resposta que um avaliador verifica).
Instalação
pip install trl[harbor]
Harbor impulsiona a geração por meio do vLLM e usa
environment_factory, que requervllmetransformers>=5.2.0.pip install vllm
Isso instala o framework harbor (Python >= 3.12). A integração importa harbor de forma preguiçosa e o executa no processo, de modo que usuários que não utilizam trl.experimental.harbor não são afetados.
Um backend de sandbox também deve estar instalado e acessível no momento do treinamento. O Harbor mantém os backends de nuvem atrás de seus próprios extras, portanto, instale aquele que você pretende usar e forneça suas credenciais:
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 daemonInício rápido
HarborSpec conecta um único conjunto de tarefas do Harbor aos três slots do treinador TRL — train_dataset, environment_factory, reward_funcs — expondo propriedades que mapeiam 1:1 para esses nomes de kwarg:
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()Por baixo dos panos, HarborSpec faz três coisas, de forma preguiçosa no primeiro acesso:
spec.train_dataset: resolve a suíte de tarefas para diretórios locais de tarefas (baixando o dataset do HF, se necessário) e constrói umdatasets.Datasetcomprompt(vazio — a instrução do ambiente é adicionada noreset),task_dir,task_index, além de colunas de metadados dotask.tomlpor tarefa.spec.environment_factory: retorna um chamável sem argumentos que produz uma nova instância de HarborEnv para cada rollout. Emreset(task_dir), ele inicia o sandbox Harbor da tarefa e retorna sua instrução; os métodos de ferramenta executam dentro do sandbox;env.rewardexecuta o verificador uma vez após o rollout.spec.reward_funcs: uma recompensa de resultado que lê o escalar do verificador do Harbor por rollout.
O conjunto de dados
dataset é um id de repositório de dataset do Hugging Face contendo uma árvore de tarefas Harbor, ou um caminho local contendo uma subárvore tasks/. Cada tarefa é um diretório:
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 rewardSelecione um subconjunto com num_tasks ou indices (mutuamente exclusivos):
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]) # specificAgentes: externos vs instalados
O Harbor suporta duas formas de um agente conduzir uma tarefa, e essa distinção determina o que pode ser treinado com RL:
- External agents run outside the sandbox and drive the loop themselves, issuing commands into the container through Harbor’s environment interface (“typically by executing bash commands via the
execmethod”). The agent decides each action and interprets each result; the sandbox only executes. - Agentes instalados são instalados na imagem do container e executados lá como um subprocesso sem interface (estendendo
BaseInstalledAgent). O Harbor inicia o agente dentro do sandbox e, em seguida, analisa seu arquivo de trajetória (populate_context_post_run); o agente opera de forma autônoma com sua própria inferência.
A integração do TRL é o padrão de agente externo, e apenas esse padrão é suportado por enquanto. O treinamento de RL exige que o trainer conduza o rollout turno a turno: o modelo de política em treinamento gera cada turno, e o TRL captura seus tokens e log-probs e aplica a máscara do ambiente — exatamente o que environment_factory fornece sobre um rollout_func de caixa preta. Um agente instalado é opaco para isso: ele roda dentro do container com seu próprio modelo e apenas emite uma trajetória a posteriori, de modo que não há tokens de política nem log-probs para o trainer otimizar, e o modelo em treinamento nunca é invocado. Um HarborEnv é, portanto, um agente externo — seus métodos de ferramenta exec no sandbox, mas o loop, e o modelo em treinamento, permanecem no TRL.
Selecionando o agente base (harness)
O agente base é a estrutura — quais métodos de ferramenta o env expõe e como ele envia. Selecione-o com 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 directlyO harness "bash" embutido (HarborBashEnv) expõe uma ferramenta bash e envia a resposta escrevendo em /workdir/answer.txt. Dois harnesses mais completos são fornecidos como exemplos — cada um em sua própria pasta com um README listando suas ferramentas — em examples/grpo_harbor/harnesses/:
jupyter/(JupyterEnv) — um kernel Python com estado (as variáveis persistem entre as células) + uma ferramenta de shell.terminal_notes/(TerminalNotesEnv) — 6 ferramentas de shell (incluindo processos em segundo plano) + um kit de ferramentas de notas persistente com 4 ferramentas.
HarborSpec(dataset, agent="examples/grpo_harbor/harnesses/jupyter/env.py:JupyterEnv")
HarborSpec(dataset, agent="examples/grpo_harbor/harnesses/terminal_notes/env.py:TerminalNotesEnv")Para escrever seu próprio harness, crie uma subclasse de HarborEnv e adicione métodos de ferramenta — todo método público se torna uma ferramenta (o TRL os descobre com inspect.getmembers), então dê a cada um uma assinatura tipada e um docstring (usado para construir o schema da ferramenta). Mantenha os auxiliares com prefixo de sublinhado. Use self._exec(cmd) para executar comandos de shell no sandbox e defina PROMPT_SUFFIX para anexar orientações do harness à instrução da tarefa:
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}")O backend de sandbox
environment_type é passado diretamente para o Harbor (não validado pelo 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 é recomendado para treinamento em cluster: apenas environment.exec atravessa para o sandbox na nuvem, de modo que as GPUs permanecem dedicadas à política e você pode executar muitos rollouts simultaneamente.
Funções de recompensa
spec.reward_funcs tem como padrão uma recompensa de resultado — por rollout, ela lê o escalar do verificador do Harbor (env.reward), calculado uma única vez após o rollout, executando o verificador tests/ da tarefa no sandbox. Para uma recompensa personalizada, escreva uma função de recompensa TRL regular:
def my_reward(environments, **kwargs) -> list[float]:
return [env.reward for env in environments]API
classe 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 )
Parâmetros
- dataset (
str) — Um id de repositório de dataset do Hugging Face contendo uma árvore de tarefas Harbor (por exemplo,"AdithyaSK/data_agent_rl_environment_train"), ou um caminho local para um diretório contendo uma subárvoretasks/. Cada tarefa é um diretório cominstruction.md/task.toml/environment//tests/. - agent (
stroutype, opcional, padrão"bash") — O agente base / harness — ou seja, a superfície de ferramentas que o env expõe. Um dos seguintes: um nome embutido ("bash"), um caminho de importação"package.module:ClassName", um caminho de arquivo"path/to/file.py:ClassName"ou uma subclasse de HarborEnv diretamente. - environment_type (
str, opcional, padrão"docker") — Backend do sandbox do Harbor, repassado ao Harbor (o que ele suporta —"docker","e2b","daytona","gke","modal","runloop", …). Não é validado aqui; o Harbor valida."docker"é o padrão próprio do Harbor; escolha"e2b"para delegar o sandbox para a nuvem. - num_tasks (
int, opcional) — Limite para o número de tarefas incluídas no conjunto de dados.Noneusa todas as tarefas na árvore. - indices (
list[int], opcional) — Índices de tarefas específicas (na lista de tarefas ordenada). Mutuamente exclusivo comnum_tasks. - include_metadata (
bool, opcional, padrãoTrue) — Inclui os metadados por tarefa dotask.toml(gold_answer, difficulty, …) nas linhas do dataset.
Objeto de especificação única que conecta um conjunto de tarefas do Harbor a um treinador do TRL.
classe trl.experimental.harbor.HarborEnv
< source >( environment_type: str = 'docker' )
Ambiente TRL base suportado por um sandbox Harbor + verificador.
Subclasses definem os métodos da ferramenta (o harness). O ciclo de vida que o TRL dirige por rollout: reset(task_dir) (inicia o sandbox da tarefa e retorna sua instrução) -> métodos da ferramenta (executa no sandbox) -> reward (executa o verificador uma vez, de forma preguiçosa, após o rollout).
Harness com uma única ferramenta bash; envie escrevendo em /workdir/answer.txt.
Execute um comando de shell no sandbox e retorne seu stdout+stderr combinado. O shell não é persistente entre as chamadas. Use-o para explorar arquivos (ls, head, cat), executar Python (python3 -c "...") e enviar a resposta (echo -n "<value>" > /workdir/answer.txt).
Limitações
- A integração está em
trl.experimental— as APIs podem mudar. DefinaTRL_EXPERIMENTAL_SILENCE=1para silenciar o aviso nos logs de CI. - O cliente de sandbox assíncrono do Harbor é vinculado a um único event loop, de modo que cada env executa start/exec/verify de forma síncrona em seu próprio loop; o provisionamento de sandboxes é, portanto, sequencial em todo o lote de geração (backends em nuvem como
e2bmitigam o custo por sandbox). - Um único
HarborSpeccobre um conjunto de tarefas + um harness; o treinamento com múltiplos conjuntos de tarefas ainda não é suportado.