TRL documentation
Ortamlarla LLM Eğitiminde OpenEnv Entegrasyonu
Ortamlarla LLM Eğitiminde OpenEnv Entegrasyonu
OpenEnv, pekiştirmeli öğrenme (RL) ve ajan tabanlı iş akışlarında ortamları tanımlamak, dağıtmak ve bu ortamlarla etkileşime girmek için kullanılan açık kaynaklı bir çerçevedir. Ortam etkileşimi için standartlaştırılmış API'ler sunar ve ortamların arka uç sunucuları olarak çalıştırılmasını destekler (WebSocket veya konteynerize çalıştırma yoluyla). Hazır kullanıma uygun OpenEnv ortamlarının bir koleksiyonunu Hugging Face Hub'da bulabilirsiniz.
Bu kılavuz, OpenEnv'in TRL ile nasıl entegre edileceğini kapsar. OpenEnv'in kendisi hakkında daha fazla bilgi için OpenEnv belgelerini inceleyin.
Hazır OpenEnv örnekleri:
grpo_echo(minimal),grpo_catch,grpo_wordle,grpo_sudoku,grpo_multi_env,grpo_browsergym,grpo_carlaveasync_grpo_harbor(yerel ve HF Jobs).
Ortamların ne zaman kullanılacağı
GRPOTrainer, ajanları eğitmek için kullanılabilir. Ajanik görevler için iki modu destekler: tools, modelin harici fonksiyonları çağırmasına olanak tanır ancak her çağrı durumdan bağımsızdır (stateless) ve environments, turlar arasında durumu koruyarak ajanın eylemlerinin gelecekteki gözlemleri şekillendirdiği gerçek çok turlu etkileşimi mümkün kılar. Süreklilik önemli olduğunda ortamları kullanın; örneğin bir oyunda gezinme, bir web sayfasını görüntüleme veya ajanın bir sonraki göreceğinin önceki eylemlerine bağlı olduğu herhangi bir görev.
Ortam entegrasyonu seçimi
OpenEnv, burada belgelenen yerel yoldur. OpenReward ve Harbor olmak üzere iki ek entegrasyon, aynı environment_factory sözleşmesine uyar ve TRL düzeyinde birbirinin yerine kullanılabilir. Görevinize uygun ekosisteme sahip olanı seçmek için GRPO kılavuzundaki ortam entegrasyonlarının karşılaştırması bölümüne bakın.
Kurulum
OpenEnv ortamları, pip ile kurulabilir Git depoları olan Hugging Face Spaces olarak barındırılır:
# Echo environment
pip install "openenv-echo-env @ git+https://huggingface.co/spaces/openenv/echo_env"
# Wordle (TextArena) environment
pip install "openenv-textarena @ git+https://huggingface.co/spaces/openenv/wordle"
# Catch (OpenSpiel) environment
pip install "openenv-openspiel-env @ git+https://huggingface.co/spaces/openenv/openspiel_env"Bu, uzak ortam sunucusuyla WebSocket üzerinden iletişim kuran ortam istemcisini (ör. EchoEnv) ve eylem/gözlem modelleri ile tüm gerekli bağımlılıkları (arasında openenv de dahil) yükler.
Herhangi bir ortamın kurulum komutunu ilgili HF Space sayfasında bulabilirsiniz. Kurulum talimatlarını görmek için ⋮ (üç nokta) menüsüne tıklayıp “Bu Space’i kullan” seçeneğini seçin.
Ayrıca çekirdek paketi
pip install "openenv>=0.3.1"komutuyla PyPI'den de yükleyebilirsiniz ancak ortamla ilgili bağımlılıkların ayrı olarak kurulması gerekebilir.
Geliştirme için OpenEnv deposunu klonlayıp yerel olarak kurabilirsiniz:
git clone https://github.com/openenv/OpenEnv.git
cd OpenEnv/envs/echo_env
pip install -e .TRL'deki her ortam betiği, uv ile doğrudan çalıştırılabilmesi için satır içi bağımlılık meta verileri (PEP 723) içerir:
uv run examples/grpo_echo/grpo_echo.pyBu, gerekli ortam paketini yalıtılmış sanal bir ortamda otomatik olarak yükler.
Hızlı başlangıç
Entegrasyonu anlamak için en hızlı yol tam bir örnektir. echo.py betiği, tamamlamaları metin uzunluklarına göre ödüllendiren Echo ortamı ile bir model eğitir:
from datasets import Dataset
from echo_env import EchoEnv
from echo_env.models import EchoAction
from trl import GRPOConfig, GRPOTrainer
ENV_URL = "https://huggingface.co/proxy/openenv-echo-env.hf.space"
class EchoToolEnv:
def __init__(self):
self.env = EchoEnv(base_url=ENV_URL)
self.reward = 0.0
def reset(self, **kwargs) -> str | None:
self.reward = 0.0
return None
def echo(self, message: str) -> str:
"""
Echo the message back from the environment.
Args:
message: The message to echo
Returns:
The echoed message.
"""
observation = self.env.step(EchoAction(message=message))
self.reward = observation.observation.reward
return observation.observation.echoed_message
def reward_func(environments, **kwargs):
return [env.reward for env in environments]
dataset = Dataset.from_dict(
{"prompt": [[{"role": "user", "content": "Try to echo 'Hello World!' in the environment."}]] * 64}
)
trainer = GRPOTrainer(
model="Qwen/Qwen3-0.6B",
train_dataset=dataset,
reward_funcs=reward_func,
args=GRPOConfig(
chat_template_kwargs={"enable_thinking": False},
log_completions=True,
),
environment_factory=EchoToolEnv,
)
trainer.train()İşte hepsi. Arka planda olanlar şunlar:
environment_factory=EchoToolEnv: Eğitmen, her üretim için birEchoToolEnvörneği oluşturur (sınıfı, bir örnek değil, iletin).reset(), her bölümün başlangıcında durumu başlatmak için çağrılır. Bir gözlem dizesi (veyaNone) döndürür.- Araç keşfi: Eğitmen, ortam örneğindeki tüm genel yöntemleri (burada
echo()) keşfeder ve bunları fonksiyon çağırma araçları olarak sunar. Her yöntemin, eğitmenin araç şemasını oluşturmak için kullandığı, tipli argümanlara sahip uygun bir docstring'e sahip olması gerekir. - Çok turlu döngü: Eğitmen bir tamamlama üretir, araç çağrılarını ayrıştırır,
echo()işlevini çalıştırır, sonucu ekler ve modelin araç çağrılarını durdurmasına ya damax_completion_lengthsınırına ulaşılmasına kadar yeniden üretir. - Ödül fonksiyonu: Bölümün ardından (ortam sıfırlanmadan önce) her ortam örneğinden
env.rewarddeğerini okur.
# Run the example
python examples/grpo_echo/grpo_echo.py
# Customize model and environment URL
python examples/grpo_echo/grpo_echo.py --model Qwen/Qwen3-0.6B --env-host https://huggingface.co/proxy/openenv-echo-env.hf.spaceAşağıda eğitimden gelen ödül eğrisi yer almaktadır:
Bu sayfanın üstündeki notta daha fazla hazır OpenEnv örneğini inceleyebilirsiniz.
environment_factory nasıl çalışır
TRL’nin GRPOTrainer bileşeni, environment_factory argümanı aracılığıyla etkileşimli ortam eğitimini destekler. Bu argüman sağlandığında, eğitimci çok turlu araç çağırma döngüsünü otomatik olarak yönetir: tamamlamaları üretir, araç çağrılarını ayrıştırır, bunları ortamda çalıştırır ve sonuçları modele geri besler. Tüm bunlar özel rollout kodu gerektirmeden yapılır.
Environment sınıfı gereksinimleri
Ortam sınıfınız şu kurallara uymalıdır:
__init__(self)(isteğe bağlı): Sağlanırsa, argüman almamalıdır. Durum veya istemcileri başlatmak için kullanın. Harici yapılandırma (ör. bir URL) gerekiyorsa, bunu kapsayan kapsamdan veya modül düzeyindeki değişkenlerden yakalayın.reset(self, **kwargs): Her bölümün başında çağrılır. Tüm veri seti sütunlarını anahtar kelime argümanları olarak alır. Bir string gözlem döndürür (başlangıç gözlemi yoksaNone).- Araç yöntemleri:
resetdışında,_ile başlamayan her halka yöntem (public method) otomatik olarak bir araç olarak sunulur. Eğitimcinin (trainer) model için araç şemasını oluşturmak için bunları kullandığından, her araç yöntemininArgs:açıklamaları içeren bir docstring'e sahip olması gerekir.
Ortam sınıfları için ipuçları
- Ödül durumu: Ortam örneğinde istediğiniz herhangi bir durumu (ör.
self.reward,self.donevb.) saklayabilir ve ödül fonksiyonunuzdaenvironmentsparametresi üzerinden erişebilirsiniz. Bu desenin bir örneği için Hızlı Başlangıç kılavuzuna bakın. - Hata yönetimi: Bir araç metodu bir istisna fırlattığında (ör.
ValueError("Game over.")), eğitimci bunu yakalar ve hata mesajını modelin araç yanıtı olarak geri besler. Bir eylemin geçersiz olduğunu veya bölümün sona erdiğini bildirmek için önerilen yöntem budur.
ENV_URL = "https://huggingface.co/proxy/my-env.hf.space"
class MyEnv:
def __init__(self):
self.client = MyClient(base_url=ENV_URL) # captured from enclosing scope
self.reward = 0.0
def reset(self, **kwargs) -> str | None:
self.reward = 0.0
return "Initial observation for the model"
def my_tool(self, arg1: str, arg2: int) -> str:
"""
Description of what this tool does.
Args:
arg1: Description of arg1
arg2: Description of arg2
Returns:
The result message.
"""
self.reward = 1.0
return "Tool result"Araçlar, açıklayıcı adlara ve tipli argümanlara sahip bireysel yöntemler olmalıdır (ör.
guess(word: str),move(direction: str)). Modelin araç çağrısını öğrenebilmesi için anlamlı araç adlarına ve argüman açıklamalarına ihtiyaç duyması nedeniyle,step(action)gibi genel yöntemlerin kullanılmasını önermiyoruz.
Ödül işlevleri
Ödül fonksiyonları, environments parametresini (ortam örneklerinin bir listesi) alır, böylece bölüm sırasında saklanan herhangi bir duruma erişebilirsiniz:
def reward_func(environments, **kwargs) -> list[float]:
return [env.reward for env in environments]Ödül fonksiyonları hakkında daha fazla bilgi için GRPO - Özel Ödül Fonksiyonları bölümüne bakın.
Ödül fonksiyonları için ipuçları
OpenEnv ortamları ve GRPO ile çalışırken faydalı bulduğumuz birkaç şey:
- Grupların farklı olduğundan emin olun. GRPO, tamamlamaları bir grup içinde karşılaştırır; bu nedenle mutlak değerlerden çok göreli sıralama önemlidir ve her tamamlamanın aynı ödülü aldığı bir grup sinyal vermez. Modelin bazen başarılı olduğu durumlarda ikili ödül (başarı için 1.0, aksi halde 0.0) temizdir. Nadiren başarılı olduğunda kısmi kredi ekleyin: Sudoku örneği çözülen ödülüne doldurulan hücrelerin oranını, Wordle örneği ise en iyi tahminin yeşillerini ekler.
- Son durumu, yolu değil kontrol edin. Mümkün olduğunda, modelin belirli bir eylem dizisini izleyip izlemediğini kontrol etmek yerine, sonucu ortamın değerlendirmesini sağlayın (ör. “model bulmacayı çözdü mü?”). Bu, modelin kendi stratejilerini keşfetmesi için ona özgürlük tanır.
- Eğitimden önce ödülünüzü test edin. Ortamın mantıklı ödüller döndürdüğünü doğrulamak için birkaç bölümü manuel olarak çalıştırın (Wordle örnek defterine bakın). Yetkin bir model, rastgele bir baz çizgisinden daha yüksek puan alamıyorsa, ödül sinyali ayarlanmalıdır.
çok turlu bölümlerde max_completion_length
max_completion_length parametresi, tek bir üretim değil, çok turlu konuşmanın tamamındaki toplam token sayısını (tüm model üretimleri + araç sonuçları bir arada) sınırlar. Çok sayıda tura sahip ortamlarda (örneğin, onlarca hamle içeren Sudoku) bunu artırmanız gerekebilir:
args = GRPOConfig(
max_completion_length=4096, # default is usually 256-1024, increase for long episodes
# ...
)Eğer bölümler yarıda kesiliyorsa (model oyunun ortasında duruyorsa), bunun nedeni büyük olasılıkla budur.
Bir Space'e karşı uzun süreli çalıştırmalar
Bir Space, saatlerce açık kalan WebSockets’leri kapatabilir (yaklaşık her 2 saatte bir gözlemledik). 0.11.0 ve öncesi OpenEnv istemcileri, yeni bir ortam oturumuna yeniden bağlanır ve bir oyun devam ediyorsa, sonraki step() istemcinin asla sıfırlamadığı bir oyunda, hata vermeden çalışır. OpenEnv 0.12.0’dan itibaren istemciler bunun yerine SessionLostError fırlatır, böylece oyun başarısız olur. Kopmaları eğitimden uzak tutmak için, her bağlantının bir bölüm (episode) sürmesi amacıyla reset() içinde yeni bir istemci açın ve eski oturumların asenkron olarak serbest bırakıldığı için MAX_CONCURRENT_ENVS değerini, aynı anda oynanan oyun sayısından biraz yüksek ayarlayın:
def reset(self, **kwargs) -> str | None:
self.client.close()
self.client = TextArenaEnv(base_url=env_url).sync()
result = self.client.reset()
...Gelişmiş örnek: Wordle
TextArena ortamını kullanarak Wordle oynamak için bir model eğitelim. Bu, çok turlu etkileşimi, kümülatif geri bildirim işleme, birden fazla terime ayrılan ödülü ve istisnalar aracılığıyla bölüm sonlanmasını gösterir.
OpenEnv Wordle öğreticisi, donanım ve maliyetler dahil olmak üzere tüm hattı kapsar: SFT verileri, SFT ısınma süreci, bu GRPO adımı ve değerlendirme. Bu örneğin defter (notebook) sürümü
grpo_wordle.ipynb'dir.
TextArena Ortamı
TextArena, Wordle, Snake, XOX gibi metin tabanlı oyunlar kullanarak LLM'lerin akıl yürütme becerilerini değerlendirmek için tasarlanmış, rekabetçi metin tabanlı oyunlardan oluşan açık kaynak bir koleksiyondur.

Neden Wordle?
Wordle, geri bildirim hakkında akıl yürütme gerektirmesi, tamamen metin tabanlı olması ve 1B parametreye sahip modellerin bu konuda gelişme gösterebilmesi nedeniyle ortam tabanlı RL için iyi bir referans noktasıdır.
Wordle nasıl çalışır? Wordle, oyuncunun 6 denemede 5 harfli bir kelimeyi bulmaya çalıştığı bir kelime tahmin oyunudur. Her tahminin ardından ortam, harf harf geri bildirim sağlar:
G U E S S X G Y X XX = kelime içinde değil, G = doğru konum (yeşil), Y = yanlış konum (sarı). Burada “U” doğru ve yerinde, “E” ise kelime içinde ama yanlış yerde.
SFT ısınma turundan başlayın
Qwen3-1.7B neredeyse hiç oyun kazanmadığından, temel modelden GRPO'nun öğrenecek pek bir şeyi yoktur: hiçbiri kazanılmamış bir oyun grubu sinyal vermez. Örnek, aynı araç çağırma biçiminde, her tahminden önce kısa bir akıl yürütme içeren, bir çözücü tarafından oynanan 1.000 oyunda bir epoch boyunca eğitilmiş openenv/Qwen3-1.7B-Wordle-SFT modelinden başlar.
Environment sınıfı
WordleEnv sınıfı TextArena istemcisini sarar, guess() işlevini araç olarak sunar ve ödülün gerektirdiği bilgileri saklar:
import re
from textarena_env import TextArenaAction, TextArenaEnv
FEEDBACK = re.compile(r"Feedback:\n([A-Z ]+)\n([GYX ]+)")
class WordleEnv:
def __init__(self):
self.client = TextArenaEnv(base_url="https://<user>-wordle.hf.space")
def reset(self, **kwargs) -> str | None:
result = self.client.reset()
self._last_full_feedback = result.observation.messages[0].content
self.done = False
self.won = False
self.num_guesses = 0
self.best_greens = 0
self.invalid_moves = 0
return self._last_full_feedback
def guess(self, guess: str) -> str:
"""
Make a guess in the Wordle environment.
Args:
guess: The guessed word, formatted as '[abcde]'
Returns:
The feedback message from the environment.
"""
if self.done:
raise ValueError("Game over.")
result = self.client.step(TextArenaAction(message=guess))
_full_feedback = result.observation.messages[0].content
feedback = _full_feedback[len(self._last_full_feedback):]
self._last_full_feedback = _full_feedback
if "invalid move" in feedback.lower():
self.invalid_moves += 1
else:
self.num_guesses += 1
match = FEEDBACK.search(feedback)
if match:
self.best_greens = max(self.best_greens, match.group(2).count("G"))
self.won = result.done and result.reward >= 1.0
self.done = result.done
return feedbackTemel tasarım tercihleri:
reset(), modelin gördüğü ilk gözlem olarak başlangıç oyun mesajını döndürür.guess()tek araçtır. Model, her turda 5 harfli bir kelimeyle bunu çağırır.- Kümülatif geri dilimleme: TextArena her turda tam oyun geçmişini döndürür. Bağlamı tekrarlamamak için yalnızca yeni kısmı dilimler.
- done'da istisna: Oyun bittikten sonra model tahmin yapmaya çalışırsa,
guess()birValueErrorfırlatır. Eğitmen bunu yakalar ve"Game over."metnini modelin araç yanıtı olarak geri besler ve bunutools/failure_frequencyiçinde sayar.
Ödül fonksiyonları ve eğitim
Ortamın kendi ödülü, 1 tahminde veya 6 tahminde kazanıldığında aynı tutarı öder ve kısmi kredi yalnızca oyunun sonunda verir. Düşünme açıkken, bir politika daha az düşünmeyi ve sona ulaşmak için 6 tahminin tamamını kullanmayı öğrenebilir. Bunu önleyen üç ödül terimi şunlardır:
from datasets import Dataset
from trl import GRPOConfig, GRPOTrainer
def reward_win(environments, **kwargs) -> list[float]:
return [1.0 + 0.5 * (1 - env.num_guesses / 6) if env.won else 0.0 for env in environments]
def reward_partial(environments, **kwargs) -> list[float]:
return [0.0 if env.won else 0.1 * env.best_greens for env in environments]
def reward_invalid(environments, **kwargs) -> list[float]:
return [-0.1 * env.invalid_moves for env in environments]
prompt = """You are an expert Wordle solver with deep knowledge of English vocabulary...
Use the tool `guess` to make a guess."""
dataset = Dataset.from_dict({"prompt": [[{"role": "user", "content": prompt}]] * 600})
trainer = GRPOTrainer(
model="openenv/Qwen3-1.7B-Wordle-SFT",
reward_funcs=[reward_win, reward_partial, reward_invalid],
train_dataset=dataset,
args=GRPOConfig(
use_vllm=True,
vllm_mode="colocate",
chat_template_kwargs={"enable_thinking": True},
max_completion_length=4096,
max_tool_calling_iterations=12,
vllm_importance_sampling_mode="token_truncate",
num_generations=16,
per_device_train_batch_size=8,
gradient_accumulation_steps=8,
learning_rate=1e-6,
lr_scheduler_type="constant",
max_steps=150,
),
environment_factory=WordleEnv,
)
trainer.train()Kazanç, ne kadar hızlı gelirse o kadar yüksek olur (bir tahminde 1.42, altıda 1.0), kayıp ise oyun bitip bitmediğine bakılmaksızın oyunun en iyi tahmini için ödenir ve her geçersiz hamle 0.1 maliyetine mal olur. TRL her terimi ayrı ayrı kaydeder, bu nedenle rewards/reward_win/mean kazanma oranıyla birlikte yükselir.
Örneğin çalıştırılması
Her adım 64 oyun oynar, her biri bir ortam oturumu. openenv/wordle Space'ini çoğaltın ve kopyanızda MAX_CONCURRENT_ENVS=64 değişkenini ayarlayın.
Colocate modu (1 GPU, önerilen)
python examples/grpo_wordle/grpo_wordle.py --vllm-mode colocate --env-url https://<user>-wordle.hf.space
Bu, vLLM'yi eğitimle aynı süreçte çalıştırır ve yalnızca tek bir GPU gerektirir. Çalışmamızda, tek bir A100 80GB üzerinde 150 adım yaklaşık 2 saat 15 dakika sürdü.
Sunucu modu (2+ GPU, ölçeklenebilir)
# Terminal 1: Start vLLM inference server
CUDA_VISIBLE_DEVICES=0 VLLM_SERVER_DEV_MODE=1 vllm serve openenv/Qwen3-1.7B-Wordle-SFT --host 0.0.0.0 --port 8000 \
--weight-transfer-config '{"backend": "nccl"}' \
--logprobs-mode processed_logprobs \
--max-logprobs -1
# Terminal 2: Run GRPO training with OpenEnv
CUDA_VISIBLE_DEVICES=1 python examples/grpo_wordle/grpo_wordle.py --vllm-mode server --vllm-server-url http://localhost:8000 \
--env-url https://<user>-wordle.hf.spaceSonuçlar
Çalışmamızdan, model başına bir eğitim çalıştırmasıyla, aynı 30 kelimenin açgözlüce oynanmasıyla:
| Model | Kazanımlar | Kazanım başına tahmin | Geçersiz tahminler |
|---|---|---|---|
| Qwen3-1.7B | 0/30 | - | 24 |
| + SFT | 10/30 | 3.2 | 41 |
| + SFT + GRPO (model) | 20/30 | 4.1 | 3 |
GRPO, tekrarlanan ve uydurma kelimeleri büyük ölçüde ortadan kaldırdı ve daha fazla oyun kazandı. Yeni kazanımların çoğu 4 ila 6 tahmin arasında gerçekleştiğinden, kazanım başına tahmin sayısı arttı. 30 kelime, modellerin eğitim sırasında da gördüğü ve TextArena'nın sırlarını buradan seçtiği 156 isimden geliyor; yeni bir çalıştırma birkaç kazanım farkıyla sonuçlanabilir (aynı tarifle iki SFT çalıştırması 10 ve 13 oyun kazandı). Üç modelin Wordle Arena'da oynamasını izleyin ve eğitim eğrilerini Trackio'da görün.
Çoklu ortam eğitimi
Tek bir modeli birden fazla ortamda eş zamanlı olarak eğitebilirsiniz. Bir modelin paralel olarak farklı beceriler öğrenmesini istediğinizde bu işe yarar. Örneğin, aynı eğitim çalışmasında Wordle (dil çıkarımı) ve Catch (uzamsal çıkarım) oynatmak.
Temel fikir, bir veri seti sütununu kullanarak her örneği doğru ortama yönlendiren ve birden fazla ortamı saran bir meta-ortam sınıfı oluşturmaktır.
Nasıl çalışır
- Veri setinize, her örneğin hangi ortama ait olduğunu belirten bir
"env"sütunu (veya benzeri) ekleyin. reset(**kwargs)içinde, o bölüm için etkin ortamı seçmek üzerekwargs["env"]değerini okuyun.- Tüm ortamlardan araçları dışa aktarın; eğitimci tüm genel yöntemleri keşfeder.
- Ortam başına ayrı ödül fonksiyonları kullanın ve o ortama ait olmayan örnekler için
Nonedöndürün. TRL,Nonedeğerlerininansum/nanmeanile işler.
Örnek: Wordle + Catch
grpo_multi_env.py betiği Wordle ve Catch üzerinde eş zamanlı eğitim yapar:
class MultiEnv:
def __init__(self):
self._wordle_client = None
self._catch_client = None
self.active = None
self.reward = 0.0
self.done = False
def reset(self, **kwargs) -> str | None:
self.active = kwargs.get("env", "wordle")
self.reward = 0.0
self.done = False
if self.active == "wordle":
if self._wordle_client is not None:
try:
self._wordle_client.close()
except Exception:
pass
self._wordle_client = TextArenaEnv(base_url=WORDLE_URL)
result = self._wordle_client.reset()
self._last_full_feedback = result.observation.messages[0].content
self.reward = 0.0
return self._last_full_feedback
elif self.active == "catch":
if self._catch_client is not None:
try:
self._catch_client.close()
except Exception:
pass
self._catch_client = OpenSpielEnv(base_url=CATCH_URL)
result = self._catch_client.reset()
self.done = result.observation.done
return _format_catch_obs(result.observation.info_state)
# Wordle tool
def guess(self, guess: str) -> str:
"""Make a guess in the Wordle environment. ..."""
...
# Catch tools
def move(self, direction: str) -> str:
"""Move the paddle left or right. ..."""
...
def stay(self) -> str:
"""Do nothing and let the ball fall one step. ..."""
...Temel kalıplar:
- Gecikmeli istemci başlatma: Gereksiz WebSocket bağlantılarını önlemek için istemcileri
reset()içinde,__init__()içinde değil oluşturun. - Yeniden açmadan önce kapat: Sunucu kapasite hatalarını önlemek için yeni bir istemci oluşturmadan önce önceki istemciyi kapatın.
kwargsyönlendirme: Veri setindeki"env"sütunu,reset()fonksiyonuna anahtar kelime argümanı olarak iletilir.- Tüm araçlar eşzamanlı olarak açığa çıkarılır: Model, aktif ortamdan bağımsız olarak
guess,movevestayaraçlarını kullanılabilir olarak görür. Yanlış aracı çağırırsa (ör. Wordle sırasındamove), yöntem, eğiticinin zarifçe yakaladığı birValueErrorfırlatır. Uygulamada, modeller sistem istemine dayanarak doğru araçları kullanmayı öğrenir.
Ortam başına ödül işlevleri
Her ödül fonksiyonu, diğer ortamlardan gelen örnekler için None döndürür:
def wordle_reward(environments, **kwargs) -> list[float | None]:
return [env.reward if env.active == "wordle" else None for env in environments]
def catch_reward(environments, **kwargs) -> list[float | None]:
rewards = []
for env in environments:
if env.active != "catch":
rewards.append(None)
elif env.done:
rewards.append(max(env.reward, 0.0))
else:
rewards.append(0.0)
return rewardsTRL, None değerini içsel olarak nan olarak dönüştürür ve toplulaştırma için nansum/nanmean kullanır; bu sayede her örnek yalnızca ilgili ödül fonksiyonuyla puanlanır.
Ortam yönlendirmeli veri seti
n = 500
dataset = Dataset.from_dict({
"prompt": (
[[{"role": "user", "content": wordle_prompt}]] * n
+ [[{"role": "user", "content": catch_prompt}]] * n
),
"env": ["wordle"] * n + ["catch"] * n,
})Çoklu ortam örneğini çalıştırma
python examples/grpo_multi_env/grpo_multi_env.py \
--wordle-url https://huggingface.co/proxy/openenv-wordle.hf.space \
--catch-url https://huggingface.co/proxy/openenv-openspiel-env.hf.space \
--vllm-mode colocate \
--gradient-accumulation-steps 4 \
--num-generations 8Çevreler arasında eğitim yapılırken, birleşik
train/rewardyerine ödül fonksiyonu başına metrikleri (train/reward_func_0,train/reward_func_1vb.) izleyin. Birleşik metrik, ortamlar arasında dönüşümlü olarak değiştiğinden gürültülü görünebilir.
Ortamların çalıştırılması
environment_factory kullanıldığında, trainer ortam sunucusuna otomatik olarak bağlanır. Sadece sunucunun çalışıyor olması yeterlidir. Bir OpenEnv ortam sunucusunu çalıştırmak için üç yol vardır:
Uzak bir Hugging Face Space'e bağlan (en basit)
Çoğu örnek betik, varsayılan olarak barındırılan bir Space kullanır (kurulum gerekmez):
env = EchoEnv(base_url="https://huggingface.co/proxy/openenv-echo-env.hf.space")Eğitim için, eşzamanlılık sorunlarını önlemek üzere Space'i kendi hesabınıza kopyalayın. Eğitimci, N eşzamanlı WebSocket bağlantısı açar (her üretim için bir tane) ve paylaşılan Space'ler bunu desteklemeyebilir. Ayrıntılar için Sunucu eşzamanlılığı bölümüne bakın.
Docker konteyneri (üretim için önerilir)
docker run -d -p 8001:8000 --platform linux/amd64 registry.hf.space/openenv-echo-env:latest
Ardından bağlanın:
env = EchoEnv(base_url="http://0.0.0.0:8001")vLLM sunucusu için 8000 portunun kullanılabilir kalmasını sağlamak amacıyla 8001 portunu 8000 portuna eşliyoruz.
Konteyneri programatik olarak da başlatabilirsiniz:
env = EchoEnv.from_docker_image("registry.hf.space/openenv-echo-env:latest")Hub'daki herhangi bir Space için Docker görüntüsünü bulabilirsiniz: Space sayfasını açın → ⋮ (üç nokta) → “Run locally.”
Yerel Python süreci (geliştirme için)
hf download openenv/echo_env --repo-type=space --local-dir=echo_env python -m uvicorn echo_env.src.envs.echo_env.server.app:app --host 0.0.0.0 --port 8001
Ardından bağlanın:
env = EchoEnv(base_url="http://0.0.0.0:8001")Daha fazla ayrıntı için OpenEnv kataloğu'na bakın.
Ortam kataloğu
Bakımı yapılan ortamların güncel kataloğunu keşfetmenin en iyi yolu, resmi OpenEnv kataloğunu ziyaret etmektir.
Kendi ortamınızı oluşturmak için OpenEnv ile Kendi Ortamınızı Oluşturma kılavuzuna göz atın. Ortamlar Hub ile sıkı bir şekilde entegre olduğundan, topluluğun yeniden kullanması için yeni ortamlar itebilirsiniz.
Sunucu eşzamanlılığı
environment_factory kullanıldığında, trainer N adet ortam örneği oluşturur (her üretim için bir adet) ve her biri sunucuya bir WebSocket bağlantısı açar. Varsayılan olarak OpenEnv sunucuları yalnızca 1 eşzamanlı oturuma izin verir; bu durum eğitim sırasında hatalara yol açar.
Paralel eğitimi desteklemek için sunucuyu eşzamanlılık için yapılandırın:
- Ortam dosyanızda eşzamanlı oturum desteğini bildirin:
SUPPORTS_CONCURRENT_SESSIONS: bool = True- Sunucu uygulamanızda eşzamanlılık sınırını ayarlayın:
app = create_app(
create_my_environment,
MyAction,
MyObservation,
max_concurrent_envs=64, # match or exceed generation_batch_size
)
max_concurrent_envs,generation_batch_size'den (varsayılan değeriper_device_train_batch_size × gradient_accumulation_stepsolan) büyük veya eşit olmalıdır. Örneğin,gradient_accumulation_steps=64ve batch boyutu 1 ile en az 64 eşzamanlı oturuma ihtiyaç duyarsınız.
environment_factory ve rollout_func
GRPOTrainer, ortam tabanlı eğitim için iki yaklaşımı destekler:
environment_factory(önerilen): Araç yöntemleri içeren bir ortam sınıfı tanımlarsınız ve eğitimci, üretim, araç çağrısı ayrıştırma ve çok turlu döngüyü otomatik olarak yönetir. Bu kılavuz boyunca kullanılan yaklaşım budur.rollout_func: Tüm üretim ve ortam etkileşim döngüsünü kendiniz yazarısınız. Bu, tamamlamaların nasıl üretileceği, araçların nasıl çalıştırılacağı ve ödüllerin nasıl hesaplanacağı üzerinde tam kontrol sağlar.
environment_factory kullanım senaryonuza uymuyorsa rollout_func kullanın. Örneğin, dış bir sunucunun üretim döngüsünü sahiplendiği ve kendi ajan-ortam etkileşim protokolünü yönettiği dış ajan sunucuları.
Test platformlarında eğitim: gerçek kodlama ajanlarının eğitimi (Harbor)
Yukarıdaki entegrasyonlar white-box niteliğindedir: TRL, çok turlu döngüyü kendisi yönetir. Her turda örneklem alır, araç çağrılarını ayrıştırır, bunları çalıştırır ve sonuçları geri besler.
Bazı ajanlar kendi döngülerine sahip oldukları için bu şekilde yönlendirilemez. opencode veya claude-code gibi üretim kodlama ajanı iskeletleri kendi planlayıcısına, araç setine, bağlam yönetimine ve durdurma koşuluna sahiptir. Yeniden bir uygulama değil, tam olarak o ajanı eğitmek istersiniz.
Bunun için TRL, experimental.async_grpo.AsyncGRPOTrainer üzerine kurulu deneysel bir siyah kutu (döngü sahibi) yolunu sağlar: HarnessAsyncGRPOTrainer, bir OpenEnv oturum fabrikasını yönetir. Ajanlar ve kum havuzları, openenv harbor serve ile OpenEnv üzerinden sunulan Harbor'dan gelir; böylece Harbor'ın kurduğu her ajan aynı şekilde eğitilebilir: --harness ile birini seçersiniz. Hugging Face Jobs başlatıcısını da içeren tam bir örnek için examples/async_grpo_harbor'a bakın.
Bu yol,
TrainingTraceyakalama API'sine sahip ilk sürüm olanopenenv>=0.7.0sürümünü gerektirir:pip install "openenv>=0.7.0".
Nasıl çalışır
TRL burada her turu örneklemiyor. Ajan kendi başına tamamlanana kadar çalışır ve TRL, ajanın ne yaptığını geri okur:
- OpenEnv Harbor sunucusu, ajanı bir Harbor görevinde bir kum havuzunda (örneğin E2B) başlatır. Ajanın yaptığı her model çağrısı, sunucunun yakalama vekili (capture proxy) üzerinden vLLM sunucunuza gider; bu sunucu, motorun kendi prompt ve tamamlama token kimliklerini, örneklenen logprobs değerlerini ve token başına kayıp maskesini kaydeder.
- Ajan durduğunda, görevin kendi doğrulayıcısı sonucu puanlar ve TRL, OpenEnv'den doğrulanmış
TrainingTracenesnesini alır; eğitim satırlarını bu nesnenin token kimlikleri ve maskelerinden oluşturur. TRL, yakalanan istekleri yeniden tokenleştirmez. - GRPO, bu satırlar üzerinde eğitim yapar. Ödül, grup-göreli avantaj yoluyla her eğitimli token'a iletilir ve yeni ağırlıklar aynı vLLM sunucusuna geri senkronize edilir.
Her rollout, kendi izole oturumunda, kendi sandbox'ında ve kendi yakalama oturumunda çalışır. İzolasyon iki nedenle önemlidir: proxy, tam olarak o rollout'un token'larını yakalamalı ve bir rollout, diğerini etkilememelidir. max_concurrent_rollouts ayarı, aynı anda kaç rollout'un çalışacağını kontrol eder ve sunucunun MAX_CONCURRENT_ENVS değeri en az max_concurrent_rollouts + 1 olmalıdır (fabrika, görev metadata'sı için bir ek bağlantı tutar).
Bağlantı
HarnessAsyncGRPOTrainer, experimental.async_grpo.AsyncGRPOTrainer gibi model, yapılandırma ve veri setini alır; ancak reward_funcs, tools ve environment_factory yerine bir oturum fabrikası kullanır. harness_adapter yoksa döngünün sahibi ajan olur. Eğitmen, kendi örneklem politikasıyla oturum fabrikasını oluşturur; bu nedenle hazır bir fabrika yerine partial(HarborSessionFactory, ...) gibi çağrılabilir bir nesne iletirsiniz. Her oturum, tam motor jetonlarını, davranış logprobs değerlerini ve önceden doldurulmuş maskeleri içeren bir OpenEnv TrainingTrace döndürür. rollout_reward_fn isteğe bağlıdır; belirtilmezse TRL, oturumun doğrulayıcı ödülünü kullanır.
from functools import partial
from harbor_env.harness import HarborSessionFactory
from trl.experimental.async_grpo import AsyncGRPOConfig
from trl.experimental.async_grpo.openenv_harness import HarnessAsyncGRPOTrainer
factory = partial(
HarborSessionFactory,
"http://localhost:8200", # the OpenEnv Harbor server
split="<hf-dataset>", # a Harbor task dataset the server serves
harness="mini-swe-agent", # or "opencode", "claude-code", ...
sandbox="e2b",
llm_url=vllm_url,
model=model,
)
config = AsyncGRPOConfig(num_generations=8, max_concurrent_rollouts=8, vllm_server_base_url=vllm_url)
trainer = HarnessAsyncGRPOTrainer(
model=model,
harness_session_factory=factory, # called by the trainer with its sampling policy
args=config,
train_dataset=dataset,
rollout_reward_fn=my_reward, # outcome -> float | None
)
trainer.train()Tanımlamanız gerekenler
OpenEnv, yakalama doğrulamasından ve jeton seçiminden sorumludur. TRL, üreticinin tam dizin maskesini dahili tamamlama maskesine dönüştürür, sonuçlanan satırları paketler ve GRPO uygular. Jetonları yeniden oluşturmak veya hangi çağrıların ajana ait olduğunu çıkarmakla ilgilenmez.
rollout_reward_fn : bir rollout'un nasıl puanlanacağı
Callable[[HarnessRolloutOutcome], float | None]
TRL, göreviniz için başarının ne anlama geldiğini bilmediğinden, tamamlanan her rollout'u bir skaler ödülüne dönüştürür. İşlev, ajanın ne yaptığını açıklayan bir HarnessRolloutOutcome alır:
env_reward(float | None): görev doğrulayıcısından gelen ödül, rollout puanlanamadığındaNone.completion(list[dict]): son mesaj dökümü.trace(list[TraceEntry]): seçilen OpenEnv yakalama kayıtları, sıfır maskeli turlar dahil.tool_call_countvetool_failure_count(int): ajanın yaptığı araç çağrılarının sayısı ve başarısız görünenlerin sayısı.tool_calls_by_name(dict[str, int]): araç başına çağrı sayısı, örneğin{"bash": 3, "edit": 2}.timed_out(bool): ajanın zaman bütçesinin tükendiğini belirtir.
float döndürün veya grup baz çizgisinden düşürülüp sıfır olarak sayılmaması için rollout’u puanlanamaz olarak işaretlemek için None döndürün. Bu işlevi iletmezseniz, ham env_reward olduğu gibi kullanılır. Harbor örneği, doğrulayıcının doğruluğunu ana sinyal olarak korur ve görev çözüldüğünde yalnızca küçük bir araç verimliliği bonusu ekler.
Neden doğrudan doğrulayıcıyı kullanmıyoruz? Doğrulayıcı, ortamın görevidir ve “sonuç ne kadar doğruydu?” sorusuna yanıt vererek temiz ve değerlendirme için yeniden kullanılabilir kalır. Eğitimde kullandığınız ödül ise ayrı bir, eğitim zamanı kararıdır (skoru ikili hale getirme, dejeneratif davranışı cezalandırma, puanlanamayan rollout’ları düşürme). Ayrıca doğrulayıcının asla görmediği sinyallere de ihtiyaç duyar; çünkü doğrulayıcı yalnızca nihai sonucu incelerken
rollout_reward_fnaynı zamanda yörüngeyi (araç sayıları,timed_out, iz) de alır. Örneğin, bir rollout bazı testleri geçse bilebashçalıştırmayabilir; bunu görebilecek ve cezalandırabilecek tek fonksiyonrollout_reward_fn’dir.
Token uygunluğu OpenEnv'den gelir
session.fetch_training_trace(), doğrulanmış bir TrainingTrace döndürür. Her turda benzersiz bir node_id, prompt_token_ids, completion_token_ids, per_token_logps ve prompt ile tamamlama üzerine zorunlu bir loss_mask bulunur. Prompt konumları sıfırdır. Kısmi tamamlama maskeleri, asistan yanıtı içindeki sıfırlar dahil olmak üzere korunur.
Örneğin, [10, 11] istemi, [20, 21, 22] tamamlama ve [0, 0, 1, 0, 1] maskesi, 20 ve 22 jetonlarında eğitim yapar. 21 jetonu bağlam olarak kalır. Tamamen maskelenmiş bir tamamlama, bağlam ve kullanım muhasebesi için korunur.
Producer yardımcı çağrıları ve atılan yeniden denemeleri hariç tutar. Bu API'de train_turn_fn veya agent_turn_fn parametreleri bulunmaz. Mevcut entegrasyonlar seçim mantığını OpenEnv maskelerine taşımak zorundadır. Görevin doğrulayıcısı, token uygunluğundan bağımsız olarak kalır.
Bozuk yakalamalar OpenEnv sınırında başarısız olur ve eğitimi durdurur. Taşıma hataları puanlanamaz olarak kalır. Yeniden yazılan geçmişler ayrı satırlarla başlar; örneklenen tokenlar ve logprobs korunur. Birden fazla satır yine de rollout ödülünü paylaşır; bu API, GRPO’nun ağırlıklandırmasını değiştirmez.
Gereksinimler
OpenEnv Harbor sunucusu veri setinin ve kum havuzlarının (sandbox) sahibidir. Kum havuzu altyapısının kimlik bilgilerine (örneğin E2B_API_KEY) ihtiyaç duyar:
MAX_CONCURRENT_ENVS=9 openenv harbor serve --dataset <hf-dataset> --port 8200 --capture-port 8300 --expose gradio
vLLM sunucusu, araç çağrılarını ve gerçek token kimliklerini dışa açmalı ve NCCL ağırlık senkronizasyonunu etkinleştirmelidir; böylece ajan her zaman güncel politikaya erişir. Rollout'lar ve ağırlık güncellemeleri aynı vLLM sunucusunu kullanmalıdır:
vllm serve <model> \
--enable-auto-tool-choice --tool-call-parser <parser> \
--logprobs-mode processed_logprobs \
--return-tokens-as-token-ids \
--weight-transfer-config '{"backend":"nccl"}'Update on GitHubLoop-owning eğitim
trl.experimentalaltında yer alır ve API'si değişebilir. Örnek, test edildiği OpenEnv revizyonunu sabitler; kesin kurulum için README'sine bakın.
