TRL documentation

مدرب GRPO

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

and get access to the augmented documentation experience

to get started

مدرب GRPO

model badge

نظرة عامة

يدعم TRL مُدرّب GRPO لتدريب نماذج اللغة، كما هو موصوف في ورقة DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models التي كتبها Zhihong Shao، Peiyi Wang، Qihao Zhu، Runxin Xu، Junxiao Song، Mingchuan Zhang، Y. K. Li، Y. Wu، Daya Guo.

المستخلص من الورقة البحثية هو كالتالي:

يُشكّل الاستدلال الرياضي تحديًا كبيرًا لنماذج اللغة بسبب طبيعته المعقدة والمنظمة. في هذه الورقة، نُقدّم DeepSeekMath 7B، الذي يستمر في التدريب المسبق لـ DeepSeek-Coder-Base-v1.5 7B باستخدام 120 مليار رمز متعلق بالرياضيات مستمد من Common Crawl، إلى جانب بيانات اللغة الطبيعية والكود. حقق DeepSeekMath 7B نتيجة مبهرة بلغت 51.7% على معيار MATH على مستوى المسابقات، دون الاعتماد على أدوات خارجية أو تقنيات التصويت، مما يقترب من مستوى أداء Gemini-Ultra و GPT-4. يحقق اتساق الذات على 64 عينة من DeepSeekMath 7B نسبة 60.9% على MATH. يُعزى قدرة الاستدلال الرياضي في DeepSeekMath إلى عاملين رئيسيين: أولاً، نستغل الإمكانات الكبيرة للبيانات المتاحة علنًا على الويب من خلال خط أنابيب هندسي دقيق لاختيار البيانات. ثانيًا، نُقدّم Group Relative Policy Optimization (GRPO)، وهو متغير من Proximal Policy Optimization (PPO)، يعزز قدرات الاستدلال الرياضي مع تحسين استخدام الذاكرة في PPO في الوقت نفسه.

تمت مساهمة Quentin Gallouédec في هذه طريقة ما بعد التدريب.

البدء السريع

يُظهر هذا المثال كيفية تدريب نموذج باستخدام طريقة GRPO. نقوم بتدريب نموذج Qwen2.5 0.5B Instruct باستخدام الأوامر من مجموعة بيانات DeepMath-103K. يمكنك عرض البيانات في مجموعة البيانات هنا:

فيما يلي السكربت لتدريب النموذج. يحتاج accuracy_reward إلى math-verify، والذي يمكنك تثبيته باستخدام pip install trl[math_verify].

# train_grpo.py
from datasets import load_dataset
from trl import GRPOTrainer
from trl.rewards import accuracy_reward

dataset = load_dataset("trl-lib/DeepMath-103K", split="train")

trainer = GRPOTrainer(
    model="Qwen/Qwen2.5-0.5B-Instruct",
    reward_funcs=accuracy_reward,
    train_dataset=dataset,
)
trainer.train()

نفّذ السكربت باستخدام الأمر التالي:

accelerate launch train_grpo.py

عند توزيع التدريب على 8 وحدات معالجة رسومية (GPU)، يستغرق التدريب حوالي يوم واحد.

GRPO curves

ملاحظة: تم توليد منحنيات المكافآت أعلاه باستخدام Qwen/Qwen2-0.5B-Instruct. ستكون النتائج باستخدام Qwen/Qwen2.5-0.5B-Instruct مشابهة نوعياً.

النظر بعمق أكبر في طريقة GRPO

GRPO هو خوارزمية تعلّم عبر الإنترنت، مما يعني أنه يتحسّن بشكل تكراري من خلال استخدام البيانات التي يولّدها النموذج المدرَّب نفسه أثناء التدريب. الفكرة الكامنة وراء هدف GRPO هي تعظيم ميزة المكملات المولَّدة، مع ضمان بقاء النموذج قريبًا من سياسة المرجع. لفهم كيفية عمل GRPO، يمكن تقسيمه إلى أربع خطوات رئيسية: توليد المكملات، حساب الميزة، تقدير تباعد KL، وحساب الخسارة.

GRPO visual

توليد الاكتمالات

في كل خطوة تدريب، نختار دفعة من الأوامر ونولّد مجموعة من G G الإكمالات لكل أمر (يُرمز إليها بـ oi o_i ).

حساب الميزة

لكلٍّ من G G التسلسلات، نحسب المكافأة باستخدام نموذج مكافآت أو دالة مكافآت. ولتوافق مع الطبيعة المقارنة لنماذج المكافآت — التي تُدرَّب عادةً على مجموعات بيانات من المقارنات بين المخرجات للسؤال نفسه — يتم حساب الميزة لتعكس هذه المقارنات النسبية. يتم تطبيعها على النحو التالي: A^i,t=ri−mean(r)std(r)\hat{A}_{i,t} = \frac{r_i - \text{mean}(\mathbf{r})}{\text{std}(\mathbf{r})}

يمنح هذا النهج الطريقة اسمه: تحسين السياسة النسبي للمجموعات (GRPO).

أُظهر في الورقة البحثية Understanding R1-Zero-Like Training: A Critical Perspective أن التوسيع بواسطة std(r) \text{std}(\mathbf{r}) قد يسبب انحيازًا في صعوبة مستوى السؤال. يمكنك تعطيل هذا التوسيع عن طريق تعيين scale_rewards=False في GRPOConfig. يُرجى ملاحظة أن إيقاف التوسيع القائم على std يزيل أيضًا تطبيع التباين، لذا تعتمد أحجام التحديث مباشرةً على مقياس المكافأة الخام وتكوين الدفعة.

كما هو موضح في الجزء الأول: حيل أم فخاخ؟ غوص عميق في التعلم المعزز لاستدلال نماذج اللغة الكبيرة (Lite PPO)، فإن حساب المتوسط على المستوى المحلي (المجموعة) والانحراف المعياري على المستوى العام (الدفع) يتيح تشكيل مكافآت أكثر متانة. يمكنك استخدام استراتيجية التوسيع هذه عن طريق تعيين scale_rewards="batch" في GRPOConfig.

تقدير تباعد كولباك-ليبل

يُقدَّر تباعد KL باستخدام المُقدِّر الذي قدمه Schulman et al. (2020). يُعرَّف المُقدِّر على النحو التالي: DKL[πθ∥πref]=πref(oi,t∣q,oi,<t)πθ(oi,t∣q,oi,<t)−log⁡πref(oi,t∣q,oi,<t)πθ(oi,t∣q,oi,<t)−1,\mathbb{D}_{\text{KL}}\left[\pi_\theta \|\pi_{\text{ref}}\right] = \frac{\pi_{\text{ref}}(o_{i,t} \mid q, o_{i,<t})}{\pi_\theta(o_{i,t} \mid q, o_{i,<t})} - \log \frac{\pi_{\text{ref}}(o_{i,t} \mid q, o_{i,<t})}{\pi_\theta(o_{i,t} \mid q, o_{i,<t})} - 1,

حساب الخسارة

الهدف هو تعظيم الميزة مع ضمان بقاء النموذج قريبًا من سياسة المرجع. وبالتالي، يُعرَّف الخسارة على النحو التالي: LGRPO(θ)=−1∑i=1G∣oi∣∑i=1G∑t=1∣oi∣[πθ(oi,t∣q,oi,<t)[πθ(oi,t∣q,oi,<t)]no gradA^i,t−βDKL[πθ∥πref]], \mathcal{L}_{\text{GRPO}}(\theta) = -\frac{1}{\sum_{i=1}^G |o_i|} \sum_{i=1}^G \sum_{t=1}^{|o_i|} \left[ \frac{\pi_\theta(o_{i,t} \mid q, o_{i,< t})}{\left[\pi_\theta(o_{i,t} \mid q, o_{i,< t})\right]_{\text{no grad}}} \hat{A}_{i,t} - \beta \mathbb{D}_{\text{KL}}\left[\pi_\theta \| \pi_{\text{ref}}\right] \right],

حيث يمثل الحد الأول الميزة المُقيّمة، بينما يعاقب الحد الثاني الانحرافات عن سياسة المرجع من خلال تباعد كوهين-ليبلينغ.

لاحظ أنه مقارنةً بالصياغة الأصلية في DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models, لا نضرب في 1∣oi∣ \frac{1}{|o_i|} لأنه تم إثبات في الورقة Understanding R1-Zero-Like Training: A Critical Perspective أن هذا يُدخل تحيّزًا في طول الاستجابة على مستوى الرد. مزيد من التفاصيل في أنواع الدالة الخاسرة.

لاحظ أنه مقارنةً بالصياغة الأصلية في DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models, نستخدم β=0.0 \beta = 0.0 كقيمة افتراضية، مما يعني أن حد تباعد KL لا يُستخدم. ينبع هذا الاختيار من عدة دراسات حديثة (مثل Open-Reasoner-Zero: An Open Source Approach to Scaling Up Reinforcement Learning on the Base Model) ) التي أظهرت أن حد تباعد KL ليس ضروريًا للتدريب باستخدام GRPO. ونتيجةً لذلك، أصبح من الشائع استبعاده (مثل Understanding R1-Zero-Like Training: A Critical Perspective, DAPO: An Open-Source LLM Reinforcement Learning System at Scale). إذا كنت ترغب في تضمين حد تباعد KL، يمكنك تعيين beta في GRPOConfig إلى قيمة غير صفرية.

في الورقة الأصلية، يتم تعميم هذه الصياغة لتأخذ في الاعتبار عدة تحديثات بعد كل توليد (يُرمز لها بـ μ \mu , يمكن ضبطها عبر num_iterations في GRPOConfig) عن طريق الاستفادة من دالة الهدف البديلة المقصوصة: LGRPO(θ)=−1∑i=1G∣oi∣∑i=1G∑t=1∣oi∣[min⁡(πθ(oi,t∣q,oi,<t)πθold(oi,t∣q,oi,<t)A^i,t, clip(πθ(oi,t∣q,oi,<t)πθold(oi,t∣q,oi,<t),1−ϵ,1+ϵ)A^i,t)−βDKL[πθ∥πref]], \mathcal{L}_{\text{GRPO}}(\theta) = - \frac{1}{\sum_{i=1}^G |o_i|} \sum_{i=1}^G \sum_{t=1}^{|o_i|} \left[ \min \left( \frac{\pi_\theta(o_{i,t} \mid q, o_{i,< t})}{\pi_{\theta_{\text{old}}}(o_{i,t} \mid q, o_{i,< t})} \hat{A}_{i,t}, \, \text{clip}\left( \frac{\pi_\theta(o_{i,t} \mid q, o_{i,< t})}{\pi_{\theta_{\text{old}}}(o_{i,t} \mid q, o_{i,< t})}, 1 - \epsilon, 1 + \epsilon \right) \hat{A}_{i,t} \right) - \beta \mathbb{D}_{\text{KL}}\left[\pi_\theta \| \pi_{\text{ref}}\right] \right],

حيث clip(⋅,1−ϵ,1+ϵ)\text{clip}(\cdot, 1 - \epsilon, 1 + \epsilon) على ضمان عدم انحراف التحديثات بشكل مفرط عن سياسة المرجع من خلال تحديد نطاق نسبة السياسة بين 1−ϵ 1 - \epsilon و 1+ϵ 1 + \epsilon . عندما μ=1 \mu = 1 (القيمة الافتراضية في TRL)، فإن الدالة البديلة المقصوصة تتبسط لتصبح الدالة الأصلية.

أنواع الدالة

قُدِّمت عدة صيغ للدالة الهدف في الأدبيات. في البداية، عُرِّفت دالة هدف GRPO على النحو التالي: LGRPO(θ)=−1G∑i=1G1∣oi∣∑t=1∣oi∣li,t, \mathcal{L}_{\text{GRPO}}(\theta) = - \frac{1}{G} \sum_{i=1}^G \frac{1}{|o_i|} \sum_{t=1}^{|o_i|} l_{i,t},

حيث li,t=πθ(oi,t∣q,oi,<t)[πθ(oi,t∣q,oi,<t)]no gradA^i,t−βDKL[πθ∥πref]. l_{i,t} = \frac{\pi_\theta(o_{i,t} \mid q, o_{i,< t})}{\left[\pi_\theta(o_{i,t} \mid q, o_{i,< t})\right]_{\text{no grad}}} \hat{A}_{i,t} - \beta \mathbb{D}_{\text{KL}}\left[\pi_\theta \| \pi_{\text{ref}}\right].

يُبرز ورقة DAPO قيود خسارة مستوى العينة في خوارزمية GRPO في سيناريوهات CoT الطويلة، حيث تُعاقَب الاستجابات الأطول بشكل غير كافٍ، مما يؤدي إلى مخرجات ذات جودة أدنى. الحل المقترح هو تطبيع على مستوى الرمز (token-level normalization)، والذي يتعامل بشكل أفضل مع التسلسلات الأطول من خلال منح مكافآت أكثر توازناً للأفراد الرموز، بغض النظر عن طول الاستجابة: LDAPO(θ)=−1∑i=1G∣oi∣∑i=1G∑t=1∣oi∣li,t, \mathcal{L}_{\text{DAPO}}(\theta) = - \frac{1}{\sum_{i=1}^G |o_i|} \sum_{i=1}^G \sum_{t=1}^{|o_i|} l_{i,t},

لاستخدام هذه الصياغة، اضبط loss_type="dapo" في GRPOConfig.

علاوة على ذلك، تم إثبات في الورقة Understanding R1-Zero-Like Training: A Critical Perspective أن صياغة GRPO الأولية تُدخل انحيازًا في طول الاستجابة. يُظهرون أنه على الرغم من أن صياغة DAPO تقلل من هذا الانحياز، إلا أنها لا تلغيه تمامًا. لإزالة هذا الانحياز بالكامل، يقترحون القسمة على ثابت بدلاً من طول التسلسل، مما يؤدي إلى الصياغة التالية: LDr. GRPO(θ)=−1LG∑i=1G∑t=1∣oi∣li,t, \mathcal{L}_{\text{Dr. GRPO}}(\theta) = - \frac{1}{LG} \sum_{i=1}^G \sum_{t=1}^{|o_i|} l_{i,t},

يُوصى بأن تكون هذه الثابتة هي الحد الأقصى لطول الإكمال. لاستخدام هذه الصياغة، اضبط loss_type="dr_grpo" في GRPOConfig.

بديلًا عن ذلك، في ورقة SAPO، يقترح فريق Qwen استبدال آلية القصّ “الصلبة” في GRPO بآلية بوابة ناعمة سلسة تتحكم فيها درجة الحرارة. بينما تُصفّر GRPO التدرّجات عندما ينحرف النموذج عن المرجع بشكل مفرط، يستخدم SAPO منطقة ثقة ناعمة تُضعف وزن التدرّج بسلاسة. وهذا يتيح للنموذج الاحتفاظ بإشارات التعلم المفيدة من الرموز “القريبة من السياسة” مع كبح الضوضاء الناتجة عن الانحرافات الشديدة.

يُعرَّف دالة الخسارة على النحو التالي: LSAPO(θ)=−1G∑i=1G1∣oi∣∑t=1∣oi∣fi,t(πθ(oi,t∣q,oi,<t)πθold(oi,t∣q,oi,<t))A^i,t \mathcal{L}_{\text{SAPO}}(\theta) = - \frac{1}{G} \sum_{i=1}^G \frac{1}{|o_i|} \sum_{t=1}^{|o_i|} f_{i,t} \left( \frac{\pi_\theta(o_{i,t} | q, o_{i,<t})}{\pi_{\theta_{old}}(o_{i,t} | q, o_{i,<t})} \right) \hat{A}_{i,t}

دالة البوابة الناعمة fi,t f_{i,t} تُعرَّف باستخدام دالة السيغمويد σ \sigma على النحو التالي: fi,t(x)=σ(τi,t(x−1))⋅4τi,t f_{i,t}(x) = \sigma \left( \tau_{i,t} (x - 1) \right) \cdot \frac{4}{\tau_{i,t}}

درجة الحرارة τi,t \tau_{i,t} تُختار بناءً على إشارة الميزة A^i,t \hat{A}_{i,t} : τi,t={τpos,if A^i,t>0τneg,otherwise \tau_{i,t} = \begin{cases} \tau_{\text{pos}}, & \text{if } \hat{A}_{i,t} > 0 \\ \tau_{\text{neg}}, & \text{otherwise} \end{cases}

يوصون باستخدام درجات حرارة غير متماثلة، τneg>τpos \tau_{\text{neg}} > \tau_{\text{pos}} (القيم الافتراضية هي τpos=1.0,τneg=1.05 \tau_{\text{pos}}=1.0, \tau_{\text{neg}}=1.05 ). يضمن هذا أن يُعاقب النموذج بشكل أكثر صرامة على الإجراءات «السيئة» لمنع عدم الاستقرار، مع كونه أكثر تساهلاً مع الإجراءات «الجيدة».

لاستخدام هذه الصياغة، اضبط loss_type="sapo" في GRPOConfig.

المقاييس المسجّلة

أثناء التدريب والتقييم، نسجّل المقاييس التالية:

  • num_tokens: إجمالي عدد الرموز التي تمت معالجتها حتى الآن، بما في ذلك كل من الاستعلامات (prompts) والإكمالات (completions). عند استخدام الأدوات، يتم احتساب الرموز غير المرتبطة بالأدوات فقط.
  • step_time: متوسط الوقت (بالثواني) المستغرق لكل خطوة تدريب (بما في ذلك التوليد).
  • completions/mean_length: متوسط طول المكملات المولّدة. عند استخدام الأدوات، تُحتسب الرموز غير المتعلقة بالأدوات فقط.
  • completions/min_length: الحد الأدنى لطول المكملات المولّدة. عند استخدام الأدوات، تُحتسب الرموز غير المرتبطة بالأدوات فقط.
  • completions/max_length: الحد الأقصى لطول المكملات المولّدة. عند استخدام الأدوات، يتم احتساب رموز غير الأدوات فقط.
  • completions/mean_terminated_length: متوسط طول الإكمالات المولّدة التي تنتهي بـ EOS. عند استخدام الأدوات، يتم احتساب رموز غير الأدوات فقط.
  • completions/min_terminated_length: الحد الأدنى لطول المكملات المولّدة التي تنتهي بـ EOS. عند استخدام الأدوات، يتم احتساب رموز غير الأدوات فقط.
  • completions/max_terminated_length: الحد الأقصى لطول المكملات المولّدة التي تنتهي بـ EOS. عند استخدام الأدوات، يتم احتساب رموز غير الأدوات فقط.
  • completions/clipped_ratio: نسبة الإكمالات المقطوعة (المُقصاة).
  • tools/call_frequency: متوسط عدد استدعاءات الأدوات لكل إكمال في دفعة التوليد. يُسجَّل فقط عند توفير tools.
  • tools/failure_frequency: نسبة استدعاءات الأدوات التي فشلت (لم يتم العثور على الأداة، أو أثار استثناءً، أو أن نوع الاستدعاء غير مدعوم). تكون قيمتها 0.0 عندما لم يتم استدعاء أي أداة. تُسجَّل فقط عند توفير tools.
  • rewards/{reward_func_name}/mean: متوسط المكافأة من دالة مكافأة محددة. عندما تمتلك البيئة المكافأة عبر get_reward، يكون {reward_func_name} اسم فئة البيئة.
  • rewards/{reward_func_name}/std: الانحراف المعياري للمكافأة من دالة مكافأة محددة.
  • reward: متوسط المكافأة الإجمالي بعد جمع المكافآت عبر الدوال (موزونة بـ reward_weights).
  • reward_std: الانحراف المعياري للمكافآت المجمعة عبر الدوال (موزونة بـ reward_weights)، محسوبًا على الدفعة الكاملة.
  • frac_reward_zero_std: نسبة العينات في دفعة التوليد التي يكون انحراف مكافأتها المعياري صفراً، مما يعني أن التنوع ضئيل لذلك الاستدعاء (جميع الإجابات صحيحة أو خاطئة).
  • sampling/sampling_logp_difference/mean: متوسط الفرق المطلق بين احتمالات اللوغاريتم التي يعيدها العيّان (vLLM) وتلك التي يعيد حسابها نموذج التدريب، على مستوى رموز الإكمال. يشير ارتفاع القيمة إلى اتساع فجوة عدم التطابق بين التدريب والاستدلال. يُسجَّل فقط عند تعيين use_vllm=True وvllm_importance_sampling_correction=True.
  • sampling/sampling_logp_difference/max: أكبر فرق مطلق من هذا النوع. يُسجَّل فقط عندما يكون use_vllm=True وvllm_importance_sampling_correction=True.
  • sampling/importance_sampling_ratio/min: أصغر نسبة أخذ عينات بالوزن المستخدمة لتصحيح عدم التطابق بين التدريب والاستدلال، بعد تطبيق القيد المحدد بواسطة vllm_importance_sampling_mode (يتم قصّها إلى [C_min, C_max] في أوضاع *_truncate، وتُضبط إلى صفر في أوضاع *_mask). تُحسب على رموز الإكمال، أو على التسلسلات في أوضاع sequence_*. تُسجَّل فقط عندما يكون use_vllm=True وvllm_importance_sampling_correction=True.
  • sampling/importance_sampling_ratio/mean: متوسط نسبة أخذ العينات المهمة المقيدة. يُسجَّل فقط عندما يكون use_vllm=True وvllm_importance_sampling_correction=True.
  • sampling/importance_sampling_ratio/max: أكبر نسبة أخذ عينات بالوزن المقيدة. يُسجَّل فقط عندما يكون use_vllm=True وvllm_importance_sampling_correction=True.
  • policy_loss: قيمة خسارة تدرج السياسة (قبل أي مكافأة إنتروبيا). تُسجَّل عندما يكون entropy_coef غير صفري أو use_adaptive_entropy=True.
  • entropy: متوسط إنتروبيا توقعات الرموز عبر المكملات المولّدة. (إذا كان mask_truncated_completions=True، يتم استبعاد رموز التسلسلات المقنّعة.)
  • entropy_coef: معامل تنظيم الإنتروبيا الحالي. يُسجَّل عندما يكون entropy_coef غير صفري أو عندما يكون use_adaptive_entropy=True. يُحدَّث مرة واحدة في كل خطوة مُحسِّن عندما يكون use_adaptive_entropy=True.
  • aux_loss: خسارة التوازن على الأحمال المساعدة لنموذج مزيج الخبراء، قبل أن تُضرب في router_aux_loss_coef وتُضاف إلى الخسارة. تُسجَّل فقط عندما يكون النموذج من نوع MoE وrouter_aux_loss_coef غير صفري.
  • kl: متوسط تباعد كوهين-ليبلر بين النموذج ونموذج المرجع، محسوبًا على المكملات المولّدة. يُسجَّل فقط إذا كان beta غير صفري.
  • clip_ratio/region_mean: نسبة الرموز (أو التسلسل، إذا كان importance_sampling_level="sequence") للاحتمالات التي يُقصّ فيها هدف GRPO ليبقى ضمن منطقة الثقة: clip(ri,t(θ),1−ϵlow,1+ϵhigh) ,ri,t(θ)=πθ(oi,t∣q,oi,<t)πθold(oi,t∣q,oi,<t) \text{clip}\left( r_{i,t}(\theta), 1 - \epsilon_\mathrm{low}, 1 + \epsilon_\mathrm{high} \right)\,, \quad r_{i,t}(\theta) = \frac{\pi_\theta(o_{i,t} \mid q, o_{i,< t})}{\pi_{\theta_{\text{old}}}(o_{i,t} \mid q, o_{i,< t})} . تدل قيمة أعلى على أن عددًا أكبر من الرموز يُقصّ، مما يقيّد مدى تغيير السياسة πθ\pi_\theta .
  • clip_ratio/low_mean: متوسط نسبة احتمالات الرموز (أو التسلسل، إذا كان importance_sampling_level="sequence") مقصوصة عند الحد الأدنى لمنطقة الثقة: ri,t(θ)<1−ϵlowr_{i,t}(\theta) < 1 - \epsilon_\mathrm{low}.
  • clip_ratio/low_min: أصغر نسبة لكل إكمال من الرموز (أو التسلسل نفسه، إذا importance_sampling_level="sequence") تم اقتطاعه عند الحد الأدنى لمنطقة الثقة: ri,t(θ)<1−ϵlowr_{i,t}(\theta) < 1 - \epsilon_\mathrm{low}.
  • clip_ratio/high_mean: متوسط نسبة احتمالات الرموز (أو التسلسل، إذا كان importance_sampling_level="sequence") مقصوصة عند الحد الأعلى لمنطقة الثقة: ri,t(θ)>1+ϵhighr_{i,t}(\theta) > 1 + \epsilon_\mathrm{high}.
  • clip_ratio/high_max: أعلى نسبة لكل إكمال من الرموز (أو التسلسل نفسه، إذا importance_sampling_level="sequence") تم اقتطاعه عند الحد الأعلى لمنطقة الثقة: ri,t(θ)>1+ϵhighr_{i,t}(\theta) > 1 + \epsilon_\mathrm{high}.
  • cispo_clip_ratio: نسبة أوزات أخذ العينات المهمة (على مستوى الرمز، أو التسلسل إذا كان importance_sampling_level="sequence") مقصوصة عند epsilon_high مع امتلاك ميزة إيجابية: ri,t(θ)>ϵhighr_{i,t}(\theta) > \epsilon_\mathrm{high}. يُسجَّل فقط عندما يكون loss_type="cispo".
  • vespo/phi_seq_mean: القيمة المتوسطة لوزن VESPO Gamma φ(w)\varphi(w) المُطبَّق على أوزان الأهمية على مستوى التسلسل. تشير القيم الأقل من 1.0 إلى تخفيض وزن التسلسلات. يُسجَّل هذا فقط عندما يكون loss_type="vespo".

التخصيص

تسريع التدريب باستخدام التوليد المدعوم من vLLM

غالبًا ما يكون التوليد هو العائق الرئيسي عند التدريب باستخدام الأساليب المباشرة. لتسريع التوليد، يمكنك استخدام vLLM، وهو محرك استدلال عالي الإنتاجية ومنخفض الكمون للنماذج اللغوية الكبيرة. لتفعيله، قم أولاً بتثبيت الحزمة باستخدام

pip install trl[vllm]

ندعم طريقتين لاستخدام vLLM أثناء التدريب: وضع الخادم ووضع التجميع.

بشكل افتراضي، يتم تفعيل أخذ عينات الأهمية المقنّعة على مستوى التسلسل (vllm_importance_sampling_mode="sequence_mask") لتوليد vLLM لمعالجة عدم التطابق بين التوليد والتدريب الذي يحدث عند استخدام أطر عمل مختلفة. يمكن تعطيل ذلك عن طريق تعيين vllm_importance_sampling_correction=False. لمزيد من المعلومات، راجع أخذ عينات الأهمية المقنّعة و أخذ عينات الأهمية على مستوى التسلسل

الخيار 1: وضع التجميع

في هذا الوضع، يعمل vLLM داخل عملية المُدرِّب ويتشارك ذاكرة GPU مع نموذج التدريب. يتجنّب هذا إطلاق خادم منفصل ويمكن أن يحسّن استخدام GPU، لكنه قد يؤدي إلى تنافس على الذاكرة في وحدات GPU الخاصة بالتدريب. هذا هو الوضع الافتراضي.

from trl import GRPOConfig

training_args = GRPOConfig(
    ...,
    use_vllm=True,  # vllm_mode="colocate" by default
)

الخيار 2: وضع الخادم

في هذا الوضع، يعمل vLLM في عملية منفصلة (ويعتمد على وحدات معالجة رسومية منفصلة) ويتواصل مع المُدرِّب عبر HTTP. وهذا مثالي إذا كانت لديك وحدات معالجة رسومية مخصصة للاستدلال.

  1. بدء خادم vLLM:

    VLLM_SERVER_DEV_MODE=1 vllm serve <model_name> \
        --weight-transfer-config '{"backend": "nccl"}' \
        --logprobs-mode processed_logprobs \
        --max-logprobs -1
  2. تفعيل وضع الخادم في سكربت التدريب الخاص بك:

    from trl import GRPOConfig
    
    training_args = GRPOConfig(
        ...,
        use_vllm=True,
        vllm_mode="server",
    )

تأكد من أن الخادم يستخدم وحدات معالجة رسومية مختلفة عن تلك التي يستخدمها المدرب، وإلا فقد تواجه أخطاء NCCL. يمكنك تحديد وحدات المعالجة الرسومية المراد استخدامها باستخدام متغير البيئة CUDA_VISIBLE_DEVICES.

يعتمد على حجم النموذج ومتطلبات ذاكرة وحدة معالجة الرسوميات (GPU) الإجمالية للتدريب، قد تحتاج إلى ضبط معامل vllm_gpu_memory_utilization في GRPOConfig لتجنب سوء الاستخدام أو أخطاء نفاد الذاكرة.

نوفر مساحة HF لمساعدتك في تقدير استهلاك ذاكرة وحدة معالجة الرسوميات الموصى به بناءً على إعدادات النموذج وإعدادات التجربة الخاصة بك. ما عليك سوى استخدامه على النحو التالي للحصول على توصية vllm_gpu_memory_utilization:

إذا لم يعمل القيمة الموصى بها في بيئتك، نقترح إضافة هامش صغير (مثل +0.05 أو +0.1) إلى القيمة الموصى بها لضمان الاستقرار.

إذا كنت لا تزال تواجه أخطاء نفاد الذاكرة، فاضبط vllm_enable_sleep_mode على True وسيتم تفريغ معاملات vllm والذاكرة المؤقتة أثناء خطوة التحسين. لمزيد من المعلومات، راجع تقليل استخدام الذاكرة مع وضع السكون في vLLM.

افتراضيًا، يستخدم GRPO MASTER_ADDR=localhost وMASTER_PORT=12345 لـ vLLM، لكن يمكنك تجاوز هذه القيم عن طريق تعيين متغيرات البيئة وفقًا لذلك.

لمزيد من المعلومات، راجع تسريع التدريب باستخدام vLLM.

التعامل مع عدم التطابق بين التدريب والاستدلال

في حين أن vLLM يُسرّع الاستدلال بشكل كبير، فإنه يفصل محرك الاستدلال عن محرك التدريب. نظريًا، هذان المحركان متطابقان رياضيًا، لكن عمليًا قد ينتجان مخرجات مختلفة بسبب تأثيرات الدقة والتحسينات الخاصة بالمعدات. يعكس هذا الاختلاف أهداف التحسين المختلفة للنظامين. تهدف محركات الاستدلال إلى تعظيم معدل إنتاج العينات، والذي يُقاس عادةً بعدد الرموز في الثانية، مع الحفاظ على دقة عينات مقبولة. في المقابل، تركز أطر التدريب على الاستقرار العددي والدقة في حساب التدرجات، وغالبًا ما تستخدم صيغًا ذات دقة أعلى مثل FP32 للأوزان الرئيسية وحالات المُحسِّن. تُدخل هذه الأولويات والقيود المختلفة عدم تطابق حتمي، وإن كان دقيقًا، بين التدريب والاستدلال.

يؤدي هذا الاختلاف إلى تحديث متدرج منحاز، وقد لوحظ أنه يُزعزع استقرار التدريب ([1][2][3][4][5]). للبساطة، لنفترض متدرج سياسة REINFORCE: ∇θJ(x,θ)=Ey∼πtrain(⋅∣x,θ)[∇θlog⁡πtrain(y∣x,θ)⋅R(x,y)] \nabla_\theta \mathcal{J}(x,\theta) = \mathbb{E}_{y \sim \pi^\text{train}(\cdot \mid x,\theta)} \left[ \nabla_\theta \log \pi^\text{train}(y \mid x,\theta) \cdot R(x,y) \right]

هنا x x تُشير إلى الأوامر المُستخرجة من توزيع بيانات معين، و πtrain \pi^\text{train} هو السياسة المُنفَّذة بواسطة محرك التدريب. عند تضمين vLLM في العملية، نحصل على سياسة استدلال منفصلة πinference \pi^\text{inference} , لذا يصبح تدرج السياسة الفعّال ∇θJbiased(x,θ)=Ey∼πinference(⋅∣x,θ)[∇θlog⁡πtrain(y∣x,θ)⋅R(x,y)]. \nabla_\theta \mathcal{J}_{\text{biased}}(x,\theta) = \mathbb{E}_{y \sim \pi^\text{inference}(\cdot \mid x,\theta)} \left[ \nabla_\theta \log \pi^\text{train}(y \mid x,\theta) \cdot R(x,y) \right].

يُحوِّل هذا مشكلة تعلُّم معزَّز كانت في الأصل ضمن السياسة إلى مشكلة خارج السياسة.

The standard way to correct for this distribution shift is importance sampling (IS). We provide two IS variants: Truncated Importance Sampling (TIS) and Masked Importance Sampling (MIS). Both variants can be applied either at the token level or at the sequence level. Let ρ \rho denote the importance weight, for example ρt \rho_t per token or ρseq \rho_{\text{seq}} per sequence. Under TIS, ratios outside of the range [vllm_importance_sampling_clip_min, vllm_importance_sampling_clip_max] are clipped, ρ←clip(ρ,Cmin⁡,Cmax⁡). \rho \leftarrow \text{clip}(\rho, C_{\min}, C_{\max}).

الورقة الأصلية TIS اقترحت آلية قصّ واحدة للحد الأعلى، أي min⁡(ρ,Cmax⁡) \min(\rho, C_{\max}) . عمّم التنفيذ في TRL هذا المفهوم من خلال تقديم حد أدنى أيضًا، مما أدى إلى الصياغة ذات الجانبين المعروضة أعلاه، مستوحاة من IcePop طريقة.
يُلاحظ أنه في IcePop، تُسمّى الحدود α \alpha و β \beta بينما نستخدم في TRL Cmin⁡ C_{\min} و Cmax⁡ C_{\max} .

في إطار MIS، تُضبط النسب خارج هذا النطاق إلى صفر، وبالتالي لا تساهم تلك العينات في التدرج. بعبارة أخرى، يتم تخفيف وزن العينات الشاذة في إطار TIS، بينما تُستبعد في إطار MIS. يحدد علم التهيئة vllm_importance_sampling_mode كلا من متغير IS (الإخفاء أو القص) والحُبيبية (على مستوى الرمز أو على مستوى التسلسل).

يُعدّ أخذ العينات حسب الأهمية (Importance sampling) الاستجابة الخوارزمية المبنية على مبادئ منهجية لاختلاف التدريب عن الاستدلال. ومع ذلك، هناك أيضاً أساليب أكثر مباشرةً تهدف إلى تقليل الفجوة بين المحركين نفسيهما. معظم هذه الأساليب حلول هندسية. فعلى سبيل المثال، يستخدم MiniMax M1 رأس نموذج لغوي بدقة FP32 في محرك الاستدلال. وقد استكشفت Thinking Machines أنوية استدلال حتمية، على الرغم من أن ذلك يأتي على حساب كفاءة كبيرة. وقد أظهر vLLM سياسات متطابقة على مستوى البت من خلال البناء على أنوية الاستدلال الحتمية غير المعتمدة على حجم الدفعة (batch invariant) من Thinking Machines، لكن حتى نوفمبر 2025 لا يزال هناك انخفاض كبير في معدل الإنتاجية مقارنةً بالاستدلال القياسي في vLLM.

تسريع التدريب باستخدام التدريج المستمر في transformers

كبديل لـ vLLM، يمكنك استخدام محرك الدفع المستمر المدمج في transformers لتوليد أسرع. يقوم الدفع المستمر بإزالة التسلسلات المكتملة من الدفعة فوراً بدلاً من الانتظار حتى يكتمل أبطأها. في المهام التي تتفاوت فيها أطوال الإكمال (مثل الاستدلال الرياضي)، يؤدي ذلك إلى توليد أسرع واستهلاك أقل لذاكرة VRAM مقارنة بـ generate() الافتراضي عند أحجام دفع كبيرة (N≥32).

يُعدّ الدفع المتواصل (Continuous batching) ترقيةً جاهزةً للاستخدام دون الحاجة إلى إعداد خادم أو مزامنة الأوزان. يعمل داخل العملية (in-process) وهو مناسب بشكل جيد لتدريب على وحدة معالجة رسومية واحدة (single-GPU) أو البيئات ذات القيود على الذاكرة. لتحقيق أقصى معدل إنتاجية توليد على نطاق واسع، استخدم vLLM بدلاً من ذلك.

from trl import GRPOConfig

training_args = GRPOConfig(
    ...,
    use_transformers_continuous_batching=True,
    transformers_continuous_batching_config={
        "use_cuda_graph": False,
        "max_memory_percent": 0.4,  # lower values leave more VRAM for the training backward pass
    },
)

تعيّن TRL قيمة max_memory_percent افتراضيًا إلى 0.5 (بدلًا من 0.9 في transformers) لتوفير مساحة كافية من ذاكرة VRAM لمرحلة الرجوع الخلفي في التدريب. اضبطها إلى ما بين 0.3 و0.4 عند استخدام دفعات توليد كبيرة (N≥32) أو عند ظهور أخطاء نفاد الذاكرة.

لمثال تدريب كامل، راجع examples/grpo_continuous_batching/grpo_continuous_batching.py.

GRPO على نطاق واسع: تدريب نموذج بحجم 70B+ على عدة عقد

عند تدريب نماذج كبيرة مثل Qwen2.5-72B، تحتاج إلى عدة تحسينات رئيسية لجعل التدريب فعالاً وقابلاً للتوسع عبر وحدات معالجة الرسوميات (GPUs) وعُقد متعددة. وتشمل هذه التحسينات:

  • DeepSpeed ZeRO Stage 3: يستفيد ZeRO من توازي البيانات لتوزيع حالات النموذج (الأوزان، التدرجات، حالات المُحسِّن) على وحدات معالجة رسومية ووحدات معالجة مركزية متعددة، مما يقلل من متطلبات الذاكرة والحساب على كل جهاز. وبما أن النماذج الكبيرة لا يمكن استيعابها على وحدة معالجة رسومية واحدة، فإن استخدام ZeRO Stage 3 مطلوب لتدريب مثل هذه النماذج. لمزيد من التفاصيل، راجع DeepSpeed Integration.
  • Accelerate: هي مكتبة تُبسّط التدريب الموزّع عبر وحدات معالجة رسومية متعددة وعُقد متعددة. فهي توفر واجهة برمجة تطبيقات بسيطة لإطلاق التدريب الموزّع، وتتعامل مع تعقيدات التدريب الموزّع، مثل توازي البيانات، وتراكم التدرجات، وتحميل البيانات الموزّع. لمزيد من التفاصيل، راجع توزيع التدريب.
  • vLLM: راجع القسم السابق لمعرفة كيفية استخدام vLLM لتسريع عملية التوليد.

فيما يلي مثال على سكربت SLURM لتدريب نموذج بحجم 70B باستخدام GRPO على عدة عقد. يقوم هذا السكربت بتدريب النموذج على 4 عقد ويستخدم العُقدة الخامسة للتوليد المدعوم بـ vLLM.

#!/bin/bash
#SBATCH --nodes=5
#SBATCH --gres=gpu:8

# Get the list of allocated nodes
NODELIST=($(scontrol show hostnames $SLURM_JOB_NODELIST))

# Assign the first 4 nodes for training and the 5th node for vLLM
TRAIN_NODES="${NODELIST[@]:0:4}"  # Nodes 0, 1, 2, 3 for training
VLLM_NODE="${NODELIST[4]}"  # Node 4 for vLLM

# Run training on the first 4 nodes (Group 1)
srun --nodes=4 --ntasks=4 --nodelist="${NODELIST[@]:0:4}" accelerate launch \
     --config_file examples/accelerate_configs/deepspeed_zero3.yaml \
     --num_processes 32 \
     --num_machines 4 \
     --main_process_ip ${NODELIST[0]} \
     --machine_rank $SLURM_PROCID \
     --rdzv_backend c10d \
     train_grpo.py \
     --server_ip $VLLM_NODE &

# Run vLLM server on the 5th node (Group 2)
srun --nodes=1 --ntasks=1 --nodelist="${NODELIST[4]}" env VLLM_SERVER_DEV_MODE=1 vllm serve Qwen/Qwen2.5-72B --tensor-parallel-size 8 \
    --weight-transfer-config '{"backend": "nccl"}' \
    --logprobs-mode processed_logprobs \
    --max-logprobs -1 &

wait
import argparse

from datasets import load_dataset
from trl import GRPOTrainer, GRPOConfig
from trl.rewards import accuracy_reward

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--vllm_server_host", type=str, default="", help="The server IP")
    args = parser.parse_args()

    dataset = load_dataset("trl-lib/DeepMath-103K", split="train")

    training_args = GRPOConfig(
        per_device_train_batch_size=4,
        use_vllm=True,
        vllm_mode="server",
        vllm_server_host=args.vllm_server_host.replace("ip-", "").replace("-", "."),  # from ip-X-X-X-X to X.X.X.X
    )

    trainer = GRPOTrainer(
        model="Qwen/Qwen2.5-72B",
        args=training_args,
        reward_funcs=accuracy_reward,
        train_dataset=dataset
    )
    trainer.train()

if __name__=="__main__":
    main()

استخدام دالة مكافأة مخصصة

يدعم GRPOTrainer استخدام دوال مكافأة مخصصة بدلاً من نماذج المكافأة الكثيفة. لضمان التوافق، يجب أن تستوفي دالة المكافأة الخاصة بك المتطلبات التالية:

يمكن أن تكون دوال المكافآت إما دوال Python متزامنة قابلة للاستدعاء، أو دوال async def غير متزامنة. عند تقديم عدة دوال مكافأة غير متزامنة، يتم انتظارها بشكل متزامن (تُنفَّذ بالتوازي عبر asyncio.gather) بحيث تتداخل أزمنتها المستجيب.

  1. حجج الإدخال:

    • يجب أن تقبل الدالة ما يلي كحجج مُسمّاة:

      • prompts (تحتوي على الأوامر)،
      • completions (تحتوي على الاكتمالات المولّدة)،
      • completion_ids (تحتوي على المكملات المُرمَّزة)،
      • trainer_state (TrainerState): الحالة الحالية للمدرّب. يمكن استخدام هذا لتنفيذ دوال مكافأة ديناميكية، مثل التعلم المنهجي (curriculum learning)، حيث يتم تعديل المكافأة بناءً على تقدم التدريب.
      • log_extra: دالة قابلة للاستدعاء log_extra(column: str, values: list) لإضافة أعمدة إضافية إلى جدول الاكتمالات. انظر إلى المثال 6.
      • log_metric: دالة قابلة للاستدعاء log_metric(name: str, value: float) لتسجيل مقاييس قياسية على شكل رسوم بيانية إلى جانب kl، entropy، وما إلى ذلك. راجع المثال 6.
      • environments: قائمة من أمثلة البيئة، مثال واحد لكل إكمال. لا تظهر إلا عند تقديم environment_factory. استخدم هذا لقراءة الحالة المتراكمة خلال الحلقة (مثل env.counter). للبيئات ذات الحالة، يُفضَّل ترك البيئة تمتلك المكافأة عبر طريقة get_reward بدلاً من ذلك — راجع المكافآت.
      • جميع أسماء الأعمدة (باستثناء prompt) التي قد يحتوي عليها مجموعة البيانات. على سبيل المثال، إذا كانت مجموعة البيانات تحتوي على عمود باسم ground_truth، فسيتم استدعاء الدالة مع ground_truth كحجة اسمية.

      أسهل طريقة للامتثال لهذا المتطلب هي استخدام **kwargs في توقيع الدالة.

    • يعتمد شكل المدخلات على صيغة مجموعة البيانات:

  2. القيمة المُعادَة: يجب أن تُعيد الدالة قائمة من الأرقام العشرية. يمثل كل رقم عشري المكافأة المقابلة لإكمال واحد.

المثال 1: مكافأة الإكمالات الأطول

فيما يلي مثال على دالة مكافأة لتنسيق قياسي يكافئ الإكمالات الأطول:

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]

يمكنك اختباره على النحو التالي:

>>> prompts = ["The sky is", "The sun is"]  # not used in the reward function, but the trainer will pass it
>>> completions = [" blue.", " 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]

المثال 1.1: مكافأة الإكمالات الأطول (بناءً على عدد الأحرف)

نفس المثال السابق، لكن هذه المرة تعتمد دالة المكافأة على عدد الأحرف بدلاً من الرموز.

def reward_func(completions, **kwargs):
    """Reward function that assigns higher scores to longer completions (in terms of character count)."""
    return [float(len(completion)) for completion in completions]

يمكنك اختباره على النحو التالي:

>>> prompts = ["The sky is", "The sun is"]
>>> completions = [" blue.", " in the sky."]
>>> completion_ids = [[6303, 13], [304, 279, 12884, 13]]  # not used in the reward function, but the trainer will pass it
>>> reward_func(prompts=prompts, completions=completions, completion_ids=completion_ids)
[6.0, 12.0]

المثال 2: مكافأة الإكمالات بصيغة محددة

فيما يلي مثال على دالة مكافأة تتحقق مما إذا كانت الإكمال (completion) يتبع تنسيقًا محددًا. استُوحِي هذا المثال من دالة format reward المستخدمة في ورقة DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning. تم تصميمها لتنسيق محادثة، حيث تتكون المحفزات (prompts) والإكمالات (completions) من رسائل منظمة.

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]

يمكنك اختبار هذه الدالة على النحو التالي:

>>> 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]

المثال 3: مكافأة الاكتمالات بناءً على مرجع

فيما يلي مثال على دالة مكافأة تتحقق من صحة الإكمال. يستلهم هذا المثال دالة مكافأة الدقة المستخدمة في ورقة DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning. تم تصميم هذا المثال لـ التنسيق القياسي، حيث يحتوي مجموعة البيانات على عمود باسم ground_truth.

import re

def reward_func(completions, ground_truth, **kwargs):
    # Regular expression to capture content inside \boxed{}
    matches = [re.search(r"\\boxed\{(.*?)\}", completion) 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)]

يمكنك اختبار هذه الدالة على النحو التالي:

>>> prompts = ["Problem: Solve the equation $2x + 3 = 7$. Solution:", "Problem: Solve the equation $3x - 5 = 10$."]
>>> completions = [r" The solution is \boxed{2}.", r" The solution is \boxed{6}."]
>>> ground_truth = ["2", "5"]
>>> reward_func(prompts=prompts, completions=completions, ground_truth=ground_truth)
[1.0, 0.0]

المثال 4: دوال المكافآت متعددة المهام

فيما يلي مثال على استخدام دوال مكافأة متعددة في GRPOTrainer. في هذا المثال، نعرّف دالتي مكافأة مخصصتين للمهام: math_reward_func وcoding_reward_func. تمنح math_reward_func مكافأة للمسائل الرياضية بناءً على صحتها، بينما تمنح coding_reward_func مكافأة لمسائل البرمجة بناءً على ما إذا كانت الحل يعمل.

from datasets import Dataset
from trl import GRPOTrainer

# Define a dataset that contains both math and coding problems
dataset = Dataset.from_list(
    [
        {"prompt": "What is 2+2?", "task": "math"},
        {"prompt": "Write a function that returns the sum of two numbers.", "task": "code"},
        {"prompt": "What is 3*4?", "task": "math"},
        {"prompt": "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
trainer = GRPOTrainer(
    model="Qwen/Qwen2.5-0.5B-Instruct",
    reward_funcs=[math_reward_func, coding_reward_func],
    train_dataset=dataset,
)

trainer.train()

في هذا المثال، صُمِّم math_reward_func وcoding_reward_func للعمل مع مجموعة بيانات مختلطة تحتوي على مسائل رياضية ومسائل برمجية. يُستخدم عمود task في مجموعة البيانات لتحديد دالة المكافأة التي يجب تطبيقها على كل مسألة. إذا لم تكن هناك دالة مكافأة ذات صلة لعينة في مجموعة البيانات، فإن دالة المكافأة ستعيد None، وسيواصل GRPOTrainer العمل بالدوال والمهام الصالحة. وهذا يتيح لـGRPOTrainer التعامل مع دوال مكافأة متعددة ذات نطاقات تطبيق مختلفة.

لاحظ أن GRPOTrainer سيتجاهل مكافآت None التي تُعاد من دوال المكافآت، وسيأخذ في الاعتبار فقط المكافآت التي تُعاد من الدوال ذات الصلة. وهذا يضمن تدريب النموذج على المهام ذات الصلة وتجاهل المهام التي لا توجد لها دالة مكافآت ذات صلة.

المثال 5: دوال المكافآت غير المتزامنة

يمكن أيضًا تعريف دوال المكافأة المخصصة كدوال async def غير متزامنة. وهذا مفيد إذا كانت مكافأتك تعتمد على عمليات إدخال/إخراج بطيئة (على سبيل المثال، استدعاء خدمة عن بُعد). عند تمرير عدة دوال مكافأة غير متزامنة، ينفذ GRPOTrainer هذه الدوال بشكل متوازٍ بحيث تتداخل أزمنه استجابتها.

فيما يلي مثال مبسّط لدالة مكافأة غير متزامنة تحاكي عملية تعتمد على الإدخال/الإخراج:

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]

المثال 6: تسجيل أعمدة ومؤشرات إضافية

فيما يلي مثال على دالة مكافأة تسجّل أعمدة إضافية في جدول الإكمالات والمقاييس القياسية على شكل رسوم بيانية.

import re

def reward_func(completions, ground_truth, log_extra=None, log_metric=None, **kwargs):
    extracted = [re.search(r"\\boxed\{(.*?)\}", c) for c in completions]
    extracted = [m.group(1) if m else None for m in extracted]
    rewards = [1.0 if e == gt else 0.0 for e, gt in zip(extracted, ground_truth)]

    if log_extra:
        log_extra("golden_answer", list(ground_truth))
        log_extra("extracted_answer", [e or "[none]" for e in extracted])

    if log_metric:
        log_metric("accuracy", sum(rewards) / len(rewards))

    return rewards

تمرير دالة المكافأة إلى المدرب

لاستخدام دالة المكافأة المخصصة الخاصة بك، قم بتمريرها إلى GRPOTrainer على النحو التالي:

from trl import GRPOTrainer

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

يمكنك تمرير عدة دوال مكافأة كقائمة؛ وقد تتضمن هذه القائمة دوالًا متزامنة وغير متزامنة على حد سواء:

from trl import GRPOTrainer

trainer = GRPOTrainer(
    reward_funcs=[reward_func, async_reward_func1, async_reward_func2],
    ...,
)

وستُحسب المكافأة على أنها مجموع المكافآت من كل دالة، أو المجموع الموزون إذا تم تقديم reward_weights في الإعدادات.

لاحظ أن GRPOTrainer يدعم دوال مكافأة متعددة من أنواع مختلفة. راجع توثيق المعلمات لمزيد من التفاصيل.

تنظيم الإنتروبيا

لشجيع الاستكشاف ومنع انهيار السياسة إلى مخرجات شبه حتمية، يمكنك إضافة مكافأة إنتروبيا إلى هدف التدريب. تعمل تنظيم الإنتروبيا على تعزيز خسارة GRPO على النحو التالي: L(θ)=LGRPO(θ)−α⋅H(πθ), \mathcal{L}(\theta) = \mathcal{L}_{\text{GRPO}}(\theta) - \alpha \cdot \mathcal{H}(\pi_\theta),

حيثH(πθ)\mathcal{H}(\pi_\theta) هو متوسط إنتروبيا الرمز الواحد للسياسة، وα\alpha هو معامل الإنتروبيا. المكافأة هي دائمًا متوسط إنتروبيا الرمز الواحد بغض النظر عن loss_type; ، فهي لا تُعاد مقياستها لتتوافق مع تطبيع السياسة الخاص بنوع الخسارة (مثل مقام batch_size * max_completion_length في Dr. GRPO)، لذا فإن entropy_coef يحمل نفس المعنى لجميع أنواع الخسارة.

إنتروبيا ثابتة — معامل ثابت طوال التدريب:

from trl import GRPOConfig, GRPOTrainer

training_args = GRPOConfig(entropy_coef=0.05, ...)

الإنتروبيا التكيفية — يتم تحديث المعامل في كل خطوة من خطوات المُحسِّن بناءً على إنتروبيا مستهدفة، كما تم تقديمه في Skywork-OR1. عندما تكون الإنتروبيا الحالية عند أو أقل من entropy_target، يتم زيادة المعامل بمقدار entropy_coef_delta؛ وإلا يتم إنقاصه. يُطبَّق المعامل (أي يكون غير صفري) فقط عندما تكون الإنتروبيا عند أو أقل من الهدف:

training_args = GRPOConfig(
    entropy_coef=0.01,          # initial coefficient
    use_adaptive_entropy=True,
    entropy_target=5.0,         # target mean per-token entropy (nats); tune for your model
    entropy_coef_delta=0.005,   # step size per optimizer step
    entropy_coef_min=0.0,
    entropy_coef_max=1.0,
    ...
)

تتميز نماذج اللغة النموذجية بإنثروبيا لكل رمز تتراوح بين 2 و10 نات، لذا فإن القيمة الافتراضية entropy_target=0.2 لا تُفعّل التنظيم تقريبًا أبدًا — إذ لا يعمل المكافأة إلا عندما تكون الإنثروبيا عند الهدف أو أدنى منه، أي عند الانهيار شبه الكامل. اضبطها على قيمة ذات معنى لنموذجك، مثلًا قريبة من الإنثروبيا التي تلاحظها في المراحل المبكرة من التدريب (المُسجَّلة كمقياس entropy). عند استخدام top_entropy_quantile < 1.0، تُطبَّق entropy_target على مجموعة الرموز ذات الإنثروبيا العالية — وستكون إنثروبيا هذه المجموعة أعلى من entropy المُسجَّلة لجميع الرموز، لذا اضبط الإعدادات وفقًا لذلك.

عند تعيين use_adaptive_entropy=True، يُحفظ معامل الإنتروبيا الحالي entropy_coef جنبًا إلى جنب مع كل نقطة تحقق، ويُستعاد عند الاستئناف، مما يجعل التدريب قابلاً للاستئناف بالكامل.

التجارب السريعة لـ GRPO

RapidFire AI هو محرك تجارب مفتوح المصدر يعمل فوق TRL ويتيح لك إطلاق عدة تكوينات GRPO في وقت واحد، حتى على وحدة معالجة رسومية واحدة. بدلاً من تجربة التكوينات بشكل تسلسلي، يتيح لك RapidFire رؤية منحنيات التعلم الخاصة بها جميعاً في وقت أبكر، وإيقاف التشغيلات ذات الأداء الضعيف، ونسخ الواعدة منها بإعدادات جديدة أثناء التنفيذ دون إعادة التشغيل. لمزيد من المعلومات، راجع تكامل RapidFire AI.

تدريب الوكيل

يدعم GRPO تدريب الوكلاء: حيث يستدعي النموذج الأدوات أثناء التوليد ويتعلم من النتيجة.

  • الأداة tool هي دالة بايثون بسيطة (متزامنة أو غير متزامنة) تُعرَض للنموذج. استخدم tools للاستدعاءات التي لا تعتمد على حالة (آلة حاسبة، بحث على الويب).
  • يُعدّ البيئة الشكل الأكثر شمولاً: فهو كائن ذو حالة يُنشأ من جديد لكل تمريرة، وتُعرض دواله العامة كأدوات، بالإضافة إلى خطاف دورة حياة reset وخطاف اختياري get_reward يتيح له امتلاك المكافأة. استخدم environment_factory عندما تحتاج إلى حالة لكل تمريرة، أو خطاف إعادة تعيين، أو مكافأة تملكها البيئة.

يمكنك دمجها — حيث يمكنك تمرير tools مستقلة جنبًا إلى جنب مع environment_factory.

الأدوات

يتوقع الحجة tools قائمة من دوال بايثون (متزامنة أو غير متزامنة) تُعرّف الأدوات المتاحة للوكيل:

from trl import GRPOTrainer

trainer = GRPOTrainer(
    tools=[tool1, tool2],
    ...,
)

يجب أن يكون كل أداة دالة بايثون قياسية مع حُجج وأنواع إرجاع مُعلَّمة بالنوع، إلى جانب سلسلة توثيق بنمط Google تصف غرضها وحُججها وقيمة الإرجاع. لمزيد من التفاصيل، راجد دليل تمرير الأدوات.

يتطلب حلقة استدعاء الأدوات في GRPO أن يكون قالب المحادثة حافظًا على البادئة (يجب ألا يؤدي إضافة رسالة أداة إلى تغيير طريقة عرض الرسائل السابقة). بالنسبة لعائلات النماذج المعروفة (مثل Qwen3 وDeepSeek-V3)، تقوم TRL تلقائيًا باستبدال قالب التدريب المُصلَح عند تمكين الأدوات. راجع قوالب المحادثة للحصول على القائمة الكاملة.

استخدم max_tool_calling_iterations في GRPOConfig لتحديد الحد الأقصى لعدد جولات استدعاء الأدوات. افتراضيًا، لا يوجد حد، ويتوقف التوليد عندما ينتج النموذج ردًا لا يتضمن أي استدعاءات للأدوات.

مثال:

from trl import GRPOTrainer

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 = GRPOTrainer(
    tools=[multiply, async_add],
    ...,
)

البيئات

يمكنك أيضًا توفير الأدوات من خلال environment_factory. في هذا الوضع، يقوم GRPOTrainer بإنشاء نسخة واحدة من البيئة لكل تمريرة (rollout) ويعرض الدوال العامة للبيئة كأدوات.

يتطلب environment_factory وجود transformers>=5.2.0.

عند استخدام environment_factory، تمتلك البيئة البيانات: فلا يوجد train_dataset خارجي. في كل تمريرة، يُنتج reset() المهمة — إما عبر أخذ عينات ذاتية من مجموعة نصوص تحتفظ بها البيئة، أو عبر توليد حالة إجرائياً — ويعيد الموجه. يحدد max_steps طول التدريب. فيما يلي مثال مبسط لبيئة تأخذ عينات ذاتية من هدف وتعرض طريقة increment (مُعرَّضة كأداة).

import random

from trl import GRPOConfig, GRPOTrainer

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

trainer = GRPOTrainer(
    model="Qwen/Qwen3-0.6B",
    args=GRPOConfig(max_steps=1000, chat_template_kwargs={"enable_thinking": False}),
    environment_factory=IncrementEnv,
)
trainer.train()

تحتوي فئة البيئة على طريقتين محجوزتين: reset وget_reward. على عكس أي طرق عامة أخرى، لا تُعرَض هذه الطرق للنموذج كأدوات.

  • يُستدعى reset (إلزامي) عند بدء التمرين. يمكن أن يعيد None أو نصًا. في GRPO، عندما يعيد نصًا، يكون ذلك النص هو موجه المستخدم.
  • get_reward (اختياري، متزامن أو غير متزامن) لا يستقبل أي حجة ويعيد قيمة من نوع float: حيث يقوم البيئة بتقييم الحلقة التي أكّدها للتو بناءً على حالته الداخلية (هل انتهت اللعبة بفوز؟ هل تم تخمين الكلمة؟). يُستدعى مرة واحدة لكل تمريرة مكتملة ويعمل كمصدر للمكافأة.

بما أن البيئة تُعيد أخذ العينات من نفسها عند كل reset()، فقد لا تتشارك أعضاء مجموعة GRPO الـG نفس الحالة الأولية، مما يجعل خط الأساس للمجموعة أكثر ضوضاءً قليلاً. للحصول على حالات متطابقة داخل المجموعة، اجعل reset() يُشتق الحالة بشكل حتمي من مفتاح مشترك.

توفير مجموعة بيانات خارجية (اختياري)

بدلاً من السماح للبيئة بأخذ عينات ذاتية، يمكنك توفير train_dataset خارجي. على سبيل المثال، عندما تكون مهامك موجودة بالفعل في مجموعة بيانات، أو للتوجيه بين بيئات متعددة. في كل تمريرة تدريبية، يأخذ المدرب صفًا واحدًا، ويستخدم عموده "prompt" كموجّه، ويمرر أعمدة الصف الأخرى إلى reset() كحجج باسم (حتى تقرأ البيئة المهمة من مجموعة البيانات).

from datasets import Dataset
from trl import GRPOTrainer

# 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

trainer = GRPOTrainer(
    model="Qwen/Qwen3-0.6B",
    train_dataset=dataset,  # the dataset owns the task; the "target" column reaches reset(target=...)
    environment_factory=IncrementEnv,
)
trainer.train()

المكافآت

لا تتعارض المكافآت التي يديرها البيئة مع المكافآت التي يديرها المدرب. مرّر reward_funcs للمكافآت التي يُعدّ حسابها من الإكمال أمراً طبيعياً (مثل فحص التنسيق على النص) و اترك البيئة تُرجع مكافأتها المعتمدة على حالتها عبر get_reward. تُجمع جميع المصادر؛ reward_weights ينطبق على reward_funcs فقط (البيئة تملك مقياسها الخاص).

def format_reward(completions, **kwargs):  # trainer-owned: scores the completion text
    ...

trainer = GRPOTrainer(
    model="Qwen/Qwen3-0.6B",
    args=GRPOConfig(max_steps=1000),
    reward_funcs=format_reward,          # trainer-owned: scores the completion
    environment_factory=IncrementEnv,    # env-owned: scores its internal state via `get_reward`
)

يمكن لـ reward_func أيضاً قراءة حالة البيئة مباشرة: عند تعيين environment_factory، يمرّن المدرب معامل environments (نسخة واحدة لكل إكمال). قد يكون هذا مفيداً في بعض الأحيان، لكن تفضّل استخدام get_reward للمكافآت المعتمدة على الحالة.

يعمل هذا بنفس الطريقة تمامًا مع AsyncGRPOTrainer.

بيئات متعددة

لتدريب النموذج على مزيج من المهام في تشغيل واحد (مثل مهمة برمجة ولعبة)، مرر قاموسًا يربط أسماء البيئات بمصانعها بدلاً من دالة قابلة للاستدعاء واحدة. يختار كل تمرين بيئته عبر حقل environment في مجموعة البيانات، وتُعرض أدوات تلك البيئة فقط. يتجنب هذا تسريب أدوات غير ذات صلة (أداة move الخاصة باللعبة إلى مثال برمجي، والعكس صحيح). ما تزال كل بيئة تمتلك بياناتها وتعيد الموجه من reset()، لذا لا تحتاج مجموعة البيانات سوى عمود environment للتوجيه بينها.

import random

from datasets import Dataset
from trl import GRPOConfig, GRPOTrainer


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
dataset = Dataset.from_dict({"environment": ["coding", "game"] * 500})

trainer = GRPOTrainer(
    model="Qwen/Qwen3-0.6B",
    args=GRPOConfig(chat_template_kwargs={"enable_thinking": False}),
    train_dataset=dataset,
    reward_funcs=reward_func,
    environment_factory={"coding": CodingEnv, "game": GameEnv},
)
trainer.train()

لا تزال دالة المكافأة تستقبل بيئة كل مثال عبر reward_kwargs["environments"]، مما يتيح لها التفرع بناءً على نوع البيئة (مثل isinstance(env, CodingEnv)). تُعاد استخدام أمثلة البيئة عبر الخطوات (مع إعادة الضبط بين الحلقات)، لذا يُدفع ثمن __init__ المكلف مرة واحدة بدلاً من كل خطوة. يُستهلك حقل environment من قِبل المدرب ولا يُمرَّر إلى reset.

استجابات الأدوات متعددة الوسائط

يمكن للأدوات إرجاع الصور إلى جانب النص عن طريق إرجاع قائمة من كتل المحتوى. وهذا مفيد لتدريب وكلاء نماذج اللغة المرئية (VLM) حيث يوفر الأداة تغذية راجعة بصرية (مثل لقطات الشاشة، والمخططات، والتقاطات الكاميرا).

from PIL import Image

def take_screenshot() -> list:
    """
    Takes a screenshot of the current screen.

    Returns:
        The screenshot image with a description.
    """
    img = Image.open("screenshot.png")
    return [{"type": "image", "image": img}, {"type": "text", "text": "Here is the screenshot."}]

تُحقن الصور المُعادَة تلقائيًا في المحادثة وتُمرَّر إلى VLM لجولات التوليد اللاحقة.

النماذج المدعومة

تم الاختبار مع:

  • Beam — على سبيل المثال، reflection/Beam-1.0-501B-A23B
  • DeepSeek-R1 — على سبيل المثال، deepseek-ai/DeepSeek-R1
  • Gemma4 — على سبيل المثال، google/gemma-4-E2B-it
  • GLM-4-MoE (4.5 أو 4.6 أو 4.7) — على سبيل المثال zai-org/GLM-4.7
  • GPT-OSS — على سبيل المثال، openai/gpt-oss-20b
  • Llama 3.1 — على سبيل المثال، meta-llama/Llama-3.1-8B-Instruct
  • Llama 3.2 — على سبيل المثال، meta-llama/Llama-3.2-3B-Instruct
  • Qwen2.5 — على سبيل المثال، Qwen/Qwen2.5-0.5B-Instruct
  • Qwen3 — على سبيل المثال، Qwen/Qwen3-0.6B
  • Qwen3-VL — على سبيل المثال، Qwen/Qwen3-VL-2B-Instruct
  • Qwen3.5 — على سبيل المثال، Qwen/Qwen3.5-2B
  • Qwen3.6 — على سبيل المثال، Qwen/Qwen3.6-35B-A3B

لا يُكفَل التوافق مع جميع نماذج اللغة الكبيرة. إذا كنت تعتقد أنه ينبغي دعم نموذج معين، فلا تتردد في فتح مشكلة على GitHub — أو الأفضل من ذلك، تقديم طلب سحب يتضمن التغييرات المطلوبة.

التكاملات مع البيئات

تتصل جميع البيئات بنفس خانة environment_factory، لذا فهي قابلة للاستبدال على مستوى TRL — اختر البيئة التي يناسب نظامها البيئي مهمتك:

التكاملما هواستخدمه عندما
OpenEnvمعيار البيئة المفتوحة (واجهة برمجة تطبيقات بأسلوب Gymnasium، تُقدَّم عبر WebSocket أو التنفيذ المُحاوِر)، مدعوم من Hugging Face والمجتمع.أنت تستخدم بيئة OpenEnv جاهزة من Hub، أو تُعرّف بيئتك الخاصة وفقًا للمعيار المفتوح (مثل Wordle وSudoku وCatch).
OpenRewardتكامل مع بيئات تدعم لغة ORS (كتالوج openreward.ai أو خادم ORS الخاص بك)؛ حيث تُقدَّم المهام و المكافآت عبر HTTP.تريد التدريب في بيئة ORS: الكتالوج (مثل Eigent/SETA)، أو بيئة تستضيفها بنفسك على بنيتك التحتية، أو خادم محلي تقوم بتطويره.
Harborتكامل مع مجموعات مهام Harbor: كل مهمة هي تعليمات، صورة رملية حقيقية (docker، e2b، …)، ومُتحقِّق داخل البيئة الرملية.تريد التدريب مقابل مجموعة مهام Harbor: وهي شجرة من المهام، كل منها عبارة عن بيئة معزولة مكتفية ذاتياً بالإضافة إلى مُتحقق (على سبيل المثال، وكيل تحليل بيانات يستكشف الملفات داخل بيئة معزولة ويكتب إجابة يتحقق منها مُقيّم).

تدريب نماذج اللغة البصرية

GRPO يدعم تدريب نماذج الرؤية واللغة (VLMs) على مجموعات بيانات متعددة الوسائط تحتوي على نص وصور.

النماذج المدعومة

تم الاختبار مع:

  • Gemma3 — على سبيل المثال، google/gemma-3-4b-it
  • LLaVA-NeXT — على سبيل المثال، llava-hf/llava-v1.6-mistral-7b-hf
  • Qwen2-VL — على سبيل المثال، Qwen/Qwen2-VL-2B-Instruct
  • Qwen2.5-VL — على سبيل المثال، Qwen/Qwen2.5-VL-3B-Instruct
  • SmolVLM2 — على سبيل المثال، HuggingFaceTB/SmolVLM2-2.2B-Instruct

لا يُكفَل التوافق مع جميع نماذج VLM. إذا كنت تعتقد أنه ينبغي دعم نموذج معين، فلا تتردد في فتح مشكلة على GitHub — أو الأفضل من ذلك، تقديم طلب سحب يتضمن التغييرات المطلوبة.

البدء السريع

استخدم grpo_vlm.py لضبط نموذج VLM. مثال على الأمر للتدريب على lmms-lab/multimodal-open-r1-8k-verified:

accelerate launch \
  --config_file=examples/accelerate_configs/deepspeed_zero3.yaml \
  examples/grpo_visual_math/grpo_visual_math.py \
  --model_name_or_path Qwen/Qwen2.5-VL-3B-Instruct \
  --output_dir grpo-Qwen2.5-VL-3B-Instruct \
  --learning_rate 1e-5 \
  --dtype bfloat16 \
  --max_completion_length 1024 \
  --use_vllm \
  --vllm_mode colocate \
  --use_peft \
  --lora_target_modules "q_proj", "v_proj" \
  --log_completions

نصائح حول التهيئة

  • استخدام LoRA على طبقات الإسقاط الخاصة بلغة الرؤية
  • تفعيل التكميم بدقة 4 بت لتقليل استهلاك الذاكرة
  • تستهلك نماذج اللغة المرئية (VLMs) ذاكرة كبيرة — ابدأ بحجم دفعات أصغر
  • تتوافق معظم النماذج مع vLLM (أوضاع server وcolocate)

تنسيق مجموعة البيانات

يجب أن يتضمن كل عينة تدريب:

  • prompt: نص منسّق عبر قالب المحادثة الخاص بالمعالج
  • image/images: صورة PIL أو قائمة بصور PIL

يتولى المدرب تلقائياً تحويل الصور إلى متجهات (تensors) عبر معالج الصور الخاص بالنموذج.

GRPOTrainer

فئة trl.GRPOTrainer

< >

( model: str | PreTrainedModel | PeftModelreward_funcs: str | transformers.modeling_utils.PreTrainedModel | collections.abc.Callable[..., list[float | None]] | list[str | transformers.modeling_utils.PreTrainedModel | collections.abc.Callable[..., list[float | None]]] | None = Noneargs: trl.trainer.grpo_config.GRPOConfig | None = Nonetrain_dataset: datasets.arrow_dataset.Dataset | datasets.iterable_dataset.IterableDataset | None = Noneeval_dataset: datasets.arrow_dataset.Dataset | datasets.iterable_dataset.IterableDataset | datasets.dataset_dict.DatasetDict | datasets.dataset_dict.IterableDatasetDict | dict[str, datasets.arrow_dataset.Dataset | datasets.iterable_dataset.IterableDataset] | None = Noneprocessing_class: transformers.tokenization_utils_base.PreTrainedTokenizerBase | transformers.processing_utils.ProcessorMixin | None = Nonereward_processing_classes: transformers.tokenization_utils_base.PreTrainedTokenizerBase | list[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)quantization_config: BitsAndBytesConfig | None = Nonepeft_config: PeftConfig | None = Nonetools: list[collections.abc.Callable] | None = Nonerollout_func: collections.abc.Callable[[list[str], 'GRPOTrainer'], dict[str, typing.Any]] | None = Noneenvironment_factory: collections.abc.Callable[[], trl.trainer.grpo_trainer._SupportsReset] | dict[str, collections.abc.Callable[[], trl.trainer.grpo_trainer._SupportsReset]] | None = None )

المعاملات

  • model (str أو PreTrainedModel أو PeftModel) — النموذج المراد تدريبه. يمكن أن يكون أحد ما يلي:
    • سلسلة نصية، تكون معرف النموذج لنموذج مُدرَّب مسبقًا مستضاف داخل مستودع نماذج على huggingface.co، أو مسارًا إلى مجلد يحتوي على أوزان النموذج المحفوظة باستخدام save_pretrained، مثل './my_model_directory/'. يتم تحميل النموذج باستخدام <ModelArchitecture>.from_pretrained (حيث يُشتق <ModelArchitecture> من إعدادات النموذج) مع الحُجج المُسمّاة الموجودة في args.model_init_kwargs. إذا لم يُحدد dtype في args.model_init_kwargs، فإن القيمة الافتراضية هي float32. وهذا يختلف عن from_pretrained، حيث (منذ Transformers v5) يُستنتج نوع البيانات من إعدادات النموذج.
    • كائن PreTrainedModel. يتم دعم نماذج اللغة السببية فقط.
    • كائن PeftModel. يتم دعم نماذج اللغة السببية فقط.
  • reward_funcs (RewardFunc | list[RewardFunc], اختياري) — دوال المكافأة المستخدمة لحساب المكافآت. لحساب المكافآت، نستدعي جميع دوال المكافأة باستخدام الأوامر (prompts) والإكمالات (completions) ثم نجمع المكافآت. يمكن ترك هذا الحقل فارغًا عندما تُوفَّر المكافأة من خلال البيئة عبر environment_factory (فيما يلي. يمكن أن يكون:
    • دالة مكافأة واحدة، مثل:

      • A string: The model ID of a pretrained model hosted inside a model repo on huggingface.co, or a path to a directory containing model weights saved using save_pretrained, e.g., './my_model_directory/'. The model is loaded using from_pretrained with num_labels=1 and the keyword arguments in args.model_init_kwargs.

      • كائن PreTrainedModel: يتم دعم نماذج تصنيف التسلسل فقط.

      • دالة مكافأة مخصصة: تُزوَّد الدالة بالموجِّهات (prompts) والإكمالات المولَّدة، بالإضافة إلى أي أعمدة إضافية في مجموعة البيانات. يجب أن تُرجع قائمة بالمكافآت. يمكن أن تكون دوال المكافأة المخصصة متزامنة أو غير متزامنة، كما يمكنها إرجاع None عندما لا تنطبق المكافأة على تلك العينات. وهذا مفيد في التدريب متعدد المهام حيث تنطبق دوال مكافأة مختلفة على أنواع مختلفة من العينات. عندما تُرجع دالة المكافأة None لعينة معينة، تُستبعد تلك الدالة من حساب المكافأة لتلك العينة. لمزيد من التفاصيل، راجع استخدام دالة مكافأة مخصصة.

        يتم تمرير حالة المدرب أيضًا إلى دالة المكافأة. حالة المدرب هي نسخة من TrainerState ويمكن الوصول إليها عن طريق الوصول إلى الحجة trainer_state في توقيع دالة المكافأة.

    • قائمة من دوال المكافأة، حيث يمكن أن يكون كل عنصر بشكل مستقل أيًا من الأنواع المذكورة أعلاه. يُسمح بخلط أنواع مختلفة داخل القائمة (مثل معرّف نموذج نصي ودالة مكافأة مخصصة).

  • args (GRPOConfig، اختياري) — إعدادات هذا المدرب. إذا كانت None، يتم استخدام إعداد افتراضي.
  • train_dataset (Dataset أو IterableDataset, اختياري) — مجموعة البيانات المستخدمة للتدريب. يجب أن تتضمن عمودًا "prompt". تُتجاهل أي أعمدة إضافية في مجموعة البيانات. يمكن أن يكون تنسيق العينات إما:
    • قياسي: يحتوي كل عينة على نص عادي.
    • حواري: تحتوي كل عينة على رسائل منظمة (مثل الدور والمحتوى).

    يمكن حذفه فقط عند توفير environment_factory وامتلاك البيئة (أو توليدها إجرائيًا) للبيانات، مع إرجاع الأمر التوجيهي من طريقة reset() الخاصة بها. في هذه الحالة، يجب تعيين max_steps لتحديد مدة التدريب.

    عندما يكون train_dataset من نوع IterableDataset (مثل مجموعة بيانات التدفق)، يجب تعيين max_steps في حُجج التدريب، لأن طولها لا يمكن استنتاجه، ويُطلب تحديد إجمالي عدد خطوات التدريب لتحديد نطاق حلقة التدريب وإعداد مجدول معدل التعلم.

  • eval_dataset (Dataset أو IterableDataset أو DatasetDict أو IterableDatasetDict أو dict[str, Dataset | IterableDataset]) — مجموعة البيانات المستخدمة للتقييم. يجب أن تستوفي نفس المتطلبات التي تستوفيها train_dataset.
  • processing_class (PreTrainedTokenizerBase، ProcessorMixin، اختياري) — فئة المعالجة المستخدمة لمعالجة البيانات. يجب ضبط جانب الحشو على “يسار”. إذا كانت None، يتم تحميل فئة المعالجة من اسم النموذج باستخدام from_pretrained. يجب ضبط رمز الحشو، tokenizer.pad_token. إذا لم تضبط فئة المعالجة رمز الحشو، سيتم استخدام tokenizer.eos_token كقيمة افتراضية.
  • reward_processing_classes (PreTrainedTokenizerBase أو list[PreTrainedTokenizerBase], اختياري) — فئات المعالجة المقابلة لدوال المكافأة المحددة في reward_funcs. يمكن أن تكون إما:
    • فئة معالجة واحدة: تُستخدم عندما يحتوي reward_funcs على دالة مكافأة واحدة فقط.
    • قائمة من فئات المعالجة: يجب أن تتطابق مع ترتيب وطول دوال المكافآت في reward_funcs. إذا تم ضبطها على None، أو إذا كان عنصر في القائمة يقابل PreTrainedModel هو None، يتم تحميل مُرمّز النموذج تلقائيًا باستخدام from_pretrained. بالنسبة للعناصر في reward_funcs التي هي دوال مكافآت مخصصة (ليست PreTrainedModel)، يتم تجاهل الإدخالات المقابلة في reward_processing_classes.
  • callbacks (قائمة من TrainerCallback, اختياري) — قائمة من استدعاءات المراجعة (callbacks) لتخصيص حلقة التدريب. ستُضاف هذه الاستدعاءات إلى قائمة استدعاءات المراجعة الافتراضية المفصّلة هنا.

    إذا كنت ترغب في إزالة أحد المراجعات الافتراضية المستخدمة، فاستخدم طريقة remove_callback.

  • optimizers (tuple[torch.optim.Optimizer | None, torch.optim.lr_scheduler.LambdaLR | None]، اختياري، القيمة الافتراضية (None, None)) — مجموعة (tuple) تحتوي على المُحسِّن (optimizer) والمُجدوِل (scheduler) المطلوبين للاستخدام. ستكون القيمة الافتراضية هي نسخة من AdamW على النموذج الخاص بك، مع مُجدوِل يُحدده get_linear_schedule_with_warmup ويُتحكم به عبر args.
  • quantization_config (BitsAndBytesConfig، اختياري) — إعدادات التكميم المستخدمة عند تحميل النموذج من معرّف النموذج. ادمجها مع peft_config لتدريب QLoRA. يتم تجاهلها إذا كان النموذج مُنشأً بالفعل.
  • peft_config (PeftConfig، اختياري) — إعدادات PEFT المستخدمة لتغليف النموذج. إذا كانت None، فلن يتم تغليف النموذج.
  • tools (قائمة من Callable، اختياري) — قائمة من دوال الأدوات القابلة للاستدعاء (مزامنة أو غير مزامنة) التي يمكن للنموذج استدعاؤها أثناء التوليد. يجب أن تكون كل أداة دالة بايثون قياسية مع حُجج وقيم إرجاع مُعلَّمة الأنواع بشكل صحيح، وتعليق مستند بنمط Google يصف غرضها وحُججها وقيمة الإرجاع. لمزيد من التفاصيل، راجع: https://huggingface.co/docs/transformers/en/chat_extras#passing-tools. يستخدم النموذج اسم الدالة، وتلميحات الأنواع، وتعليق المستند لتحديد كيفية استدعائها. تأكد من أن قالب الدردشة الخاص بالنموذج يدعم استخدام الأدوات وأنه تم ضبطه الدقيق (fine-tuned) لاستدعاء الأدوات.
  • rollout_func (RolloutFunc، اختياري) — الدالة المستخدمة لتوليد الإكمالات. تستقبل قائمة الأوامر المخصصة للعملية الحالية ومثال المدرب. يجب أن تعيد قاموسًا يحتوي على الحقول "prompt_ids" و"completion_ids" و "logprobs"، ويمكنها اختيارًا أن تعيد "logprob_token_ids" (بنفس الشكل مثل "logprobs"). تُمرَّر أي حقول أخرى إلى دوال المكافأة. تستقبل الدالة شريحة الأوامر الخام لكل عملية دون تكرار؛ وهي مسؤولة عن إرجاع العدد الصحيح من الإكمالات لكل أمر (انظر num_generations / num_generations_eval على المدرب). هذه الميزة تجريبية وقد تتغير أو تُحذف في أي وقت دون إشعار مسبق.
  • environment_factory (EnvironmentFactory أو dict[str, EnvironmentFactory], اختياري) — دالة قابلة للاستدعاء تنشئ وتعيد نسخة من البيئة، أو قاموس يربط أسماء البيئات بدوال قابلة للاستدعاء من هذا النوع. يجب أن تعرّف فئة البيئة طرقًا يمكن استدعاؤها كأدوات أثناء التوليد. يجب أن تلتزم كل طريقة بنفس المتطلبات الخاصة بـ tools الموصوفة أعلاه. كما يجب على البيئة أن تنفّذ دالة قابلة للاستدعاء باسم reset يمكن استخدامها لإعادة تعيين الحالة بين عمليات التوليد. يجب أن تعيد دالة reset إما None أو نصًا: عند إرجاع نص، يُضاف هذا النص إلى آخر رسالة مستخدم قبل التوليد. كما يمكن للبيئة أن تعرّف دالة get_reward لا تتخذ أي حجة وتعيد قيمة من نوع float: عند وجودها، تمتلك البيئة المكافأة، وتُستدعى get_reward مرة واحدة لكل تمريرة مكتملة لتقييمها من الحالة الداخلية للبيئة. تعمل كمصدر مكافأة إضافي (بوزن 1، ويُسجَّل باسم فئة البيئة) إلى جانب reward_funcs, الذي يصبح اختياريًا في هذه الحالة.

    باستخدام دالة قابلة للاستدعاء واحدة، يستخدم كل مثال نفس البيئة، مع وجود نسخة واحدة لكل تمرين حتى تبقى تفاعلاتها معزولة. أما عند استخدام قاموس، فيجب أن يحمل كل مثال حقل environment لاختيار بيئته بالاسم، ولا تُعرض في موجهه إلا أدوات تلك البيئة — مما يتيح لتمرين واحد خلط المهام (مثل بيئة برمجة وبيئة لعبة). هذه الميزة تجريبية وقد تتغير أو تُحذف في أي وقت دون إشعار مسبق.

Trainer for the Group Relative Policy Optimization (GRPO) method. This algorithm was initially proposed in the paper DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models.

مثال:

>>> from trl import GRPOTrainer
>>> from trl.rewards import accuracy_reward
>>> from datasets import load_dataset

>>> dataset = load_dataset("trl-lib/DeepMath-103K", split="train")

>>> trainer = GRPOTrainer(
...     model="Qwen/Qwen2.5-0.5B-Instruct",
...     reward_funcs=accuracy_reward,
...     train_dataset=dataset,
... )
>>> trainer.train()

تدريب

< >

( resume_from_checkpoint: str | bool | None = Nonetrial: optuna.Trial | dict[str, Any] | None = Noneignore_keys_for_eval: list[str] | None = None ) → ~trainer_utils.TrainOutput

المعاملات

  • resume_from_checkpoint (str أو bool، اختياري) — إذا كان str، فهو المسار المحلي لنقطة تفتيش محفوظة بواسطة نسخة سابقة من Trainer. وإذا كان bool ويساوي True، يتم تحميل آخر نقطة تفتيش في args.output_dir كما حفظتها نسخة سابقة من Trainer. إذا كانت موجودة، فسيستأنف التدريب من حالات النموذج/المُحسِّن/المُجدوِل المحمَّلة هنا.
  • trial (optuna.Trial أو dict[str, Any]، اختياري) — التجربة أو قاموس المعاملات الفائقة للبحث في المعاملات الفائقة.
  • ignore_keys_for_eval (list[str]، اختياري) — قائمة بالمفاتيح في مخرجات النموذج الخاص بك (إذا كان قاموسًا) التي يجب تجاهلها عند جمع التوقعات للتقييم أثناء التدريب.

يعيد

~trainer_utils.TrainOutput

كائن يحتوي على عدد الخطوات العالمية، وخسارة التدريب، والمقاييس.

نقطة الدخول الرئيسية للتدريب.

save_model

< >

( output_dir: str | None = None_internal_call: bool = False )

سيحفظ النموذج، بحيث يمكنك إعادة تحميله باستخدام from_pretrained().

سيتم الحفظ من العملية الرئيسية فقط.

push_to_hub

< >

( commit_message: str | None = 'End of training'blocking: bool = Truetoken: str | None = Nonerevision: str | None = None**kwargs )

المعاملات

  • commit_message (str، اختياري، الافتراضي "End of training") — الرسالة التي تُرسل عند الدفع.
  • blocking (bool، اختياري، الافتراضي True) — ما إذا كان ينبغي للدالة أن تُرجع فقط بعد اكتمال git push.
  • token (str، اختياري، القيمة الافتراضية None) — رمز (Token) يملك صلاحية الكتابة لتجاوز الحجج الأصلية الخاصة بـ Trainer.
  • revision (str، اختياري) — مراجعة git التي سيتم الالتزام منها. الافتراضي هو رأس فرع “main”.
  • kwargs (dict[str, Any]، اختياري) — معلمات إضافية تُمرَّر إلى ~Trainer.create_model_card.

ارفع self.model وself.processing_class إلى مركز النماذج 🤗 في المستودع self.args.hub_model_id.

GRPOConfig

فئة trl.GRPOConfig

< >

( 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: transformers.trainer_utils.SchedulerType | str = 'linear'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 = 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 = 10logging_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 = Falserestore_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 | None = 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 = Nonetrust_remote_code: bool = Falserouter_aux_loss_coef: float | None = Nonedisable_dropout: bool = Falsecast_lm_head_to_fp32: bool = Falsenum_generations: int | None = 8num_generations_eval: int | None = Nonemax_completion_length: int | None = 512ds3_gather_for_generation: bool = Trueshuffle_dataset: bool | None = Truepad_to_multiple_of: int | str | None = 'auto'generation_batch_size: int | None = Nonesteps_per_generation: int | None = Nonetemperature: float = 1.0top_p: float = 1.0top_k: int = 0min_p: float | None = Nonegeneration_kwargs: dict | str | None = Nonechat_template_kwargs: dict | str | None = Nonerepetition_penalty: float = 1.0cache_implementation: str | None = Noneuse_vllm: bool = Falsevllm_mode: str = 'colocate'vllm_model_impl: str = 'vllm'vllm_enable_sleep_mode: bool = Falsevllm_structured_outputs_regex: str | None = Nonevllm_server_base_url: str | None = Nonevllm_server_host: str = '0.0.0.0'vllm_server_port: int = 8000vllm_server_timeout: float = 240.0vllm_group_port: int = 51216vllm_gpu_memory_utilization: float = 0.3vllm_max_model_length: int | None = Nonevllm_tensor_parallel_size: int = 1beta: float = 0.0num_iterations: int = 1epsilon: float = 0.2delta: float | None = Noneepsilon_high: float | None = Nonesapo_temperature_neg: float = 1.05sapo_temperature_pos: float = 1.0vespo_k_pos: float = 2.0vespo_lambda_pos: float = 3.0vespo_k_neg: float = 3.0vespo_lambda_neg: float = 2.0importance_sampling_level: str = 'token'reward_weights: list[float] | None = Nonemulti_objective_aggregation: str = 'sum_then_normalize'scale_rewards: str = 'group'loss_type: str = 'dapo'mask_truncated_completions: bool = Falsesync_ref_model: bool = Falseref_model_mixup_alpha: float = 0.6ref_model_sync_steps: int = 512top_entropy_quantile: float = 1.0entropy_coef: float = 0.0use_adaptive_entropy: bool = Falseentropy_coef_min: float = 0.0entropy_coef_max: float = 1.0entropy_coef_delta: float = 0.005entropy_target: float = 0.2max_tool_calling_iterations: int | None = Nonevllm_importance_sampling_correction: bool = Truevllm_importance_sampling_mode: str = 'sequence_mask'vllm_importance_sampling_clip_max: float | None = 3.0vllm_importance_sampling_clip_min: float | None = Noneoff_policy_mask_threshold: float | None = Noneuse_bias_correction_kl: bool = Truelog_completions: bool = Falselog_multimodal: bool = Truenum_completions_to_print: int | None = Nonelog_unique_prompts: bool = Falselog_completions_hub_repo: str | None = Noneuse_transformers_continuous_batching: bool = Falsetransformers_continuous_batching_config: dict | str | None = Noneuse_transformers_paged: bool = Falsevllm_importance_sampling_cap: float | None = None )

المعاملات التي تتحكم في النموذج ونموذج المرجع

  • model_init_kwargs (str أو dict[str, Any]، اختياري) — حجج الكلمات المفتاحية لـ from_pretrained، تُستخدم عندما يُقدَّم معامل model الخاص بـ GRPOTrainer كنص. كما يُستخدم قيمة revision عند تحميل فئات المعالجة.
  • trust_remote_code (bool, optional, defaults to False) — Whether to allow loading models and tokenizers that ship custom Python code from the Hub. Forwarded to from_pretrained and from_pretrained. Also applied to reward-model and reward-tokenizer loads.
  • router_aux_loss_coef (float, اختياري) — معامل خسارة التوازن على الأحمال المساعدة لنماذج مزيج الخبراء (MoE)، تُضاف إلى خسارة التدريب بهذا الوزن. عند عدم تعيينه، يُستخدم القيمة المُعلنة في إعدادات النموذج. عيّن 0.0 لتعطيله. يفشل عند استخدامه مع نموذج غير MoE.
  • disable_dropout (bool، اختياري، القيمة الافتراضية False) — ما إذا كان سيتم تعطيل إسقاط العينة (dropout) في النموذج. هذا مفيد للتدريب مع نموذج مرجعي، حيث يمنع النموذج من توليد احتمالات سجلات (logprobs) مختلفة لنفس المدخل.
  • cast_lm_head_to_fp32 (bool، اختياري، القيمة الافتراضية False) — ما إذا كان سيتم تحويل رأس نمذجة اللغة (language modeling head) في نموذجي السياسة والمرجع إلى float32. كما يوصي به وصفة ScaleRL. يُدعم هذا العلم فقط عندما يحتوي النموذج على طبقات مدمجة للكلمات (word embedding) ورأس نمذجة اللغة غير مرتبطة ببعضهما، أي أن tie_word_embeddings في إعدادات النموذج تساوي False.

المعاملات التي تتحكم في معالجة البيانات المسبقة

  • remove_unused_columns (bool، اختياري، القيمة الافتراضية False) — ما إذا كان يجب الإبقاء على العمود "prompt" فقط في مجموعة البيانات. إذا كنت تستخدم دالة مكافأة مخصصة تتطلب أي عمود غير "prompts" و"completions"، فيجب عليك إبقاء هذا الإعداد على False.
  • num_generations (int, اختياري, القيمة الافتراضية هي 8) — عدد الأجيال لكل موجه يُسحب. يجب أن يكون حجم الدفعة الفعّال (num_processes * per_device_batch_size * gradient_accumulation_steps) قابلاً للقسمة على هذه القيمة دون باقي.
    • gradient_accumulation_steps) يجب أن يكون قابلاً للقسمة على هذا القيمة.
  • num_generations_eval (int, اختياري) — عدد الأجيال التي سيتم أخذ عينات منها أثناء التقييم. يتيح ذلك استخدام عدد أقل من الأجيال أثناء التقييم لتوفير الحسابات. إذا كان None، يتم استخدام قيمة num_generations.
  • max_completion_length (int أو None، اختياري، القيمة الافتراضية 512) — الحد الأقصى لطول الإكمال المولّد.
  • ds3_gather_for_generation (bool، اختياري، القيمة الافتراضية True) — تنطبق هذه الإعدادات على DeepSpeed ZeRO-3. إذا تم تفعيلها، يتم تجميع أوزان نموذج السياسة للتوليد، مما يحسّن سرعة التوليد. ومع ذلك، فإن تعطيل هذا الخيار يتيح تدريب نماذج تتجاوز سعة ذاكرة VRAM لبطاقة رسومات واحدة، على الرغم من أن ذلك يأتي على حساب بطء التوليد. لا يتوافق تعطيل هذا الخيار مع توليد vLLM.
  • shuffle_dataset (bool، اختياري، القيمة الافتراضية True) — ما إذا كان سيتم خلط مجموعة بيانات التدريب.
  • pad_to_multiple_of (int أو str، اختياري، القيمة الافتراضية "auto") — إذا تم ضبطه، فسيتم ملء معرّفات الأوامر (prompts ids) ومعرّفات الإكمالات (completions ids) إلى مضاعف لهذا القيمة. "auto" يملأ إلى مضاعف لـ 128 على Neuron (AWS Trainium)، حيث يُترجم مرة واحدة لكل شكل إدخال، ولا يملأ في أي مكان آخر.

المعاملات التي تتحكم في التوليد

  • generation_batch_size (int, اختياري) — حجم الدفعة المستخدمة للتوليد. إذا كانت None، فإن القيمة الافتراضية هي حجم دفعة التدريب الفعلية: per_device_train_batch_size * num_processes * steps_per_generation. بمعنى آخر، يتم معالجة دفعة توليد واحدة لكل خطوة تحسين. يتعارض مع steps_per_generation.
  • steps_per_generation (int، اختياري) — عدد الخطوات لكل عملية توليد. إذا كانت None، فإن القيمة الافتراضية هي gradient_accumulation_steps. يتعارض مع generation_batch_size.
  • temperature (float، اختياري، القيمة الافتراضية 1.0) — درجة الحرارة للعينات. كلما زادت درجة الحرارة، زادت عشوائية المكملات.
  • top_p (float، اختياري، القيمة الافتراضية 1.0) — قيمة عشرية تتحكم في الاحتمال التراكمي لأعلى الرموز المراد أخذها في الاعتبار. يجب أن تكون ضمن المجال (0، 1]. اضبطها على 1.0 لاعتبار جميع الرموز.
  • top_k (int، اختياري، القيمة الافتراضية 0) — عدد رموز المفردات ذات أعلى احتمالات التي يجب الاحتفاظ بها لتصفية top-k. إذا كانت القيمة 0، يتم تعطيل تصفية top-k وتُعتبر جميع الرموز.
  • min_p (float, اختياري) — أدنى احتمال للرمز، والذي يُضرب في احتمال الرمز الأكثر احتمالاً. يجب أن يكون قيمة بين 0.0 و1.0. القيم النموذجية تقع في نطاق 0.01-0.2.
  • generation_kwargs (dict[str, Any]، اختياري) — معلمات إضافية بالكلمات المفتاحية تُمرَّر إلى GenerationConfig (في حال استخدام transformers) أو SamplingParams (في حال استخدام vLLM) عند أخذ عينات من المكملات. يمكن استخدام هذا لتخصيص سلوك التوليد بشكل أكبر، مثل تعيين suppress_tokens، num_beams، وما إلى ذلك. إذا احتوى على مفاتيح تتعارض مع معلمات التوليد الأخرى (مثل min_p، top_p، وما إلى ذلك)، فإنها ستُلغيها.
  • chat_template_kwargs (dict[str, Any]، اختياري) — معلمات إضافية بالكلمات المفتاحية تُمرَّر إلى دالة apply_chat_template عند توليد الإكمالات.
  • repetition_penalty (float، اختياري، القيمة الافتراضية 1.0) — قيمة عشرية تعاقب الرموز الجديدة بناءً على ما إذا كانت تظهر في الاستعلام والنص المولَّد حتى الآن. القيم > 1.0 تشجع النموذج على استخدام رموز جديدة، بينما القيم < 1.0 تشجع النموذج على تكرار الرموز.
  • cache_implementation (str، اختياري) — تنفيذ طريقة التخزين المؤقت لتسريع التوليد عندما يكون use_vllm مضبوطًا على False.

المعاملات التي تتحكم في تسريع التوليد المدعوم بواسطة vLLM

  • use_vllm (bool، اختياري، القيمة الافتراضية False) — ما إذا كان سيتم استخدام vLLM لتوليد المكملات. إذا تم ضبطه على True، فسيستخدم المدرب vLLM للتوليد بدلاً من model.generate() الافتراضي. يتطلب تثبيت vllm.
  • vllm_mode (str, اختياري, الافتراضي هو "colocate") — الوضع المستخدم لتكامل vLLM عندما use_vllm يُضبط على True. يجب أن يكون أحد "server" أو "colocate".
    • "server": سيقوم المدرب بإرسال طلبات التوليد إلى خادم vLLM منفصل. تأكد من أن خادم vLLM قيد التشغيل (ابدأ باستخدام vllm serve).
    • "colocate": سيعمل vLLM في نفس العملية ويشارك وحدات معالجة الرسوميات المستخدمة في التدريب. هذا يتجنب الحاجة إلى خادم منفصل، لكنه قد يسبب تنافساً على الموارد مع التدريب.
  • vllm_model_impl (str، اختياري، القيمة الافتراضية "vllm") — تنفيذ النموذج المستخدم في vLLM. يجب أن يكون أحد "transformers" أو "vllm". "transformers": استخدم واجهة transformers الخلفية لتنفيذ النموذج. "vllm": استخدم مكتبة vllm لتنفيذ النموذج.
  • vllm_enable_sleep_mode (bool، اختياري، القيمة الافتراضية False) — تفعيل وضع السكون في vLLM لتفريغ الأوزان/الذاكرة المؤقتة أثناء خطوة المُحسِّن. يُبقي استخدام ذاكرة وحدة معالجة الرسوميات منخفضًا، لكن استيقاظ المحرّك يضيف زمن انتقال بين المضيف والوحدة.
  • vllm_structured_outputs_regex (str، اختياري) — نمط Regex للمخرجات المهيكلة في vLLM. إذا كان None (الافتراضي)، يتم تعطيل المخرجات المهيكلة.

المعاملات التي تتحكم في خادم vLLM (تُستخدم فقط عندما تكون `vllm_mode` هي `"server"`)

  • vllm_server_base_url (str, اختياري) — العنوان الأساسي لخادم vLLM (مثل "http://localhost:8000"). إذا تم تقديمه، يتم تجاهل vllm_server_host و vllm_server_port.
  • vllm_server_host (str، اختياري، القيمة الافتراضية "0.0.0.0") — عنوان مضيف خادم vLLM الذي سيتم الاتصال به. يتم تجاهله إذا تم تقديم vllm_server_base_url.
  • vllm_server_port (int، اختياري، القيمة الافتراضية 8000) — منفذ خادم vLLM الذي يجب الاتصال به. يتم تجاهله إذا تم تقديم vllm_server_base_url.
  • vllm_server_timeout (float, اختياري, القيمة الافتراضية 240.0) — المدة الإجمالية للوقت المحدد بالثواني للانتظار حتى يصبح خادم vLLM قيد التشغيل. إذا لم يكن الخادم قيد التشغيل بعد انتهاء المهلة، يتم رفع ConnectionError.
  • vllm_group_port (int، اختياري، القيمة الافتراضية 51216) — رقم المنفذ لمجموعة تحديث الأوزان. يُستخدم للتواصل مع خادم vLLM. ما لم يكن المنفذ مشغولاً، فلا حاجة لتغييره.

المعاملات التي تتحكم في تنفيذ vLLM المتزامن (تُستخدم فقط عندما يكون `vllm_mode` هو `"colocate"`)

  • vllm_gpu_memory_utilization (float, اختياري، القيمة الافتراضية 0.3) — التحكم في استهلاك ذاكرة GPU في vLLM. لا تنطبق هذه الإعدادات إلا عندما تكون قيمة vllm_mode هي "colocate". إذا كنت تستخدم vllm_mode="server"، فيجب تمرير هذا المعامل بشكل منفصل عند إطلاق خادم vLLM عبر علم --vllm_gpu_memory_utilization.
  • vllm_max_model_length (int, اختياري) — نافذة السياق الخاصة بـ vLLM. اضبطه على الأقل على طول الإدخال الأقصى في مجموعة البيانات مضافًا إليه max_completion_length؛ وإذا تم تجاهله، فسيتم استنتاجه من إعدادات النموذج.
  • vllm_tensor_parallel_size (int, اختياري، القيمة الافتراضية 1) — التحكم في حجم التوازي للتensors في vLLM. لا تنطبق هذه الإعدادات إلا عندما تكون vllm_mode مضبوطة على "colocate". إذا كنت تستخدم vllm_mode="server"، فيجب تمرير هذا المعامل بشكل منفصل عند إطلاق خادم vLLM عبر علم --vllm_tensor_parallel_size.

المعاملات التي تتحكم في التدريب

  • beta (float، اختياري، القيمة الافتراضية 0.0) — معامل KL. إذا كانت القيمة 0.0 (الافتراضية)، فلن يتم تحميل النموذج المرجعي، مما يقلل من استهلاك الذاكرة ويحسّن سرعة التدريب. يستخدم DeepSeek-R1 incentivizes reasoning in LLMs through reinforcement learning قيمة 0.001.
  • num_iterations (int، اختياري، القيمة الافتراضية 1) — عدد التكرارات لكل دفعة (يُرمز له بـ μ في الخوارزمية).
  • epsilon (float، اختياري، القيمة الافتراضية 0.2) — قيمة إيبسلون للقص.
  • delta (float, اختياري) — يُفعّل حدّ القصّ العلوي في خسارة GRPO ذات الجانبين عند تعيينه كقيمة float. إذا كان None (الافتراضي)، يُستخدم القصّ القياسي لـ GRPO. يُوصى بأن يكون أكبر من 1 + ε عند التفعيل. تم تقديم هذه الطريقة في تقرير INTELLECT-2 التقني.
  • epsilon_high (float, اختياري) — قيمة إبسيلون الحد الأعلى للتقليم. إذا لم يتم تحديدها، فإن القيمة الافتراضية هي نفس قيمة الحد الأدنى المحددة في الحجة epsilon. يوصي الورق DAPO بقيمة 0.28. عند الاستخدام مع loss_type='cispo'، يتوافق هذا مع معامل ε_max المحدد في ورقة ScaleRL وقيمته الافتراضية هي القيمة الموصى بها 5.0.
  • sapo_temperature_neg (float، اختياري، القيمة الافتراضية 1.05) — درجة الحرارة للرموز ذات درجات الأفضلية غير الموجبة المستخدمة في دالة الخسارة sapo. تم تقديم هذا المعامل في ورقة Soft Adaptive Policy Optimization.
  • sapo_temperature_pos (float, اختياري، القيمة الافتراضية 1.0) — درجة الحرارة للرموز ذات درجات الأفضلية الموجبة المستخدمة في دالة الخسارة sapo. تم تقديم هذا المعامل في ورقة Soft Adaptive Policy Optimization.
  • vespo_k_pos (float، اختياري، القيمة الافتراضية 2.0) — معامل k للمزايا الإيجابية، وهو أُس القوة في خسارة VESPO. يتحكم في مدى حدة تخفيض وزن العينات ذات أوزان الأهمية المنخفضة (عندما يكون نسبة أخذ العينات المهمة < 1).
  • vespo_lambda_pos (float، اختياري، القيمة الافتراضية 3.0) — معامل lambda للمزايا الإيجابية، وهو عامل التلاشي في خسارة VESPO. يتحكم في مدى حدة تخفيض وزن العينات ذات أوزان الأهمية العالية (عندما يكون نسبة أخذ العينات المهمة > 1).
  • vespo_k_neg (float، اختياري، القيمة الافتراضية 3.0) — معامل k للمزايا السلبية، وهو أُس القوة في خسارة VESPO. يتحكم في مدى حدة تخفيض وزن العينات ذات أوزان الأهمية المنخفضة (عندما يكون نسبة أخذ العينات المهمة < 1).
  • vespo_lambda_neg (float, اختياري, القيمة الافتراضية 2.0) — معامل lambda للمزايا السلبية، وهو عامل الاضمحلال الأسي في خسارة VESPO. يتحكم في مدى خفض وزن العينات ذات أوزان الأهمية العالية (عندما يكون نسبة أخذ العينات المهمة > 1).
  • importance_sampling_level (str، اختياري، القيمة الافتراضية "token") — يتحكم في ما إذا كانت نسب أخذ العينات المهمة تُحسب على مستوى "token" أو "sequence". "token" يحافظ على نسب احتمالات السجل الخام لكل رمز (وزن واحد لكل رمز). "sequence" يحسب متوسط نسب احتمالات السجل عبر الرموز الصالحة لإنتاج نسبة واحدة لكل تسلسل. تُظهر ورقة GSPO أن أخذ العينات على مستوى التسلسل غالبًا ما يؤدي إلى تدريب أكثر استقرارًا ومواءمة أفضل مع المكافآت على مستوى التسلسل.
  • reward_weights (list[float], اختياري) — أوزان لكل دالة مكافأة. يجب أن تتطابق مع عدد دوال المكافأة. إذا كانت None، فجميع المكافآت موزونة بالتساوي مع وزن 1.0.
  • multi_objective_aggregation (str, اختياري, الافتراضي هو "sum_then_normalize") — طريقة تجميع دوال المكافآت المتعددة. القيم المدعومة هي:
    • "sum_then_normalize" (الافتراضي): يجمع أولاً المكافآت المرجّحة من كل دالة مكافآت، ثم يطبّق تحجيم/تطبيع المكافآت كما هو محدد بواسطة scale_rewards (انظر scale_rewards للتفاصيل).
    • "normalize_then_sum": يقوم أولاً بتطبيع/تحجيم كل دالة مكافأة عبر الأجيال (داخل كل مجموعة)، ثم يجمع المكافآت المطبّعة باستخدام الأوزان المحددة. بعد ذلك، يتم تطبيع المكافأة المجمّعة على مستوى الدفعة عند تشكيل المزايا. هذا هو النهج المقترح في الورقة GDPO: Group reward-Decoupled Normalization Policy Optimization for Multi-reward RL Optimization.
  • scale_rewards (str أو bool, اختياري, الافتراضي هو "group") — يحدد استراتيجية توسيع المكافآت. القيم المدعومة هي:
    • True أو "group" (الافتراضي): تُقاس الأرباح بانحراف المعيار داخل كل مجموعة، مما يضمن تباينًا معياريًا داخل المجموعة.
    • "batch": يتم قياس المكافآت وفق الانحراف المعياري عبر الدفعة بأكملها، كما هو موصى به في ورقة PPO Lite.
    • False أو "none": لا يُطبَّق أي توسيع. يوصي ورقة Dr. GRPO بعدم توسيع المكافآت، لأن التوسيع باستخدام الانحراف المعياري يُدخل تحيّزًا في صعوبة مستوى السؤال.
  • loss_type (str, اختياري, الافتراضي هو "dapo") — يحدد صيغة الدالة الخاسرة (loss) المستخدمة. القيم المدعومة هي:
    • "grpo": يجمع خسائر مستوى الرموز من خلال تطبيعها على طول التسلسل. لا يُنصح باستخدامه بسبب انحياز الطول؛ فتنحى هذه الطريقة إلى تفضيل الإكمالات الأقصر ذات المزايا الإيجابية والأطول ذات المزايا السلبية.
    • "dr_grpo": يجمع خسائر مستوى الرموز من خلال تطبيعها بثابت عام. تم تقديم هذه الطريقة في ورقة Dr. GRPO للقضاء على التحيز الناتج عن الطول. تتوافق قيمة الثابت مع max_completion_length.
    • "dapo" (الافتراضي): يجمع خسائر مستوى الرموز من خلال تطبيعها بعدد الرموز النشطة في الدفعة المتراكمة عالميًا. وقد قُدِّم هذا الأسلوب في ورقة DAPO للقضاء على التحيز الناتج عن الطول.
    • "bnpo": يجمع خسائر مستوى الرموز من خلال تطبيعها بعدد الرموز النشطة في الدفعة المحلية. لاحظ أن التطبيع يتم على الدفعة المحلية فقط، لذا قد تختلف النتائج قليلاً اعتمادًا على حجم الدفعة المحلية، على الرغم من ثبات حجم الدفعة الفعّال. عند استخدام per_device_train_batch_size==1، تكون الخسارة مكافئة لخسارة GRPO.
    • "cispo": يقصّ أوزات أخذ العينات المهمة بدلاً من أوزات أخذ العينات المهمة المُقيّمة بالفائدة. ثم تُضرب الأوزات المقصوصة في الفوائد وفي احتمالات السجل لنموذج السياسة. وتُجمَّع خسائر الرموز الفردية عن طريق تطبيعها بعدد الرموز النشطة في الدفعة المتراكمة عالمياً. وقد قُدِّم هذا الأسلوب في ورقة MiniMax-M1.
    • "sapo": خسارة تحسين السياسة التكيفية الناعمة، كما طُرحت في ورقة تحسين السياسة التكيفية الناعمة. تحلّ محلّ القصّ الصارم ببوابة سلسة تتحكم فيها درجة الحرارة، تُخفِّض بشكل تكيفي تحديثات خارج السياسة مع الحفاظ على إشارات التعلم المفيدة.
    • "luspo": خسارة تحسين سياسة التسلسل غير المتحيزة طولياً. خسارة على مستوى التسلسل تقوم بتعديل خسارة كل تسلسل بناءً على طوله. هذا تعديل على GSPO ويتطلب importance_sampling_level="sequence". تم تقديمه في ورقة LUSPO.
    • "vespo": تحسين سياسة ناعمة على مستوى التسلسل باستخدام التباين. يستبدل القص الصارم بدالة وزن جاما ناعمة غير متماثلة تُطبَّق مباشرةً على أوزان الأهمية على مستوى التسلسل. تم تقديمه في ورقة VESPO.
  • mask_truncated_completions (bool، اختياري، القيمة الافتراضية False) — عند التفعيل، تُستبعد الإكمالات المقطوعة من حساب الخسارة، مما يمنع معاقبتها بشكل غير صحيح وإدخال ضوضاء أثناء التدريب. وفقًا لورقة DAPO، يُعد هذا ممارسة جيدة لاستقرار التدريب.
  • sync_ref_model (bool، اختياري، القيمة الافتراضية False) — ما إذا كان سيتم مزامنة النموذج المرجعي مع النموذج النشط كل ref_model_sync_steps خطوات، باستخدام المعامل ref_model_mixup_alpha. تنبع هذه المزامنة من ورقة TR-DPO.
  • ref_model_mixup_alpha (float, اختياري، القيمة الافتراضية 0.6) — معامل α من ورقة TR-DPO، والذي يتحكم في المزج بين السياسة الحالية والسياسة المرجعية السابقة أثناء التحديثات. يتم تحديث السياسة المرجعية وفقًا للمعادلة: π_ref = α * π_θ + (1 - α) * π_ref_prev. لاستخدام هذا المعامل، يجب إعداد sync_ref_model=True.
  • ref_model_sync_steps (int، اختياري، القيمة الافتراضية 512) — معامل τ من ورقة TR-DPO، والذي يحدد مدى تكرار مزامنة السياسة الحالية مع السياسة المرجعية. لاستخدام هذا المعامل، يجب إعداد sync_ref_model=True.
  • top_entropy_quantile (float, اختياري، القيمة الافتراضية 1.0) — معامل ρ من Beyond the 80/20 Rule. يحتفظ في حد الخسارة الخاص بالسياسة فقط بأعلى ρ من الكمية (quantile) من الرموز (tokens) حسب إنتروبيا توزيع الاحتمالات عند كل موضع في التسلسل، مما يحسّن النتائج. النطاق: [0.0-1.0]. القيمة 0.0 تخفي جميع الرموز عدا الرمز ذي الإنتروبيا الأعلى؛ بينما 1.0 يحتفظ بجميع الرموز. يوصي البحث بقيمة 0.2. عند استخدامه مع mask_truncated_completions=True، تُؤخذ في الاعتبار الرموز من الاكتمالات غير المقطوعة فقط.
  • entropy_coef (float, اختياري، القيمة الافتراضية 0.0) — معامل حد تنظيم الإنتروبيا في دالة الخسارة. القيمة الموجبة تضيف مكافأة إنتروبيا تشجع على الاستكشاف من خلال منع انهيار السياسة إلى مخرجات شبه حتمية. تكون المكافأة دائمًا متوسط إنتروبيا الرمز الواحد بغض النظر عن loss_type؛ فهي لا تُعاد مقياستها لتتطابق مع تطبيع السياسة لنوع الخسارة، لذا فإن entropy_coef يحمل نفس المعنى لجميع أنواع الخسارة. عند تعيين use_adaptive_entropy=True، يعمل هذا المعامل كمعامل مبدئي ويُحدَّث في كل خطوة من خطوات المُحسِّن. لا يؤثر عند تعيينه إلى 0.0 (الافتراضي).
  • use_adaptive_entropy (bool، اختياري، القيمة الافتراضية False) — ما إذا كان سيتم استخدام التحكم التكيفي في الإنتروبيا، الذي تم تقديمه في Skywork-OR1. عند التفعيل، يتم تحديث معامل الإنتروبيا entropy_coef في كل خطوة من خطوات المُحسِّن: يزداد بمقدار entropy_coef_delta عندما تكون الإنتروبيا الحالية أقل من entropy_target، وينقص في حال العكس. لا يُطبَّق المعامل إلا عندما تكون الإنتروبيا عند entropy_target أو أقل.
  • entropy_coef_min (float، اختياري، القيمة الافتراضية 0.0) — الحد الأدنى لمعامل الإنتروبيا عند استخدام التحكم التكيفي في الإنتروبيا.
  • entropy_coef_max (float، اختياري، القيمة الافتراضية 1.0) — الحد الأعلى لمعامل الإنتروبيا عند استخدام التحكم التكيفي في الإنتروبيا.
  • entropy_coef_delta (float، اختياري، القيمة الافتراضية 0.005) — حجم الخطوة لضامل معامل الإنتروبيا في كل خطوة من خطوات المُحسِّن أثناء التحكم التكيفي بالإنتروبيا.
  • entropy_target (float، اختياري، القيمة الافتراضية 0.2) — متوسط إنتروبيا الهدف لكل رمز (بالنات) المستخدم في التحكم التكيفي بالإنتروبيا. يُطبَّق المعامل فقط عندما تكون الإنتروبيا الحالية عند هذه القيمة أو أقل. يتم القياس على مجموعة الرموز نفسها المستخدمة في خسارة السياسة: جميع رموز الإكمال افتراضيًا، أو فقط مجموعة الإكمال ذات الإنتروبيا العالية عندما يكون top_entropy_quantile < 1.0. تتراوح إنتروبيا الرموز في نماذج اللغة النموذجية عادةً بين 2 و10 نات، لذا فإن القيمة الافتراضية 0.2 نادرًا ما تُفعّل التنظيم (إلا في حالات الانهيار شبه الكامل للإنتروبيا)؛ اضبطها قريبة من الإنتروبيا التي ترصدها في المراحل المبكرة من التدريب (المُسجَّلة كمقياس entropy) حتى يُفعَّل المكافأة قبل انهيار السياسة (واحتسب مجموعة الرموز الفرعية عند استخدام top_entropy_quantile).
  • max_tool_calling_iterations (int, اختياري) — الحد الأقصى لعدد جولات استدعاء الأدوات عند تدريب وكيل. إذا كانت None، فلا يوجد حد، ويتوقف التوليد عندما يولّد النموذج ردًا في جولة دون أي استدعاءات للأدوات، أو عندما يبلغ طول الرد الإجمالي max_model_length.
  • vllm_importance_sampling_correction (bool, optional, defaults to True) — Whether to apply Importance Sampling (IS) to correct for the mismatch between vLLM completion logprobs and recomputed training logprobs. If set to False, no IS is applied regardless of vllm_importance_sampling_mode. When True, the selected mode determines how the IS ratios are computed and constrained. With top_p < 1, top_k > 0 or min_p > 0, the recomputed logprobs are normalized over the candidate set each token was sampled from, which requires vllm_mode="colocate" and vLLM 0.28 or later; otherwise, the IS ratios are biased. vLLM bounds that candidate set with top_k, so top_p < 1 and min_p > 0 require top_k > 0 (e.g. top_k=512). vLLM also applies repetition_penalty to the logprobs it returns, so repetition_penalty != 1.0 requires vllm_importance_sampling_correction=False.
  • vllm_importance_sampling_mode (str, اختياري, الافتراضي هو "sequence_mask") — يحدد كيفية تنفيذ Importance Sampling عندما يكون vllm_importance_sampling_correction=True. القيم الممكنة هي:
    • "token_truncate": اقتطاع نسبة العينة على مستوى الرموز. يتم اقتطاع النسب لكل رمز إلى [C_min, C_max].
    • "token_mask": إسقاط مقنّع على مستوى الرموز. تُضبط النسب لكل رمز خارج النطاق [C_min, C_max] إلى الصفر.
    • "sequence_truncate": اقتطاع نسبة العينة على مستوى التسلسل. يتم اقتطاع نسبة تسلسل واحدة إلى [C_min, C_max] وتطبيقها على جميع الرموز في التسلسل.
    • "sequence_mask": إسكات على مستوى التسلسل. يتم إسكات التسلسلات التي تكون نسبها خارج النطاق [C_min, C_max].
  • vllm_importance_sampling_clip_max (float، اختياري، القيمة الافتراضية 3.0) — الحد الأعلى C_max لعينة الأهمية (Importance sampling) المستخدم بواسطة vllm_importance_sampling_mode. في أوضاع *_truncate، تُقصّ نسب الأهمية من الأعلى عند C_max. في أوضاع *_mask، تُضبط النسب الأكبر من C_max إلى صفر.
  • vllm_importance_sampling_clip_min (float, اختياري) — الحد الأدنى C_min لعينة الأهمية (Importance sampling) المستخدم بواسطة vllm_importance_sampling_mode. في أوضاع *_truncate، تُقصّ النسب من الأسفل عند C_min. في أوضاع *_mask، تُضبط النسب الأقل من C_min إلى صفر. لتقنيع النسب الأقل من C_min بشكل صارم دون حد أعلى، اضبط vllm_importance_sampling_clip_max=None.
  • off_policy_mask_threshold (float, اختياري) — الحدّ العتبة لتقنّية تسلسلات خارج السياسة. إذا كان None، فإن تقنّية تسلسلات خارج السياسة تكون معطّلة. عند ضبطه، تُتقنّى التسلسلات ذات المزايا السالبة وانحراف كولباك-ليبل العالي لتثبيت التدريب. يتوافق هذا المعامل مع عتبة delta في المعادلة 9 من ورقة DeepSeek-V3.2. يتوقع قيمة موجبة (مثل 0.5).
  • use_bias_correction_kl (bool، اختياري، القيمة الافتراضية True) — ما إذا كان يجب ضرب حد KL في نسبة أخذ العينات المهمة، بحيث يصبح تدرج KL هو تدرج reverse-KL غير المتحيز، كما هو موصوف في ورقة DeepSeek-V3.2. يغيّر هذا تدرج KL في كل مرة يكون فيها beta != 0، بما في ذلك على السياسة: النسبة قابلة للاشتقاق، لذا تؤثر على التدرج حتى حيث تكون قيمتها تساوي 1 تمامًا. خاصية reverse-KL غير المتحيز تنطبق عند importance_sampling_level="token"؛ أما مع "sequence" فيتم بث وزن على مستوى التسلسل على KL لكل رمز.

المعاملات التي تتحكم في التسجيل

  • log_completions (bool، اختياري، القيمة الافتراضية False) — ما إذا كان سيتم تسجيل عينة من أزواج (الموجّه، الإكمال) كل logging_steps خطوات. إذا كان rich مثبّتًا، فسيتم طباعة العينة. إذا كان تسجيل wandb و/أو trackio مفعّلًا، فسيتم تسجيلها في wandb و/أو trackio.
  • log_multimodal (bool، اختياري، القيمة الافتراضية True) — ما إذا كان سيتم تسجيل المحتوى متعدد الوسائط (الصور، مقاطع الفيديو، إلخ) مع الإكمالات. عطّل هذا الخيار لتقليل حجم السجلات عند استخدام بيانات متعددة الوسائط عالية الدقة.
  • num_completions_to_print (int, اختياري) — عدد الإكمالات التي سيتم طباعتها باستخدام rich. إذا كانت None، فسيتم تسجيل جميع الإكمالات.
  • log_unique_prompts (bool، اختياري، القيمة الافتراضية False) — ما إذا كان سيتم تسجيل الأوامر الفريدة. إذا كانت True، يتم تسجيل الأوامر الفريدة فقط. إذا كانت False، يتم تسجيل جميع الأوامر.
  • log_completions_hub_repo (str, اختياري) — مستودع Hugging Face Hub لحفظ الاكتمالات. يجب أن يكون اسم مستودع كاملًا مثل 'username/reponame' أو 'orgname/reponame'، أو مجرد 'reponame' وفي هذه الحالة سيتم إنشاء المستودع في مساحة اسم مستخدم Hugging Face المسجّل حاليًا. لاحظ أن هذا المستودع سيكون عامًا إلا إذا قمت بتعيين hub_private_repo=True أو كان الافتراضي في مؤسستك هو إنشاء مستودعات خاصة.

المعاملات التي تتحكم في تسريع التوليد المدعوم من transformers عبر الدفع المستمر

  • use_transformers_continuous_batching (bool، اختياري، القيمة الافتراضية False) — ما إذا كان سيتم استخدام محرك الدفعات المستمر (continuous batching) الخاص بـ transformers لتوليد الإكمالات. يتطلب transformers>=5.8.0.
  • transformers_continuous_batching_config (dict، اختياري) — حجج الكلمات المفتاحية لـContinuousBatchingConfig.

معاملات غير مستخدمة

  • use_transformers_paged —

    تم إيقاف استخدام المعامل use_transformers_paged وسيتم حذفه في الإصدار v2.0.0. استخدم use_transformers_continuous_batching بدلاً منه.

  • vllm_importance_sampling_cap —

    تم إيقاف استخدام المعامل vllm_importance_sampling_cap وسيتم حذفه في الإصدار v2.0.0. استخدم vllm_importance_sampling_clip_max بدلاً منه.

فئة التهيئة الخاصة بـ GRPOTrainer.

تتضمن هذه الفئة فقط المعلمات الخاصة بتدريب GRPO. للحصول على قائمة كاملة بحجج التدريب، يرجى الرجوع إلى توثيق TrainingArguments. لاحظ أن القيم الافتراضية في هذه الفئة قد تختلف عن تلك الموجودة في TrainingArguments.

باستخدام HfArgumentParser يمكننا تحويل هذه الفئة إلى حُجج argparse يمكن تحديدها على سطر الأوامر.

تتميز هذه المعلمات بقيم افتراضية مختلفة عن TrainingArguments:

  • logging_steps: القيمة الافتراضية هي 10 بدلاً من 500.
  • gradient_checkpointing: القيمة الافتراضية هي True بدلاً من False.
  • bf16: القيمة الافتراضية هي True إذا لم يتم تعيين fp16، بدلاً من False.
  • learning_rate: القيمة الافتراضية هي 1e-6 بدلاً من 5e-5.
Update on GitHub