TRL documentation
Trainer GRPO bất đồng bộ
Trainer GRPO bất đồng bộ
Tổng quan
AsyncGRPOTrainer triển khai cùng thuật toán GRPO nhưng tách rời việc tạo rollout khỏi quá trình huấn luyện. Một worker nền liên tục stream các completion từ một máy chủ vLLM trong khi vòng lặp huấn luyện tiêu thụ chúng, nhờ đó việc tạo và cập nhật gradient diễn ra chồng chéo thay vì luân phiên.
Trainer này được đóng góp bởi Amine Dirhoussi và Quentin Gallouédec.
Bắt đầu nhanh
Ví dụ này minh họa cách huấn luyện một mô hình bằng phương pháp Asynchronous GRPO. Chúng ta huấn luyện mô hình Qwen3.5 2B với các prompt từ dataset DeepMath-103K. Bạn có thể xem dữ liệu trong dataset tại đây:
Dưới đây là script để huấn luyện mô hình. Trainer cần vLLM và kernels, và accuracy_reward cần math-verify, bạn có thể cài đặt bằng pip install trl[vllm,kernels,math_verify].
# train_async_grpo.py
from datasets import load_dataset
from trl import AsyncGRPOTrainer
from trl.rewards import accuracy_reward
if __name__ == "__main__": # the rollout worker is a spawned process that re-imports this script
dataset = load_dataset("trl-lib/DeepMath-103K", split="train")
trainer = AsyncGRPOTrainer(
model="Qwen/Qwen3.5-2B",
reward_funcs=accuracy_reward,
train_dataset=dataset,
)
trainer.train()Quá trình sinh (Generation) chạy trên một máy chủ vLLM, trên các GPU khác với máy huấn luyện (trainer). Khởi động nó trên GPU 0:
CUDA_VISIBLE_DEVICES=0 VLLM_SERVER_DEV_MODE=1 vllm serve Qwen/Qwen3.5-2B \
--weight-transfer-config '{"backend": "nccl"}' \
--logprobs-mode processed_logprobs \
--api-server-count 8 \
--max-model-len 4096Sau đó, thực thi script trên GPU 1 bằng lệnh sau:
CUDA_VISIBLE_DEVICES=1 python train_async_grpo.py
Tương thích và ràng buộc
Một số tổ hợp tham số bị hạn chế có chủ đích trong triển khai AsyncGRPOTrainer hiện tại:
- Việc sinh (Generation) luôn được chạy trên một máy chủ vLLM riêng biệt, được khởi động bằng
vllm serve. Không có chế độ colocate. - Prompts from the dataset must be in conversational format. With an
environment_factory, the dataset may have nopromptcolumn, andreset()provides it. - Hàm thưởng phải là các callable Python. Các mô hình thưởng được cung cấp dưới dạng model id hoặc PreTrainedModel không được hỗ trợ, xem Sử dụng hàm thưởng tùy chỉnh.
- Trainer cần
transformers>=5.2.0. - Huấn luyện phân mảnh (Sharded training) sử dụng FSDP2. DeepSpeed không được hỗ trợ, và cả song song ngữ cảnh lẫn song song chuỗi (
cp_size > 1hoặcsp_size > 1trongparallelism_config) cũng không được hỗ trợ. use_liger_kernel=Truekhông được hỗ trợ.- Các bộ thích ứng PEFT nhắm vào
lm_headkhông được hỗ trợ. - Các mô hình có attention sinks không được hỗ trợ. Các lớp không phải attention duy nhất được hỗ trợ là các lớp gated DeltaNet của các mô hình hybrid (Qwen3.5, Qwen3.6, Qwen3-Next, …), cần
transformers>=5.15.0. - Hình ảnh không được hỗ trợ, xem Đào tạo Mô hình Ngôn ngữ Thị giác.
Training nạp attention kernel từ Hub thông qua thư viện kernels: kernels-community/aiter-flash-attn trên GPU AMD (ROCm), kernels-community/flash-attn4 trên GPU NVIDIA Blackwell và kernels-community/flash-attn3 trên các GPU NVIDIA khác. Các mô hình giới hạn attention logits (attn_logit_softcapping), chẳng hạn như Gemma 2, không được hỗ trợ trên GPU AMD hoặc GPU NVIDIA Blackwell.
Đi sâu hơn vào phương pháp GRPO bất đồng bộ
Trong GRPOTrainer, quá trình sinh và huấn luyện diễn ra tuần tự: sinh một lô dữ liệu, tính toán loss, cập nhật trọng số, lặp lại. Ngay cả trong colocate mode, một pha phải hoàn tất trước khi pha kia bắt đầu. Trong AsyncGRPOTrainer, một worker rollout sinh và chấm điểm các câu trả lời trong một tiến trình nền trong khi vòng lặp huấn luyện tính toán loss và cập nhật mô hình. Để hiểu cách hoạt động, quy trình có thể được chia thành ba bước chính: Sinh các câu trả lời, tính toán advantage và tính toán loss. Không có mô hình tham chiếu, do đó không có số hạng KL divergence (mặc định của GRPO, beta=0.0).
Tạo các câu trả lời hoàn chỉnh
Worker rollout duy trì tối đa max_concurrent_rollouts yêu cầu đang chạy tới máy chủ vLLM. Với mỗi prompt, nó tạo ra một nhóm bổ sung (num_generations) và, khi toàn bộ nhóm hoàn tất, chấm điểm và tính toán lợi thế của chúng. Các mẫu huấn luyện kết quả được đưa vào hàng đợi, nơi vòng lặp huấn luyện sẽ lấy ra. Quá trình tạo chỉ chờ khi nó đi trước huấn luyện max_staleness bước (xem Độ song song), và một bước huấn luyện chỉ chờ khi hàng đợi trống.
Mỗi weight_sync_steps bước huấn luyện, trainer gửi trọng số đã cập nhật của nó đến máy chủ vLLM qua NCCL, để các completion tiếp theo được tạo từ chính sách mới nhất. Do đó, một completion có thể đến từ một chính sách cũ hơn vài bước so với chính sách đang được huấn luyện: một mẫu bị bỏ nếu nó cũ hơn max_staleness lần cập nhật trọng số tại thời điểm trainer lấy nó.
Các chỉ số và phần còn lại của trang này sử dụng các thuật ngữ sau cho các giai đoạn mà một completion trải qua:
- a nhóm là một prompt và các rollouts của nó. Lợi thế được tính toán bên trong nhóm đó.
- Một rollout là một cuộc hội thoại hoàn chỉnh được tạo ra cho một prompt, bao gồm mọi lần gọi công cụ. Nó được cấu thành từ một hoặc nhiều turns, mỗi turn tương ứng với một yêu cầu vLLM.
- sample là thứ mà loss được tính trên đó: các token của một rollout, kèm theo advantage của nó. Một rollout đa lượt có thể tạo ra nhiều hơn một sample (xem Multi-turn rollouts).
- Một dòng là những gì một tiến trình chuyển tiếp trong một micro-batch: một vài mẫu được đóng gói cùng nhau (xem Đóng gói cây). Một micro-batch chứa một dòng cho mỗi tiến trình, và
gradient_accumulation_stepsmicro-batches tạo thành một bước, tức là bước tối ưu hóa.
Số lượng token được chia thành ba loại: token được tạo ra là những token do mô hình tạo ra, token được chuyển tiếp là tất cả các token của một mẫu (bao gồm cả prompt và kết quả công cụ), và token được huấn luyện là những token mà loss được tính trên đó.
Tính toán lợi thế
Với mỗi bổ sung của một nhóm, phần thưởng là tổng các phần thưởng từ mỗi hàm phần thưởng. Lợi thế được chuẩn hóa trong nhóm, giống như trong GRPO:
Không có tùy chọn scale_rewards: lợi thế luôn được nhân với độ lệch chuẩn của nhóm. Một kết quả mà mọi hàm phần thưởng đều trả về None sẽ bị loại khỏi trung bình và độ lệch chuẩn của nhóm và nhận lợi thế bằng không.
Một nhóm có phần thưởng đều nhau sẽ bị loại bỏ: với lợi thế mặc định, giá trị của nó bằng không ở mọi vị trí, nên huấn luyện trên nhóm đó sẽ tốn một lần truyền thuận và một lần truyền ngược mà không thay đổi gì. Tỷ lệ các nhóm như vậy được ghi log dưới dạng frac_zero_std_groups. Bước huấn luyện được lấp đầy từ các nhóm được giữ lại, do đó nhiều nhóm bị loại nghĩa là phải sinh thêm dữ liệu cho mỗi bước. Một nhóm bị loại vẫn được tính vào epoch, vốn chỉ là một lượt quét qua các prompt.
Tính toán tổn thất
Log-probabilities của server vLLM không bao giờ khớp hoàn toàn với trainer: các kernel khác nhau, độ chính xác khác nhau, và một policy chậm hơn vài bước (xem Xử lý sự không khớp giữa huấn luyện và suy luận). Trainer sử dụng log-probabilities của sampler làm policy cũ, do đó một tỷ lệ quan trọng duy nhất bao phủ cả sự không khớp lẫn độ cũ:
Các token có tỷ lệ nằm ngoài [vllm_importance_sampling_clip_min, vllm_importance_sampling_clip_max] sẽ bị loại khỏi loss. Để biết thêm thông tin, xem Masked Importance Sampling.
Mặc định (score_centering=True), trainer sử dụng Score Centering. Chỉ riêng trọng số quan trọng không loại bỏ được sự lệch khớp: điểm của một token được lấy mẫu không có trung bình bằng không dưới bộ lấy mẫu , nên mỗi lần cập nhật cũng kéo chính sách về phía bộ lấy mẫu. Score centering trừ đi kỳ vọng đó tại mỗi vị trí:
trong đó bên trong và bên ngoài. Kỳ vọng bên trong được tính trên num_sampler_logprobs các token có khả năng cao nhất tại mỗi vị trí, do worker rollout yêu cầu từ server.
Với score_centering=False, trainer sẽ sử dụng hàm mục tiêu surrogate bị cắt của GRPO thay thế, với tỷ lệ được che (masked ratio) tương tự:
trong đó là epsilon và là epsilon_high.
Trong cả hai trường hợp, loss được chuẩn hóa theo số lượng token được huấn luyện trong micro-batch, được đếm trên tất cả các process, và lấy trung bình trên gradient_accumulation_steps micro-batches của một bước.
Các chỉ số được ghi log
Trong quá trình huấn luyện, chúng ta ghi lại các chỉ số sau:
num_tokens: Tổng số token đã được chuyển tiếp cho đến nay, bao gồm prompts và completions. Với tree packing, một prefix được chia sẻ bởi nhiều mẫu chỉ được tính một lần.completions/mean_length: Độ dài trung bình của các phần hoàn thành được tạo ra. Khi sử dụng công cụ, chỉ các token không phải của công cụ mới được tính.completions/min_length: Độ dài tối thiểu của các phần hoàn thành được tạo ra. Khi sử dụng công cụ, chỉ các token không phải của công cụ mới được tính.completions/max_length: Độ dài tối đa của các phần hoàn thành được tạo ra. Khi sử dụng công cụ, chỉ các token không phải của công cụ mới được tính.completions/mean_terminated_length: Độ dài trung bình của các chuỗi hoàn thành được tạo ra kết thúc bằng EOS. Khi sử dụng công cụ, chỉ các token không phải công cụ được tính.completions/min_terminated_length: Độ dài tối thiểu của các phần hoàn thành được tạo ra kết thúc bằng EOS. Khi sử dụng công cụ, chỉ các token không phải công cụ được tính.completions/max_terminated_length: Độ dài tối đa của các completion được tạo ra kết thúc bằng EOS. Khi sử dụng công cụ, chỉ các token không phải công cụ được tính.completions/clipped_ratio: Tỷ lệ các câu trả lời bị cắt (clipped), trong đó lượt cuối không kết thúc bằng token EOS.completions/duplicate_frac: Tỷ lệ các rollout lặp lại một rollout trước đó của nhóm chúng theo từng token. Xem Bão hòa và bản sao.tools/call_frequency: Số lần gọi công cụ trung bình cho mỗi lần hoàn thành, tính trên mọi lượt rollout, bao gồm cả các nhóm sau đó bị loại bỏ. Chỉ được ghi log khi trainer có công cụ.tools/failure_frequency: Tỷ lệ các lần gọi công cụ bị thất bại (công cụ không được tìm thấy hoặc gây ra ngoại lệ) trên tổng số lần gọi công cụ, bao gồm cả các nhóm sau đó bị loại bỏ. Giá trị là NaN trong một cửa sổ ghi log không có lần gọi công cụ nào, nơi GRPO ghi log0.0. Chỉ được ghi log khi trainer có công cụ.rewards/{reward_func_name}/mean: Phần thưởng trung bình từ một hàm phần thưởng cụ thể, tính trên mọi completion mà nó đã chấm điểm, bao gồm cả các nhóm sau đó bị loại bỏ. Khi một môi trường sở hữu phần thưởng thông quaget_reward,{reward_func_name}là tên lớp của môi trường đó.rewards/{reward_func_name}/group_std: Độ lệch chuẩn của phần thưởng từ một hàm phần thưởng cụ thể, được tính trong từng nhóm và lấy trung bình trên các mẫu đã huấn luyện.reward: Phần thưởng trung bình tổng thể sau khi cộng phần thưởng từ các hàm, trên mọi hoàn thành được chấm điểm, bao gồm cả các nhóm sau đó bị loại bỏ. Đây là phần thưởng của chính sách, vì vậy đây là chỉ số cần theo dõi:reward_trainedloại trừ các nhóm có phần thưởng đều bằng nhau.reward_group_std: Độ lệch chuẩn của phần thưởng tổng hợp trên các hàm, được tính trong từng nhóm và lấy trung bình trên các mẫu đã huấn luyện. Đây là giá trị mà lợi thế được chia cho, khác vớireward_stdcủa GRPO, vốn được tính trên toàn bộ lô (batch).reward_trained: Phần thưởng trung bình của các mẫu mà trình huấn luyện đã dùng để huấn luyện. Giá trị này loại trừ các nhóm có phần thưởng đều bằng nhau và các mẫu bị loại do vượt quámax_staleness.reward_zero_std_groups: Phần thưởng trung bình của các nhóm có phần thưởng đều bằng nhau, những nhóm này bị loại bỏ: mức phần thưởng mà chúng bị mắc kẹt. Xem Bão hòa và bản sao để đọc nó cùng vớifrac_zero_std_groupsvàreward.frac_zero_std_groups: Tỷ lệ các nhóm có độ lệch chuẩn phần thưởng bằng 0 (tất cả các câu trả lời đều đúng hoặc đều sai), hoặc có ít hơn hai câu hoàn thành có thể chấm điểm. Những nhóm này sẽ bị loại bỏ.sampling/sampling_logp_difference/mean: Chênh lệch tuyệt đối trung bình giữa các xác suất log do trình lấy mẫu (vLLM) trả về và các xác suất log được tính lại bởi mô hình huấn luyện, trên các token đã được huấn luyện.sampling/sampling_logp_difference/max: Chênh lệch tuyệt đối lớn nhất như vậy.sampling/importance_sampling_ratio/min: Tỷ lệ importance sampling nhỏ nhất giữa mô hình và bộ lấy mẫu, trên các token đã huấn luyện, trước khi loại bỏ các token nằm ngoài[vllm_importance_sampling_clip_min, vllm_importance_sampling_clip_max].sampling/importance_sampling_ratio/mean: Trung bình của tỷ lệ lấy mẫu quan trọng như vậy.sampling/importance_sampling_ratio/max: Tỷ lệ lấy mẫu quan trọng lớn nhất như vậy.sampling/masked_mean: Tỷ lệ các token được huấn luyện bị loại khỏi loss do tỷ lệ importance sampling của chúng nằm ngoài khoảng[vllm_importance_sampling_clip_min, vllm_importance_sampling_clip_max].sampling/sampler_mass: Khối lượng xác suất trung bình mà các token có khả năng cao nhất theonum_sampler_logprobscủa bộ lấy mẫu bao phủ. Chỉ được ghi lại khiscore_centering=True.entropy: Entropy trung bình của các dự đoán token trên các token đã được huấn luyện.aux_loss: Tổn phụ trợ cân bằng tải của mô hình Mixture-of-Experts, trước khi được nhân vớirouter_aux_loss_coefvà cộng vào tổn. Chỉ được ghi log khi mô hình là mô hình MoE vàrouter_aux_loss_coefkhác không.clip_ratio/region_mean: Tỷ lệ xác suất của các token mà mục tiêu GRPO bị cắt (clip) để giữ trong vùng tin cậy (trust region): . Vớiscore_centering=Truethì loss không bị cắt, do đó cácclip_ratio/*metrics đếm số token nằm ngoài vùng tin cậy.clip_ratio/low_mean: Tỷ lệ trung bình của xác suất token bị cắt ở cận dưới của vùng tin cậy: .clip_ratio/low_min: Tỷ lệ phần nhỏ nhất trên mỗi completion của các token bị cắt ở cận dưới của vùng tin cậy: .clip_ratio/high_mean: Tỷ lệ trung bình của xác suất token bị cắt ở cận trên của vùng tin cậy: .clip_ratio/high_max: Tỷ lệ phần token bị cắt ở cận trên của vùng tin cậy cho mỗi lần hoàn thành lớn nhất: .
Các chỉ số khác mô tả đường ống xử lý bất đồng bộ.
Các chỉ số được ghi log một lần mỗi cửa sổ ghi log: tất cả những gì được ghi lại kể từ lần log trước, bao phủ logging_steps bước tối ưu hóa gần nhất. Trong cửa sổ:
- Một giá trị trung bình được đo cho mỗi lượt rollout, mẫu hoặc cuộc gọi, chẳng hạn như
reward,rollout/turns_meanvàtools/latency_s, sẽ được tính trung bình trên tất cả các lượt rollout, mẫu hoặc cuộc gọi trong cửa sổ. Một tỷ lệ nhưrollout/generated_tokens_per_slà tổng số token chia cho tổng số giây. - Ngược lại, một tên mà phần cuối chứa từ
countsẽ được cộng dồn:sample/dropped_stale_countlà số lượng mẫu bị loại kể từ lần ghi log cuối, không phải kể từ khi bắt đầu huấn luyện. - Tên mà phần cuối chứa từ
maxhoặcmin, chẳng hạn nhưsample/staleness_maxhoặccompletions/max_length, sẽ giữ lại giá trị lớn nhất hoặc nhỏ nhất. - Bất kỳ chỉ số nào khác đều là giá trị trung bình của các giá trị được ghi lại trong cửa sổ.
Đơn vị:
_s: giây.tokens_per_s: số token mỗi giây._frac: tỷ lệ nằm trong khoảng từ 0 đến 1._per_step: lượng trong một bước tối ưu hóa, được trung bình hóa trên các bước trong cửa sổ.
Chỉ số triển khai
rollout/duration_s: Thời gian thực tế của một lượt rollout, tính từ khi gửi lệnh cho đến khi vòng lặp rollout thu thập kết quả.rollout/generated_tokens_per_s: Thông lượng sinh, tính bằng số token được sinh mỗi giây, kể từ lần báo cáo trước.rollout/concurrency: Số lượng rollout đang chạy đến máy chủ vLLM.rollout/concurrency_cap: Giới hạn hiện tại cho các rollout đang chạy, tuân theo tải của máy chủ. Xem Độ song song.rollout/turns_mean,rollout/turns_max: Số lượt trung bình và tối đa cho mỗi rollout.rollout/samples_per_rollout: Số lượng mẫu huấn luyện cho mỗi rollout. Lớn hơn1.0, một số rollout đã được phân nhánh; nhỏ hơn1.0, một số không tạo ra token nào được huấn luyện. Xem Multi-turn rollouts.rollout/fork_frac: Tỷ lệ các bước chuyển đổi lượt mà prompt của chúng không bắt đầu bằng các token được giữ lại, do đó lượt đó đã bắt đầu một mẫu mới.rollout/drift_tokens_mean,rollout/drift_tokens_max: Số lượng token được giữ lại mà một fork đã render lại, tính trung bình trên các lần chuyển đổi lượt (một lượt không fork được tính là0). Mẫu mới chia sẻ các token trước điểm phân kỳ, do đó đây là phần mà mỗi fork thêm vào quá trình forward.rollout/score_queue_size: Số nhóm đã hoàn thành đang chờ được chấm điểm.rollout/queue_size: Số lượng mẫu đã được chấm điểm đang chờ trong hàng đợi rollout, được đo tại vị trí trainer lấy chúng. Xem Hàng đợi rollout.rollout/score_s: Thời gian để chấm điểm một nhóm.rollout/score_wait_s: Thời gian một nhóm đã hoàn thành chờ trước khi được chấm điểm.rollout/score_block_s: Thời gian sinh bị chặn do hàng đợi chấm điểm đã đầy.rollout/backpressure_s: Thời gian sinh chờ để bắt đầu một rollout vì nó đã đi trước huấn luyệnmax_stalenessbước, tính trung bình trên các lần chờ trong cửa sổ ghi log. Xem Độ song song.rollout/vllm_retry_count: Số lượng yêu cầu vLLM đã được thử lại. Nếu không có chỉ số này, một máy chủ bị suy giảm hiệu năng sẽ trông giống như sự chậm trễ không rõ nguyên nhân.rollout/vllm_kv_cache_usage_frac: Mức sử dụng bộ đệm KV của vLLM (giá trị tối đa trên các engine), được lấy trung bình trên các lần lấy mẫu trong cửa sổ ghi log.rollout/vllm_running_requests: Số lượng yêu cầu mà các engine của server đang giải mã (tổng củanum_requests_runningcủa vLLM trên tất cả các engine). Chênh lệch so vớirollout/concurrencylà phần nằm trong tiến trình API server, đang xây dựng các phản hồi.rollout/vllm_queued_requests: Số lượng yêu cầu mà máy chủ đã chấp nhận nhưng chưa được lên lịch (tổng củanum_requests_waitingcủa vLLM trên các engine).rollout/vllm_preemption_count: Số lượng yêu cầu mà máy chủ đã tạm dừng (tổng củanum_preemptions_totalcủa vLLM trên tất cả các engine). Việc đồng bộ trọng số sẽ đặt lại bộ nhớ đệm của máy chủ, dẫn đến việc tạm dừng mọi yêu cầu đang chạy, do đó chỉ số này không phải là tín hiệu cho thấy áp lực hệ thống.
Chỉ số công cụ
tools/latency_s,tools/{tool_name}/latency_s: Thời gian thực hiện một lệnh gọi công cụ, tính trên tất cả các công cụ và theo từng công cụ.tools/{tool_name}/call_count,tools/{tool_name}/failure_count: Số lượng các cuộc gọi và các cuộc gọi thất bại cho mỗi công cụ.tools/unknown_name_count: Số lần gọi một công cụ không tồn tại. Khác với một công cụ đã chạy và gây ra lỗi, đây là một lỗi chính sách.tools/parallel_calls_mean: Số lượng trung bình các lần gọi công cụ trong một thông điệp của trợ lý có gọi công cụ.tools/loop_exhausted_frac: Tỷ lệ các rollout bị cắt ởmax_tool_calling_iterationstrong khi vẫn đang gọi công cụ, trên tổng số mọi rollout, bao gồm cả các rollout không có lần gọi nào và các nhóm bị loại bỏ sau đó. Chỉ được ghi log khi trainer có công cụ.
HarnessAsyncGRPOTrainer ghi log hầu hết các mục này dưới cùng tên gọi. Xem Training on harnesses để biết các khác biệt.
Chỉ số môi trường
env/reset_s: Thời gian dành choreset()của môi trường trước khi một rollout bắt đầu. Chỉ được ghi log khienvironment_factoryđược cung cấp.env/reward_s: Thời gian dành choget_reward()của môi trường sau khi một rollout kết thúc. Chỉ được ghi log khi môi trường định nghĩaget_reward.
Chỉ số mẫu
sample/forwarded_tokens_mean,sample/forwarded_tokens_max: Số lượng trung bình và tối đa của các token được chuyển tiếp trên mỗi mẫu.sample/trained_tokens_mean: Số lượng token được huấn luyện trung bình trên mỗi mẫu.sample/time_in_queue_s: Thời gian một mẫu chờ trong hàng đợi rollout trước khi được huấn luyện.sample/staleness_mean,sample/staleness_max: Số lần cập nhật trọng số giữa chính sách tạo ra mẫu và chính sách đang huấn luyện trên mẫu đó. Các chỉ sốsampling/importance_sampling_ratio/*vàsampling/sampling_logp_difference/*kết hợp độ cũ (staleness) này với sự không khớp giữa huấn luyện và suy luận: một tỷ lệ lệch khỏi1.0hoặc một chênh lệch log-xác suất lệch khỏi0.0ở mức độ cũ bằng không cho thấy sự không khớp, chẳng hạn như sự khác biệt về dtype với máy chủ.sample/dropped_stale_count: Số lượng mẫu bị loại do vượt quámax_staleness.
Chỉ số theo lô
batch/forwarded_tokens_per_step,batch/trained_tokens_per_step: Số lượng token được forward và train trong mỗi bước, trên tất cả các tiến trình.batch/samples_per_step,batch/groups_per_step: Số lượng mẫu và số lượng nhóm riêng biệt trong mỗi bước. Chúng khác nhau bởi số lượng mẫu trong mỗi nhóm.batch/microbatches_per_step: Số lượng micro-batch cho mỗi bước.batch/masked_token_frac: Tỷ lệ các token được chuyển tiếp nhưng không được huấn luyện.batch/samples_per_row,batch/row_tokens_mean,batch/row_tokens_max: Số lượng mẫu trên mỗi hàng, cùng với số lượng token được chuyển tiếp trung bình và tối đa trên mỗi hàng.batch/row_fill_frac: Tỷ lệtoken_budgetmà các hàng sử dụng.batch/row_imbalance: Tỷ lệ giữa chi phí attention của hàng đắt nhất so với chi phí trung bình. Tiến trình có hàng đắt nhất sẽ làm các tiến trình khác bị dừng lại tại bước all-reduce gradient;1.0là cân bằng hoàn hảo.batch/packing_ratio: Số lượng token trước khi đóng gói trên mỗi token được truyền đi: hệ số mà đóng gói làm thu nhỏ bước truyền đi,1.0khi không có gì được chia sẻ.batch/pad_frac: Tỷ lệ padding được thêm vào để các hàng có cùng độ dài. Nó chỉ tốn chi phí truyền tải và sẽ được loại bỏ trước khi thực hiện forward.batch/dropped_oversize_count: Số lượng mẫu bị loại do vượt quátoken_budget.
Các chỉ số hiệu năng
perf/step_s: Thời gian thực tế của một bước, bao gồm optimizer, đồng bộ trọng số và thời gian chờ mẫu.perf/fwd_bwd_s,perf/fwd_s: Thời gian dành cho các bước truyền thuận và truyền ngược của một bước, và chỉ riêng các bước truyền thuận.perf/optimizer_s: Thời gian dành cho bước tối ưu hóa.perf/rollout_wait_s: Thời gian huấn luyện phải chờ do hàng đợi rollout trống. Xem Hàng đợi rollout.perf/weight_sync_s: Thời gian của một lần đồng bộ trọng số, được chia thànhperf/weight_sync_pause_s(chờ vLLM tạm dừng),perf/weight_sync_barrier_s(chờ các tiến trình khác) vàperf/weight_sync_transfer_s(gửi các trọng số).perf/fwd_bwd_forwarded_tokens_per_s,perf/wall_clock_forwarded_tokens_per_s: Số lượng token được forward mỗi giây, tính trên các bước forward và backward hoặc trên toàn bộ bước.perf/wall_clock_trained_tokens_per_s: Số lượng token được huấn luyện mỗi giây, tính trên toàn bộ bước.perf/fwd_bwd_mfu,perf/wall_clock_mfu: Mức sử dụng FLOPs của mô hình trên các thiết bị huấn luyện, tính trên các bước truyền thuận và truyền ngược hoặc trên toàn bộ bước. Chúng loại trừ máy chủ vLLM. Chỉ được ghi log khi công suất tính toán đỉnh của thiết bị huấn luyện ở độ chính xác huấn luyện được biết đến, và khi ước tính FLOPs hỗ trợ kiến trúc của mô hình (chẳng hạn như Llama, Qwen2, Qwen3, Qwen3-MoE hoặc Qwen3-VL).
Tùy chỉnh
Cấu hình máy chủ vLLM
Trainer tạo ra bằng một máy chủ vLLM, được truy cập tại vllm_server_base_url (mặc định là http://localhost:8000):
VLLM_SERVER_DEV_MODE=1 vllm serve <model_name> \
--weight-transfer-config '{"backend": "nccl"}' \
--logprobs-mode processed_logprobs \
--api-server-count 8 \
--max-model-len 4096VLLM_SERVER_DEV_MODE=1và--weight-transfer-configmở các endpoint mà trình huấn luyện dùng để gửi trọng số của nó.--logprobs-mode processed_logprobskhiến server trả về log-probabilities của phân phối mà nó đã lấy mẫu, sau khi áp dụng temperature và top-k/top-p, đây là giá trị mà importance ratio so sánh.--api-server-count 8giữ lại các log-probabilities hàng đầu để các yêu cầu score centering có chi phí phục vụ thấp (xem cảnh báo bên dưới).--max-model-lenlà tổng độ dài chuỗi tối đa (prompt và completion) mà bạn dự kiến. Giá trị thấp hơn sẽ giảm mức sử dụng bộ nhớ GPU trên server, giải phóng thêm bộ nhớ cho KV cache và tăng thông lượng. Điểm khởi đầu tốt là độ dài prompt cộng vớimax_completion_lengthtừ config của bạn. Khi có tools, mỗi lượt thêm tối đamax_completion_lengthtokens cùng với kết quả tool, vì vậy hãy đặt nó bằng cuộc trò chuyện dài nhất mà bạn dự kiến. Nếu prompt của một lượt cộng vớimax_completion_lengthdài hơn--max-model-len, server sẽ từ chối yêu cầu và quá trình chạy sẽ dừng lại với lỗi từ server. Vớitop_khoặctop_p, server sẽ dừng lượt đó khi đạt đến--max-model-len, và chỉ từ chối một prompt vốn đã dài bằng mức đó. Đây cũng là giá trị mặc định củatoken_budget.
Hãy đảm bảo rằng server đang sử dụng các GPU khác với trainer, nếu không bạn có thể gặp lỗi NCCL. Bạn có thể chỉ định các GPU cần sử dụng bằng biến môi trường
CUDA_VISIBLE_DEVICES.
Việc serialize các log-probability hàng đầu là công việc trên CPU trong API server của vLLM, và với cấu hình mặc định là một API server duy nhất,
num_sampler_logprobs=8làm giảm một nửa thông lượng sinh. Khởi động server với--api-server-count 8trên vLLM 0.32 trở lên: đo trên một H100 với các mô hình từ 1.5B đến 7B, các log-probability hàng đầu (top-8) khi đó chỉ tốn dưới 3% thông lượng sinh. Trên vLLM 0.31, cùng cờ này vẫn để lại mức tổn thất 20 đến 40%, đã được sửa ở upstream bởi vllm-project/vllm#58181.
Sự đồng thời
Ba giới hạn quyết định số lượng rollout chạy đồng thời. Hai giới hạn đầu tiên tự động điều chỉnh; giới hạn thứ ba do bạn thiết lập.
Độ cũ (Staleness). max_staleness xác định số bước huấn luyện mà quá trình sinh có thể chạy trước trainer. Worker theo dõi điều này theo token, vì số lượng mẫu trong một bước thay đổi khi các completion dài hơn hoặc ngắn hơn. Sau mỗi bước, trainer đếm số token đã sử dụng và cho phép worker giữ tối đa max(max_staleness, 1) lần số token đó trong hàng đợi hoặc đang xử lý. Trước bước đầu tiên, nó giả định rằng mỗi hàng đều đầy. Worker chỉ bắt đầu một nhóm rollout mới khi vẫn dưới ngưỡng đó. Ngay từ đầu, nó chưa biết một rollout tạo ra bao nhiêu token, nên nó bắt đầu từng nhóm một cho đến khi nhóm đầu tiên hoàn thành. Một mẫu mà cuối cùng vẫn cũ hơn max_staleness bước sẽ bị loại bỏ.
Tải vLLM. Gửi quá nhiều yêu cầu cho vLLM cùng lúc sẽ làm nó chậm hơn: bộ nhớ đệm KV bị đầy và vLLM phải tạm dừng rồi làm lại một số yêu cầu. Vì vậy, worker cũng duy trì một giới hạn trực tiếp về số lượng rollout chạy đồng thời, được ghi log dưới dạng rollout/concurrency_cap, và kiểm tra /metrics của máy chủ mỗi 5 giây để điều chỉnh. Giới hạn bắt đầu bằng số yêu cầu vừa đủ trong bộ nhớ đệm KV ở độ dài tối đa (KV cache tokens / max_model_len), để máy chủ không bị quá tải ngay từ đầu. Trong khi mức sử dụng bộ nhớ đệm KV duy trì dưới 60% và không có yêu cầu nào đang chờ, giới hạn tăng lên 25%, tối đa một lần cho mỗi lượng rollout hoàn thành tương đương một cap. Khi mức sử dụng vượt quá 80%, giới hạn giảm xuống 30%: các yêu cầu đang chạy tiếp tục, và các yêu cầu mới sẽ chờ. Nếu máy chủ không có endpoint /metrics, giới hạn sẽ là max_concurrent_rollouts.
Tài nguyên. max_concurrent_rollouts (mặc định là 512) là giới hạn trên về số lượng rollout chạy đồng thời. Đây là giới hạn duy nhất do bạn tự thiết lập, vì trình huấn luyện không thể biết môi trường và công cụ của bạn có thể xử lý được bao nhiêu. Mỗi rollout đang chạy sẽ sử dụng một môi trường, có thể thực hiện các lời gọi công cụ đồng bộ trên một nhóm luồng có kích thước bằng giá trị này, và giữ một kết nối mở với máy chủ vLLM. Hãy đặt giá trị này theo khả năng xử lý của các thành phần đó, ví dụ như số phiên mà máy chủ môi trường của bạn chấp nhận:
from trl import AsyncGRPOConfig
training_args = AsyncGRPOConfig(
...,
max_concurrent_rollouts=64,
)Nếu giá trị quá thấp, quá trình sinh sẽ chậm lại. Một rollout giữ nguyên slot của nó trong khi chạy công cụ hoặc chờ giữa các lượt, không chỉ trong khi vLLM sinh, do đó các rollout gọi nhiều công cụ cần nhiều slot hơn để giữ cho vLLM bận. Nếu giá trị cao hơn nhiều so với mặc định, máy chủ vLLM có thể bắt đầu ngắt kết nối.
Các chỉ số được ghi lại cho thấy giới hạn nào đang kìm hãm quá trình tạo:
rollout/backpressure_slớn hơn 0: giới hạn độ cũ. Việc sinh đang đi trước huấn luyện, điều này là dự kiến khi suy luận nhanh hơn huấn luyện.rollout/concurrencytạirollout/concurrency_cap, thấp hơnmax_concurrent_rollouts: tải của máy chủ vLLM.rollout/concurrencyở mứcmax_concurrent_rollouts, vớirollout/vllm_kv_cache_usage_fracthấp vàperf/rollout_wait_scao: đây là giới hạn trên. Hãy tăngmax_concurrent_rolloutsnếu môi trường và công cụ của bạn cho phép.
Hàng đợi triển khai
Worker đẩy các mẫu đã chấm điểm vào hàng đợi và trainer lấy từ đó. Bốn chỉ số mô tả hàng đợi đó:
rollout/queue_size: số lượng mẫu đang chờ.sample/time_in_queue_s: thời gian một mẫu đơn lẻ chờ trước khi được huấn luyện, phần thời gian của độ cũ (staleness) của nó.perf/rollout_wait_s: thời gian huấn luyện phải chờ do hàng đợi trống.rollout/backpressure_s: thời gian chờ của quá trình sinh do nó đi trước quá trình huấn luyệnmax_stalenessbước.
Hai chỉ số cuối cùng là hình ảnh phản chiếu của nhau. Khi đọc cùng với kích thước hàng đợi, chúng cho bạn biết phía nào là nút thắt cổ chai:
- Hàng đợi gần như trống,
perf/rollout_wait_scao: giới hạn bởi quá trình sinh. Trình huấn luyện đang thiếu dữ liệu; hãy xemrollout/generated_tokens_per_s,rollout/concurrencyvàrollout/score_queue_size. - hàng đợi chứa khoảng
max_stalenessbước token,rollout/backpressure_scao: trainer-bound. Việc sinh bị giữ lại, vàsample/staleness_meannằm gần giới hạn của nó. - cả hai đều cao: chính giới hạn
max_stalenesslà quá chặt. Các rollout đang chạy sẽ lấp đầy giới hạn này trước khi mẫu của chúng đến hàng đợi, khiến trình huấn luyện phải chờ trong khi quá trình sinh bị giữ lại. Hãy tăngmax_staleness. - cả hai đều gần bằng không: cân bằng.
Bão hòa và các bản sao
Chính sách học từ sự khác biệt giữa các rollout của một nhóm: mỗi lợi thế (advantage) được tính so với phần thưởng trung bình của nhóm. Khi mọi rollout trong một nhóm nhận cùng một phần thưởng, tất cả đều có lợi thế bằng không, do đó nhóm đó bị loại bỏ (xem Các chỉ số được ghi log) và không dạy cho chính sách bất kỳ điều gì. Khi một lượt chạy bão hòa, ngày càng nhiều nhóm rơi vào tình trạng này, hoặc vì mọi rollout đều giải quyết được prompt, hoặc vì không rollout nào giải quyết được. Bốn chỉ số giúp phân biệt các trường hợp này, và mỗi chỉ số trả lời một câu hỏi riêng, nên bạn có thể đọc chúng trực tiếp từ biểu đồ:
| metric | câu hỏi |
|---|---|
frac_zero_std_groups | tỷ lệ nhóm không mang tín hiệu |
reward_zero_std_groups | nơi các nhóm đó đang mắc kẹt: phần thưởng trung bình của chúng. Với phần thưởng 0/1, đây là tỷ lệ các nhóm mà trong đó mọi rollout đều đạt, do đó 0.9 có nghĩa là gần như tất cả đều được giải quyết, và 0.1 có nghĩa là gần như tất cả đều thất bại ở mọi rollout |
reward | mức độ hiệu quả của chính sách trên mọi nhóm được chấm điểm, bao gồm cả những nhóm bị loại |
completions/duplicate_frac | liệu việc lấy mẫu có vẫn tạo ra các lượt triển khai khác nhau cho cùng một lời nhắc hay không |
Đọc ba điều đầu tiên cùng nhau, đối chiếu với phạm vi phần thưởng của bạn:
frac_zero_std_groups | reward_zero_std_groups | reward | chẩn đoán | cần làm gì |
|---|---|---|---|---|
| thấp | bất kỳ (nhiều nhiễu trên một vài nhóm) | bất kỳ | healthy: hầu hết các nhóm tạo ra gradient | nothing |
| leo lên | gần đầu trên của khoảng | leo lên | đạt mức bão hòa ở đỉnh: các prompt đã trở nên quá dễ đối với chính sách, đây là cách một lần chạy thành công thường kết thúc | dừng lượt chạy, hoặc chuyển sang các prompt khó hơn |
| high | gần phần dưới của khoảng | thấp và phẳng | kẹt ở dưới cùng: các prompt quá khó, hoặc hàm thưởng không bao giờ ghi nhận | Kiểm tra completions/clipped_ratio trước, vì một completion bị cắt trước khi có câu trả lời sẽ đạt điểm 0, sau đó đọc một vài completion để kiểm tra xem hàm reward có phân tích chúng được không |
| leo lên | giảm | giảm | regression: các nhóm trước đó đã vượt qua giờ cùng nhau thất bại | kiểm tra completions/duplicate_frac và entropy để phát hiện sự sụp đổ |
| high | ở giữa | bất kỳ | sự pha trộn: với phần thưởng 0/1, một số prompt quá dễ trong khi những prompt khác lại quá khó. Với phần thưởng tính điểm một phần, các nhóm cũng có thể bị mắc kẹt ở cùng một mức điểm một phần | đọc các rollout |
completions/duplicate_frac là tỷ lệ các rollout lặp lại một rollout trước đó của nhóm chúng, khớp từng token, trên tất cả các lượt của chúng. Các rollout giống hệt nhau nhận phần thưởng giống hệt nhau, do đó các bản sao cũng đẩy frac_zero_std_groups lên cao.
completions/duplicate_frac | chẩn đoán |
|---|---|
| gần 0, với một mức nền nhỏ trên các tác vụ có độ dài hoàn thành đủ ngắn để có thể lặp lại ngẫu nhiên | healthy: các rollout của một nhóm được lấy mẫu độc lập |
nhảy về phía (num_generations - 1) / num_generations | quá trình lấy mẫu không còn ngẫu nhiên nữa: mỗi nhóm đều trả về các bản sao của một lượt rollout duy nhất. Ví dụ, nhiệt độ bằng 0, hoặc các engine vLLM song song dữ liệu giải mã cùng một văn bản vì chúng chia sẻ cùng một hạt lấy mẫu (worker gửi một hạt duy nhất với mỗi yêu cầu để ngăn chặn điều này) |
tăng dần, với entropy giảm | collapse: chính sách đang hội tụ về một câu trả lời duy nhất cho mỗi prompt |
Các chỉ số này được ghi lại khi worker chấm điểm một nhóm, chứ không phải khi các mẫu của nhóm đó được huấn luyện, do đó chúng chạy hơi nhanh hơn quá trình huấn luyện và bao gồm cả những nhóm mà các mẫu sau đó bị loại do vượt quá max_staleness. Một nhóm mà không có rollout nào được chấm điểm, vì mọi hàm phần thưởng đều trả về None, sẽ bị loại và được tính vào frac_zero_std_groups, nhưng vì nhóm này không có phần thưởng nên reward_zero_std_groups sẽ không bao gồm nó.
Đóng gói cây
Các mẫu của một micro-batch được đóng gói vào một hàng cho mỗi tiến trình, không có padding. Một hàng là một prefix trie, không phải một phép nối: một token được chia sẻ bởi nhiều mẫu chỉ được truyền đi một lần, và attention vẫn hiển thị cho mỗi mẫu chính xác lịch sử của riêng nó. Các rollout của một nhóm đều lặp lại prompt của nhóm đó, và mỗi lượt của một rollout nhiều lượt lặp lại cuộc trò chuyện cho đến thời điểm đó, do đó phép truyền đi (forward) được thu nhỏ theo tỷ lệ đóng gói (batch/packing_ratio). Đây chỉ là một thay đổi về bố cục: mỗi token được huấn luyện giữ nguyên target, advantage và old log-probability của riêng nó, và log-probability của nó khớp với việc truyền đi mẫu đó một cách độc lập.
Với hai lần chạy trên một prompt, trong đó p là prompt và a, b là hai phần hoàn thành:
1. Rollouts r0: p1 p2 p3 a1 a2 10 tokens
r1: p1 p2 p3 b1 b2
2. Trie S0 [p1 p2] ─┬─ S1 [p3 a1 a2] p3 is not shared: a position predicts
└─ S2 [p3 b1 b2] one token, and p3 predicts a1 or b1
3. Packed row index 0 1 | 2 3 4 | 5 6 7
(depth-first) input_ids p1 p2 | p3 a1 a2 | p3 b1 b2 8 tokens: everything but attention
position_ids 0 1 | 2 3 4 | 2 3 4 runs on 8 instead of 10
segment S0 | S1 | S2
4. Attention segment queries keys and values: the segment's path in the trie
(one call) S0 p1 p2 p1 p2 index 0 1
S1 p3 a1 a2 p1 p2 p3 a1 a2 index 0 1 2 3 4
S2 p3 b1 b2 p1 p2 p3 b1 b2 index 0 1 5 6 7
5. Loss r0: a1 a2 predicted at index 2 3 each trained token is predicted at the index
r1: b1 b2 predicted at index 5 6 of the token before it in its rolloutMột vài hệ quả:
- Mọi tiền tố chung đều được chia sẻ: các rollout của một prompt, và giữa các prompt là một system prompt hoặc tool schema chung. Một sample sẽ được đưa vào hàng đã chứa nhóm của nó, nơi prompt của nó đã có sẵn. Khi hàng đó đầy, sample sẽ được đưa sang hàng khác nếu một process vẫn còn một hàng trống, hoặc nếu điều đó không làm tăng tải của hàng có tải cao nhất (hàng này quyết định thời gian của micro-batch); nếu không, micro-batch sẽ đóng lại.
- Không chia sẻ gì là đóng gói thuần túy: mỗi mẫu sau đó sẽ là một phân đoạn riêng, tức là đóng gói không đệm thông thường.
- Chỉ K/V bị nhân bản: một tiền tố chung được thu thập một lần cho mỗi phân đoạn con, tương đương với những gì huấn luyện không đóng gói sẽ giữ lại, và khá nhỏ khi sử dụng chú ý truy vấn nhóm.
- Các hybrid Gated DeltaNet được hỗ trợ (Qwen3.5, Qwen3.6, Qwen3-Next, …): phần convolution của chúng đọc các token tiền nhiệm của chính mỗi token, và quy tắc delta dạng chunk của chúng khởi tạo mỗi đoạn từ trạng thái cuối cùng của đoạn cha.
token_budget giới hạn số token của một hàng, trong đó một token dùng chung chỉ được tính một lần. Mặc định, giá trị này là max_model_len của server, nên không mẫu nào có thể vượt quá nó. Khi không có gì dùng chung, tree packing chạy với tốc độ xấp xỉ bằng packing không padding thông thường, và mức tăng tốc tăng xấp xỉ theo tỷ lệ packing (khoảng 2,8 đến 3 lần ở tỷ lệ 3,4 trên Qwen3-0.6B và 1.7B, trên H100). Tỷ lệ này bằng tiền tố dùng chung nhân với số mẫu trên mỗi hàng, nên batch/samples_per_row là chỉ báo chính: khi gần bằng 1, không có gì để dùng chung, và đòn bẩy là token_budget. batch/row_fill_frac quan trọng khi các mẫu dài: một mẫu 10k token lấp đầy ngân sách 32k kém (ba mẫu vừa, bốn mẫu thì không bao giờ vừa, nên planner thường chỉ nhận được hai và hàng chạy ở mức khoảng 77% đầy), trong khi các mẫu 1k token lấp đầy nó gần như hoàn hảo.
Đánh giá việc đóng gói cây (tree packing) dựa trên thông lượng, batch/trained_tokens_per_step / perf/fwd_bwd_s. Một micro-batch đã đóng gói chứa nhiều mẫu hơn, do đó perf/fwd_bwd_s tăng lên và perf/fwd_bwd_mfu, vốn được chia cho số token đã truyền, giảm xuống: cả hai đều không phải là sự thụt lùi. Nhiều mẫu hơn trên mỗi hàng cũng có nghĩa là nhiều rollout được lấy ra hơn ở mỗi bước, khiến một lần chạy bị giới hạn bởi quá trình sinh (generation-bound) trở nên bị giới hạn hơn nữa.
Các chỉ số theo batch được tổng hợp như sau: một bước giữ gradient_accumulation_steps × num_processes dòng, do đó batch/samples_per_step xấp xỉ bằng số lần đó nhân với batch/samples_per_row, và tương tự cho số token. Hai phía chỉ khớp nhau trong phạm vi biến động giữa các micro-batch của một bước, vì các chỉ số theo bước là tổng còn các chỉ số theo dòng là trung bình.
Bất kỳ yếu tố nào làm cho các hàng dài hơn hoặc ít hơn sẽ loại bỏ việc chia sẻ. Một cuộc hội thoại nhiều lượt không bao giờ phân nhánh là một mẫu dài duy nhất, và
rollout/samples_per_rolloutcho biết một cuộc hội thoại tạo ra bao nhiêu mẫu.
Mẫu top-k và top-p
Top-k và top-p chuẩn hóa lại phân phối lấy mẫu trên một tập ứng viên bị hạn chế thay vì toàn bộ bảng từ vựng. Log-probabilities của máy chủ phản ánh điều đó (--logprobs-mode processed_logprobs), do đó trainer phải chuẩn hóa trên cùng một tập, nếu không mọi tỷ lệ quan trọng đều bị thiên lệch: xác suất của một token trên toàn bộ bảng từ vựng thấp hơn so với trên tập ứng viên mà nó được lấy ra (DeepSeek-V3.2, mục 3.1). Với top_p < 1 hoặc top_k > 0, worker sẽ yêu cầu máy chủ cung cấp tập ứng viên của mỗi token được lấy mẫu và trainer sẽ chuẩn hóa lại log-probabilities của nó trên tập đó. Điều này cần thêm hai cờ máy chủ, và top_k phải được đặt, vì vLLM giới hạn kích thước của tập ứng viên bằng tham số này:
VLLM_SERVER_DEV_MODE=1 vllm serve <model_name> \
--weight-transfer-config '{"backend": "nccl"}' \
--logprobs-mode processed_logprobs \
--api-server-count 8 \
--max-model-len 4096 \
--return-sampling-mask \
--enable-scale-outfrom trl import AsyncGRPOConfig
training_args = AsyncGRPOConfig(
...,
top_p=0.95,
top_k=512,
)--return-sampling-mask khiến vLLM ghi lại tập ứng viên (vLLM 0.28 trở lên, trên trình chạy mô hình V2 của nó: VLLM_USE_V2_MODEL_RUNNER=1 nếu máy chủ từ chối cờ này), và --enable-scale-out phơi bày điểm cuối token-in-token-out để trả về tập đó. Worker kiểm tra cả hai trên máy chủ khi nó khởi động. Một phiên bản vLLM cũ hơn không thể trả về tập này, do đó trainer tiếp tục chuẩn hóa trên toàn bộ bảng mã và cảnh báo về tỷ lệ có thiên lệch.
Huấn luyện adapter với PEFT
Chúng tôi hỗ trợ tích hợp chặt chẽ với thư viện 🤗 PEFT, cho phép bạn huấn luyện các adapter và chia sẻ chúng trên Hub thay vì huấn luyện toàn bộ mô hình.
from datasets import load_dataset
from peft import LoraConfig
from trl import AsyncGRPOTrainer
from trl.rewards import accuracy_reward
if __name__ == "__main__":
dataset = load_dataset("trl-lib/DeepMath-103K", split="train")
trainer = AsyncGRPOTrainer(
model="Qwen/Qwen3.5-2B",
reward_funcs=accuracy_reward,
train_dataset=dataset,
peft_config=LoraConfig(r=32, lora_alpha=64, target_modules="all-linear"),
)
trainer.train()Mọi lần đồng bộ trọng số đều phải gửi chính sách đã cập nhật đến máy chủ. Mặc định, trainer sẽ gộp adapter vào mô hình gốc và gửi toàn bộ trọng số đã gộp, tương đương khoảng 15 GB cho một mô hình 7B ở mỗi lần đồng bộ. Khởi động máy chủ vLLM với --enable-lora và nó sẽ chỉ gửi adapter, khoảng 160 MB ở r=32:
VLLM_SERVER_DEV_MODE=1 VLLM_ALLOW_RUNTIME_LORA_UPDATING=1 vllm serve <model_name> \
--weight-transfer-config '{"backend": "nccl"}' \
--logprobs-mode processed_logprobs \
--api-server-count 8 \
--max-model-len 4096 \
--enable-lora \
--max-lora-rank 32 \
--max-loras 6VLLM_ALLOW_RUNTIME_LORA_UPDATING=1 mở endpoint mà trainer gửi mỗi adapter mới tới. Giữ lại --weight-transfer-config ngay cả khi dùng --enable-lora: trainer chỉ chọn chế độ đồng bộ khi nó khởi động, lúc đó server đã chạy sẵn, và đồng bộ gộp là phương án dự phòng.
--max-lora-rank phải là một trong các giá trị 1, 8, 16, 32, 64, 128, 256, 320, 512. Tham số này đặt rank cao nhất mà server có thể phục vụ, chứ không phải rank mà server sẽ phục vụ, do đó adapter r=4 hoạt động bình thường dưới 8. --max-loras phải ít nhất bằng max_staleness + 2: trainer giữ max_staleness + 1 phiên bản adapter được đăng ký để một rollout bắt đầu dưới một policy cũ hơn có thể hoàn tất dưới policy đó thay vì chuyển đổi policy giữa chừng quá trình sinh, và mỗi lần đồng bộ sẽ nạp phiên bản tiếp theo trước khi gỡ phiên bản cũ nhất. Trainer kiểm tra cả hai giá trị khi khởi động và cho bạn biết cần khởi động lại server với giá trị nào.
vLLM nạp adapter từ đĩa thay vì qua mạng, do đó trainer ghi mỗi phiên bản dưới <output_dir>/.vllm_lora/ và cung cấp đường dẫn cho server. Nếu server chạy trên một máy khác, thư mục đó phải nằm trên một hệ thống tệp mà cả hai đều có thể truy cập.
<output_dir>/.vllm_lora/là bộ nhớ đệm phục vụ, không phải nơi lưu adapter đã huấn luyện. Thư mục này chỉ giữ các phiên bản mới nhất và mỗi phiên bản sẽ bị xóa ngay sau khi hết cửa sổ thời gian hợp lệ. Checkpoint mới là thứ bảo toàn adapter bạn đã huấn luyện, vì vậy đừng tắt tính năng này: vớisave_strategy="no", một phiên chạy kéo dài nhiều giờ sẽ kết thúc mà không để lại gì.output_dircũng phải có thể đọc được bởi server và phải tồn tại lâu hơn thời gian chạy của job, nên không thể dùng vùng lưu tạm cục bộ trên node, dù cách đó sẽ tránh được việc đồng bộ hóa trên hệ thống tệp chia sẻ chậm.
Adapter sync không phải lúc nào cũng nhanh hơn. vLLM tạo ra token chậm hơn khoảng 1,33 đến 1,39 lần khi phục vụ một adapter LoRA so với khi phục vụ các trọng số đã hợp nhất, và quá trình tạo ra thường là yếu tố chi phối thời gian thực tế trong RL. Đổi lại, bạn có được thời gian tạm dừng ngắn hơn đáng kể ở mỗi lần đồng bộ và khoảng 1% băng thông đồng bộ. Nếu thông lượng tạo ra là nút thắt của bạn, đồng bộ hợp nhất thường vẫn là lựa chọn tốt hơn.
Sử dụng hàm phần thưởng tùy chỉnh
AsyncGRPOTrainer hỗ trợ sử dụng các hàm thưởng tùy chỉnh. Để đảm bảo tính tương thích, hàm thưởng của bạn phải đáp ứng các yêu cầu sau:
Các hàm reward có thể là các callable Python đồng bộ hoặc các coroutine async def bất đồng bộ. Khi bạn cung cấp nhiều hàm reward, chúng sẽ chạy song song: các hàm bất đồng bộ được await cùng nhau và các hàm đồng bộ chạy trong các thread, do đó độ trễ của chúng sẽ chồng lên nhau.
Các đối số đầu vào:
Hàm phải nhận các đối số sau dưới dạng đối số từ khóa:
prompts(chứa các prompts),completions(chứa các phần hoàn thành đã tạo),completion_ids(chứa các completion đã được token hóa),- Tất cả tên cột (ngoại trừ
prompt) mà bộ dữ liệu có thể có. Ví dụ, nếu bộ dữ liệu chứa một cột có tênground_truth, hàm sẽ được gọi vớiground_truthnhư một đối số từ khóa.
Cách dễ nhất để đáp ứng yêu cầu này là sử dụng
**kwargstrong chữ ký hàm.Bộ dữ liệu ở định dạng hội thoại, do đó
promptsvàcompletionslà các danh sách từ điển tin nhắn.
Giá trị trả về: Hàm phải trả về một danh sách các số float. Mỗi số float đại diện cho phần thưởng tương ứng với một kết quả hoàn thành duy nhất.
Các hàm reward được thực thi trong rollout worker, một tiến trình riêng biệt, nên mọi thứ được truyền vào nó đều phải pickled. Mỗi hàm reward, công cụ và
environment_factory(cùng với bất kỳ thứ gì chúng đóng gói) đều phải có thể picklable: hãy sử dụng một hàm ở cấp module,functools.partial, hoặc một thực thể lớp callable. Các lambda và closure sẽ gây raTypeErrorkhi gọitrainer.train(). Đây là điểm khác biệt so với GRPOTrainer, nơi các hàm reward được gọi trong tiến trình và closure hoạt động bình thường.Quy trình rollout cũng được chạy với
CUDA_VISIBLE_DEVICES="", do đó không thể sử dụng GPU. Một mô hình phần thưởng dựa trên GPU (ví dụ: bộ chấm điểmAutoModelForSequenceClassification) sẽ được nạp mà không có lỗi nhưng âm thầm chuyển sang chạy trên CPU. Hãy giữ các hàm phần thưởng ở mức nhẹ (các bộ xác minh nhưaccuracy_reward, kiểm tra định dạng hoặc độ dài). Nếu bạn cần một mô hình phần thưởng trên GPU, hãy triển khai nó sau một engine suy luận riêng (vLLM, TGI, …) trên các GPU riêng biệt và để một hàm phần thưởng có thể picklable gọi nó qua HTTP.
Ví dụ 1: Phần thưởng cho các câu trả lời dài hơn
Dưới đây là một ví dụ về hàm phần thưởng (reward function) thưởng cho các câu trả lời dài hơn:
def reward_func(completion_ids, **kwargs):
"""Reward function that assigns higher scores to longer completions (in terms of token count)."""
return [float(len(ids)) for ids in completion_ids]Bạn có thể kiểm tra nó như sau:
>>> prompts = [[{"role": "user", "content": "The sky is"}], [{"role": "user", "content": "The sun is"}]] # not used in the reward function, but the trainer will pass it
>>> completions = [[{"role": "assistant", "content": " blue."}], [{"role": "assistant", "content": " in the sky."}]] # not used in the reward function, but the trainer will pass it
>>> completion_ids = [[6303, 13], [304, 279, 12884, 13]]
>>> reward_func(prompts=prompts, completions=completions, completion_ids=completion_ids)
[2.0, 4.0]Ví dụ 2: Thưởng cho các phần hoàn thành có định dạng cụ thể
Dưới đây là một ví dụ về hàm phần thưởng kiểm tra xem phần hoàn thành có đúng định dạng cụ thể hay không. Ví dụ này được lấy cảm hứng từ hàm phần thưởng định dạng được sử dụng trong bài báo DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning. Nó được thiết kế cho định dạng hội thoại, trong đó các prompt và phần hoàn thành bao gồm các tin nhắn có cấu trúc.
import re
def format_reward_func(completions, **kwargs):
"""Reward function that checks if the completion has a specific format."""
pattern = r"^<think>.*?</think><answer>.*?</answer>$"
completion_contents = [completion[0]["content"] for completion in completions]
matches = [re.match(pattern, content) for content in completion_contents]
return [1.0 if match else 0.0 for match in matches]Bạn có thể kiểm tra hàm này như sau:
>>> prompts = [
... [{"role": "user", "content": "What is the result of (1 + 2) * 4?"}],
... [{"role": "user", "content": "What is the result of (3 + 1) * 2?"}],
... ]
>>> completions = [
... [{"role": "assistant", "content": "<think>The sum of 1 and 2 is 3, which we multiply by 4 to get 12.</think><answer>(1 + 2) * 4 = 12</answer>"}],
... [{"role": "assistant", "content": "The sum of 3 and 1 is 4, which we multiply by 2 to get 8. So (3 + 1) * 2 = 8."}],
... ]
>>> format_reward_func(prompts=prompts, completions=completions)
[1.0, 0.0]Ví dụ 3: Hoàn thành phần thưởng dựa trên một tham chiếu
Dưới đây là một ví dụ về hàm phần thưởng kiểm tra xem câu trả liệu có chính xác hay không. Ví dụ này được lấy cảm hứng từ hàm phần thưởng độ chính xác được sử dụng trong bài báo DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning. Bộ dữ liệu chứa một cột có tên là ground_truth.
import re
def reward_func(completions, ground_truth, **kwargs):
# Regular expression to capture content inside \boxed{}
matches = [re.search(r"\\boxed\{(.*?)\}", completion[0]["content"]) for completion in completions]
contents = [match.group(1) if match else "" for match in matches]
# Reward 1 if the content is the same as the ground truth, 0 otherwise
return [1.0 if c == gt else 0.0 for c, gt in zip(contents, ground_truth)]Bạn có thể kiểm tra hàm này như sau:
>>> prompts = [
... [{"role": "user", "content": "Solve the equation $2x + 3 = 7$."}],
... [{"role": "user", "content": "Solve the equation $3x - 5 = 10$."}],
... ]
>>> completions = [
... [{"role": "assistant", "content": r"The solution is \boxed{2}."}],
... [{"role": "assistant", "content": r"The solution is \boxed{6}."}],
... ]
>>> ground_truth = ["2", "5"]
>>> reward_func(prompts=prompts, completions=completions, ground_truth=ground_truth)
[1.0, 0.0]Ví dụ 4: Các hàm phần thưởng đa nhiệm
Dưới đây là một ví dụ về việc sử dụng nhiều hàm phần thưởng trong AsyncGRPOTrainer. Trong ví dụ này, chúng ta định nghĩa hai hàm phần thưởng dành riêng cho từng tác vụ: math_reward_func và coding_reward_func. Hàm math_reward_func cấp phần thưởng cho các bài toán dựa trên tính chính xác của chúng, trong khi hàm coding_reward_func cấp phần thưởng cho các bài toán lập trình dựa trên việc giải pháp có hoạt động được hay không.
from datasets import Dataset
from trl import AsyncGRPOTrainer
# Define a dataset that contains both math and coding problems
dataset = Dataset.from_list(
[
{"prompt": [{"role": "user", "content": "What is 2+2?"}], "task": "math"},
{"prompt": [{"role": "user", "content": "Write a function that returns the sum of two numbers."}], "task": "code"},
{"prompt": [{"role": "user", "content": "What is 3*4?"}], "task": "math"},
{"prompt": [{"role": "user", "content": "Write a function that returns the product of two numbers."}], "task": "code"},
]
)
# Math-specific reward function
def math_reward_func(prompts, completions, task, **kwargs):
rewards = []
for prompt, completion, t in zip(prompts, completions, task):
if t == "math":
# Calculate math-specific reward
correct = check_math_solution(prompt, completion)
reward = 1.0 if correct else -1.0
rewards.append(reward)
else:
# Return None for non-math tasks
rewards.append(None)
return rewards
# Coding-specific reward function
def coding_reward_func(prompts, completions, task, **kwargs):
rewards = []
for prompt, completion, t in zip(prompts, completions, task):
if t == "code":
# Calculate coding-specific reward
works = test_code_solution(prompt, completion)
reward = 1.0 if works else -1.0
rewards.append(reward)
else:
# Return None for non-coding tasks
rewards.append(None)
return rewards
# Use both task-specific reward functions
if __name__ == "__main__":
trainer = AsyncGRPOTrainer(
model="Qwen/Qwen2.5-0.5B-Instruct",
reward_funcs=[math_reward_func, coding_reward_func],
train_dataset=dataset,
)
trainer.train()Trong ví dụ này, math_reward_func và coding_reward_func được thiết kế để hoạt động với một tập dữ liệu hỗn hợp chứa cả các bài toán toán học và lập trình. Cột task trong tập dữ liệu được dùng để xác định hàm thưởng nào sẽ được áp dụng cho từng bài toán. Nếu không có hàm thưởng phù hợp cho một mẫu trong tập dữ liệu, hàm thưởng sẽ trả về None, và AsyncGRPOTrainer sẽ tiếp tục với các hàm và tác vụ hợp lệ. Điều này cho phép AsyncGRPOTrainer xử lý nhiều hàm thưởng với phạm vi áp dụng khác nhau.
Lưu ý rằng AsyncGRPOTrainer sẽ bỏ qua các phần thưởng None được trả về bởi các hàm phần thưởng và chỉ xem xét các phần thưởng được trả về bởi các hàm liên quan. Điều này đảm bảo rằng mô hình được huấn luyện trên các tác vụ liên quan và bỏ qua các tác vụ không có hàm phần thưởng liên quan.
Ví dụ 5: Các hàm phần thưởng bất đồng bộ
Các hàm phần thưởng tùy chỉnh cũng có thể được định nghĩa dưới dạng coroutine async def. Điều này hữu ích nếu phần thưởng của bạn phụ thuộc vào I/O chậm (ví dụ: gọi một dịch vụ từ xa). Khi bạn truyền nhiều hàm phần thưởng async, AsyncGRPOTrainer sẽ thực thi chúng đồng thời để độ trễ của chúng chồng lên nhau.
Dưới đây là một ví dụ tối giản về một hàm thưởng bất đồng bộ mô phỏng một thao tác bị giới hạn bởi I/O:
import asyncio
async def async_reward_func(prompts, completions, **kwargs):
# Simulate an I/O-bound call (e.g., HTTP request, database lookup)
await asyncio.sleep(0.01)
# Simple toy reward: 1.0 if the completion is non-empty, else 0.0
return [1.0 if completion else 0.0 for completion in completions]Truyền hàm phần thưởng cho trình huấn luyện
Để sử dụng hàm phần thưởng tùy chỉnh của bạn, hãy truyền nó vào AsyncGRPOTrainer như sau:
from trl import AsyncGRPOTrainer
trainer = AsyncGRPOTrainer(
reward_funcs=reward_func,
...,
)Bạn có thể truyền nhiều hàm phần thưởng dưới dạng một danh sách; danh sách này có thể bao gồm cả các hàm đồng bộ và bất đồng bộ:
from trl import AsyncGRPOTrainer
trainer = AsyncGRPOTrainer(
reward_funcs=[reward_func, async_reward_func1, async_reward_func2],
...,
)và phần thưởng sẽ được tính là tổng các phần thưởng từ mỗi hàm.
Tùy chỉnh vòng lặp rollout
Việc tạo dữ liệu, tính phần thưởng, tính lợi thế và lọc được thực hiện trong quy trình rollout, trong AsyncRolloutLoop. Để thay đổi một trong các bước đó, hãy tạo lớp con của vòng lặp, ghi đè phương thức cho bước tương ứng, và đặt lớp con đó làm loop_cls trên một lớp con của trainer. Constructor của trainer không thay đổi.
| Phương pháp | Được gọi | Mặc định |
|---|---|---|
filter_prompt(row_index, row, epoch) | một lần cho mỗi prompt, trước khi tạo | chấp nhận mọi prompt |
generate_one(prompt, tools, group_id) | một lần mỗi lượt triển khai | vòng lặp công cụ đa lượt |
generate_one_turn(prompt_ids) | một lần cho mỗi yêu cầu lấy mẫu | một yêu cầu vLLM với các cài đặt lấy mẫu của cấu hình |
compute_advantages(group) | một lần cho mỗi nhóm, sau khi phần thưởng được cộng dồn vào group.rewards | phần thưởng được chuẩn hóa trong nhóm |
setup(), close() | khi các vòng lặp bắt đầu và kết thúc | nothing |
Ví dụ, một chương trình đào tạo dừng lấy mẫu các prompt mà chính sách đã giải quyết được, với ngưỡng của nó nằm trong một lớp con của cấu hình:
from dataclasses import dataclass
import numpy as np
from trl import AsyncGRPOConfig, AsyncGRPOTrainer
from trl.trainer.async_grpo_trainer import AsyncRolloutLoop
@dataclass
class CurriculumConfig(AsyncGRPOConfig):
pass_rate_cap: float = 0.9
class CurriculumRolloutLoop(AsyncRolloutLoop):
def filter_prompt(self, row_index, row, epoch):
return self.pass_rates.get(row_index, 0.0) < self.config.pass_rate_cap
async def setup(self):
self.pass_rates = {}
def compute_advantages(self, group):
scored = group.rewards[~np.isnan(group.rewards)]
if len(scored):
self.pass_rates[group.row_index] = float(np.mean(scored > 0))
return super().compute_advantages(group)
class CurriculumTrainer(AsyncGRPOTrainer):
loop_cls = CurriculumRolloutLoopRewards được cộng dồn trên reward_funcs, các môi trường định nghĩa get_reward, và reward do generate_one tùy chỉnh đặt trên Rollout của nó: để chấm điểm bằng judge, hãy truyền một hàm reward bất đồng bộ, hoặc chấm điểm bên trong generate_one. compute_advantages được chạy cho mọi nhóm, bao gồm cả nhóm sau đó bị loại bỏ vì tất cả các reward được chấm điểm của nó đều bằng nhau; việc loại bỏ dựa trên các reward, không phải trên các advantages. Vòng lặp được xây dựng trong một tiến trình được khởi tạo, vì vậy hãy định nghĩa lớp con ở cấp độ module và giữ mã huấn luyện bên dưới if __name__ == "__main__":. Hãy tạo các client trong setup, vốn được chạy trên event loop của vòng lặp, thay vì ghi đè __init__. Một prompt bị filter_prompt từ chối sẽ bị bỏ qua trong epoch đó và được tính vào epoch, giống như một nhóm bị loại bỏ. Nếu nó từ chối mọi prompt của một epoch, vòng lặp sẽ ném ngoại lệ.
Tiếp tục từ một checkpoint
Trainer cơ bản sẽ tiếp tục bằng cách bỏ qua và phát lại các batch đã được huấn luyện, điều này không áp dụng cho hàng đợi rollout trực tiếp, do đó ignore_data_skip luôn là True. Thay vào đó, chỉ số của prompt đầu tiên chưa được huấn luyện sẽ được lưu vào rollout_state.json cùng với mỗi checkpoint và được khôi phục khi tiếp tục, giúp worker tua nhanh đến prompt đó mà không cần phát lại các mẫu. Đây là vị trí đã huấn luyện, không phải vị trí của generator: worker chạy trước tiến độ huấn luyện một khoảng bằng độ sâu của hàng đợi rollout, và các mẫu được đệm đó sẽ bị mất khi phiên chạy kết thúc, do đó việc tiếp tục từ vị trí của generator sẽ bỏ qua các prompt đã được tạo ra nhưng chưa bao giờ được huấn luyện. Datasets dạng streaming (IterableDataset) không thể được định vị lại, do đó worker của chúng sẽ bắt đầu lại từ prompt đầu tiên khi tiếp tục.
Đào tạo Agent
Asynchronous GRPO hỗ trợ đào tạo agent: mô hình gọi công cụ trong quá trình sinh và học từ kết quả.
- Một công cụ là một hàm Python thuần túy (đồng bộ hoặc bất đồng bộ) được cung cấp cho mô hình. Sử dụng
toolscho các cuộc gọi không trạng thái (máy tính, tìm kiếm web). - Môi trường là dạng tổng quát hơn: một đối tượng có trạng thái được tạo mới cho mỗi lần rollout, trong đó các phương thức công khai được phơi bày dưới dạng công cụ, kèm theo hook vòng đời
resetvàget_rewardtùy chọn cho phép nó tự quản lý phần thưởng. Sử dụngenvironment_factorykhi bạn cần trạng thái cho từng lần rollout, hook reset, hoặc phần thưởng do môi trường quản lý.
Chúng có thể kết hợp với nhau — bạn có thể truyền các tools độc lập cùng với một environment_factory.
Công cụ
Tham số tools mong đợi một danh sách các hàm Python (đồng bộ hoặc bất đồng bộ) xác định các công cụ có sẵn cho tác tử:
from trl import AsyncGRPOTrainer
trainer = AsyncGRPOTrainer(
tools=[tool1, tool2],
...,
)Mỗi công cụ phải là một hàm Python chuẩn với tham số và kiểu trả về có chú thích kiểu (type-hint), cùng với một docstring theo phong cách Google mô tả mục đích, các tham số và giá trị trả về. Để biết thêm chi tiết, hãy xem hướng dẫn Truyền công cụ.
Mô hình gọi công cụ theo tên của nó, vì vậy mỗi công cụ được đăng ký dưới __name__ của nó và phải là một hàm ở cấp module, điều này cũng giúp nó có thể được pickle cho worker rollout. Các công cụ đồng bộ chạy trên một thread pool có kích thước bằng max_concurrent_rollouts, do đó một công cụ chậm sẽ không bao giờ chặn các rollout khác đang chạy. Trong một lượt của trợ lý, các lời gọi công cụ được thực hiện theo thứ tự mà mô hình đã phát ra. Do đó, tối đa max_concurrent_rollouts công cụ đồng bộ có thể chạy cùng lúc, vì vậy một công cụ đọc hoặc ghi trạng thái chia sẻ phải an toàn cho thread.
Vòng lặp gọi công cụ yêu cầu mẫu chat phải giữ nguyên phần đầu (việc thêm một thông điệp công cụ không được làm thay đổi cách các thông điệp trước đó được hiển thị). Đối với các họ model đã biết (ví dụ: Qwen3, DeepSeek-V3), TRL sẽ tự động thay thế bằng mẫu huấn luyện đã vá khi công cụ được bật. Xem Mẫu Chat để biết danh sách đầy đủ.
Sử dụng max_tool_calling_iterations trong AsyncGRPOConfig để giới hạn số lượt gọi công cụ. Mặc định không có giới hạn, và quá trình sinh sẽ dừng lại khi mô hình tạo ra lượt phản hồi không chứa bất kỳ lời gọi công cụ nào.
Ví dụ:
from trl import AsyncGRPOTrainer
def multiply(a: int, b: int) -> int:
"""
Multiplies two integers.
Args:
a: The first integer.
b: The second integer.
Returns:
The product of the two integers.
"""
return a * b
async def async_add(a: int, b: int) -> int:
"""
Asynchronously adds two integers.
Args:
a: The first integer.
b: The second integer.
Returns:
The sum of the two integers.
"""
return a + b
trainer = AsyncGRPOTrainer(
tools=[multiply, async_add],
...,
)Môi trường
Bạn cũng có thể cung cấp các công cụ thông qua environment_factory. Ở chế độ này, AsyncGRPOTrainer tạo một instance môi trường cho mỗi rollout và công khai các phương thức công khai của môi trường dưới dạng các công cụ.
Khi bạn sử dụng environment_factory, môi trường sẽ sở hữu dữ liệu: không có train_dataset bên ngoài. Ở mỗi lượt rollout, reset() tạo ra tác vụ — tự lấy mẫu từ một kho ngữ liệu mà môi trường giữ, hoặc tạo trạng thái theo thủ tục — và trả về prompt. max_steps đặt độ dài huấn luyện. Dưới đây là một ví dụ tối giản về một môi trường tự lấy mẫu một mục tiêu và phơi bày phương thức increment (được phơi bày dưới dạng công cụ).
import random
from trl import AsyncGRPOConfig, AsyncGRPOTrainer
class IncrementEnv:
# Reserved methods
def reset(self, **kwargs) -> str | None: # required; called at the start of each rollout
self.counter = 0
self.target = random.randint(1, 6) # self-sample the task
return f"Increment the counter by {self.target}." # returned string becomes the prompt
def get_reward(self) -> float: # optional: the environment scores itself from its own state
return float(self.counter == self.target)
# Public methods (exposed as tools)
def increment(self, step: int) -> int:
"""
Increment the internal counter.
Args:
step: Value to add to the counter.
Returns:
The updated counter value.
"""
self.counter += step
return self.counter
if __name__ == "__main__":
trainer = AsyncGRPOTrainer(
model="Qwen/Qwen3-0.6B",
args=AsyncGRPOConfig(max_steps=1000, chat_template_kwargs={"enable_thinking": False}),
environment_factory=IncrementEnv,
)
trainer.train()Một lớp môi trường có hai phương thức được dành riêng: reset và get_reward. Khác với các phương thức công khai khác, những phương thức này không được phơi bày cho mô hình dưới dạng công cụ.
reset(bắt buộc) được gọi khi rollout bắt đầu. Nó có thể trả vềNonehoặc một chuỗi. Khi trả về một chuỗi, chuỗi đó chính là prompt của người dùng.get_reward(tùy chọn, đồng bộ hoặc bất đồng bộ) không nhận đối số và trả về mộtfloat: môi trường chấm điểm cho episode vừa chạy dựa trên trạng thái nội bộ của chính nó (trò chơi có kết thúc bằng chiến thắng không? từ đã được đoán đúng chưa?). Hàm này được gọi một lần cho mỗi rollout hoàn thành và đóng vai trò là nguồn phần thưởng.
Cả hai đều chạy trên pool luồng công cụ của worker, do đó một môi trường chậm sẽ chỉ làm chậm rollout của chính nó mà không ảnh hưởng đến các rollout khác đang chạy. Thời lượng của chúng được ghi log dưới dạng env/reset_s và env/reward_s.
Vì môi trường tự lấy mẫu trên mỗi
reset(),Gthành viên của một nhóm GRPO có thể không chia sẻ cùng một trạng thái ban đầu, khiến đường cơ sở của nhóm hơi nhiễu hơn. Đối với các trạng thái giống nhau trong một nhóm, hãy đểreset()suy ra trạng thái một cách tất định từ một khóa chung.
Cung cấp bộ dữ liệu bên ngoài (tùy chọn)
Thay vì để môi trường tự lấy mẫu, bạn có thể cung cấp một train_dataset bên ngoài. Ví dụ, khi các tác vụ của bạn đã nằm trong một dataset, hoặc để định tuyến giữa nhiều môi trường. Với mỗi rollout, trainer sẽ lấy mẫu một hàng, sử dụng cột "prompt" của hàng đó làm prompt, và truyền các cột của hàng vào reset() dưới dạng các tham số keyword (để môi trường đọc tác vụ từ dataset).
from datasets import Dataset
from trl import AsyncGRPOTrainer
# Each row carries the prompt and the task data (here, the counter target to reach).
dataset = Dataset.from_dict(
{
"prompt": [[{"role": "user", "content": f"Increment the counter to {i}."}] for i in range(1, 7)],
"target": list(range(1, 7)),
}
)
class IncrementEnv:
def reset(self, target, **kwargs) -> None: # the row's `target` column arrives as a keyword argument
self.counter = 0
self.target = target
def get_reward(self) -> float:
return float(self.counter == self.target)
def increment(self, step: int) -> int: # exposed as a tool (see the full docstring above)
self.counter += step
return self.counter
if __name__ == "__main__":
trainer = AsyncGRPOTrainer(
model="Qwen/Qwen3-0.6B",
train_dataset=dataset, # the dataset owns the task; the "target" column reaches reset(target=...)
environment_factory=IncrementEnv,
)
trainer.train()Phần thưởng
Rewards do môi trường và rewards do trainer sở hữu không loại trừ nhau. Truyền reward_funcs cho các rewards tự nhiên để tính từ completion (ví dụ: kiểm tra định dạng trên văn bản) và để môi trường trả về reward phụ thuộc trạng thái của nó thông qua get_reward. Tất cả các nguồn đều được cộng lại với trọng số 1.
def format_reward(completions, **kwargs): # trainer-owned: scores the completion text
...
trainer = AsyncGRPOTrainer(
model="Qwen/Qwen3-0.6B",
args=AsyncGRPOConfig(max_steps=1000),
reward_funcs=format_reward, # trainer-owned: scores the completion
environment_factory=IncrementEnv, # env-owned: scores its internal state via `get_reward`
)Nhiều môi trường
Để huấn luyện trên một hỗn hợp các tác vụ trong một lần chạy (ví dụ: một tác vụ lập trình và một trò chơi), hãy truyền một từ điển ánh xạ tên môi trường đến các nhà máy thay vì một callable duy nhất. Mỗi rollout sẽ chọn môi trường của nó thông qua trường environment trong bộ dữ liệu, và chỉ các công cụ của môi trường đó được phơi bày. Điều này tránh việc rò rỉ các công cụ không liên quan (công cụ move của trò chơi cho một ví dụ lập trình, và ngược lại). Mỗi môi trường vẫn sở hữu dữ liệu của riêng mình và trả về prompt từ reset(), do đó bộ dữ liệu chỉ cần cột environment để định tuyến giữa chúng.
import random
from datasets import Dataset
from trl import AsyncGRPOConfig, AsyncGRPOTrainer
class CodingEnv:
def reset(self, **kwargs) -> str:
n = random.randint(1, 20)
return f"Compute the {n}th Fibonacci number."
def run_code(self, code: str) -> str: # exposed as a tool only for "coding" examples
"""Run the given Python code and return its stdout.
Args:
code: The Python source to execute.
Returns:
The captured standard output.
"""
...
class GameEnv:
def reset(self, **kwargs) -> str:
return "Reach the goal tile."
def move(self, action: str) -> str: # exposed as a tool only for "game" examples
"""Apply an action to the game and return the new observation.
Args:
action: One of "up", "down", "left", "right".
Returns:
The observation after the move.
"""
...
# The dataset only routes: each row picks the environment for that rollout
if __name__ == "__main__":
dataset = Dataset.from_dict({"environment": ["coding", "game"] * 500})
trainer = AsyncGRPOTrainer(
model="Qwen/Qwen3-0.6B",
args=AsyncGRPOConfig(chat_template_kwargs={"enable_thinking": False}),
train_dataset=dataset,
reward_funcs=reward_func,
environment_factory={"coding": CodingEnv, "game": GameEnv},
)
trainer.train()Các instance môi trường được tái sử dụng giữa các bước (được reset giữa các episode), do đó một __init__ tốn kém chỉ được thực hiện một lần thay vì ở mỗi bước. Trường environment được trainer sử dụng và không được chuyển tiếp đến reset.
Cuộn đa lượt
Mỗi lượt hội thoại sẽ render toàn bộ cuộc trò chuyện thông qua chat template và sinh ra từ đó. Một chat template không phải lúc nào cũng render một cuộc trò chuyện đang phát triển theo cùng một cách (ví dụ, một số loại bỏ phần suy luận của các lượt trước), do đó các token prompt của một lượt có thể khác với các token đã được giữ lại cho đến thời điểm đó. Vào cuối quá trình rollout, worker sẽ đối chiếu các lượt để tạo thành các mẫu huấn luyện: một lượt có prompt bắt đầu bằng các token đã giữ sẽ được thêm vào cùng một mẫu, còn bất kỳ lượt nào khác sẽ bắt đầu một mẫu mới. Mỗi token được sinh ra đều được huấn luyện trong đúng một mẫu, do đó một nhánh rẽ (fork) chỉ tốn token forward mà không tạo ra tín hiệu huấn luyện.
Mỗi mẫu của một rollout nhận được lợi thế của rollout đó. rollout/fork_frac và rollout/drift_tokens_* cho thấy các lượt đã được điều chỉnh như thế nào.
Tích hợp Môi trường
Để huấn luyện các tác nhân chạy trong môi trường riêng của chúng, chẳng hạn như các tác nhân lập trình trong các sandbox Harbor, hãy xem Training on harnesses trong hướng dẫn OpenEnv.
Huấn luyện Mô hình Ngôn ngữ Thị giác
Các mô hình thị giác-ngôn ngữ (Qwen3.5, Qwen3.6, Qwen3-VL, …) có thể được huấn luyện trên các bộ dữ liệu chỉ chứa văn bản. Truyền id của mô hình như bình thường; không có gì khác thay đổi.
Tháp thị giác bị đóng băng. Bộ dữ liệu chỉ chứa văn bản không bao giờ tạo ra token hình ảnh, do đó tháp thị giác không bao giờ được thực thi trong bước truyền thẳng. Mọi thành phần nằm ngoài mô hình văn bản (tháp thị giác, bộ chiếu đa phương tiện) đều có requires_grad=False: chúng không nhận gradient, không có trạng thái optimizer, và quá trình đồng bộ trọng số sẽ bỏ qua chúng, nên máy chủ giữ nguyên các giá trị đã tải từ checkpoint. Tháp thị giác vẫn được tải, vì vậy nó vẫn chiếm bộ nhớ GPU cho phần trọng số.
Ảnh chưa được hỗ trợ. Các prompt chứa ảnh sẽ không được truyền đến máy chủ vLLM hay bước forward trong quá trình huấn luyện. Huấn luyện đa phương thức cũng cần đường dẫn packing không có padding để xây dựng vị trí M-RoPE 3D từ lưới ảnh, điều này chưa được triển khai ở đây.
AsyncGRPOTrainer
lớp trl.AsyncGRPOTrainer
< source >( model: str | PreTrainedModelreward_funcs: collections.abc.Callable[..., list[float]] | list[collections.abc.Callable[..., list[float]]] | None = Noneargs: trl.trainer.async_grpo_config.AsyncGRPOConfig | None = Nonetrain_dataset: datasets.arrow_dataset.Dataset | datasets.iterable_dataset.IterableDataset | None = Noneprocessing_class: transformers.tokenization_utils_base.PreTrainedTokenizerBase | None = Nonecallbacks: list[transformers.trainer_callback.TrainerCallback] | None = Noneoptimizers: tuple[typing.Optional[torch.optim.Optimizer], typing.Optional[torch.optim.lr_scheduler.LambdaLR]] = (None, None)peft_config: PeftConfig | None = Nonetools: list[collections.abc.Callable] | None = Noneenvironment_factory: collections.abc.Callable[[], trl.trainer.async_grpo_trainer._SupportsReset] | dict[str, collections.abc.Callable[[], trl.trainer.async_grpo_trainer._SupportsReset]] | None = None )
Tham số
- model (
strhoặc PreTrainedModel) — Mô hình cần huấn luyện. Có thể là:- Một chuỗi, là model id của một model được huấn luyện trước lưu trữ trong một model repo trên huggingface.co, hoặc một
đường dẫn đến một thư mục chứa các trọng số model được lưu bằng
save_pretrained, ví dụ:
'./my_model_directory/'. Model sẽ được nạp với kiến trúc được khai báo trong config của nó: AutoModelForImageTextToText cho một checkpoint vision-language (trong đó vision tower được nạp nhưng bị đóng băng, xem Training Vision Language Models), AutoModelForCausalLM trong các trường hợp khác. - Một đối tượng PreTrainedModel. Việc triển khai chú ý của nó được chuyển sang bộ xử lý chú ý dạng cây của trainer để huấn luyện đóng gói.
Tên mô hình từ cấu hình được sử dụng để xác định mô hình trên máy chủ vLLM được dùng cho việc tạo sinh.
- Một chuỗi, là model id của một model được huấn luyện trước lưu trữ trong một model repo trên huggingface.co, hoặc một
đường dẫn đến một thư mục chứa các trọng số model được lưu bằng
save_pretrained, ví dụ:
- reward_funcs (
RewardFunc | list[RewardFunc], tùy chọn) — Các hàm phần thưởng được sử dụng để tính toán phần thưởng. Để tính toán phần thưởng, chúng ta gọi tất cả các hàm phần thưởng với các prompt và completions, sau đó cộng tổng các phần thưởng. Có thể bỏ qua khi phần thưởng được cung cấp bởi môi trường thông quaenvironment_factory(xem bên dưới). Có thể là:- Một hàm phần thưởng duy nhất: Hàm này nhận vào các prompt và các câu trả lời được tạo ra, cùng với bất kỳ cột bổ sung nào trong bộ dữ liệu. Nó phải trả về một danh sách các phần thưởng. Các hàm phần thưởng có thể đồng bộ hoặc bất đồng bộ và cũng có thể trả về
Nonekhi phần thưởng không áp dụng cho các mẫu đó. Điều này hữu ích cho việc huấn luyện đa nhiệm, nơi các hàm phần thưởng khác nhau áp dụng cho các loại mẫu khác nhau. Khi một hàm phần thưởng trả vềNonecho một mẫu, hàm phần thưởng đó sẽ bị loại khỏi việc tính toán phần thưởng cho mẫu đó. Để biết thêm chi tiết, xem Sử dụng hàm phần thưởng tùy chỉnh. - Một danh sách các hàm phần thưởng, trong đó mỗi mục là một hàm phần thưởng như đã mô tả ở trên. Phần thưởng từ tất cả các hàm sẽ được cộng lại.
Khác với GRPOTrainer, phần thưởng được tính toán trong một tiến trình con được khởi tạo, do đó mỗi hàm phần thưởng (cùng với
toolsvàenvironment_factory) phải có thể picklable: hãy sử dụng một hàm ở cấp module,functools.partial, hoặc một instance của lớp callable — lambda và closure sẽ thất bại khi khởi động. Các công cụ được đăng ký theo__name__của chúng, vì vậy chúng phải là các hàm ở cấp module. Tiến trình con cũng chạy vớiCUDA_VISIBLE_DEVICES="", do đó một mô hình phần thưởng dựa trên GPU sẽ chạy trên CPU (chậm), thay vì trên GPU của trainer. - Một hàm phần thưởng duy nhất: Hàm này nhận vào các prompt và các câu trả lời được tạo ra, cùng với bất kỳ cột bổ sung nào trong bộ dữ liệu. Nó phải trả về một danh sách các phần thưởng. Các hàm phần thưởng có thể đồng bộ hoặc bất đồng bộ và cũng có thể trả về
- args (AsyncGRPOConfig, tuỳ chọn) —
Cấu hình cho trainer này. Nếu là
None, một cấu hình mặc định sẽ được sử dụng. - train_dataset (Dataset hoặc IterableDataset, tùy chọn) —
Dataset để sử dụng cho huấn luyện. Nó phải bao gồm một cột
"prompt". Các cột bổ sung khác trong dataset sẽ bị bỏ qua. Các mẫu phải ở định dạng đối thoại : mỗi mẫu chứa các tin nhắn có cấu trúc (ví dụ: role và content).Chỉ có thể được bỏ qua khi một
environment_factoryđược cung cấp và môi trường sở hữu (hoặc tạo ra theo thủ tục) dữ liệu, trả về prompt từ phương thứcreset()của nó. Trong trường hợp đó,max_stepsphải được đặt để xác định độ dài huấn luyện. - processing_class (PreTrainedTokenizerBase, tuỳ chọn) —
Lớp xử lý được dùng để xử lý dữ liệu. Bên đệm (padding side) phải được đặt là “left”. Nếu
None, lớp xử lý sẽ được nạp từ tên mô hình bằng from_pretrained. Một token đệm,tokenizer.pad_token, phải được đặt. Nếu lớp xử lý chưa đặt token đệm,tokenizer.eos_tokensẽ được dùng làm mặc định. - callbacks (danh sách TrainerCallback, tùy chọn) —
Danh sách các callback để tùy chỉnh vòng lặp huấn luyện. Những callback này sẽ được thêm vào danh sách các callback mặc định được mô tả chi tiết tại đây.
Nếu bạn muốn xóa một trong các callback mặc định đang được sử dụng, hãy dùng phương thức remove_callback.
- optimizers (
tuple[torch.optim.Optimizer | None, torch.optim.lr_scheduler.LambdaLR | None], tùy chọn, mặc định là(None, None)) — Một tuple chứa optimizer và scheduler cần sử dụng. Mặc định sẽ là một instance củaAdamWtrên model của bạn và một scheduler được cung cấp bởi get_linear_schedule_with_warmup được điều khiển bởiargs. - peft_config (PeftConfig, tuỳ chọn) —
Cấu hình PEFT được sử dụng để bọc model. Nếu là
None, model sẽ không được bọc. Khi server vLLM được khởi chạy với--enable-lora, adapter LoRA sẽ được đồng bộ hóa đến server đó dưới dạng adapter thay vì dạng trọng số đã hợp nhất; xem phần LoRA trong tài liệu AsyncGRPO. - tools (list of
Callable, optional) — Một danh sách các hàm công cụ callable (đồng bộ hoặc bất đồng bộ) mà mô hình có thể gọi trong quá trình sinh. Mỗi công cụ phải là một hàm Python chuẩn với các đối số và giá trị trả về được chú thích kiểu (type-hint) đúng cách, cùng một docstring theo phong cách Google mô tả mục đích, các đối số và giá trị trả về. Để biết thêm chi tiết, xem: https://huggingface.co/docs/transformers/en/chat_extras#passing-tools. Mô hình sử dụng tên hàm, type hints và docstring để xác định cách gọi nó. Đảm bảo rằng chat template của mô hình hỗ trợ việc sử dụng công cụ và rằng nó đã được fine-tune cho việc gọi công cụ. - environment_factory (
EnvironmentFactoryhoặcdict[str, EnvironmentFactory], tùy chọn) — Một callable tạo và trả về một instance môi trường, hoặc một dictionary ánh xạ tên môi trường đến các callable như vậy. Lớp môi trường nên định nghĩa các phương thức có thể được gọi như công cụ trong quá trình sinh. Mỗi phương thức nên tuân thủ cùng các yêu cầu nhưtoolsđược mô tả ở trên. Môi trường cũng phải triển khai một callableresetphương thức có thể được sử dụng để đặt lại trạng thái giữa các lần sinh. Phương thứcresetnên trả vềNonehoặc một chuỗi: khi trả về một chuỗi, chuỗi đó được thêm vào cuối thông điệp người dùng trước khi sinh. Môi trường cũng có thể định nghĩa mộtget_rewardphương thức không nhận đối số và trả về mộtfloat: khi có mặt, môi trường sở hữu phần thưởng, vàget_rewardđược gọi một lần cho mỗi rollout hoàn thành để chấm điểm nó từ trạng thái nội bộ của môi trường. Nó hoạt động như một nguồn phần thưởng bổ sung (với trọng số 1, được ghi log dưới tên lớp của môi trường) bên cạnhreward_funcs, sau đó trở thành tùy chọn.Với một callable duy nhất, mọi ví dụ đều sử dụng cùng một môi trường, với một instance cho mỗi rollout để các tương tác của chúng được cách ly. Với một dictionary, mỗi ví dụ phải có trường
environmentđể chọn môi trường của nó theo tên, và chỉ các công cụ của môi trường đó được hiển thị trong prompt của nó — cho phép một lần chạy kết hợp các tác vụ (ví dụ: một môi trường lập trình và một trò chơi). Tính năng này đang ở giai đoạn thử nghiệm và có thể thay đổi hoặc bị loại bỏ vào bất kỳ lúc nào mà không cần thông báo trước.
Trainer cho phương pháp Tối ưu hóa Chính sách Tương đối Nhóm (Group Relative Policy Optimization - GRPO). Thuật toán này ban đầu được đề xuất trong bài báo DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models. Trainer này là phiên bản bất đồng bộ của GRPO, trong đó quá trình sinh dữ liệu được chuyển sang một máy chủ vLLM bên ngoài chạy bất đồng bộ song song với huấn luyện, tách rời quá trình rollout khỏi vòng lặp cập nhật gradient.
Ví dụ:
>>> from trl import AsyncGRPOTrainer
>>> from trl.rewards import accuracy_reward
>>> from datasets import load_dataset
>>> dataset = load_dataset("trl-lib/DeepMath-103K", split="train")
>>> trainer = AsyncGRPOTrainer(
... model="Qwen/Qwen2.5-0.5B-Instruct",
... reward_funcs=accuracy_reward,
... train_dataset=dataset,
... )
>>> trainer.train()Để tùy chỉnh các prompt được lấy mẫu, cách tạo một rollout hoặc cách tính các lợi thế, hãy tạo lớp con của AsyncRolloutLoop và đặt nó làm loop_cls của trainer. TRL xây dựng vòng lặp trong
quá trình rollout:
>>> class CurriculumTrainer(AsyncGRPOTrainer):
... loop_cls = CurriculumRolloutLooptrain
< source >( resume_from_checkpoint: str | bool | None = Nonetrial: optuna.Trial | dict[str, Any] | None = Noneignore_keys_for_eval: list[str] | None = None ) → ~trainer_utils.TrainOutput
Tham số
- resume_from_checkpoint (
strhoặcbool, tùy chọn) — Nếu làstr, đường dẫn cục bộ đến một checkpoint đã lưu bởi một phiênTrainertrước đó. Nếu làboolvà bằngTrue, tải checkpoint cuối cùng trong args.output_dir do một phiênTrainertrước đó lưu lại. Nếu có, quá trình huấn luyện sẽ tiếp tục từ trạng thái model/optimizer/scheduler được tải ở đây. - trial (
optuna.Trialhoặcdict[str, Any], tùy chọn) — Lần chạy thử nghiệm hoặc từ điển siêu tham số cho việc tìm kiếm siêu tham số. - ignore_keys_for_eval (
list[str], tùy chọn) — Một danh sách các khóa trong đầu ra của mô hình của bạn (nếu đó là một từ điển) cần được bỏ qua khi thu thập các dự đoán để đánh giá trong quá trình huấn luyện.
Trả về
~trainer_utils.TrainOutput
Đối tượng chứa số bước toàn cục, tổn thất huấn luyện và các chỉ số.
Điểm vào chính cho quá trình huấn luyện.
Sẽ lưu mô hình, để bạn có thể tải lại bằng from_pretrained().
Chỉ lưu từ tiến trình chính.
push_to_hub
< source >( commit_message: str | None = 'End of training'blocking: bool = Truetoken: str | None = Nonerevision: str | None = Noneprivate: bool | None = None**kwargs )
Tham số
- commit_message (
str, tùy chọn, mặc định là"End of training") — Thông điệp để commit khi đẩy lên. - blocking (
bool, tùy chọn, mặc định làTrue) — Xác định xem hàm có chỉ trả về khigit pushđã hoàn tất hay không. - token (
str, tùy chọn, mặc định làNone) — Token có quyền ghi để ghi đè lên các args gốc của Trainer. - revision (
str, tùy chọn) — Phiên bản git để commit từ. Mặc định là đầu của nhánh “main”. - private (
bool, tuỳ chọn) — Xác định xem có đặt kho thành riêng tư khi tạo hay không. Mặc định làargs.hub_private_repo. Không có tác dụng nếu kho đã tồn tại. - kwargs (
dict[str, Any], tùy chọn) — Các đối số từ khóa bổ sung được truyền đến~Trainer.create_model_card.
Tải self.model và self.processing_class lên 🤗 model hub tại repo self.args.hub_model_id.
AsyncGRPOConfig
lớp trl.AsyncGRPOConfig
< source >( output_dir: str | None = Noneper_device_train_batch_size: int = 8num_train_epochs: float = 3.0max_steps: int = -1learning_rate: float = 1e-06lr_scheduler_type: str = 'constant'lr_scheduler_kwargs: dict | str | None = Nonewarmup_steps: float = 0optim: transformers.training_args.OptimizerNames | str = 'adamw_torch_fused'optim_args: str | None = Noneweight_decay: float = 0.0adam_beta1: float = 0.9adam_beta2: float = 0.999adam_epsilon: float = 1e-08optim_target_modules: None | str | list[str] = Nonegradient_accumulation_steps: int = 1average_tokens_across_devices: bool = Truemax_grad_norm: float = 1.0label_smoothing_factor: float = 0.0bf16: bool | None = Nonefp16: bool = Falsebf16_full_eval: bool = Falsefp16_full_eval: bool = Falsetf32: bool | None = Noneactivation_checkpointing: bool | None = Noneactivation_checkpointing_kwargs: dict[str, typing.Any] | str | None = Nonegradient_checkpointing: bool = Truegradient_checkpointing_kwargs: dict[str, typing.Any] | str | None = Nonetorch_compile: bool = Falsetorch_compile_backend: str | None = Nonetorch_compile_mode: str | None = Noneuse_liger_kernel: bool = Falseliger_kernel_config: dict[str, bool] | None = Noneuse_cache: bool = Falseneftune_noise_alpha: float | None = Nonetorch_empty_cache_steps: int | None = Noneauto_find_batch_size: bool = Falselogging_strategy: transformers.trainer_utils.IntervalStrategy | str = 'steps'logging_steps: float = 1logging_first_step: bool = Falselog_on_each_node: bool = Truelogging_nan_inf_filter: bool = Trueinclude_num_input_tokens_seen: str | bool = 'no'log_level: str = 'passive'log_level_replica: str = 'warning'disable_tqdm: bool | None = Nonereport_to: None | str | list[str] = 'none'run_name: str | None = Noneproject: str = 'huggingface'trackio_space_id: str | None = Nonetrackio_bucket_id: str | None = Nonetrackio_static_space_id: typing.Union[str, NoneType, typing.Literal[False]] = Noneeval_strategy: transformers.trainer_utils.IntervalStrategy | str = 'no'eval_steps: float | None = Noneeval_delay: float = 0per_device_eval_batch_size: int = 8prediction_loss_only: bool = Falseeval_on_start: bool = Falseeval_do_concat_batches: bool = Trueeval_use_gather_object: bool = Falseeval_accumulation_steps: int | None = Noneinclude_for_metrics: list[str] = <factory>batch_eval_metrics: bool = Falsesave_only_model: bool = Falsesave_strategy: transformers.trainer_utils.SaveStrategy | str = 'steps'save_steps: float = 500save_on_each_node: bool = Falsesave_total_limit: int | None = Noneenable_jit_checkpoint: bool = Falsepush_to_hub: bool = Falsehub_token: str | None = Nonehub_private_repo: bool | None = Nonehub_model_id: str | None = Nonehub_strategy: transformers.trainer_utils.HubStrategy | str = 'every_save'hub_always_push: bool = Falsehub_revision: str | None = Noneload_best_model_at_end: bool = Falsemetric_for_best_model: str | None = Nonegreater_is_better: bool | None = Noneignore_data_skip: bool = Truerestore_callback_states_from_checkpoint: bool = Falsefull_determinism: bool = Falseseed: int = 42data_seed: int | None = Noneuse_cpu: bool = Falseaccelerator_config: dict | str | None = Noneparallelism_config: accelerate.parallelism_config.ParallelismConfig | None = Nonedataloader_drop_last: bool = Falsedataloader_num_workers: int = 0dataloader_pin_memory: bool = Truedataloader_persistent_workers: bool = Falsedataloader_prefetch_factor: int | None = Nonedataloader_multiprocessing_context: str | None = Nonedataloader_in_order: bool = Trueremove_unused_columns: bool = Falselabel_names: list[str] | None = Nonetrain_sampling_strategy: str = 'random'length_column_name: str = 'length'ddp_find_unused_parameters: bool | None = Noneddp_bucket_cap_mb: int | None = Noneddp_broadcast_buffers: bool | None = Noneddp_static_graph: bool | None = Noneddp_backend: str | None = Noneddp_timeout: int = 1800fsdp: str | None = Nonefsdp_config: dict[str, typing.Any] | str | None = Nonedeepspeed: dict | str | None = Nonedebug: str | list[transformers.debug_utils.DebugOption] = ''skip_memory_metrics: bool = Truedo_train: bool = Falsedo_eval: bool = Falsedo_predict: bool = Falseresume_from_checkpoint: str | None = Nonelocal_rank: int = -1model_init_kwargs: dict[str, typing.Any] | str | None = Nonedtype: str = 'float32'trust_remote_code: bool = Falserouter_aux_loss_coef: float | None = Nonenum_generations: int = 8max_completion_length: int = 2048temperature: float = 1.0top_p: float = 1.0top_k: int = 0min_p: float | None = Nonechat_template_kwargs: dict | str | None = Nonemax_tool_calling_iterations: int | None = Nonevllm_server_base_url: str = 'http://localhost:8000'vllm_server_timeout: float = 1800.0epsilon: float = 0.2epsilon_high: float | None = Nonescore_centering: bool = Truevllm_importance_sampling_clip_min: float = 0.5vllm_importance_sampling_clip_max: float = 5.0num_sampler_logprobs: int = 8token_budget: int | None = Nonemax_concurrent_rollouts: int = 512max_staleness: int = 4weight_sync_steps: int = 1rollout_worker_timeout: float = 300.0log_completions: bool = Falsenum_completions_to_print: int | None = None )
Các tham số điều khiển mô hình
- model_init_kwargs (
dict[str, Any]hoặcstr, tùy chọn) — Các đối số dạng từ khóa cho from_pretrained, được sử dụng khi khởi tạo mô hình từ một đường dẫn. Giá trịrevisioncũng được sử dụng khi nạp lớp xử lý. - dtype (
str, tuỳ chọn, mặc định là"float32") — Kiểu dữ liệu để nạp mô hình, một trong số"auto","bfloat16","float16"hoặc"float32". Mặc định là"float32"vì sự không khớp giữa huấn luyện và suy luận mà trainer này được đo lường so với (Đánh bại sự không khớp giữa Huấn luyện và Suy luận thông qua FP16) rất nhạy cảm với độ chính xác của chính trainer. Việc thu hẹp khoảng cách đó từ đầu đến cuối cũng yêu cầu phục vụ máy chủ vLLM với cùng một kiểu dữ liệu (vllm serve --dtype); sự không khớp sẽ được ghi nhận dưới dạng cảnh báo khi bắt đầu huấn luyện. Mộtdtypetrongmodel_init_kwargscó quyền ưu tiên.Điều này chỉ đặt dtype mà các trọng số được nạp vào. Dưới FSDP với độ chính xác hỗn hợp (
bf16=Truelà mặc định), accelerate sẽ upcast mọi tham số có thể huấn luyện lên fp32 trước khi sharding, do đó trọng số master và trạng thái optimizer luôn là fp32 bất kểdtypenói gì, trong khi forward và backward chạy ở bf16 hoặc fp16. Checkpoint sau đó được ghi ở dtype độ chính xác hỗn hợp đó, không phải fp32. Không có FSDP thì không có gì được upcast:dtype="bfloat16"vớibf16=Truegiữ nguyên trọng số và trạng thái optimizer ở bf16, tức là huấn luyện thuần bf16. - trust_remote_code (
bool, tùy chọn, mặc định làFalse) — Có cho phép tải các model và tokenizer có kèm theo mã Python tùy chỉnh từ Hub hay không. Tham số này được chuyển tiếp đến from_pretrained và from_pretrained. - router_aux_loss_coef (
float, tùy chọn) — Hệ số của tổn thất phụ cân bằng tải cho các mô hình Mixture-of-Experts (MoE), được cộng vào tổn thất huấn luyện với trọng số này. Khi không được đặt, giá trị được khai báo trong cấu hình mô hình sẽ được sử dụng. Đặt thành0.0để tắt nó. Gặp lỗi khi sử dụng với mô hình không phải MoE.
Các tham số kiểm soát quá trình sinh
- num_generations (
int, tùy chọn, mặc định là8) — Số lượng thế hệ cần lấy mẫu cho mỗi prompt. - max_completion_length (
int, tùy chọn, mặc định là2048) — Số lượng token tối đa được tạo ra cho mỗi yêu cầu vLLM, tức là cho mỗi lượt trong một rollout nhiều lượt. - temperature (
float, tùy chọn, mặc định là1.0) — Nhiệt độ cho quá trình lấy mẫu. Nhiệt độ càng cao, các phần hoàn thành càng ngẫu nhiên. - top_p (
float, tùy chọn, mặc định là1.0) — Giá trịfloatkiểm soát xác suất tích lũy của các token hàng đầu cần xem xét. Phải nằm trong khoảng (0, 1]. Đặt bằng 1.0 để xem xét tất cả các token. Nếu nhỏ hơn1.0,top_kcũng phải được đặt, và máy chủ vLLM (>= 0.28) phải được khởi động với--return-sampling-mask --enable-scale-out: trình huấn luyện sẽ chuẩn hóa lại log-probabilities của nó trên tập ứng viên mà mỗi token được lấy mẫu từ đó, giống như máy chủ thực hiện. Các phiên bản vLLM cũ hơn sẽ giữ nguyên toàn bộ bảng từ vựng. - top_k (
int, tùy chọn, mặc định là0) — Số lượng token từ vựng có xác suất cao nhất được giữ lại cho lọc top-k. Nếu là0, lọc top-k sẽ bị vô hiệu hóa và tất cả các token đều được xem xét. Mọi giá trị khác đều cần các cờ máy chủ được mô tả dướitop_p. - min_p (
float, tùy chọn) — Xác suất tối thiểu của token, sẽ được nhân với xác suất của token có khả năng cao nhất. Giá trị này phải nằm trong khoảng từ 0.0 đến 1.0. Các giá trị điển hình nằm trong khoảng 0.01-0.2. Nếu lớn hơn0.0, bạn cũng phải đặttop_k, với các cờ máy chủ được mô tả dướitop_p. - chat_template_kwargs (
dict[str, Any], tùy chọn) — Các đối số từ khóa bổ sung để truyền cho hàmapply_chat_templatekhi tạo các câu trả lời hoàn chỉnh. - max_tool_calling_iterations (
int, tùy chọn) — Số lượt gọi công cụ tối đa khi huấn luyện một agent. Nếu làNone, sẽ không có giới hạn và quá trình sinh sẽ dừng lại khi mô hình tạo ra một lượt phản hồi không chứa bất kỳ lời gọi công cụ nào.
Các tham số điều khiển máy chủ vLLM
- vllm_server_base_url (
str, tùy chọn, mặc định là"http --//localhost:8000"): URL gốc của máy chủ vLLM được sử dụng cho việc tạo (ví dụ:"http://localhost:8000"). - vllm_server_timeout (
float, tùy chọn, mặc định là1800.0) — Thời gian chờ (giây) cho các cuộc gọi đến máy chủ vLLM: chờ máy chủ sẵn sàng khi khởi động, mỗi yêu cầu sinh và mỗi cuộc gọi đồng bộ trọng số. Chờ máy chủ và các cuộc gọi đồng bộ trọng số sẽ gây ra lỗi khi hết thời gian; một yêu cầu sinh hết thời gian sẽ được thử lại.
Các tham số kiểm soát quá trình huấn luyện
- epsilon (
float, tùy chọn, mặc định là0.2) — Giá trị epsilon cho việc cắt (clipping). - epsilon_high (
float, tùy chọn) — Giá trị epsilon cận trên để cắt. Nếu không được chỉ định, mặc định sẽ bằng giá trị cận dưới được chỉ định trong tham sốepsilon. Bài báo DAPO khuyến nghị0.28. - score_centering (
bool, tùy chọn, mặc định làTrue) — Có huấn luyện với score centering (bài báo) thay vì mục tiêu bị cắt (clipped objective) hay không: điểm số có trọng số quan trọng (importance-weighted score) của mỗi token được lấy mẫu trừ đi kỳ vọng của nó dưới bộ lấy mẫu vLLM, sao cho một lợi thế (advantage) hằng không kéo chính sách (policy) về phía bộ lấy mẫu. Kỳ vọng được tính trênnum_sampler_logprobstoken có khả năng cao nhất tại mỗi vị trí, với các log-probability do bộ lấy mẫu báo cáo. - vllm_importance_sampling_clip_min (
float, tuỳ chọn, mặc định là0.5) — Giới hạn dưới C_min của tỷ lệ quan trọng giữa chính sách và bộ lấy mẫu vLLM. Các token có tỷ lệ nằm ngoài khoảng [vllm_importance_sampling_clip_min,vllm_importance_sampling_clip_max] sẽ bị loại khỏi lỗ (lấy mẫu quan trọng có mặt nạ). - vllm_importance_sampling_clip_max (
float, tùy chọn, mặc định là5.0) — Giới hạn trên C_max của tỷ lệ quan trọng. - num_sampler_logprobs (
int, tuỳ chọn, mặc định là8) — Số lượng log-probabilities hàng đầu được yêu cầu từ bộ lấy mẫu vLLM cho mỗi token được tạo ra, dùng cho việc căn giữa điểm số. Càng nhiều thì càng bao phủ nhiều hơn khối lượng xác suất của bộ lấy mẫu nhưng tốn kém hơn để serialize;--max-logprobscủa máy chủ đặt giới hạn cho nó. - token_budget (
int, tuỳ chọn) — Số lượng token tối đa được chuyển tiếp trong một hàng (một lần forward của một DP rank). MộtTokenBudgetBatchersẽ tạo ra các micro-batch được cân bằng theo chi phí attention, trong đó mỗi hàng đều nằm trong giới hạn ngân sách này, từ đó giới hạn bộ nhớ đỉnh một cách độc lập với số lượng mẫu (số mẫu trên mỗi hàng sẽ trở nên động). Ngân sách giới hạn số token duy nhất chứ không phải token thô, do đó các token được chia sẻ bởi nhiều mẫu chỉ được tính một lần, và nó cũng giới hạn các số hạng loss của hàng đó. Nếu làNone(mặc định), giá trị này sẽ được đặt bằngmax_model_lencủa máy chủ vLLM (được truy vấn khi bắt đầu huấn luyện) — tức là giới hạn trên của độ dài prompt + completion — để đảm bảo không có mẫu rollout nào có thể vượt quá ngân sách. Một mẫu dài hơntoken_budgetsẽ không vừa trong bất kỳ hàng nào và sẽ bị loại bỏ kèm theo cảnh báo.
Các tham số điều khiển pipeline rollout bất đồng bộ
- max_concurrent_rollouts (
int, tuỳ chọn, mặc định là512) — Số lượng rollout chạy đồng thời tối đa. Mỗi rollout giữ một môi trường, có thể thực hiện các cuộc gọi công cụ đồng bộ và duy trì kết nối với máy chủ vLLM, vì vậy hãy đặt giá trị này phù hợp với khả năng chịu tải của các tài nguyên đó. Dưới ngưỡng này, số lượng rollout đang chạy sẽ phụ thuộc vào mức sử dụng bộ nhớ đệm KV của máy chủ vLLM vàmax_staleness. - max_staleness (
int, tùy chọn, mặc định là4) — Số bước cập nhật trọng số tối đa mà một mẫu rollout có thể bị tụt lại so với phiên bản mô hình hiện tại trước khi bị loại bỏ. Quá trình sinh được giữ ở mức này: một nhóm rollout mới chỉ bắt đầu khi các token đang xếp hàng và đang xử lý vừa với lượng mà trainer tiêu thụ trongmax(max_staleness, 1)bước. - weight_sync_steps (
int, tùy chọn, mặc định là1) — Số bước huấn luyện giữa các lần đồng bộ trọng số sang máy chủ vLLM. - rollout_worker_timeout (
float, tùy chọn, mặc định là300.0) — Số giây kể từ lần heartbeat cuối cùng của rollout worker, sau đó trainer sẽ coi nó là bị treo và hủy bỏ.
Các tham số kiểm soát việc ghi log
Lớp cấu hình cho AsyncGRPOTrainer.
Lớp này chỉ bao gồm các tham số đặc thù cho huấn luyện GRPO bất đồng bộ. Để xem danh sách đầy đủ các đối số huấn luyện, vui lòng tham khảo tài liệu TrainingArguments. Lưu ý rằng các giá trị mặc định trong lớp này có thể khác với các giá trị trong TrainingArguments.
Các tham số này có giá trị mặc định khác với TrainingArguments:
logging_steps: Mặc định là1thay vì500.gradient_checkpointing: Mặc định làTruethay vìFalse.bf16: Mặc định làTruenếufp16không được đặt, thay vìFalse.learning_rate: Mặc định là1e-6thay vì5e-5.lr_scheduler_type: Mặc định làconstantthay vìlinear(xem bên dưới).ignore_data_skip: Mặc định làTruethay vìFalse; vòng lặp bỏ qua và phát lại của Trainer cơ sở không áp dụng cho hàng đợi rollout bất đồng bộ.remove_unused_columns: Mặc định làFalsethay vìTrue, và phải giữ nguyênFalse: mọi cột của tập dữ liệu đều được truyền vào các hàm phần thưởng.
Thời lượng huấn luyện và tốc độ học dưới cơ chế đối soát theo chế độ tin nhắn: Một cuộc hội thoại nhiều lượt có thể phân nhánh thành một số lượng dòng huấn luyện thay đổi (việc viết lại cuộc hội thoại sẽ bắt đầu một dòng mới), do đó số lượng mẫu, và vì vậy số bước tối ưu hóa, cho mỗi epoch không được biết trước. Hệ quả là:
num_train_epochsgiới hạn quá trình huấn luyện bằng số lần chạy toàn bộ tập dữ liệu prompt, được tính là số lượng prompt riêng biệt thực sự được huấn luyện. Điều này độc lập với số dòng mà các nhánh (forks) tạo ra, do đó việc yêu cầu N epoch luôn huấn luyện trên N lần chạy qua dữ liệu. Khimax_stepskhông được đặt, đây là điều kiện dừng vàmax_stepschỉ là giới hạn an toàn.max_steps, nếu được đặt rõ ràng (> 0), sẽ trở thành điều kiện dừng (giới hạn theo số bước của optimizer thay vì theo số epoch) và vô hiệu hóa điều kiện dừng dựa trên epoch.lr_scheduler_typemặc định làconstantvì khoảng thời gian suy giảm được đo bằng số bước tối ưu hóa, điều này không thể biết trước khi số bước phụ thuộc vào tỷ lệ fork. Để sử dụng tốc độ học suy giảm, hãy đặt lịch trình suy giảm cùng vớimax_stepsrõ ràng.
AsyncRolloutLoop
lớp trl.trainer.async_grpo_trainer.AsyncRolloutLoop
< source >( config: AsyncGRPOConfigmodel_name: strdataset: Datasetreward_funcs: list[collections.abc.Callable[..., list[float]]]processing_class: PreTrainedTokenizerBaseeos_token_ids: list[int]rollout_buffer: Queuemodel_version_value: Synchronizedtoken_allowance: Synchronizedheartbeat_value: Synchronizedfailed_event: Eventexception_info_queue: Queuemetrics_queue: Queuetools: list[collections.abc.Callable] | None = Noneenvironment_factory: collections.abc.Callable[[], object] | dict[str, collections.abc.Callable[[], object]] | None = Nonescore_queue_maxsize: int = 16lora_name: str | None = Nonedataset_start_index: int = 0 )
Tạo và chấm điểm các rollout cho AsyncGRPOTrainer, trong một tiến trình rollout được khởi tạo.
Phiên bản mặc định triển khai GRPO. Để tùy chỉnh một lần chạy, hãy tạo lớp con của nó, ghi đè chỉ các phương thức có thay đổi, và đặt lớp con đó làm loop_cls của trainer. Mỗi prompt sẽ đi qua theo thứ tự:
- filter_prompt(): có nên tạo cho prompt hay không.
- generate_one(): một lượt rollout hoàn chỉnh, gọi generate_one_turn() cho mỗi yêu cầu lấy mẫu.
- Nhóm
num_generationsrollout được chấm điểm: phần thưởng của nó là tổng củareward_funcscủa trainer, của các môi trường định nghĩaget_reward, và của Rollout.reward. Sau đó, compute_advantages() được chạy một lần cho mỗi nhóm.
setup() và close() tạo và giải phóng các tài nguyên trên vòng lặp sự kiện của vòng lặp, chẳng hạn như một client HTTP. Một hook có thể đọc self.config (một lớp con của AsyncGRPOConfig có thể mang theo các trường riêng của nó) và self.tokenizer. Vì vòng lặp được xây dựng trong một tiến trình được sinh ra, lớp con phải có thể nhập được (được định nghĩa ở cấp độ module).
filter_prompt
< source >( row_index: introw: dict[str, typing.Any]epoch: int ) → bool
Liệu có tạo cho một prompt hay không. Một prompt bị từ chối sẽ bị bỏ qua trong epoch này và được tính là đã tiêu thụ, giống như một nhóm bị loại bỏ. Mặc định chấp nhận mọi prompt. Việc từ chối mọi prompt của một epoch đầy đủ sẽ gây ra lỗi, vì sau đó không có batch nào có thể đến được trainer.
generate_one
< source >( prompt: list[dict[str, str]]tools: list[collections.abc.Callable]group_id: int = 0 ) → Rollout
Tham số
- prompt (
list[dict[str, Any]]) — Các tin nhắn prompt. - tools (
list[Callable]) — Các công cụ khả dụng cho rollout này:toolscủa trainer, cùng với các phương thức công khai của môi trường khi sử dụngenvironment_factory. - group_id (
int, tùy chọn, mặc định là0) — Định danh của nhóm mà rollout thuộc về.
Trả về
Cuộn hoàn chỉnh.
Tạo một lượt rollout cho một prompt.
Mặc định, một vòng lặp công cụ đa lượt: mỗi lượt sẽ render toàn bộ cuộc trò chuyện bằng chat template, lấy mẫu một phản hồi bằng generate_one_turn() và thực thi các lời gọi công cụ có trong đó, cho đến khi mô hình ngừng gọi công cụ hoặc đạt đến max_tool_calling_iterations. Ghi đè nó để tạo ra nội dung theo cách khác, ví dụ bằng một framework agent. Trả về mọi yêu cầu lấy mẫu trong Rollout.turns, vì các chuỗi huấn luyện được xây dựng từ chúng, và đặt Rollout.reward để chấm điểm rollout tại đây.
generate_one_turn
< source >( prompt_ids: list[int] ) → TurnRecord
Tham số
Trả về
TurnRecord
Prompt và các token được lấy mẫu cùng với log-probabilities của chúng. Khi sử dụng top_k hoặc top_p, nó cũng chứa tập ứng viên của mỗi token được lấy mẫu, và khi sử dụng num_sampler_logprobs, nó chứa các log-probabilities hàng đầu của bộ lấy mẫu.
Lấy mẫu một phản hồi từ máy chủ vLLM, với các cài đặt lấy mẫu của cấu hình (temperature, top_p, top_k, min_p, repetition_penalty và max_completion_length).
compute_advantages
< source >( group: RolloutGroup ) → np.ndarray
Tham số
- group (RolloutGroup) —
Các rollout
num_generationscủa một prompt, với tổng phần thưởng của chúng tronggroup.rewards.
Trả về
np.ndarray
Một lợi thế cho mỗi lần rollout, theo thứ tự của group.rewards.
Tính một lợi thế cho mỗi lượt rollout của một nhóm. Mặc định, mỗi phần thưởng được chuẩn hóa trong nhóm; một lượt rollout có phần thưởng NaN sẽ nhận lợi thế 0 và bị loại khỏi trung bình và độ lệch chuẩn.
Nó được thực hiện cho mỗi nhóm. Một nhóm có phần thưởng được chấm điểm đều bằng nhau sẽ bị loại bỏ, bất kể các lợi thế mà điều này trả về là gì.
Tạo các tài nguyên mà các hook khác cần, chẳng hạn như một client HTTP. Chạy trên event loop của vòng lặp trước prompt đầu tiên. Mặc định không thực hiện gì.
Giải phóng những gì setup() đã tạo. Được thực thi khi các vòng lặp dừng lại, bao gồm cả khi xảy ra lỗi. Mặc định không thực hiện gì.
Rollout
class trl.trainer.async_grpo_trainer.Rollout
< source >( completion: list[dict[str, str]]completion_ids: list[int]turns: list[trl.trainer.async_grpo_trainer.TurnRecord]tool_call_count: int = 0tool_failure_count: int = 0reward: float | None = Nonerollout_id: str = <factory> )
Tham số
- completion (
list[dict[str, Any]]) — Messages generated after the prompt, in conversational format. Passed to the reward functions ascompletions. - completion_ids (
list[int]) — Các id token của phần hoàn thành được tạo ra. Được truyền vào các hàm phần thưởng dưới dạngcompletion_ids. - turns (
list[TurnRecord]) — Các yêu cầu lấy mẫu tạo ra rollout, theo thứ tự. Các chuỗi huấn luyện được xây dựng từ chúng: các token được lấy mẫu sẽ được huấn luyện, phần còn lại của mỗi prompt đóng vai trò ngữ cảnh. - tool_call_count (
int, tùy chọn, mặc định là0) — Số lượng cuộc gọi công cụ được thực hiện trong quá trình rollout. - tool_failure_count (
int, tùy chọn, mặc định là0) — Số lượng các cuộc gọi công cụ đã thất bại. - reward (
float, tùy chọn) — Phần thưởng được tính trong quá trình sinh, ví dụ như bởi một bộ chấm điểm bên ngoài. Nó được cộng vào phần thưởng của các hàm phần thưởng và môi trường. Nếu làNone, lượt rollout này sẽ không nhận phần thưởng từ nguồn này. - rollout_id (
str, tùy chọn) — Xác định rollout trong các hàng huấn luyện của nó, để gỡ lỗi. Mặc định là một id hex ngẫu nhiên mới.
Một lượt rollout hoàn chỉnh, như được trả về bởi generate_one().
TurnRecord
class trl.trainer.async_grpo_trainer.TurnRecord
< source >( prompt_ids: list[int]output_ids: list[int]output_log_probs: list[float] = <factory>output_mask: list[int] | None = Noneoutput_sampling_mask: list[list[int]] | None = Noneoutput_sampler_logprobs: list[dict[int, float]] | None = None )
Tham số
- prompt_ids (
list[int]) — Các id token của toàn bộ prompt được gửi cho lượt này, bao gồm mọi lượt trước đó của cuộc hội thoại. - output_ids (
list[int]) — Các id token do trình lấy mẫu tạo ra. - output_log_probs (
list[float], tuỳ chọn, mặc định là[]) — Log-probability của Sampler cho từng token trongoutput_ids. Bắt buộc khi bất kỳ token nào trong số đó được huấn luyện. - output_mask (
list[int], tùy chọn) — Một giá trị cho mỗi token trongoutput_ids:1để huấn luyện trên token đó,0để giữ nó chỉ làm ngữ cảnh. NếuNone, mọi token đầu ra đều được huấn luyện. - output_sampling_mask (
list[list[int]], tùy chọn) — Một danh sách cho mỗi token trongoutput_ids: các id token mà bộ lấy mẫu có thể rút ra dưới sự cắt bớttop_k/top_p. Nếu làNone, thì là toàn bộ từ vựng. - output_sampler_logprobs (
list[dict[int, float]], optional) — Một dict cho mỗi token trongoutput_ids: log-probabilities của các token có khả năng cao nhất của sampler, được đánh dấu bằng token id. Được sử dụng bởi score centering (num_sampler_logprobs).
Một yêu cầu lấy mẫu: prompt được gửi đến trình lấy mẫu và các token mà nó đã tạo ra.
RolloutGroup
lớp trl.trainer.async_grpo_trainer.RolloutGroup
< source >( prompts: list[list[dict[str, str]]]reward_kwargs: dict[str, list[typing.Any]]completions: list[list[dict[str, str]]]completions_ids: list[list[int]]completions_sequences: list[list[trl.trainer.async_grpo_trainer.TrainingSequence]]tool_call_counts: list[int]tool_failure_counts: list[int]model_version: intgroup_id: introw_index: intenv_rewards: list[tuple[type, float] | None]rollout_rewards: list[float | None]queued_at: float = 0.0rewards: numpy.ndarray | None = None )
Tham số
- prompts (
list[list[dict[str, Any]]]) — Prompt của mỗi rollout. - reward_kwargs (
dict[str, list[Any]]) — Các cột khác của hàng dữ liệu prompt, được truyền vào các hàm reward dưới dạng các tham số keyword. - completions (
list[list[dict[str, Any]]]) — Các thông tin hoàn thành của mỗi lần rollout. - completions_ids (
list[list[int]]) — Các id token hoàn thành của mỗi rollout. - completions_sequences (
list[list[TrainingSequence]]) — Các chuỗi huấn luyện được xây dựng từ mỗi rollout. Một rollout mà lịch sử được mã hóa lại (re-tokenized) thay đổi giữa các lượt sẽ tạo ra nhiều hơn một chuỗi. - tool_call_counts (
list[int]) — Số lượng lần gọi công cụ trong mỗi rollout. - tool_failure_counts (
list[int]) — Số lượng các cuộc gọi công cụ thất bại trong mỗi lượt rollout. - model_version (
int) — Phiên bản chính sách khi lượt rollout đầu tiên của nhóm bắt đầu. - group_id (
int) — Định danh của nhóm, được đếm từ0trong quá trình rollout. - row_index (
int) — Chỉ số của hàng chứa prompt trong tập dữ liệu huấn luyện. - env_rewards (
list[tuple[type, float] or None]) — Đối với một rollout mà môi trường của nó định nghĩaget_reward, đây là lớp môi trường và phần thưởng của nó; nếu không thì làNone. - rollout_rewards (
list[float or None]) — Rollout.rewardcủa mỗi rollout. - queued_at (
float, tùy chọn, mặc định là0.0) —time.monotonic()khi nhóm được đưa vào hàng đợi để chấm điểm. - rewards (
np.ndarray, tuỳ chọn) — Tổng phần thưởng của mỗi rollout, được cộng gộp từ mọi nguồn phần thưởng, có giá trị NaN nếu không có nguồn nào chấm điểm cho nó. Được đặt trước khi compute_advantages() được gọi.
Các rollout num_generations của một prompt, được chấm điểm cùng nhau. Mỗi danh sách có một mục cho mỗi rollout.