كيفية تحديد حد الإخراج num_predict في Ollama
يحدد num_predict عدد الرموز التي يكتبها Ollama. تعرّف إلى مواضع ضبطه الثلاثة، وأيها يتغلب على الآخر، وكيف تقرأ done_reason في الاستجابة.
ما الذي يفعله num_predict في Ollama
num_predict هو خيار Ollama الذي يحدّ الحد الأقصى لعدد الرموز التي يمكن للنموذج توليدها في استجابة واحدة. ويُحتسب عدد رموز المخرجات فقط، لذلك لا تُحتسب المطالبة ضمن هذا الحد. عندما يصل النموذج إلى الحد الأقصى، يتوقف التوليد عند موضعه الحالي، وقد يتوقف أحياناً في منتصف كلمة، وتعود الاستجابة مع ضبط done_reason على length.
هذه هي الوظيفة كاملة. تكمن الصعوبة في أن Ollama يتيح لك ضبط القيمة في ثلاثة مواضع منفصلة، وتكون الأولوية للإعداد الأقرب إلى الطلب. تنشأ كل تقارير "num_predict لا يفعل شيئاً" تقريباً لأن إحدى الطبقات تتجاوز إعداد طبقة أخرى بصمت.
num_predict ليس num_ctx
يحدث الخلط بين هذين الخيارين أكثر من أي زوج آخر في Ollama، ويؤدي هذا الخلط إلى إهدار وقت فعلي في تصحيح الأخطاء.
num_ctx يحدد مقدار ما يستطيع النموذج قراءته. وهو حجم نافذة السياق التي تحتوي على المطالبة وكل ما أُنتج حتى تلك اللحظة. تؤدي زيادته إلى استهلاك مزيد من الذاكرة، لأن ذاكرة المفتاح/القيمة التي يحتفظ بها النموذج لهذه الرموز تنمو مع حجم النافذة. تُعد تحديد حجم num_ctx بما يناسب عتادك مهمة منفصلة، ولها حالات فشل خاصة بها.
num_predict يحدد مقدار ما سيقوم النموذج بكتابته. وهو قاعدة لإيقاف التوليد، وليس تخصيصاً للموارد. تؤدي زيادته إلى استهلاك مزيد من الوقت الفعلي بدلاً من RAM، ولا يُحجز أي مقدار مسبقاً.
يلتقي الخياران في موضع واحد. تدخل الرموز المُولَّدة إلى نافذة السياق أثناء توليدها، لذلك قد تتوقف الإجابة أيضاً لأن النافذة امتلأت، لا لأن الحد الذي حددته قد بُلغ. يعرض Ollama القيمة length في كلتا الحالتين، ولذلك فإن الرقم الذي يميّز بينهما هو eval_count، وسنتناوله بمزيد من التفصيل أدناه.
ضبطه مرة واحدة باستخدام Modelfile
تُثبّت Modelfile القيمة داخل نموذج تنشئه. اكتب الملف:
FROM qwen3:8b
PARAMETER num_ctx 8192
PARAMETER num_predict 512ثم أنشئ النموذج واقرأ القيمة التي ثبّتَّها:
ollama create qwen3-capped -f Modelfile
ollama show --parameters qwen3-cappedيعرض ollama show --parameters سطراً واحداً لكل معلمة مخزنة مع قيمتها. إذا لم يظهر num_predict في ذلك الناتج، فلا يحتوي النموذج على حد أقصى مثبت داخلياً، ويُطبَّق الإعداد الافتراضي الخاص بـOllama. يعرض ollama show --modelfile qwen3-capped التعريف الكامل، وهي أيضاً أسرع طريقة لنسخ المعلمات التي يأتي بها نموذج موجود مسبقاً. لا يتطلب إنشاء نموذج بحد أقصى بهذه الطريقة مساحة إضافية تُذكر على القرص، لأن الإدخال الجديد يعيد استخدام كتل الأوزان التي نزّلها النموذج الأساسي مسبقاً بدلاً من نسخها، ومن المفيد معرفة مكان احتفاظ Ollama بهذه الكتل قبل امتلاء قرص root في VPS.
هذه هي الطبقة المناسبة لقيمة تريد أن يرثها كل مستدعٍ. لكنها ليست الطبقة المناسبة إذا كنت تتوقع أن تكون القيمة نهائية، لأنها ليست كذلك.
اضبطه لكل طلب داخل كائن الخيارات
تتلقى كل نقطة نهاية للتوليد كائن options، ويُوضَع num_predict داخله:
curl http://localhost:11434/api/generate -d '{
"model": "qwen3:8b",
"prompt": "Explain what a reverse proxy does.",
"stream": false,
"options": { "num_predict": 128 }
}'يستخدم /api/chat مفتاح options نفسه بالمعنى نفسه. تنطبق القيمة المحددة هنا على هذه المكالمة الواحدة فقط، ولا تنطبق على أي شيء آخر. هذه هي الطبقة التي تستخدمها أدواتك: واجهة أمامية للمحادثة، أو نص برمجي، أو غلاف SDK، أو وكيل برمجي. ترسل جميعها كائن options، سواء أظهرت لك حقلاً له أم لا.
عيّنه لجلسة واحدة باستخدام المعامل /set
داخل ollama run، تضبط الجلسة التفاعلية الخيارات لبقية الجلسة:
>>> /set parameter num_predict 256
>>> /show parametersيعرض /show parameters ما سترسله الجلسة مع رسالتك التالية، لذلك فهو أسرع طريقة للتأكد من تطبيق التغيير. تبقى القيمة حتى تكتب /bye. للاحتفاظ بها، يحفظ /save qwen3-capped الجلسة الحالية، بما في ذلك المعاملات، كنموذج جديد. لا يصل أي شيء تكتبه هنا باستخدام /set إلى أي عميل آخر.
أي إعداد يسري، ولماذا يبدو إعدادك متجاهلاً
ترتيب الأولوية بسيط. تتغلب الخيارات المرسلة مع الطلب على كل ما عداها. يكون السطر PARAMETER num_predict في Modelfile الخاص بالنموذج هو الخيار الاحتياطي المستخدم عندما لا يحمل الطلب قيمة. وعند غياب الخيارين، يُطبّق الإعداد الافتراضي المضمّن في Ollama.
لا يمثل /set parameter قاعدة ثالثة. فالجلسة التفاعلية عميل API، ولذلك تُرسل القيمة التي تضبطها هناك ضمن options الخاص بذلك الطلب. وهذا يفسر بالضبط سبب تجاوزها لإعداد Modelfile طوال الجلسة.
إليك سبب المشكلة التي يفسرها ذلك. تضيف PARAMETER num_predict 512، ثم تعيد بناء النموذج، لكن الردود تستمر في الوصول إلى آلاف الرموز. إعدادك موجود، ويثبت ollama show --parameters ذلك. لكنه يُتجاوز في كل طلب، لأن العميل يرسل كائن options خاصاً به، ويحمل رقماً خاصاً به. وغالباً ما يكون هذا الرقم قد أدخلته في شاشة إعدادات قبل أشهر ثم نسيته. يقرأ ollama show النموذج المخزّن. لكنه لا يستطيع إظهار ما يصل عبر HTTP.
أثبت ما يحدث على جانب الخادم باستخدام أمر واحد. أرسل طلباً سينتج إجابة طويلة، وخفّض الحد الأقصى قسراً، ثم اقرأ حقلين:
curl -s http://localhost:11434/api/generate -d '{
"model": "qwen3-capped",
"prompt": "Describe the Linux boot process in detail.",
"stream": false,
"options": { "num_predict": 32 }
}' | jq '.done_reason, .eval_count'من المفترض أن يطبع ذلك "length" و32. ثبّت jq أولاً باستخدام sudo apt install -y jq إذا لم يكن مثبتاً. تعني الاستجابة "length" و32 أن الخادم يلتزم بالخيار، وأن تطبيقك يرسل قيمة مختلفة. ولمعرفة ما سجله الخادم نفسه عن الطلب، أعد تشغيله مع OLLAMA_DEBUG=1 في البيئة، ثم راقب journalctl -u ollama -f أثناء اتصال تطبيقك به.
القيم السالبة والأرقام التي يجب ألا تنسخها
يقبل num_predict أيضاً قيماً سالبة، وتُستخدم هذه القيم كإشارات خاصة لا كأعداد. تعني إحدى القيم السالبة «لا تضع حداً لهذا؛ واصل التوليد». وكانت قيمة أخرى تعني «املأ السياق المتبقي». اعتباراً من August 2026، يذكر مرجع Ollama Modelfile أن القيمة الافتراضية هي -1، أي التوليد غير المحدود، كما أدرجت إصدارات أقدم من الجدول نفسه -2 لملء السياق.
تعامل مع هذه القيم على أنها مرتبطة بالإصدار، لأنها تغيّرت. فقد وثّق المرجع القيمة الافتراضية على أنها 128 مدة طويلة، قبل تصحيح الإدخال في نهاية 2024. لذلك ما زالت أدلة كثيرة تكرر الرقم القديم. اقرأ مرجع معلمات Modelfile للإصدار الذي تشغّله فعلياً، ثم تحقّق من السلوك باستخدام الفحص eval_count أعلاه. القيمة التي تحققت منها على جهازك أفضل من قيمة قرأتها في أي مكان، بما في ذلك هذا المنشور.
سبب كون طول المخرجات هو التكلفة الرئيسية على VPS يعمل بالـCPU فقط
تتم عملية التوليد على مرحلتين بسرعتين مختلفتين جداً. تُقيَّم رموز الطلب على دفعات، بعدة رموز في كل مرة. أما رموز المخرجات فتُنتَج واحداً تلو الآخر، ويحتاج كل رمز منها إلى تمريرة كاملة على أوزان النموذج. في VPS يعمل بالـCPU فقط، تكون هذه التمريرة محدودة بعرض نطاق الذاكرة، لذلك تكلف كل خانة مولّدة أكثر بكثير من كل خانة في الطلب. وبما أن التمريرة تقرأ كل وزن، فإن عدد وحدات البايت التي يشغلها كل وزن يحدد الحد الأقصى لمعدل إنتاج الرموز، ولهذا يفكّ إصدار q4 الرموز بسرعة أكبر من النموذج نفسه عند q8 أو fp16.
اطلب استجابة من دون streaming، وستظهر الأرقام مباشرة:
"prompt_eval_count": 26,
"prompt_eval_duration": 107345000,
"eval_count": 237,
"eval_duration": 4289432000المدد بوحدة النانوثانية. في ذلك المقطع، وهو استجابة نموذجية منشورة في وثائق Ollama API وليس قياساً لأي خادم محدد، استغرقت 26 خانة في الطلب نحو 0.1 ثانية، بينما استغرقت 237 خانة في المخرجات نحو 4.3 ثوانٍ. معدل التوليد لديك هو eval_count مقسوماً على eval_duration بعد تحويله إلى ثوانٍ، ومن المفيد قياس عدد الرموز في الثانية على أجهزتك مرة واحدة قبل ضبط أي شيء آخر. يعتمد هذا المعدل على النموذج بقدر اعتماده على الجهاز، لذلك إذا كانت الإجابات الطويلة هي التكلفة الفعلية، فإن نموذجاً مصمماً للفك السريع مثل Nemotron 3.5 Lightning على VPS يستعيد بعض الوقت الذي يحاول الحد المنخفض توفيره.
تتولى الحسابات بقية الأمر. عند معدل 8 رموز في الثانية، تُبقي إجابة من 2,000 رمز الجهاز مشغولاً لأكثر من أربع دقائق، ولا يعرف النموذج أنك أردت فقرة واحدة. ينفق نموذج الاستدلال جزءاً من هذه الميزانية في التفكير قبل أن يكتب الكلمة التي طلبتها، ويُولَّد هذا التفكير رمزاً تلو الآخر مثل كل شيء آخر، لذلك فإن جهد الاستدلال الذي تطلبه عامل آخر يؤثر في الفاتورة نفسها. تدخل بعض النماذج أيضاً في حلقات، فتكرر عبارة إلى أن يوقفها شيء ما. من دون حد، يبقي ذلك الطلب الواحد نواةً مشغولة حتى تنفد نافذة السياق. ويحدد num_predict هذا الحد، وهو أمر مهم خصوصاً على VPS صغير مستضاف ذاتياً ويشغّل Ollama حيث يشغل طلب طويل واحد الجهاز بأكمله.
يكون الإخراج المبتور عادةً بسبب الحد الأقصى، لا بسبب تعطل النموذج
تبدو الأعراض كأنها فشل في النموذج. إجابة تتوقف في منتصف الجملة. وJSON يتعذر تحليله لأن القوس الختامي لم يصل. يكون رد الفعل التلقائي هو إلقاء اللوم على النموذج أو على quantisation. اقرأ الاستجابة أولاً.
تعني done_reason أن الإجابة تجيب عن السؤال مباشرةً. وتعني stop أن النموذج أنهى التوليد من تلقاء نفسه، إما بإصدار رمز نهاية التسلسل أو بمطابقة إحدى السلاسل في الخيار stop. وتعني length أن التوليد توقف لأنه نفد الحيز المتاح. عند ظهور length، قارن eval_count بالحد الأقصى الذي حددته: إذا تطابق الرقمان تماماً، فهذا يعني أن num_predict أوقف التوليد، أما الرقم الأصغر فيعني أن نافذة السياق امتلأت أولاً.
عند استخدام البث، تصل هذه الحقول في الجزء الأخير، أي الجزء الذي يحمل "done": true. تتخلص كثير من مكتبات العملاء من هذا الجزء، ولا تسلّم إلى برنامجك سوى النص؛ لذلك يبدو الاقتطاع نفسه غير مفسر داخل التطبيق، بينما يكون واضحاً تحت curl. إذا كانت مكتبة ما تخفي هذه المعلومات، فأرسل طلباً واحداً مع curl لمعرفة ما قاله الخادم فعلياً.
هناك نقطة أخرى تمنع إضاعة فترة بعد الظهر. لا يؤدي رفع num_predict إلى جعل النموذج يكتب أكثر. إنه يزيل سقفاً فقط. إذا انتهت إجابة عند 200 token مع done_reason من stop، فهذا يعني أن النموذج قرر أنه انتهى، ولن يغيّر رفع الحد الأقصى شيئاً. الإجابات القصيرة مع stop تعني أن المشكلة في صياغة الطلب. والإجابات القصيرة مع length تعني أن المشكلة في الحد الأقصى.
اختيار قيمة
- بالنسبة إلى الدردشة التفاعلية، اتركها بلا حد واضغط على Ctrl+C لإيقاف الرد الخارج عن السيطرة. فأنت تراقب الشاشة في كل الأحوال.
- بالنسبة إلى أي شيء يعمل بواسطة script، حدّدها. فتوليد غير محدود داخل حلقة هو ما يجعل مهمة batch يُفترض أن تستغرق عشر دقائق تستمر حتى صباح اليوم التالي.
- بالنسبة إلى الإخراج المنظّم، حدّد الحد أعلى من أكبر مستند صالح تتوقعه، ثم اعتبر
done_reasonمنlengthخطأً حرجاً وأعد المحاولة بدلاً من تحليل الناتج الذي وصل. - بالنسبة إلى coding agent، يجب أن تكون القيمة في إعداداته الخاصة، لأن الوكيل يرسل خياراته الخاصة مع كل طلب. يوضّح توجيه coding agent إلى Ollama موضع هذه الإعدادات.
يحسب الحدّ tokens، وليس الكلمات أو الأحرف، لذلك لا تقدّره. أنشئ إجابة تمثيلية واحدة بلا حد، واقرأ eval_count، ثم اضبط الحد أعلى منها بهامش مناسب. تختلف طريقة tokenise بين عائلات النماذج، لذلك قد تكفي قيمة معيّنة لنموذج Llama، لكنها قد تقتطع الإجابة نفسها من نموذج Qwen 3 على VPS نفسه.
FAQ
ما الفرق بين num_ctx وnum_predict في Ollama؟
يمثل num_ctx حجم نافذة السياق، ولذلك يحدد مقدار ما يمكن للنموذج قراءته: المطالبة وكل ما أُنتج حتى الآن. يستهلك ذلك الذاكرة، لأن ذاكرة التخزين المؤقت للمفاتيح والقيم تزداد معه. يحدد num_predict عدد الرموز المميزة التي يمكن للنموذج كتابتها في استجابة واحدة. ويستهلك ذلك الوقت بدلاً من الذاكرة، ولا يُحجز شيء مسبقاً. تُحتسب الرموز المميزة المُنشأة ضمن الحدين، لذلك يمكن أن تتوقف الاستجابة مبكراً بسبب أي منهما.
لماذا يبدو أن إعداد num_predict لديّ متجاهَل؟
لأن القيمة المُرسلة مع الطلب تتجاوز القيمة المخزنة في النموذج. ضع PARAMETER num_predict 512 في Modelfile، ثم شغّل ذلك النموذج من واجهة محادثة أو وكيل برمجي، وسيرسل العميل كائن options الخاص به، وتكون قيمته هي المعتمدة. سيظل ollama show --parameters يعرض قيمتك، لأنه يقرأ النموذج المخزن ولا يمكنه معرفة ما يصل عبر HTTP. أرسل طلباً واحداً باستخدام curl عبر "options": {"num_predict": 32}، وتحقق من أن eval_count تعود بالقيمة 32. يؤكد ذلك أن الخادم نفسه يعمل كما ينبغي، وينقل البحث إلى تطبيقك.
كيف أعرف ما إذا كان num_predict قد أوقف إخراجي؟
أرسل الطلب باستخدام "stream": false واقرأ done_reason. تعني القيمة stop أن النموذج أنهى التوليد من تلقاء نفسه. وتعني القيمة length أنه نفد الحيز المتاح. قارن بعد ذلك eval_count بالحد الذي حددته: إذا تطابقا تماماً، فإن num_predict هو الذي أوقف التوليد، وإذا كانت eval_count أصغر، فقد امتلأت نافذة السياق أولاً. عند استخدام البث، يصل الحقلان في المقطع الأخير مع "done": true، لكن العديد من مكتبات العملاء تتخلص منه قبل أن يراه تطبيقك.
ما القيمة الافتراضية لـ num_predict؟
اقرأها من تثبيتك أنت بدلاً من الاعتماد على مقالة. حتى August 2026، يذكر مرجع Ollama Modelfile أن القيمة الافتراضية هي -1، ما يعني أن التوليد غير مقيّد بحد، وقد صُحّحت هذه المعلومة في نهاية 2024 بعد سنوات من توثيق 128. القيم السالبة مؤشرات خاصة وليست أعداداً، كما كانت الإصدارات الأقدم من الجدول نفسه تسرد -2 لملء ما تبقى من السياق. راجع مرجع معاملات Modelfile للإصدار الذي تستخدمه، ثم أكّد ذلك باستخدام ollama show --parameters وطلب واحد من curl.
هل يؤدي رفع num_predict إلى جعل النموذج يكتب إجابات أطول؟
لا. فهو يزيل سقفاً فقط. إذا انتهت الاستجابة مع done_reason من stop، فهذا يعني أن النموذج قرر أنه انتهى، ولن يغيّر رفع الحد شيئاً. يكون طول الاستجابة في هذه الحالة مسألة تتعلق بصياغة المطالبة: اطلب بنية محددة، أو عدداً من الأقسام، أو مستوى تفصيل معلناً. ارفع num_predict فقط عندما تعود done_reason بالقيمة length.