TRL documentation
Tích hợp OpenReward để huấn luyện LLM với các môi trường
Tích hợp OpenReward để huấn luyện LLM với các môi trường
OpenReward là một hệ sinh thái mở dành cho các môi trường RL được xây dựng dựa trên Open Reward Standard (ORS) — một giao thức HTTP/SSE công khai, không phụ thuộc ngôn ngữ, quy định cách một môi trường công bố các tác vụ, công cụ, phiên và phần thưởng của nó. Vì ORS chỉ là một giao thức, cùng một môi trường có thể chạy trên nền tảng OpenReward, tự lưu trữ trên bất kỳ dịch vụ container nào, hoặc chạy cục bộ trên localhost để phát triển. Danh mục các môi trường sẵn sàng sử dụng có sẵn tại openreward.ai.
Hướng dẫn này bao gồm cách tích hợp OpenReward với TRL. Để biết thêm về chính tiêu chuẩn, hãy xem tài liệu ORS.
Tích hợp này nằm tại
trl.experimental.openrewardvà được đặt sau extratrl[openreward](nhập theo kiểu lazy — người dùng không sử dụng sẽ không phải trả thêm chi phí gì).
Khi nào nên sử dụng môi trường OpenReward
GRPOTrainer hỗ trợ huấn luyện dựa trên môi trường thông qua slot environment_factory — xem OpenEnv để biết về hợp đồng chung. Sử dụng OpenReward khi bạn muốn huấn luyện đối với một môi trường nói ngôn ngữ ORS: OpenReward catalog (ví dụ Eigent/SETA, kanishk/EndlessTerminals, nebius/SWE-rebench-V2), một môi trường do bạn tự lưu trữ trên hạ tầng của mình, hoặc một máy chủ cục bộ mà bạn đang phát triển.
Cài đặt
pip install trl[openreward]
Lệnh này cài đặt SDK Python openreward. Bản thân tích hợp chỉ import openreward một cách lười (lazy), nên người dùng không chạm đến trl.experimental.openreward sẽ không bị ảnh hưởng.
Bắt đầu nhanh
Lớp OpenRewardSpec kết nối một môi trường ORS duy nhất vào ba vị trí của trình huấn luyện TRL — train_dataset, environment_factory, reward_funcs — bằng cách phơi bày các thuộc tính ánh xạ 1:1 với các tên tham số đó:
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()Bên trong, OpenRewardSpec thực hiện ba việc, được thực hiện một cách lười biếng khi truy cập lần đầu:
spec.train_dataset: tạo ra mộtdatasets.Datasettừ danh sách tác vụ của môi trường (một vòng lặp HTTP duy nhất qua SDK). Có ít nhấtprompt,task_index, cùng các cột metadata riêng cho từng tác vụ được gộp vào.spec.environment_factory: trả về một callable không tham số, tạo ra một adapter mới cho mỗi lần rollout khi được gọi. Adapter này phơi bày một phương thức Python cho mỗi công cụ ORS, với chữ ký kiểu dữ liệu và docstring được tự động tạo từ JSON Schema của env. Bộ thu thập công cụ của TRL sẽ nhận chúng thông quainspect.getmembers.spec.reward_funcs: một hàm phần thưởng chỉ dựa trên kết quả (phần thưởng khác null cuối cùng trong quỹ đạo), phù hợp với các môi trường phần thưởng thưa như SETA.
Sử dụng môi trường hub
Truyền tên catalog openreward.ai làm mục tiêu. SDK đọc OPENREWARD_API_KEY từ môi trường để xác thực.
spec = OpenRewardSpec("Eigent/SETA", num_tasks=64)Sử dụng môi trường tự lưu trữ
Truyền URL trực tiếp. Không cần API key nếu máy chủ của bạn không yêu cầu.
spec = OpenRewardSpec("https://my-org-my-env.hf.space", env_name="my_env")SDK
openrewardmặc định kỳ vọng bố cục nền tảng có hai subdomain (api.<host>cho các cuộc gọi không trạng thái vàsessions.<host>cho các cuộc gọi phiên dựa trên SSE). Đối với các máy chủ tự lưu trữ single-host (một URL phục vụ mọi thứ), hãy đặt các biến môi trường ghi đè bên dưới trước khi khởi tạoOpenRewardSpec: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")
Chạy môi trường tối thiểu cục bộ
Cách nhanh nhất để thử nghiệm tích hợp đầu-cuối mà không cần phụ thuộc bên ngoài là một máy chủ ORS nhỏ được định nghĩa bằng bộ khung Environment + Server của SDK openreward. Ví dụ bên dưới là một môi trường echo hoàn chỉnh — mô hình chiến thắng bằng cách gọi echo(text=...) với chuỗi đích của tác vụ.
# 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)Chạy nó:
pip install openreward fastapi uvicorn pydantic
python server.py # listens on :8000Sau đó, trỏ OpenRewardSpec đến nó (với các ghi đè URL được mô tả ở trên):
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Đây cũng là mẫu fixture được sử dụng bởi chính các bài kiểm tra của TRL — xem trl-internal-testing/openreward-echo-env cho Space đã triển khai.
Chọn các tác vụ
OpenRewardSpec chấp nhận một số lượng hoặc một danh sách chỉ mục rõ ràng:
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))) # rangenum_tasks và indices là hai tham số loại trừ lẫn nhau và cả hai đều chỉ lấy các tác vụ cần thiết (không quét toàn bộ danh sách tác vụ).
Cách hoạt động của việc liên kết công cụ
Khi khởi tạo, spec gọi endpoint /tools của env để lấy danh sách các tool spec (mỗi spec gồm tên, mô tả và JSON Schema cho các tham số). Với mỗi tool, nó tạo ra một phương thức Python trên adapter cho từng rollout, có chữ ký kiểu dữ liệu và docstring được suy ra từ schema. Các phương thức này được đặt trên class của adapter, nơi bộ thu thập tool của TRL tìm thấy chúng, do đó cả transformers.utils.get_json_schema và inspect.getmembers(type(env), isfunction) của TRL đều tạo ra đúng tool schema cho model mà không cần mã wrapper riêng cho từng env.
Nếu mô tả công cụ chứa các ký tự không an toàn để ghép vào mã nguồn Python, trình liên kết sẽ chuyển sang dạng đã được làm sạch để việc liên kết không bao giờ thất bại trong các môi trường thực tế.
Hàm phần thưởng
spec.reward_funcs mặc định là phần thưởng chỉ dựa trên kết quả — với mỗi rollout, nó trả về phần thưởng không rỗng cuối cùng được quan sát trong suốt quỹ đạo. Đây là mặc định phù hợp cho các môi trường có phần thưởng thưa (ví dụ SETA, nơi chỉ submit_solution trả về phần thưởng không rỗng).
Nếu không có công cụ nào trả về phần thưởng khác null, hàm phần thưởng mặc định sẽ trả về None, chứ không phải 0.0. Điều này bao gồm các lượt rollout không có lời gọi công cụ, chỉ có các lời gọi công cụ không được chấm điểm, hoặc chỉ có các lời gọi công cụ thất bại. Phần thưởng quan sát được là 0.0 hoặc âm vẫn là một điểm số hợp lệ. Một lời gọi công cụ không được chấm điểm hoặc thất bại ở sau đó sẽ không xóa bỏ điểm số trước đó.
GRPO loại bỏ các rollout mà tất cả các hàm phần thưởng đều trả về None khỏi baseline phần thưởng và gán cho chúng lợi thế bằng không. Điều này không loại bỏ các token của chúng khỏi việc chuẩn hóa loss, cũng không vô hiệu hóa các thành phần khác như điều chỉnh KL. Nếu một hàm phần thưởng khác chấm điểm cho rollout, nó vẫn có thể nhận được lợi thế khác không.
Các điểm bị thiếu không xác định được lý do một episode kết thúc. Nếu việc từ bỏ hoặc đạt đến giới hạn gọi công cụ nên được tính là một thất bại của tác vụ, hãy trả về một phần thưởng thất bại rõ ràng từ môi trường hoặc hàm phần thưởng tùy chỉnh của bạn. Các lỗi hạ tầng hoặc lỗi bộ chấm điểm có thể vẫn ở trạng thái không chấm điểm được; hãy theo dõi phạm vi bao phủ của việc chấm điểm cùng với phần thưởng trung bình.
Nếu bạn muốn sử dụng hàm thưởng tùy chỉnh, hãy viết một hàm thưởng TRL thông thường và truyền nó trực tiếp:
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 cho từng lượt rollout cung cấp trạng thái chạy mà TRL cần — env.reward, env.rewards, env.metadata, env.finished, env.last_output — cho việc định hình phần thưởng sau khi chạy tùy ý.
OpenRewardSpec
class trl.experimental.openreward.OpenRewardSpec
< source >( 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 )
Tham số
- target (str) — Tên trong danh mục openreward.ai (“Eigent/SETA”) hoặc một URL trỏ đến bất kỳ máy chủ ORS nào (”https://you-seta.hf.space”, “http://localhost:8080”). Được tự động phát hiện dựa trên sự hiện diện của :// trong chuỗi.
- num_tasks (int, tuỳ chọn) —
Giới hạn số lượng tác vụ được đưa vào bộ dữ liệu.
Nonesẽ sử dụng mọi tác vụ mà môi trường cung cấp. - split (str, optional, mặc định là “train”) — Danh sách tác vụ của split nào để lấy.
- indices (list[int], optional) —
Các chỉ mục tác vụ cụ thể để huấn luyện. Loại trừ lẫn nhau với
num_tasks. Hữu ích cho việc gỡ lỗi hoặc các tập con theo chương trình giảng dạy. - api_key (str, tuỳ chọn) —
Ghi đè
OPENREWARD_API_KEY. Chỉ được sử dụng khitargetlà tên catalog. - secrets (dict[str, str], tuỳ chọn) —
Các bí mật theo phiên được chuyển tiếp đến
env.session(secrets=). - env_name (str, không bắt buộc) — Ghi đè tên môi trường để tìm kiếm trên máy chủ. Hiếm khi cần.
- include_metadata (bool, tuỳ chọn, mặc định là True) —
Gộp metadata của từng tác vụ (difficulty, category, tags, …) vào các dòng của dataset để các hàm reward có thể
đọc chúng thông qua đối số
inputscủa TRL. - discover_task_tools (bool, tuỳ chọn, mặc định là True) —
Nếu
True, sẽ mở một phiên ORS có thời gian sống ngắn và sử dụngsession.list_tools()để các công cụ dành riêng cho tác vụ (GET …/task_toolstheo ORS — ví dụ@tool(shared=False)vàlist_task_tools()) được liên kết cho GRPO. Nếu quá trình dò tìm thất bại, chỉ chuyển sangenvironment.list_tools(). ĐặtFalseđể bỏ qua phiên bổ sung (chỉ dùng công cụ chia sẻ / các vấn đề ngoại lệ khi ngoại tuyến). - task_tools_discovery_index (int, optional) —
Chỉ mục tác vụ chỉ được sử dụng cho phiên khám phá khi được đặt; ghi đè việc dò nhiều chỉ mục bên dưới. Khi
bỏ qua và
indices=được đặt, khám phá sẽ mở một phiên dò cho mỗi mục khác nhau trongindices(đã sắp xếp) và ghép các thông số công cụ theo tên để ràng buộc các công cụ cụ thể cho tác vụ từ mọi tác vụ được liệt kê. Khi bỏ qua và sử dụngnum_tasks/ chế độ danh sách đầy đủ, chỉ dò tác vụ0. Bị bỏ qua khidiscover_task_tools=False.
Đối tượng spec đơn lẻ kết nối môi trường ORS vào trình huấn luyện TRL.
Hạn chế
- Tích hợp này nằm trong
trl.experimental— API có thể thay đổi. ĐặtTRL_EXPERIMENTAL_SILENCE=1để tắt cảnh báo trong nhật ký CI. - Hiện tại chỉ cung cấp một
OpenRewardSpecbao phủ một môi trường; việc huấn luyện đa môi trường (theo mô hình “meta-environment” của OpenEnv) chưa được hỗ trợ. - Các lượt rollout kéo dài (>15 phút mỗi episode) cần một ping keepalive — hiện chưa được tích hợp.
Tham khảo
- Chuẩn phần thưởng mở
- Nền tảng OpenReward
- SDK Python
openreward - Môi trường Echo —
trl-internal-testing/openreward-echo-env