RL agéntico verificable + evaluación rigurosa (cierra C2)
llevar GRPO/RLVR del problema de una sola respuesta (GSM8K) al multi-turno agéntico (un modelo que llama herramientas, recibe resultados y decide), y entrenar un agente que bate a su baseline SFT en un benchmark verificable. Más evaluar con rigor. Cierra C2b(b) y el Nivel 2.
8.1De "una respuesta" a "una trayectoria"
En GSM8K el modelo genera una respuesta y se acaba. Un agente genera una trayectoria: piensa → llama una tool → recibe el resultado → piensa → llama otra → ... → responde. La recompensa verificable llega al final (¿resolvió la tarea?), y a veces hay recompensas intermedias (¿cada tool-call fue válida?).
Retos nuevos respecto a L7:
- Multi-turno: la "acción" ya no es un token suelto sino turnos enteros con llamadas a herramientas.
- Entorno: necesitas algo que ejecute las tools y devuelva resultados (un environment).
- Crédito a largo plazo: la recompensa terminal debe propagarse a decisiones tempranas de la trayectoria.
8.2El ecosistema de frameworks (elige según el caso)
| Framework | Para qué | Nota |
|---|---|---|
TRL GRPOTrainer + rollout_func | rollouts custom (multi-turno, tools) sobre la base que ya conoces | el camino de menor fricción desde L7; soporta entornos vía OpenEnv |
| ART (OpenPipe) | agentes multi-turno contra cualquier MCP server; RULER (auto-rewards) | ideal si tus tools ya son MCP; envuelve tu agente y entrena con GRPO |
| SkyRL-Agent (NovaSky) | long-horizon (20–50 turnos) | SkyRL-SQL-7B venció a GPT-4o con 653 muestras |
| rLLM (Agentica) | "cualquier framework de agente"; swap del cliente OpenAI | base de DeepSWE (59% SWE-Bench-Verified solo con RL) |
| verl / OpenRLHF | escala multi-GPU (cloud) | HybridFlow, async; cuando pases de la 5090 |
Para tu 5090 y tu nivel, TRL con rollout_func custom (transparente, ya lo dominas) o ART (si tus herramientas son MCP) son las apuestas. Los demás cuando escales a cloud.
8.3La recompensa verificable de un agente (tool-calling)
Reusa la idea de L5.2 pero a nivel de trayectoria. Para un agente texto→SQL con ejecución:
1# lab_n2l8_agent_reward.py — recompensa verificable para un agente de tool-calling SQL
2import sqlite3, sqlglot, json
3
4def agent_reward(trajectory: dict, gold_sql: str, schema_setup_sql: str) -> float:
5 """
6 trajectory = {"tool_calls": [...], "final_sql": "..."}
7 Recompensa compuesta:
8 +1.0 resultado correcto (ejecuta y compara)
9 +0.2 todas las tool-calls parsean como JSON válido y tienen los campos requeridos
10 -0.5 la SQL final no parsea
11 """
12 reward = 0.0
13 # (a) validez de las tool-calls (señal intermedia, ayuda al crédito temprano)
14 try:
15 if all(_valid_tool_call(tc) for tc in trajectory["tool_calls"]):
16 reward += 0.2
17 except Exception:
18 pass
19 # (b) correctness terminal (la señal que manda)
20 sql = trajectory.get("final_sql", "")
21 try:
22 sqlglot.parse_one(sql)
23 except Exception:
24 return reward - 0.5
25 try:
26 con = sqlite3.connect(":memory:"); con.executescript(schema_setup_sql)
27 ok = con.execute(sql).fetchall() == con.execute(gold_sql).fetchall()
28 con.close()
29 reward += 1.0 if ok else 0.0
30 except Exception:
31 pass
32 return reward
33
34def _valid_tool_call(tc):
35 d = json.loads(tc) if isinstance(tc, str) else tc
36 return "name" in d and "arguments" in dLíneas no triviales:
- Recompensa compuesta: una señal terminal fuerte (correctness, +1.0) + señales intermedias pequeñas (tool-calls válidas, +0.2) que ayudan al crédito temprano sin dominar. Mantén la terminal dominante para no incentivar "hacer tool-calls bonitas sin resolver" (reward hacking).
- Compara resultados de ejecución, no strings de SQL (L5.5).
- Esta función es exactamente lo que pasarás como
reward_funcsal entrenar el agente.
8.4Laboratorio L8.1 — Entrenar el agente y batir al baseline SFT
El reto integrador del nivel: tu agente entrenado con RLVR debe superar al sql-sft de L3.
Esquema (con TRL + rollout multi-turno):
1# lab_n2l8_train_agent.py — GRPO multi-turno para un agente de tool-calling (esquema)
2from trl import GRPOConfig, GRPOTrainer
3from lab_n2l8_agent_reward import agent_reward
4
5# rollout_func: define cómo el modelo interactúa con el entorno durante el entrenamiento.
6# Recibe el prompt, deja que el modelo genere tool-calls, las EJECUTA contra el entorno
7# (sqlite en memoria), realimenta los resultados, y devuelve la trayectoria completa.
8def rollout_func(prompts, llm, sampling_params, **kwargs):
9 trajectories = []
10 for p in prompts:
11 traj = run_agent_episode(p, llm, sampling_params) # tu bucle agente<->entorno
12 trajectories.append(traj)
13 return trajectories # TRL las pasa a las reward_funcs
14
15def reward_wrapper(completions, gold_sql, schema, **kwargs):
16 return [agent_reward(c, g, s) for c, g, s in zip(completions, gold_sql, schema)]
17
18trainer = GRPOTrainer(
19 model="adapters/sql-sft", # ¡parte del SFT! (warm start; mejor que desde base)
20 reward_funcs=[reward_wrapper],
21 args=GRPOConfig(num_generations=8, learning_rate=1e-6, beta=0.04,
22 max_steps=800, use_vllm=True, vllm_mode="colocate",
23 vllm_gpu_memory_utilization=0.3, output_dir="agent_grpo",
24 report_to="wandb"),
25 train_dataset=ds_with_gold_and_schema,
26 # rollout_func=rollout_func, # API de rollout custom de TRL para multi-turno/tools
27)
28trainer.train()Por qué warm-start desde el SFT: entrenar RL desde el base puro sobre una tarea agéntica suele dar recompensa de ruido al principio (el modelo ni formatea tool-calls). Partir del SFT (que ya formatea) hace que la señal de RL sea útil desde el paso 1. (R1-zero saltó el SFT porque su tarea tenía recompensa muy limpia; en agentes, warm-start es lo prudente.)
Si usas ART + MCP•RL: envuelves tu agente (cliente OpenAI) con ART, apuntas a tu MCP server, defines la recompensa verificable, y ART corre los rollouts y el GRPO por ti. Es el camino si tus herramientas ya hablan MCP.
8.5Evaluación rigurosa (no hay maestría sin esto)
Entrenar sin evaluar bien es engañarte. Para agentes/tool-calling:
- BFCL v4 (Berkeley Function Calling Leaderboard): el referente de tool-calling. Dockerízalo y evalúa tu agente RL vs el SFT vs el base. Es el número "oficial" de tu checkpoint.
- Tu benchmark verificable propio: un holdout de 100+ tareas con gold, success-rate end-to-end. Más fiel a tu caso que cualquier benchmark genérico.
- τ²-bench / ToolSandbox: para agentes multi-turno conversacionales.
Disciplina anti-autoengaño:
- Holdout estricto: las tareas de eval nunca en train (contaminación → números inflados, ver SWE-Bench Verified en el informe de mercado).
- Detección de reward hacking: inspecciona las trayectorias de mayor reward a mano. ¿Resuelve de verdad o explota el verificador? (p.ej. devuelve un resultado vacío que casualmente coincide con un gold vacío).
- Varias seeds: RL tiene varianza alta; reporta media±std de varios runs, no un cherry-pick.
8.6CHECKPOINT C2b(b) — criterio de aprobado (cierra C2)
- Un agente entrenado con recompensas verificables que bate a su baseline SFT por margen medible en BFCL v4 y/o en tu benchmark verificable de ≥100 tareas.
- La mejora es robusta: holdout limpio, varias seeds, sin reward hacking detectable al inspeccionar trayectorias.
- Sabes explicar tu recompensa compuesta y por qué la terminal domina.
Rúbrica: Nivel 3 si el agente RL bate al SFT y lo evalúas con rigor; Nivel 4 si diseñaste el entorno/recompensa, mitigaste un reward hacking concreto, y/o contribuiste algo (un environment, un recipe) reutilizable.
8.7Ejercicios
E1. Entrena el agente con y sin las señales intermedias (+0.2 tool-call válida). ¿Acelera la convergencia la señal intermedia? ¿Introduce algún hack?
E2. Evalúa en BFCL v4 el base, el SFT y el RL. Construye la tabla de progresión por etapa (conecta con la receta de L1).
E3. Caza un reward hacking: busca la trayectoria de mayor reward que NO resuelve la tarea de verdad. Arregla la recompensa para cerrarlo. Documenta el antes/después.
8.8Trampas comunes
- Entrenar el agente desde el base (no desde SFT) → recompensa de ruido al inicio.
- Evaluar sobre datos vistos en train → mejora ilusoria.
- Reportar un solo run afortunado en vez de media±std.
- Recompensa terminal débil frente a intermedias → el agente optimiza el proceso, no el resultado.
8.9Referencias
- ART/MCP•RL (OpenPipe), SkyRL-Agent (arXiv 2511.16108), rLLM/DeepSWE (Agentica), verl (ByteDance), OpenRLHF. BFCL v4 (Patil et al., ICML 2025). τ²-bench, ToolSandbox. Docs TRL (rollout custom, OpenEnv).
8.10Cierre del Nivel 2 (spine principal)
Has recorrido la cadena completa: del mapa del post-training, por PEFT y datos, preferencias y reward modeling, la teoría de GRPO derivada, el "aha moment" reproducido, hasta un agente verificable que bate a su baseline. Esto es el spine principal a nivel world-class: ya no usas modelos entrenados por otros — los entrenas tú, y entiendes por qué funcionan. Combinado con el Nivel 1, cierras el círculo entrenar ↔ servir: los adaptadores de este nivel se sirven con el gateway multi-LoRA del anterior.