TRL documentation
مدرب GRPO
مدرب GRPO
نظرة عامة
يدعم 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)، يستغرق التدريب حوالي يوم واحد.

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

توليد الاكتمالات
في كل خطوة تدريب، نختار دفعة من الأوامر ونولّد مجموعة من الإكمالات لكل أمر (يُرمز إليها بـ ).
حساب الميزة
لكلٍّ من التسلسلات، نحسب المكافأة باستخدام نموذج مكافآت أو دالة مكافآت. ولتوافق مع الطبيعة المقارنة لنماذج المكافآت — التي تُدرَّب عادةً على مجموعات بيانات من المقارنات بين المخرجات للسؤال نفسه — يتم حساب الميزة لتعكس هذه المقارنات النسبية. يتم تطبيعها على النحو التالي:
يمنح هذا النهج الطريقة اسمه: تحسين السياسة النسبي للمجموعات (GRPO).
أُظهر في الورقة البحثية Understanding R1-Zero-Like Training: A Critical Perspective أن التوسيع بواسطة قد يسبب انحيازًا في صعوبة مستوى السؤال. يمكنك تعطيل هذا التوسيع عن طريق تعيين
scale_rewards=Falseفي GRPOConfig. يُرجى ملاحظة أن إيقاف التوسيع القائم على std يزيل أيضًا تطبيع التباين، لذا تعتمد أحجام التحديث مباشرةً على مقياس المكافأة الخام وتكوين الدفعة.
كما هو موضح في الجزء الأول: حيل أم فخاخ؟ غوص عميق في التعلم المعزز لاستدلال نماذج اللغة الكبيرة (Lite PPO)، فإن حساب المتوسط على المستوى المحلي (المجموعة) والانحراف المعياري على المستوى العام (الدفع) يتيح تشكيل مكافآت أكثر متانة. يمكنك استخدام استراتيجية التوسيع هذه عن طريق تعيين
scale_rewards="batch"في GRPOConfig.
تقدير تباعد كولباك-ليبل
يُقدَّر تباعد KL باستخدام المُقدِّر الذي قدمه Schulman et al. (2020). يُعرَّف المُقدِّر على النحو التالي:
حساب الخسارة
الهدف هو تعظيم الميزة مع ضمان بقاء النموذج قريبًا من سياسة المرجع. وبالتالي، يُعرَّف الخسارة على النحو التالي:
حيث يمثل الحد الأول الميزة المُقيّمة، بينما يعاقب الحد الثاني الانحرافات عن سياسة المرجع من خلال تباعد كوهين-ليبلينغ.
لاحظ أنه مقارنةً بالصياغة الأصلية في DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models, لا نضرب في لأنه تم إثبات في الورقة Understanding R1-Zero-Like Training: A Critical Perspective أن هذا يُدخل تحيّزًا في طول الاستجابة على مستوى الرد. مزيد من التفاصيل في أنواع الدالة الخاسرة.
لاحظ أنه مقارنةً بالصياغة الأصلية في DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models, نستخدم كقيمة افتراضية، مما يعني أن حد تباعد 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 إلى قيمة غير صفرية.
في الورقة الأصلية، يتم تعميم هذه الصياغة لتأخذ في الاعتبار عدة تحديثات بعد كل توليد (يُرمز لها بـ , يمكن ضبطها عبر num_iterations في GRPOConfig) عن طريق الاستفادة من دالة الهدف البديلة المقصوصة:
حيث على ضمان عدم انحراف التحديثات بشكل مفرط عن سياسة المرجع من خلال تحديد نطاق نسبة السياسة بين و . عندما (القيمة الافتراضية في TRL)، فإن الدالة البديلة المقصوصة تتبسط لتصبح الدالة الأصلية.
أنواع الدالة
قُدِّمت عدة صيغ للدالة الهدف في الأدبيات. في البداية، عُرِّفت دالة هدف GRPO على النحو التالي:
حيث
يُبرز ورقة DAPO قيود خسارة مستوى العينة في خوارزمية GRPO في سيناريوهات CoT الطويلة، حيث تُعاقَب الاستجابات الأطول بشكل غير كافٍ، مما يؤدي إلى مخرجات ذات جودة أدنى. الحل المقترح هو تطبيع على مستوى الرمز (token-level normalization)، والذي يتعامل بشكل أفضل مع التسلسلات الأطول من خلال منح مكافآت أكثر توازناً للأفراد الرموز، بغض النظر عن طول الاستجابة:
لاستخدام هذه الصياغة، اضبط loss_type="dapo" في GRPOConfig.
علاوة على ذلك، تم إثبات في الورقة Understanding R1-Zero-Like Training: A Critical Perspective أن صياغة GRPO الأولية تُدخل انحيازًا في طول الاستجابة. يُظهرون أنه على الرغم من أن صياغة DAPO تقلل من هذا الانحياز، إلا أنها لا تلغيه تمامًا. لإزالة هذا الانحياز بالكامل، يقترحون القسمة على ثابت بدلاً من طول التسلسل، مما يؤدي إلى الصياغة التالية:
يُوصى بأن تكون هذه الثابتة هي الحد الأقصى لطول الإكمال. لاستخدام هذه الصياغة، اضبط loss_type="dr_grpo" في GRPOConfig.
بديلًا عن ذلك، في ورقة SAPO، يقترح فريق Qwen استبدال آلية القصّ “الصلبة” في GRPO بآلية بوابة ناعمة سلسة تتحكم فيها درجة الحرارة. بينما تُصفّر GRPO التدرّجات عندما ينحرف النموذج عن المرجع بشكل مفرط، يستخدم SAPO منطقة ثقة ناعمة تُضعف وزن التدرّج بسلاسة. وهذا يتيح للنموذج الاحتفاظ بإشارات التعلم المفيدة من الرموز “القريبة من السياسة” مع كبح الضوضاء الناتجة عن الانحرافات الشديدة.
يُعرَّف دالة الخسارة على النحو التالي:
دالة البوابة الناعمة تُعرَّف باستخدام دالة السيغمويد على النحو التالي:
درجة الحرارة تُختار بناءً على إشارة الميزة :
يوصون باستخدام درجات حرارة غير متماثلة، (القيم الافتراضية هي ). يضمن هذا أن يُعاقب النموذج بشكل أكثر صرامة على الإجراءات «السيئة» لمنع عدم الاستقرار، مع كونه أكثر تساهلاً مع الإجراءات «الجيدة».
لاستخدام هذه الصياغة، اضبط 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_ratio/low_mean: متوسط نسبة احتمالات الرموز (أو التسلسل، إذا كانimportance_sampling_level="sequence") مقصوصة عند الحد الأدنى لمنطقة الثقة: .clip_ratio/low_min: أصغر نسبة لكل إكمال من الرموز (أو التسلسل نفسه، إذاimportance_sampling_level="sequence") تم اقتطاعه عند الحد الأدنى لمنطقة الثقة: .clip_ratio/high_mean: متوسط نسبة احتمالات الرموز (أو التسلسل، إذا كانimportance_sampling_level="sequence") مقصوصة عند الحد الأعلى لمنطقة الثقة: .clip_ratio/high_max: أعلى نسبة لكل إكمال من الرموز (أو التسلسل نفسه، إذاimportance_sampling_level="sequence") تم اقتطاعه عند الحد الأعلى لمنطقة الثقة: .cispo_clip_ratio: نسبة أوزات أخذ العينات المهمة (على مستوى الرمز، أو التسلسل إذا كانimportance_sampling_level="sequence") مقصوصة عندepsilon_highمع امتلاك ميزة إيجابية: . يُسجَّل فقط عندما يكونloss_type="cispo".vespo/phi_seq_mean: القيمة المتوسطة لوزن VESPO Gamma المُطبَّق على أوزان الأهمية على مستوى التسلسل. تشير القيم الأقل من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. وهذا مثالي إذا كانت لديك وحدات معالجة رسومية مخصصة للاستدلال.
بدء خادم vLLM:
VLLM_SERVER_DEV_MODE=1 vllm serve <model_name> \ --weight-transfer-config '{"backend": "nccl"}' \ --logprobs-mode processed_logprobs \ --max-logprobs -1تفعيل وضع الخادم في سكربت التدريب الخاص بك:
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:
هنا تُشير إلى الأوامر المُستخرجة من توزيع بيانات معين، و هو السياسة المُنفَّذة بواسطة محرك التدريب. عند تضمين vLLM في العملية، نحصل على سياسة استدلال منفصلة , لذا يصبح تدرج السياسة الفعّال
يُحوِّل هذا مشكلة تعلُّم معزَّز كانت في الأصل ضمن السياسة إلى مشكلة خارج السياسة.
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 denote the importance weight, for example per token or per sequence. Under TIS, ratios outside of the range [vllm_importance_sampling_clip_min, vllm_importance_sampling_clip_max] are clipped,
الورقة الأصلية TIS اقترحت آلية قصّ واحدة للحد الأعلى، أي . عمّم التنفيذ في TRL هذا المفهوم من خلال تقديم حد أدنى أيضًا، مما أدى إلى الصياغة ذات الجانبين المعروضة أعلاه، مستوحاة من IcePop طريقة.
يُلاحظ أنه في IcePop، تُسمّى الحدود و بينما نستخدم في TRL و .
في إطار 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 &
waitimport 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) بحيث تتداخل أزمنتها المستجيب.
حجج الإدخال:
يجب أن تقبل الدالة ما يلي كحجج مُسمّاة:
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في توقيع الدالة.يعتمد شكل المدخلات على صيغة مجموعة البيانات:
- في الصيغة القياسية، ستكون
promptsوcompletionsقوائم من النصوص. - في الصيغة الحوارية، ستكون
promptsوcompletionsقوائم من قواميس الرسائل.
- في الصيغة القياسية، ستكون
القيمة المُعادَة: يجب أن تُعيد الدالة قائمة من الأرقام العشرية. يمثل كل رقم عشري المكافأة المقابلة لإكمال واحد.
المثال 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 على النحو التالي:
حيث هو متوسط إنتروبيا الرمز الواحد للسياسة، و هو معامل الإنتروبيا. المكافأة هي دائمًا متوسط إنتروبيا الرمز الواحد بغض النظر عن 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
< source >( 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. يتم دعم نماذج اللغة السببية فقط.
- سلسلة نصية، تكون معرف النموذج لنموذج مُدرَّب مسبقًا مستضاف داخل مستودع نماذج على huggingface.co، أو مسارًا إلى مجلد يحتوي على أوزان النموذج المحفوظة باستخدام save_pretrained، مثل
- 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 withnum_labels=1and the keyword arguments inargs.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()تدريب
< source >( resume_from_checkpoint: str | bool | None = Nonetrial: optuna.Trial | dict[str, Any] | None = Noneignore_keys_for_eval: list[str] | None = None ) → ~trainer_utils.TrainOutput
المعاملات
- 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
كائن يحتوي على عدد الخطوات العالمية، وخسارة التدريب، والمقاييس.
نقطة الدخول الرئيسية للتدريب.
سيحفظ النموذج، بحيث يمكنك إعادة تحميله باستخدام from_pretrained().
سيتم الحفظ من العملية الرئيسية فقط.
push_to_hub
< source >( 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
< source >( output_dir: str | None = Noneper_device_train_batch_size: int = 8num_train_epochs: float = 3.0max_steps: int = -1learning_rate: float = 1e-06lr_scheduler_type: 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 toFalse) — 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 toTrue) — Whether to apply Importance Sampling (IS) to correct for the mismatch between vLLM completion logprobs and recomputed training logprobs. If set toFalse, no IS is applied regardless ofvllm_importance_sampling_mode. WhenTrue, the selected mode determines how the IS ratios are computed and constrained. Withtop_p < 1,top_k > 0ormin_p > 0, the recomputed logprobs are normalized over the candidate set each token was sampled from, which requiresvllm_mode="colocate"and vLLM 0.28 or later; otherwise, the IS ratios are biased. vLLM bounds that candidate set withtop_k, sotop_p < 1andmin_p > 0requiretop_k > 0(e.g.top_k=512). vLLM also appliesrepetition_penaltyto the logprobs it returns, sorepetition_penalty != 1.0requiresvllm_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.