TRL documentation

Integrasi OpenReward untuk Pelatihan LLM dengan Lingkungan

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v1.18.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Integrasi OpenReward untuk Pelatihan LLM dengan Lingkungan

OpenReward adalah ekosistem terbuka untuk lingkungan RL yang dibangun di atas Open Reward Standard (ORS) — protokol HTTP/SSE publik yang tidak bergantung pada bahasa untuk cara lingkungan mengekspos tugas, alat, sesi, dan reward-nya. Karena ORS hanyalah protokol, lingkungan yang sama dapat dijalankan di platform OpenReward, self-hosted di layanan container apa pun, atau secara lokal di localhost untuk pengembangan. Katalog lingkungan siap pakai tersedia di openreward.ai.

Panduan ini membahas bagaimana mengintegrasikan OpenReward dengan TRL. Untuk informasi lebih lanjut tentang standar itu sendiri, lihat dokumentasi ORS.

Integrasi ini berada di trl.experimental.openreward dan diaktifkan melalui extra trl[openreward] (diimpor secara lazy — pengguna yang tidak memakainya tidak menanggung biaya apa pun).

Kapan menggunakan lingkungan OpenReward

GRPOTrainer mendukung pelatihan berbasis lingkungan melalui slot environment_factory — lihat OpenEnv untuk kontrak umum. Gunakan OpenReward ketika Anda ingin melatih terhadap lingkungan yang berbicara ORS: katalog OpenReward (mis. Eigent/SETA, kanishk/EndlessTerminals, nebius/SWE-rebench-V2), lingkungan yang Anda host sendiri di infrastruktur Anda, atau server lokal yang sedang Anda kembangkan.

Instalasi

pip install trl[openreward]

Ini menginstal SDK Python openreward. Integrasi itu sendiri mengimpor openreward secara lambat, sehingga pengguna yang tidak menyentuh trl.experimental.openreward tidak terpengaruh.

Mulai cepat

Kelas OpenRewardSpec menghubungkan satu lingkungan ORS ke tiga slot trainer TRL — train_dataset, environment_factory, reward_funcs — dengan mengekspos properti yang memetakan 1:1 ke nama kwarg tersebut:

from trl import GRPOConfig, GRPOTrainer
from trl.experimental.openreward import OpenRewardSpec

spec = OpenRewardSpec("Eigent/SETA", num_tasks=64)

trainer = GRPOTrainer(
    model="Qwen/Qwen3-4B",
    args=GRPOConfig(
        num_generations=2,
        max_steps=5,
        max_tool_calling_iterations=20,
        log_completions=True,
    ),
    train_dataset=spec.train_dataset,
    environment_factory=spec.environment_factory,
    reward_funcs=spec.reward_funcs,
)
trainer.train()

Di balik layar, OpenRewardSpec melakukan tiga hal, secara malas (lazy) pada akses pertama:

  1. spec.train_dataset: menurunkan datasets.Dataset dari daftar tugas env (satu roundtrip HTTP via SDK). Memiliki setidaknya prompt, task_index, ditambah kolom metadata per tugas yang digabungkan.
  2. spec.environment_factory: mengembalikan callable tanpa argumen yang menghasilkan adapter baru per-rollout pada setiap pemanggilan. Adapter ini mengekspos satu metode Python per tool ORS, dengan tanda tangan bertipe dan docstring yang dibuat secara otomatis dari JSON Schema env. Kolektor tool TRL mengambilnya melalui inspect.getmembers.
  3. spec.reward_funcs: fungsi reward yang hanya berdasarkan hasil akhir (reward non-nol terakhir dalam trajektori), cocok untuk lingkungan dengan reward jarang seperti SETA.

Menggunakan lingkungan hub

Lewatkan nama katalog openreward.ai sebagai target. SDK membaca OPENREWARD_API_KEY dari lingkungan untuk autentikasi.

spec = OpenRewardSpec("Eigent/SETA", num_tasks=64)

Menggunakan lingkungan self-hosted

Lewatkan URL secara langsung. Tidak diperlukan API key jika server Anda tidak mewajibkannya.

spec = OpenRewardSpec("https://my-org-my-env.hf.space", env_name="my_env")

SDK openreward secara default mengharapkan tata letak platform dengan dua subdomain (api.<host> untuk panggilan stateless dan sessions.<host> untuk panggilan sesi berbasis SSE). Untuk server self-hosted single-host (satu URL yang melayani semuanya), atur variabel lingkungan override di bawah ini sebelum membuat OpenRewardSpec:

import os

URL = "https://my-org-my-env.hf.space"
os.environ["OPENREWARD_API_URL"]     = URL
os.environ["OPENREWARD_SESSION_URL"] = URL

spec = OpenRewardSpec(URL, env_name="my_env")

Menjalankan lingkungan minimal secara lokal

Cara tercepat untuk mencoba integrasi secara end-to-end tanpa dependensi eksternal adalah server ORS kecil yang didefinisikan dengan scaffolding Environment + Server dari SDK openreward. Contoh di bawah ini adalah lingkungan echo lengkap — model menang dengan memanggil echo(text=...) menggunakan string target dari tugas.

# server.py
from pydantic import BaseModel
from openreward.environments import Environment, JSONObject, Server, TextBlock, ToolOutput, tool


class EchoTaskSpec(BaseModel):
    target: str

class EchoParams(BaseModel):
    text: str


class EchoEnvironment(Environment):
    def __init__(self, task_spec: JSONObject = {}, secrets: dict[str, str] = {}):
        super().__init__(task_spec)
        self.config = EchoTaskSpec.model_validate(task_spec)

    @classmethod
    def list_splits(cls) -> list[str]:
        return ["train"]

    @classmethod
    def list_tasks(cls, split: str) -> list[JSONObject]:
        return [{"target": "hello"}, {"target": "world"}]

    def get_prompt(self) -> list[TextBlock]:
        return [TextBlock(type="text", text=f"Echo '{self.config.target}' to win.")]

    @tool
    async def echo(self, params: EchoParams) -> ToolOutput:
        """Submit a string. Reward 1.0 + finished if it matches the target.

        Args:
            text: The string to echo back.
        """
        correct = params.text == self.config.target
        return ToolOutput(
            blocks=[TextBlock(type="text", text="match" if correct else "no match")],
            reward=1.0 if correct else 0.0,
            finished=correct,
        )


if __name__ == "__main__":
    Server([EchoEnvironment]).run(host="0.0.0.0", port=8000)

Jalankan:

pip install openreward fastapi uvicorn pydantic
python server.py     # listens on :8000

Lalu arahkan OpenRewardSpec ke sana (dengan penimpaan URL yang dijelaskan di atas):

import os
URL = "http://127.0.0.1:8000"
os.environ["OPENREWARD_API_URL"]     = URL
os.environ["OPENREWARD_SESSION_URL"] = URL

from trl.experimental.openreward import OpenRewardSpec
spec = OpenRewardSpec(URL, env_name="echoenvironment")
print(spec.train_dataset)        # 2 rows, task_index + target columns

Ini juga pola fixture yang digunakan oleh tes TRL sendiri — lihat trl-internal-testing/openreward-echo-env untuk Space yang di-deploy.

Memilih tugas

OpenRewardSpec menerima jumlah atau daftar indeks eksplisit:

spec = OpenRewardSpec("Eigent/SETA", num_tasks=10)                      # first 10 tasks
spec = OpenRewardSpec("Eigent/SETA", indices=[0, 5, 13, 27])            # specific indices
spec = OpenRewardSpec("Eigent/SETA", indices=list(range(50, 100)))      # range

num_tasks dan indices saling eksklusif dan keduanya hanya mengambil tugas yang diperlukan (tanpa memindai daftar tugas secara keseluruhan).

Cara kerja pengikatan alat

Saat konstruksi, spec memanggil endpoint /tools dari env untuk mengambil daftar spesifikasi tool (masing-masing dengan nama, deskripsi, dan JSON Schema untuk argumen). Untuk setiap tool, ia menghasilkan metode Python pada adapter per-rollout dengan signature bertipe dan docstring yang diturunkan dari schema. Metode-metode tersebut diset pada kelas adapter, di mana tool collector TRL menemukannya, sehingga transformers.utils.get_json_schema dan inspect.getmembers(type(env), isfunction) dari TRL keduanya menghasilkan skema tool yang tepat untuk model tanpa kode wrapper per-env.

Jika deskripsi alat berisi karakter yang tidak aman untuk disisipkan ke dalam sumber Python, binder akan beralih ke bentuk yang telah disanitasi sehingga pengikatan tidak pernah gagal di lingkungan nyata.

Fungsi reward

spec.reward_funcs secara default menggunakan reward berbasis hasil akhir — untuk setiap rollout, fungsi ini mengembalikan reward non-null terakhir yang diamati selama trajektori. Ini adalah default yang tepat untuk lingkungan dengan reward jarang (misalnya SETA, di mana hanya submit_solution yang mengembalikan reward non-null).

Jika tidak ada tool yang mengembalikan reward non-null, fungsi reward default mengembalikan None, bukan 0.0. Ini mencakup rollout tanpa pemanggilan tool, hanya pemanggilan tool yang tidak dinilai, atau hanya pemanggilan tool yang gagal. Reward 0.0 atau negatif yang diamati tetap merupakan skor yang valid. Pemanggilan tool yang tidak dinilai atau gagal di kemudian hari tidak menghapus skor sebelumnya.

GRPO mengecualikan rollout yang semua fungsi reward-nya mengembalikan None dari baseline reward dan memberikan mereka advantage nol. Hal ini tidak menghapus token mereka dari normalisasi loss atau menonaktifkan istilah lain seperti regularisasi KL. Jika fungsi reward lain memberikan skor pada rollout tersebut, ia masih dapat menerima advantage yang tidak nol.

Skor yang hilang tidak mengidentifikasi mengapa sebuah episode berakhir. Jika menyerah atau mencapai batas pemanggilan alat harus dihitung sebagai kegagalan tugas, kembalikan reward kegagalan yang eksplisit dari lingkungan atau fungsi reward kustom Anda. Kegagalan infrastruktur atau grader dapat tetap tidak dapat dinilai; pantau cakupan penilaian bersama dengan reward rata-rata.

Jika Anda menginginkan reward kustom, tulis fungsi reward TRL biasa dan teruskan secara langsung:

def my_reward(environments, **kwargs) -> list[float | None]:
    rewards = spec.reward_funcs(environments=environments)
    return [2.0 * reward if reward is not None else None for reward in rewards]

trainer = GRPOTrainer(
    ...,
    reward_funcs=my_reward,
)

Adapter per-rollout mengekspos status berjalan yang dibutuhkan TRL — env.reward, env.rewards, env.metadata, env.finished, env.last_output — untuk pembentukan reward pasca-pemrosesan yang arbitrer.

OpenRewardSpec

kelas trl.experimental.openreward.OpenRewardSpec

< >

( target: strnum_tasks: int | None = Nonesplit: str = 'train'indices: list[int] | None = Noneapi_key: str | None = Nonesecrets: dict[str, str] | None = Noneenv_name: str | None = Noneinclude_metadata: bool = Truediscover_task_tools: bool = Truetask_tools_discovery_index: int | None = None )

Parameter

  • target (str) — Nama katalog openreward.ai (“Eigent/SETA”) atau URL yang menunjuk ke server ORS mana pun (”https://you-seta.hf.space”, “http://localhost:8080”). Dideteksi secara otomatis berdasarkan keberadaan :// dalam string.
  • num_tasks (int, opsional) — Batas atas jumlah tugas yang ditarik ke dalam dataset. None menggunakan setiap tugas yang diekspos oleh env.
  • split (str, opsional, default “train”) — Split mana yang daftar tugasnya akan diambil.
  • indices (list[int], opsional) — Indeks tugas spesifik untuk dilatih. Saling eksklusif dengan num_tasks. Berguna untuk debugging atau subset kurikulum.
  • api_key (str, opsional) — penggantian untuk OPENREWARD_API_KEY. Hanya digunakan ketika target adalah nama katalog.
  • secrets (dict[str, str], opsional) — Rahasia per sesi yang diteruskan ke env.session(secrets=).
  • env_name (str, opsional) — Penimpaan untuk nama env yang akan dicari di server. Jarang diperlukan.
  • include_metadata (bool, opsional, default True) — Gabungkan metadata per tugas (difficulty, category, tags, …) ke dalam baris dataset sehingga fungsi reward dapat membacanya melalui argumen inputs TRL.
  • discover_task_tools (bool, opsional, default True) — Jika True, membuka sesi ORS berumur pendek dan menggunakan session.list_tools() sehingga alat yang spesifik untuk tugas (GET …/task_tools per ORS — mis. @tool(shared=False) dan list_task_tools()) terikat untuk GRPO. Jika probe gagal, hanya fallback ke environment.list_tools(). Atur False untuk melewati sesi tambahan (hanya alat bersama / keanehan offline).
  • task_tools_discovery_index (int, opsional) — Indeks tugas yang hanya digunakan untuk sesi penemuan saat diset; mengabaikan probing multi-indeks di bawah. Saat dihilangkan dan indices= diset, penemuan membuka satu sesi probe per entri unik dalam indices (yang diurutkan) dan menggabungkan spesifikasi alat berdasarkan nama sehingga alat khusus tugas dari setiap tugas yang terdaftar terikat. Saat dihilangkan dan mode num_tasks / daftar penuh digunakan, hanya probe tugas 0. Diabaikan saat discover_task_tools=False.

Objek spesifikasi tunggal yang menghubungkan lingkungan ORS ke pelatih TRL.

Keterbatasan

  • Integrasi ini ada di trl.experimental — API dapat berubah. Atur TRL_EXPERIMENTAL_SILENCE=1 untuk membisukan peringatan di log CI.
  • Saat ini hanya mengekspos satu OpenRewardSpec yang mencakup satu lingkungan; pelatihan multi-lingkungan (mengikuti pola “meta-environment” dari OpenEnv) belum didukung.
  • Rollout berdurasi panjang (>15 menit per episode) memerlukan ping keepalive — belum diintegrasikan.

Referensi

Update on GitHub