TRL documentation
Integración de Harbor para entrenar LLMs con entornos
Integración de Harbor para entrenar LLMs con entornos
Harbor es un framework para ejecutar tareas agénticas en entornos aislados. Separa una tarea (instrucción + imagen de sandbox + verificador), un harness/agent (la superficie de herramientas + bucle) y un sandbox (docker, e2b, daytona, gke, …) para que puedan combinarse libremente. Esto lo convierte en una opción natural para RL: el mismo conjunto de tareas puede entrenarse con diferentes superficies de herramientas, en el backend de sandbox que prefieras.
Esta guía cubre cómo integrar Harbor con TRL. Para más información sobre Harbor, consulte la documentación de Harbor.
La integración se encuentra en
trl.experimental.harbory está condicionada al extratrl[harbor](importación perezosa: los usuarios que no la utilicen no incurren en ningún coste).
Cuándo usar entornos de Harbor
GRPOTrainer admite el entrenamiento basado en entornos a través del slot environment_factory; consulte OpenEnv para el contrato general. Utilice Harbor cuando desee entrenar contra un Harbor task suite: un árbol de directorios de tareas, donde cada una es un sandbox y un verificador autocontenidos (por ejemplo, un suite de agentes de análisis de datos donde el modelo explora archivos en un sandbox y escribe una respuesta que un corrector verifica).
Instalación
pip install trl[harbor]
Harbor impulsa la generación a través de vLLM y utiliza
environment_factory, que requierevllmytransformers>=5.2.0.pip install vllm
Esto instala el marco de trabajo harbor (Python >= 3.12). La integración importa harbor de forma perezosa y lo ejecuta en el proceso, por lo que los usuarios que no utilicen trl.experimental.harbor no se verán afectados.
También debe estar instalado y ser accesible en el momento del entrenamiento un backend de sandbox. Harbor mantiene los backends de la nube detrás de sus propios extras, por lo que instale el que pretenda usar y proporcione sus credenciales:
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 daemonInicio rápido
HarborSpec conecta un único conjunto de tareas de Harbor con los tres espacios del entrenador de TRL — train_dataset, environment_factory, reward_funcs — mediante propiedades que se mapean 1:1 con esos nombres de parámetros:
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 debajo, HarborSpec hace tres cosas, de forma perezosa en el primer acceso:
spec.train_dataset: resuelve la suite de tareas en directorios locales de tareas (descargando el dataset de HF si es necesario) y construye undatasets.Datasetconprompt(vacío: la instrucción del entorno se añade enreset),task_dir,task_index, además de columnas de metadatos por tarea detask.toml.spec.environment_factory: devuelve un callable sin argumentos que produce una instancia nueva de HarborEnv para cada rollout. Enreset(task_dir)inicia el sandbox de Harbor de la tarea y devuelve su instrucción; los métodos de herramientas ejecutan comandos dentro del sandbox;env.rewardejecuta el verificador una vez después del rollout.spec.reward_funcs: una recompensa de resultado que lee el escalar del verificador de Harbor por despliegue.
El conjunto de datos
dataset es un identificador de repositorio de datos de Hugging Face que contiene un árbol de tareas de Harbor, o una ruta local que contiene un subárbol tasks/. Cada tarea es un directorio:
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 rewardSeleccione un subconjunto con num_tasks o indices (mutuamente excluyentes):
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
Harbor admite dos formas en las que un agente dirige una tarea, y esta distinción determina lo que se puede entrenar con RL:
- Los agentes externos se ejecutan fuera del sandbox y controlan el bucle por sí mismos, emitiendo comandos en el contenedor a través de la interfaz de entorno de Harbor (“típicamente ejecutando comandos bash mediante el método
exec”). El agente decide cada acción e interpreta cada resultado; el sandbox solo ejecuta. - Los agentes instalados se instalan en la imagen del contenedor y se ejecutan allí como un subproceso sin interfaz (ampliando
BaseInstalledAgent). Harbor inicia el agente dentro del sandbox y analiza su archivo de trayectoria después (populate_context_post_run); el agente se ejecuta de forma autónoma con su propia inferencia.
La integración de TRL es el patrón de agente externo, y por ahora solo se admite ese patrón. El entrenamiento con RL requiere que el trainer dirija el rollout turno a turno: el modelo de política en entrenamiento genera cada turno, y TRL captura sus tokens y log-probs y aplica la máscara del entorno, exactamente lo que environment_factory proporciona sobre una rollout_func de caja negra. Un agente instalado es opaco para esto: se ejecuta dentro del contenedor con su propio modelo y solo emite una trayectoria a posteriori, por lo que no hay tokens de política ni log-probs para que el trainer optimice, y el modelo en entrenamiento nunca se invoca. Un HarborEnv es, por tanto, un agente externo: sus métodos de herramienta exec en el sandbox, pero el bucle, y el modelo en entrenamiento, permanecen en TRL.
Seleccionar el agente base (harness)
El agente base es el arnés: qué métodos de herramientas expone el env y cómo los envía. Selecciónalo con 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 directlyEl arnés "bash" integrado (HarborBashEnv) expone una herramienta bash y envía la respuesta escribiendo en /workdir/answer.txt. Dos arneses más completos se incluyen como ejemplos, cada uno en su propia carpeta con un README que lista sus herramientas, bajo examples/grpo_harbor/harnesses/:
jupyter/(JupyterEnv) — un kernel de Python con estado (las variables persisten entre celdas) + una herramienta de shell.terminal_notes/(TerminalNotesEnv) — 6 herramientas de shell (incluidos procesos en segundo plano) + un kit de notas persistente de 4 herramientas.
HarborSpec(dataset, agent="examples/grpo_harbor/harnesses/jupyter/env.py:JupyterEnv")
HarborSpec(dataset, agent="examples/grpo_harbor/harnesses/terminal_notes/env.py:TerminalNotesEnv")Para escribir tu propio harness, subclasa HarborEnv y añade métodos de herramienta: cada método público se convierte en una herramienta (TRL las descubre con inspect.getmembers), por lo que dale a cada uno una firma tipada y un docstring (se usa para construir el esquema de la herramienta). Mantén los auxiliares con prefijo de guion bajo. Usa self._exec(cmd) para ejecutar comandos de shell en el sandbox, y establece PROMPT_SUFFIX para añadir la guía del harness a la instrucción de la tarea:
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}")El backend de sandbox
environment_type se pasa directamente a Harbor (TRL no lo valida):
HarborSpec(dataset, environment_type="e2b") # cloud sandbox (offloads provisioning), needs E2B_API_KEY
HarborSpec(dataset, environment_type="docker") # default; needs a local Docker daemonSe recomienda e2b para el entrenamiento en clúster: solo environment.exec se ejecuta en el sandbox de la nube, por lo que las GPUs se mantienen dedicadas a la política y se pueden ejecutar muchos rollouts de forma concurrente.
Funciones de recompensa
spec.reward_funcs tiene como valor predeterminado una recompensa de resultado: por cada rollout, lee el escalar del verificador de Harbor (env.reward), calculado una vez después del rollout al ejecutar el verificador de tests/ de la tarea en el sandbox. Para una recompensa personalizada, escribe una función de recompensa regular de TRL:
def my_reward(environments, **kwargs) -> list[float]:
return [env.reward for env in environments]API
clase 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) — Un identificador de repositorio de dataset de Hugging Face que contiene un árbol de tareas de Harbor (p. ej."AdithyaSK/data_agent_rl_environment_train"), o una ruta local a un directorio que contiene un subárboltasks/. Cada tarea es un directorio coninstruction.md/task.toml/environment//tests/. - agent (
strotype, opcional, valor predeterminado"bash") — El agente base / harness, es decir, la superficie de herramientas que expone el env. Puede ser: un nombre integrado ("bash"), una ruta de importación"package.module:ClassName", una ruta de archivo"path/to/file.py:ClassName"o una subclase de HarborEnv directamente. - environment_type (
str, opcional, valor predeterminado"docker") — Backend del sandbox de Harbor, se transmite a Harbor (lo que este soporte —"docker","e2b","daytona","gke","modal","runloop", …). No se valida aquí; lo valida Harbor."docker"es el valor predeterminado propio de Harbor; elige"e2b"para delegar el sandboxing en la nube. - num_tasks (
int, opcional) — Límite del número de tareas que se incluyen en el conjunto de datos.Noneutiliza todas las tareas del árbol. - indices (
list[int], opcional) — Índices de tareas específicas (en la lista de tareas ordenada). Mutuamente excluyente connum_tasks. - include_metadata (
bool, opcional, valor predeterminadoTrue) — Incorpora los metadatos detask.tomlde cada tarea (gold_answer, difficulty, …) en las filas del conjunto de datos.
Objeto de especificación única que conecta una suite de tareas de Harbor con un entrenador de TRL.
clase trl.experimental.harbor.HarborEnv
< source >( environment_type: str = 'docker' )
Entorno base de TRL respaldado por un sandbox de Harbor + verificador.
Las subclases definen los métodos de la herramienta (el andamiaje). El ciclo de vida que TRL dirige por cada despliegue: reset(task_dir) (inicia el entorno aislado de la tarea y devuelve su instrucción) -> métodos de la herramienta (ejecuta en el entorno aislado) -> reward (ejecuta el verificador una vez, de forma perezosa, después del despliegue).
Arnés de una sola herramienta bash; envía escribiendo en /workdir/answer.txt.
Ejecuta un comando de shell en el sandbox y devuelve su salida combinada de stdout+stderr. El shell no es persistente entre llamadas. Úsalo para explorar archivos (ls, head, cat), ejecutar Python (python3 -c "...") y enviar la respuesta (echo -n "<value>" > /workdir/answer.txt).
Limitaciones
- La integración está en
trl.experimental— las API pueden cambiar. EstableceTRL_EXPERIMENTAL_SILENCE=1para silenciar la advertencia en los registros de CI. - El cliente de sandbox asíncrono de Harbor está vinculado a un solo bucle de eventos, por lo que cada env ejecuta start/exec/verify de forma síncrona en su propio bucle; la aprovisionamiento de sandboxes es, por tanto, secuencial en el lote de generación (los backends en la nube como
e2bmitigan el coste por sandbox). - Un único
HarborSpeccubre un conjunto de tareas + un harness; el entrenamiento con múltiples conjuntos de tareas aún no se admite.