SSD Nodes Learn 🎉 VPS من $5.50/شهر
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-08-21

ما الذي يغيّره جهد الاستدلال في نموذج محلي؟

تعرّف إلى ما تغيّره مستويات جهد الاستدلال في نموذجك المحلي، ولماذا قد يتحول زمن الرد من ثانيتين إلى دقيقتين، وكيف تقيس التكلفة الفعلية.

ما الذي يتغير عند ضبط جهد الاستدلال في نموذج LLM محلي

جهد الاستدلال هو إعداد يحدد المدة التي يفكر فيها النموذج قبل أن يجيب. ويغيّر طول جزء الاستدلال فقط، ولا يغيّر أي شيء آخر. تظل الأوزان المخزنة على القرص متطابقة عند كل مستوى، وتظل عملية التكميم متطابقة، وتصدر الإجابة من التمريرة الأمامية نفسها. ما يتغير هو عدد الرموز التي يخصصها النموذج أولاً لمسودة التفكير الخاصة به.

يهم هذا التمييز بسبب المكان الذي تُستهلك فيه هذه الرموز. في واجهة API مستضافة، تظهر رموز الاستدلال في الفاتورة. أما على VPS تملكه، فتُستهلك في زمن التوليد على CPU أو GPU الخاص بك، وفي المساحة داخل نافذة السياق. قد يستهلك النموذج، إذا تُرك على أعلى مستوى من الجهد، معظم مخرجاته في الاستدلال قبل ظهور الكلمة الأولى من الإجابة. وعلى العتاد المستضاف ذاتياً، قد يعني ذلك الفرق بين رد يستغرق ثانيتين وآخر يستغرق دقيقتين.

أين يوجد مستوى الجهد: في قالب المحادثة، لا في الأوزان

يُدرَّب نموذج التفكير على إخراج جزء للاستدلال، يُغلَّف عادةً بوسمي <think> و</think>، قبل إجابته النهائية. مستوى الجهد هو تعليمة يكتبها قالب المحادثة الخاص بالنموذج داخل الموجّه. هذا القالب ملف Jinja يأتي مع النموذج. ويقرأ متغيراً مثل reasoning_effort، ثم يُنشئ سطراً مختلفاً على مستوى النظام لكل قيمة. وقد دُرِّب النموذج على تقصير مساحة العمل الداخلية أو إطالتها استجابةً لذلك السطر.

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

حتى 2026-08-20، توثّق بطاقة نموذج Qwen3.8-27B ثلاثة مستويات للجهد: low وmedium وxhigh، مع xhigh بوصفه المستوى الافتراضي. لا يوجد high. ويُفعَّل التفكير باستخدام enable_thinking، وهو مفعّل افتراضياً. كما توثّق البطاقة preserve_thinking، وهو مفعّل افتراضياً أيضاً، ويحتفظ بالاستدلال من الأدوار السابقة في سجل المحادثة. ويستخدم gpt-oss بدلاً من ذلك low وmedium وhigh. وتقبل عائلات أخرى كثيرة قيمة منطقية فقط، ولا تقبل مستويات إضافية. راجع بطاقة الإصدار المحدد الذي نزّلته، لأن هذه الأسماء ليست معياراً موحداً. ابدأ بـتشغيل نموذج 27B على VPS. تتناول هذه الصفحة الإعدادات التي ينبغي ضبطها بعد أن يبدأ النموذج بالإجابة.

لماذا ترتفع التكلفة عند استخدام جهد استدلال كبير على VPS

رموز الإخراج. تُحتسب رموز الاستدلال المولَّدة ضمن الرموز المولَّدة نفسها. تمر هذه الرموز في حلقة فك الترميز نفسها التي تمر فيها رموز الإجابة، وبمعدل الرموز نفسه الذي تسمح به أجهزتك. افترض أن المهمة تنتج 200 رمز للإجابة و4,000 رمز للاستدلال. لقد ولّدت 4,200 رمز، لكن القارئ رأى 200 رمز فقط. يتحدد معدل فك الترميز بعرض نطاق الذاكرة وبـالتكميم الذي اخترته، لذلك يبقى عدد الرموز نفسه الرافعة الوحيدة المتاحة.

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

السياق. تشغل رموز الاستدلال مساحة في نافذة السياق مثل أي رموز أخرى. عند تفعيل preserve_thinking، تظل المسودة الناتجة من الدور الأول ضمن الطلب في الدور الخامس، لذلك تصبح معالجة الطلب أبطأ في كل دور، بينما تمتلئ النافذة من الطرفين. إن رفع قيمة num_ctx لاستيعابها يستهلك ذاكرة KV cache، وهي في VPS الذي لا يحتوي على GPU ذاكرة النظام RAM التي قد لا تتوفر لديك.

متى ترفع المستوى، ومتى تبقيه منخفضاً

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

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

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

كيفية ضبط المستوى في llama.cpp

يكتب llama.cpp المتغير مباشرةً في القالب، ما يجعل بيئة التشغيل هذه هي المكان الذي يمكنك فيه التأكد من وصول المستوى. وجّه -m إلى ملف GGUF الموجود لديك.

llama-server -m ./qwen3.8-27b-Q4_K_M.gguf \
  --jinja \
  --reasoning-effort medium \
  --reasoning-format deepseek \
  -c 32768 \
  --host 127.0.0.1 --port 8080

يستخدم --jinja قالب المحادثة الخاص بالنموذج، وهو مفعّل افتراضياً في الإصدارات الحالية. يقبل --reasoning-effort القيم default أو minimal أو low أو medium أو high أو xhigh أو max، حيث يعني default ترك القيمة الافتراضية المحددة في القالب كما هي. هذه القائمة هي مفردات llama.cpp وليست مفردات النموذج، لذلك مرّر اسماً مدرجاً في بطاقة النموذج فقط. فقد يؤدي استخدام مستوى لا يعرّفه القالب إلى ظهور خطأ في القالب وقت الطلب. ينقل --reasoning-format deepseek الاستدلال من message.content إلى message.reasoning_content، وهذا ما يجعل فصل الجزأين قابلاً للقياس في القسم التالي.

لإيقاف التفكير بدلاً من تقصيره، اضبط متغير القالب بنفسك:

llama-server -m ./qwen3.8-27b-Q4_K_M.gguf --jinja \
  --chat-template-kwargs '{"enable_thinking": false}'

تعمل --reasoning-budget بآلية مختلفة. فهي تحدد الحد الأقصى لجزء الاستدلال بعدد الرموز، إذ تنهيه 0 فوراً، بينما تتركه -1 بلا قيود، بدلاً من مطالبة النموذج بالتخطيط لجزء أقصر. ينطبق كلا الخيارين على الخادم بأكمله. لا يقبل llama-server قيمة reasoning_effort كحقل خاص بالطلب، لذلك يتطلب تقديم مستويين من الجهد في الوقت نفسه تشغيل عمليتين على منفذين مختلفين.

يتيح vLLM المتغير نفسه لكل طلب، داخل النص المتوافق مع OpenAI:

{"model": "Qwen/Qwen3.8-27B",
 "messages": [{"role": "user", "content": "Summarise this changelog in two lines."}],
 "chat_template_kwargs": {"reasoning_effort": "medium"}}

كيفية ضبط المستوى في Ollama

يحتوي Ollama على الحقل الخاص به، think، في /api/chat و/api/generate. ويقبل true أو false أو إحدى القيم low وmedium وhigh وmax، حيث تطلب max أعلى مستوى يوفّره النموذج. يكون التفكير مفعّلاً افتراضياً في النماذج التي تدعمه.

ollama run qwen3.8:27b --think=low "Draft a one line commit message for a README typo fix"
{"model": "qwen3.8:27b",
 "messages": [{"role": "user", "content": "Which HTTP status code means the request body was too large?"}],
 "think": "low",
 "stream": false}

تظهر عملية الاستدلال في message.thinking، وتظهر الإجابة في message.content، وقد فُصل كل منهما لك. داخل جلسة ollama run تفاعلية، يبدّل /set think و/set nothink هذه الميزة من دون إعادة التشغيل.

لاحظ الآن عدم التطابق. يستخدم Ollama مستويات low وmedium وhigh وmax. بينما يعرّف قالب Qwen3.8 المستويات low وmedium وxhigh. لذلك يجب تحويل أحدهما إلى الآخر. ويحمل نموذج Ollama قالباً مضمّناً داخل وسمه، بدلاً من ملف Jinja الموجود في المستودع الأصلي. لذلك يعتمد وصول المستوى الذي تحدده إلى النموذج على ذلك القالب المضمّن. لا تفترض أن الإعداد نجح. يستغرق قياس ذلك نحو دقيقة واحدة.

كيفية قياس ما إذا كان المستوى قد طُبِّق فعلياً

أرسل الطلب نفسه على أكثر من مستوى مع ضبط temperature على 0، ثم قارن أعداد الرموز. هنا ينشئ jq النص، لذلك لا تحتاج إلى تهريب علامات الاقتباس يدوياً.

for level in low medium max; do
  body=$(jq -n --arg lvl "$level" '{
    model: "qwen3.8:27b",
    messages: [{role: "user", content: "A pump fills a 4500 litre tank in 25 minutes. A second pump is 40 percent slower. How long do both together take? Answer in minutes."}],
    think: $lvl,
    stream: false,
    options: {temperature: 0, num_ctx: 8192}
  }')
  echo "== $level"
  curl -s http://localhost:11434/api/chat -d "$body" | jq '{
    thinking_chars: (.message.thinking // "" | length),
    answer_chars: (.message.content | length),
    eval_count: .eval_count,
    seconds: (.total_duration / 1e9),
    tok_per_sec: (.eval_count / (.eval_duration / 1e9))
  }'
done

يشمل eval_count كل رمز تم إنشاؤه، بما في ذلك رموز الاستدلال، لذلك يكون الفرق بين مستويين مكوّناً تقريباً بالكامل من الاستدلال. ويعرض thinking_chars هذا التقسيم مباشرة. يجب أن يتحقق أمران: أن تتغير الأرقام بين المستويات، وأن تظل الإجابة صحيحة عند المستوى الأدنى. إذا بقي eval_count ضمن نطاق الضجيج في عمليات التشغيل الثلاث كلها، فهذا يعني أن المستوى متجاهَل. ويكون الحل حينها استخدام runtime يمرره، لا اختيار اسم مستوى مختلف.

الوقت الإجمالي ليس سوى نصف الصورة. لذلك قِس الفاصل حتى أول رمز في الإجابة عبر البث، وأوقف التنفيذ عند أول جزء غير فارغ من content. يتطلب ذلك jq وbc.

start=$(date +%s.%N)
curl -sN http://localhost:11434/api/chat -d '{
  "model": "qwen3.8:27b",
  "messages": [{"role": "user", "content": "Explain what a reverse proxy does, in three sentences."}],
  "think": "low",
  "stream": true
}' |
while IFS= read -r line; do
  if [ -n "$(printf '%s' "$line" | jq -r '.message.content // ""')" ]; then
    echo "first answer token after $(echo "$(date +%s.%N) - $start" | bc)s"
    break
  fi
done

شغّله عند low، ثم شغّله مرة أخرى عند max. الفرق بين القيمتين هو مدة الانتظار التي أضفتها. في llama.cpp تعود الأرقام نفسها ضمن الاستجابة، ولا تحتاج إلى إجراء حسابات في shell:

curl -s http://localhost:8080/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"model": "local", "temperature": 0,
       "messages": [{"role": "user", "content": "A pump fills a 4500 litre tank in 25 minutes. A second pump is 40 percent slower. How long do both together take?"}]}' | jq '{
  reasoning_chars: (.choices[0].message.reasoning_content // "" | length),
  answer_chars: (.choices[0].message.content | length),
  predicted_n: .timings.predicted_n,
  tok_per_sec: .timings.predicted_per_second
}'

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

ما الذي يحدث خطأ

يُقتطع الجواب، أو يكون content فارغاً بينما يكون thinking ممتلئاً. استُهلك حد التوليد في الاستدلال. يحدّد num_predict في Ollama التوليد بأكمله، بما في ذلك الاستدلال، ويأتي الاستدلال أولاً؛ لذلك قد ينتهي الرد قبل بدء الجواب عند ضبط الحد على 512 رمزاً مع مستوى جهد مرتفع. يعرض Ollama القيمة "done_reason": "length" لذلك الرد. ارفع الحد أو خفّض مستوى الجهد. يشرح كيفية احتساب num_predict للرموز هذا التفاعل بالتفصيل.

لا يغيّر المستوى أي شيء. تكون أعداد الرموز متطابقة في كل مستوى. إما أن بيئة التشغيل لا تمرّر المتغير، أو أن القالب لا يقرأه. افحص القالب الذي تستخدمه بيئة التشغيل فعلياً، لا القالب الموجود في المستودع الأصلي. يكتب llama.cpp المتغير يدوياً عند استخدام --jinja و--chat-template-kwargs، لذلك يصلح كاختبار ضابط: إذا عمل المستوى هناك ولم يعمل في أي مكان آخر، فالنموذج سليم وبيئة التشغيل الأخرى تُسقط المتغير.

يُرفض اسم المستوى. يعني خطأ في القالب وقت الطلب، أو فشل في الرسالة الأولى مع خادم سليم من النواحي الأخرى، عادةً أنك مرّرت مستوى لا يعرّفه القالب، مثل high إلى نموذج تسرد بطاقة النموذج مستوياته على أنها low وmedium وxhigh فقط.

تتباطأ المحادثات متعددة الأدوار في كل دور. يجري الاحتفاظ بالاستدلال القديم في السجل. اضبط preserve_thinking على false إذا كان النموذج يدعم ذلك، أو احذف الحقل thinking من الرسائل التي ترسلها مجدداً. وإلا يزداد حجم معالجة الطلب في كل دور، بينما تبقى الإجابات بالطول نفسه.

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

تشغيل مستويين في الوقت نفسه

يثبّت llama.cpp المستوى عند بدء التشغيل، لذلك يحتاج خادم يقدّم محرراً ومهمة دفعية ليلية إلى عمليتين على منفذين، ولكل عملية --reasoning-effort الخاص بها. تعني العمليتان أيضاً وجود نسختين من الأوزان في الذاكرة، ما لم تفصل بين المهمتين زمنياً. على VPS واحد، يكون الترتيب الأقل تكلفة عادةً خادماً منخفض الجهد لأي شيء ينتظر نتيجته شخص، مع تشغيل مجدول بمستوى جهد أعلى للأعمال التي لا يراقبها أحد. ينطبق هنا أيضاً ماذا يحدث عندما يتشارك عدة مستخدمين نموذجاً محلياً: رموز الاستدلال هي عمل فك ترميز، لذلك يؤدي رفع مستوى الجهد إلى خفض التزامن الفعلي لديك تقريباً بالعامل نفسه الذي يزيد به عدد الرموز.

FAQ

ما مستوى جهد الاستدلال الذي يجب أن أستخدمه افتراضياً؟

ابدأ بأدنى مستوى يتيحه النموذج، وارفعه فقط للمهام التي لاحظت فشلها. تُصدر بعض نماذج التفكير بإعداد افتراضي مرتفع، ويستخدم Qwen3.8-27B المستوى xhigh افتراضياً، وهو أعلى مستوى لديه، اعتباراً من August 2026. اختير هذا الإعداد ليبدو جيداً في جداول اختبارات الأداء، لكن جدول الاختبار لا يحاسبك على الوقت. أما على أجهزتك، فأنت تدفع بالثواني؛ لذلك اجعل المستوى الأعلى خياراً تفعّله لكل مهمة، بدلاً من أن يكون الإعداد الذي ترثه كل طلباتك.

هل تُحتسب رموز الاستدلال ضمن نافذة السياق؟

نعم. هذه الرموز عادية في المخرجات، وتبقى في نافذة السياق مع كل شيء آخر. يعتمد بقاؤها في الدور التالي على بيئة التشغيل والنموذج. توثّق بطاقة Qwen3.8 الحقل preserve_thinking، وهو مفعّل افتراضياً، ويحتفظ بالاستدلال السابق في السجل؛ لذلك تحمل المحادثة الطويلة كل مسودات التفكير التي أنشأها النموذج. اضبطه على false، أو احذف الحقل thinking من الرسائل التي تعيد تمريرها، وسيتوقف ازدياد وقت معالجة الطلب.

لماذا لا يغيّر تغيير مستوى التفكير عدد الرموز لدي؟

الإعداد لا يصل إلى قالب المحادثة. المستوى متغير في القالب، لذلك يعمل فقط إذا مرّرته بيئة التشغيل وقرأه القالب المضمّن. تُصدر بعض بيئات التشغيل قالبها الخاص مع النموذج بدلاً من استخدام ملف Jinja من المستودع الأصلي، وعندها يُحذف المتغير من دون طباعة أي خطأ. أثبت ذلك بإرسال الطلب نفسه عند أدنى مستوى وأعلى مستوى، مع ضبط temperature على 0، ثم قارن eval_count. إذا تطابقت الأعداد ضمن هامش الضوضاء، فإن المستوى يجري تجاهله.

هل يجعل خفض جهد الاستدلال النموذج أقل دقة؟

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