محدود کردن تعداد توکن خروجی در Ollama با num_predict
با تنظیم num_predict در Ollama تعداد توکنهای تولیدی را کنترل کنید. این راهنما اولویت تنظیمات در سه لایه مختلف و نحوه بررسی done_reason برای تشخیص پایان پاسخ را توضیح میدهد.
عملکرد num_predict در Ollama
num_predict گزینهای در Ollama است که تعداد توکنهایی که یک مدل میتواند در هر پاسخ تولید کند را محدود میکند. این گزینه فقط توکنهای خروجی را میشمارد، بنابراین prompt هرگز جزو این محدودیت محاسبه نمیشود. هنگامی که مدل به این سقف برسد، تولید متن در همان نقطه متوقف میشود (گاهی در میان یک کلمه) و پاسخ با مقدار length برای فیلد done_reason بازگردانده میشود.
این تمام عملکرد این قابلیت است. دشواری کار در اینجاست که Ollama سه جای مختلف برای تنظیم این مقدار در اختیار شما میگذارد و تنظیمی که به درخواست نزدیکتر باشد، اولویت دارد. تقریباً تمام گزارشهای مبنی بر «کار نکردن num_predict» ناشی از این است که یک لایه بهطور بیصدا لایه دیگر را بازنویسی میکند.
تفاوت num_predict و num_ctx
این دو گزینه بیش از هر جفت تنظیمات دیگری در Ollama باعث سردرگمی میشوند و این اشتباه، زمان زیادی را برای عیبیابی هدر میدهد.
num_ctx مشخص میکند که مدل چقدر میتواند بخواند. این مقدار، اندازه پنجره کانتکست (context window) است که شامل پرامپت و تمام محتوای تولیدشده تا این لحظه میشود. افزایش این مقدار باعث مصرف حافظه بیشتر میشود، زیرا کش کلید/مقدار (key/value cache) که مدل برای این توکنها نگه میدارد، با بزرگ شدن پنجره رشد میکند. تعیین اندازه num_ctx برای سختافزار شما یک وظیفه جداگانه با حالتهای شکست خاص خود است.
num_predict مشخص میکند که مدل چقدر میتواند بنویسد. این یک قانون توقف است، نه یک تخصیص حافظه. افزایش آن به جای RAM، زمان اجرای واقعی (wall-clock time) را افزایش میدهد و هیچ فضایی از قبل رزرو نمیشود.
این دو در یک نقطه به هم میرسند. توکنهای تولیدشده همزمان با ساخته شدن، درون پنجره کانتکست قرار میگیرند؛ بنابراین پاسخ مدل ممکن است به دلیل پر شدن پنجره متوقف شود، نه لزوماً به این دلیل که سقف تعیینشده شما رسیده است. Ollama در هر دو حالت length را گزارش میدهد، بنابراین عددی که این دو را از هم متمایز میکند eval_count است که در ادامه به آن پرداخته شده است.
تنظیم یکباره با Modelfile
یک Modelfile مقدار موردنظر را در مدلی که میسازید، تثبیت میکند. فایل را بنویسید:
FROM qwen3:8b
PARAMETER num_ctx 8192
PARAMETER num_predict 512سپس آن را build کرده و خروجی ساختهشده را بررسی کنید:
ollama create qwen3-capped -f Modelfile
ollama show --parameters qwen3-cappedدستور ollama show --parameters برای هر پارامتر ذخیرهشده، یک خط شامل مقدار آن چاپ میکند. اگر num_predict در این خروجی وجود نداشته باشد، مدل هیچ محدودیت (cap) تثبیتشدهای ندارد و مقدار پیشفرض خود Ollama اعمال میشود. دستور ollama show --modelfile qwen3-capped کل تعریف مدل را چاپ میکند که سریعترین راه برای کپی کردن پارامترهایی است که یک مدل موجود از قبل با خود دارد. ایجاد یک مدل محدودشده به این روش تقریباً هیچ فضای دیسک اضافی اشغال نمیکند، زیرا ورودی جدید بهجای کپی کردن، از همان blobهای وزنی که مدل پایه قبلاً دانلود کرده استفاده مجدد میکند؛ دانستن اینکه Ollama آن blobها را کجا نگه میدارد پیش از پر شدن دیسک root در VPS اهمیت دارد.
این لایه برای مقداری که میخواهید همه فراخوانکنندهها (callers) از آن ارثبری کنند، مناسب است. اگر انتظار دارید این مقدار نهایی باشد، این لایه انتخاب اشتباهی است، زیرا چنین نیست.
تنظیم آن برای هر درخواست در شیء options
هر endpoint تولید محتوا یک شیء 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 با همان معنا استفاده میکند. مقداری که در اینجا تعیین میشود، فقط برای همان فراخوانی اعمال میگردد و بر هیچ چیز دیگری تأثیر نمیگذارد. این همان لایهای است که ابزارهای شما از آن استفاده میکنند: یک رابط کاربری چت، یک اسکریپت، یک wrapper برای SDK یا یک عامل برنامهنویسی. همه آنها یک شیء options ارسال میکنند، فارغ از اینکه آیا کادری برای نمایش آن به شما نشان دهند یا خیر.
تنظیم آن برای یک نشست با پارامتر /set
در داخل ollama run، نشست تعاملی گزینهها را برای باقیماندهٔ همان نشست تنظیم میکند:
>>> /set parameter num_predict 256
>>> /show parameters/show parameters آنچه را که نشست با پیام بعدی شما ارسال خواهد کرد چاپ میکند، که سریعترین راه برای تأیید اعمال تغییرات است. این مقدار تا زمانی که /bye را تایپ کنید باقی میماند. برای حفظ آن، /save qwen3-capped نشست فعلی را به همراه پارامترها به عنوان یک مدل جدید ذخیره میکند. هیچچیزی که در اینجا /set میکنید به کلاینت دیگری نمیرسد.
کدام تنظیمات اولویت دارند و چرا تنظیمات شما نادیده گرفته میشود
ترتیب اولویت کوتاه است. گزینههایی که همراه با درخواست ارسال میشوند، بر همه چیز مقدم هستند. یک خط PARAMETER num_predict در فایل Modelfile مدل، تنظیمات جایگزین (fallback) است که در صورت عدم وجود مقدار در درخواست، استفاده میشود. در صورت نبود هر دو، مقدار پیشفرض داخلی Ollama اعمال میشود.
/set parameter یک قانون سوم نیست. نشست تعاملی (interactive session) یک کلاینت API است، بنابراین آنچه در آنجا تنظیم میکنید به عنوان options آن درخواست ارسال میشود؛ دقیقاً به همین دلیل است که تنظیمات Modelfile را برای آن نشست بازنویسی میکند.
حال، این موضوع دلیل شکست شما را توضیح میدهد. شما PARAMETER num_predict 512 را اضافه میکنید، مدل را بازسازی میکنید، اما پاسخها همچنان به هزاران توکن میرسند. تنظیمات شما موجود است و ollama show --parameters صحت آن را تأیید میکند. این تنظیمات در هر درخواست بازنویسی میشود، زیرا کلاینت شیء options خاص خود را با عدد مخصوص خود ارسال میکند؛ عددی که احتمالاً ماهها پیش در صفحه تنظیمات وارد کردهاید و فراموش کردهاید. ollama show مدل ذخیرهشده را میخواند. این ابزار نمیتواند آنچه را که از طریق HTTP دریافت میشود به شما نشان دهد.
سمت سرور را با یک دستور اثبات کنید. درخواستی بفرستید که پاسخ طولانی تولید کند، سقف (cap) را روی مقدار کمی تنظیم کنید و دو فیلد را بخوانید:
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 در محیط اجرا (environment) مجدداً راهاندازی کنید و همزمان با برقراری ارتباط اپلیکیشن، journalctl -u ollama -f را مانیتور کنید.
مقادیر منفی و اعدادی که نباید کپی کنید
num_predict مقادیر منفی را نیز میپذیرد، اما این مقادیر به جای شمارش، نقش نشانگر (sentinel) را دارند. یک مقدار منفی به معنای «محدودیت را اعمال نکن و به تولید ادامه بده» است. مقدار منفی دیگر در گذشته به معنای «پر کردن باقیمانده context» بوده است. از اوت 2026، مرجع Modelfile در Ollama مقدار پیشفرض را -1 یعنی تولید نامحدود اعلام کرده است و نسخههای قدیمیتر همان جدول، مقدار -2 را برای پر کردن context ذکر کرده بودند.
با تمام این موارد به عنوان تنظیمات وابسته به نسخه برخورد کنید، زیرا این مقادیر تغییر کردهاند. مستندات مرجع برای مدت طولانی مقدار پیشفرض را 128 ذکر میکردند تا اینکه این ورودی در پایان سال 2024 اصلاح شد؛ بنابراین بسیاری از راهنماها هنوز همان عدد قدیمی را تکرار میکنند. مرجع پارامترهای Modelfile را برای نسخهای که واقعاً اجرا میکنید بخوانید و سپس رفتار آن را با بررسی eval_count که در بالا ذکر شد، تأیید کنید. مقداری که خودتان روی سیستمتان تأیید کردهاید، از هر مقداری که در هر جای دیگری (از جمله این نوشته) میخوانید، معتبرتر است.
چرا طول خروجی هزینه اصلی در یک VPS بدون GPU است
تولید متن دارای دو مرحله با سرعتهای بسیار متفاوت است. توکنهای پرامپت بهصورت دستهای و تعداد زیاد در هر لحظه ارزیابی میشوند. توکنهای خروجی اما یکییکی تولید میشوند و هر کدام نیازمند یک گذر کامل از روی وزنهای مدل هستند. در یک VPS که فقط از CPU استفاده میکند، این گذر توسط پهنای باند حافظه محدود میشود؛ بنابراین هزینه تولید هر توکن خروجی بسیار بیشتر از یک توکن پرامپت است. از آنجا که این گذر باید تمام وزنها را بخواند، تعداد بایتهای اشغالشده توسط هر وزن، سقف نرخ تولید توکن شما را تعیین میکند؛ به همین دلیل است که یک نسخه q4 سریعتر از همان مدل در حالت q8 یا fp16 دیکد میشود.
اگر درخواست کنید که پاسخ بدون استریم (streaming) ارسال شود، اعداد بهوضوح قابل مشاهده خواهند بود:
"prompt_eval_count": 26,
"prompt_eval_duration": 107345000,
"eval_count": 237,
"eval_duration": 4289432000مدتزمانها به نانوثانیه هستند. در آن بلوک، که نمونه پاسخ منتشرشده در مستندات API مدل Ollama است و نه اندازهگیری یک سرور خاص، پردازش 26 توکن پرامپت حدود 0.1 ثانیه طول کشیده، در حالی که تولید 237 توکن خروجی حدود 4.3 ثانیه زمان برده است. نرخ تولید شما برابر است با eval_count تقسیم بر eval_duration که به ثانیه تبدیل شده است، و اندازهگیری توکن بر ثانیه روی سختافزار خودتان کاری است که ارزش دارد پیش از هر بهینهسازی دیگری انجام دهید. این نرخ به همان اندازه که به ماشین وابسته است، به مدل نیز بستگی دارد؛ بنابراین اگر پاسخهای طولانی هزینه اصلی شما هستند، مدلی که برای دیکد سریع ساخته شده باشد، مانند Nemotron 3.5 Lightning روی یک VPS، بخشی از زمانی را که محدودیتهای پایین (low cap) از شما میگیرند، جبران میکند.
محاسبات ریاضی بقیه کار را انجام میدهند. با نرخ 8 توکن بر ثانیه، یک پاسخ 2000 توکنی ماشین را بیش از چهار دقیقه درگیر میکند و مدل هیچ اطلاعی ندارد که شما فقط یک پاراگراف میخواستید. یک مدل استدلالی (reasoning model) بخشی از این بودجه را صرف فکر کردن پیش از نوشتن اولین کلمه درخواستی شما میکند و این تفکر نیز مانند هر چیز دیگری، توکن به توکن تولید میشود؛ بنابراین میزان استدلالی که درخواست میکنید اهرم دیگری در همان صورتحساب است. برخی مدلها نیز دچار حلقه میشوند و یک عبارت را تا زمانی که چیزی متوقفشان کند، تکرار میکنند. بدون وجود محدودیت (cap)، همان یک درخواست، یک هسته پردازشی را تا پر شدن پنجره کانتکست (context window) مشغول نگه میدارد. num_predict تنظیمی است که این موضوع را محدود میکند و اهمیت آن در یک VPS کوچک برای میزبانی Ollama که در آن یک درخواست طولانی تمام توان ماشین را میگیرد، بسیار زیاد است.
خروجی ناقص معمولاً به دلیل محدودیت است، نه خرابی مدل
علائم، شبیه به خرابی مدل به نظر میرسند. پاسخی که در میان جمله متوقف میشود. کدی با فرمت JSON که تجزیه نمیشود، زیرا براکت پایانی هرگز ارسال نشده است. واکنش غریزی، مقصر دانستن مدل یا کوانتایزیشن (quantisation) است. ابتدا پاسخ را بخوانید.
done_reason به سؤال مستقیماً پاسخ میدهد. stop به این معنی است که مدل به تنهایی کار را تمام کرده است؛ یا با ارسال توکن پایان توالی (end-of-sequence) یا با مطابقت دادن یکی از رشتههای موجود در گزینه stop شما. length به این معنی است که تولید متن به دلیل تمام شدن فضا قطع شده است. هنگامی که length را مشاهده کردید، مقدار eval_count را با سقف (cap) خود مقایسه کنید: مطابقت دقیق به این معنی است که num_predict آن را متوقف کرده است و عدد کوچکتر به این معنی است که پنجره کانتکست (context window) ابتدا پر شده است.
هنگامی که از استریم (stream) استفاده میکنید، این فیلدها در آخرین تکه (chunk) ارسال میشوند، همان تکهای که حاوی "done": true است. بسیاری از کتابخانههای کلاینت آن تکه را دور میریزند و فقط متن را به کد شما تحویل میدهند؛ به همین دلیل است که همان نقص در داخل یک اپلیکیشن غیرقابل توضیح به نظر میرسد، اما در curl کاملاً واضح است. اگر کتابخانهای آن را پنهان میکند، یک درخواست با curl ارسال کنید تا بفهمید سرور واقعاً چه گفته است.
یک نکته دیگر میتواند از هدر رفتن یک بعدازظهر جلوگیری کند. افزایش num_predict باعث نمیشود مدل بیشتر بنویسد. این کار فقط یک سقف را برمیدارد. اگر پاسخی در 200 توکن با done_reason از stop تمام شود، مدل تصمیم گرفته است که کار تمام شده است و افزایش سقف هیچ تغییری ایجاد نمیکند. پاسخهای کوتاه با stop یک مشکل در پرامپتنویسی (prompting) هستند. پاسخهای کوتاه با length یک مشکل در سقف (cap) هستند.
انتخاب یک مقدار
- برای چت تعاملی، آن را بدون محدودیت رها کنید و در صورت پاسخهای طولانی و خارج از کنترل، از Ctrl+C برای توقف استفاده کنید. در هر صورت شما در حال مشاهدهٔ صفحه هستید.
- برای هر فرآیند اسکریپتشده، حتماً محدودیت تعیین کنید. یک تولید متن بدون محدودیت در داخل یک حلقه، عاملی است که باعث میشود یک پردازش دستهای (batch job) که باید 10 دقیقه طول بکشد، تا صبح روز بعد همچنان در حال اجرا باقی بماند.
- برای خروجیهای ساختاریافته، سقف را بالاتر از بزرگترین سند معتبری که انتظار دارید تنظیم کنید، سپس
done_reasonازlengthرا به عنوان یک خطای جدی در نظر بگیرید و بهجای تلاش برای پارس کردن خروجی ناقص، دوباره تلاش کنید. - برای یک عامل برنامهنویسی (coding agent)، این مقدار باید در پیکربندی خودِ عامل قرار بگیرد، زیرا عامل در هر درخواست، گزینههای خاص خود را ارسال میکند. اشاره به یک عامل برنامهنویسی در Ollama توضیح میدهد که این تنظیمات کجا قرار دارند.
این سقف، توکنها را میشمارد، نه کلمات و نه کاراکترها؛ بنابراین آن را حدس نزنید. یک پاسخ نمونه بدون محدودیت تولید کنید، eval_count را بخوانید و سقف را با حاشیهٔ اطمینان بالاتر از آن تنظیم کنید. خانوادههای مدل به روشهای متفاوتی توکنبندی میکنند، بنابراین مقداری که برای یک مدل Llama مناسب است، ممکن است پاسخ مشابه را در یک مدل Qwen 3 روی همان VPS ناقص بگذارد.
FAQ
تفاوت num_ctx و num_predict در Ollama چیست؟
num_ctx اندازه پنجره کانتکست است و تعیین میکند مدل چقدر میتواند بخواند: پرامپت به علاوه تمام مطالبی که تاکنون تولید شده است. این پارامتر حافظه مصرف میکند، زیرا کش کلید/مقدار (key/value cache) با آن رشد میکند. 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 کوچکتر باشد، پنجره کانتکست زودتر پر شده است. هنگام استریم، هر دو فیلد در آخرین تکه (chunk) با "done": true ارسال میشوند که بسیاری از کتابخانههای کلاینت قبل از رسیدن به کد شما، آن را حذف میکنند.
مقدار پیشفرض num_predict چقدر است؟
آن را از نصب خودتان بخوانید نه از مقالات. تا اوت 2026، مرجع Modelfile در Ollama مقدار پیشفرض را -1 اعلام کرده است، به این معنی که تولید متن محدود نیست. این مورد در پایان سال 2024 پس از سالها مستندسازی به عنوان 128 اصلاح شد. مقادیر منفی به عنوان نشانگر (sentinel) عمل میکنند نه تعداد، و نسخههای قدیمیتر همان جدول، مقدار -2 را برای پر کردن کانتکست باقیمانده ذکر کرده بودند. مرجع پارامترهای Modelfile را برای نسخه خود بررسی کنید و سپس آن را با ollama show --parameters و یک درخواست curl تأیید نمایید.
آیا افزایش num_predict باعث میشود مدل پاسخهای طولانیتری بنویسد؟
خیر. این کار فقط سقف محدودیت را برمیدارد. اگر یک پاسخ با done_reason از stop تمام شود، یعنی مدل تصمیم گرفته است که کار تمام شده است و افزایش سقف تغییری ایجاد نمیکند. طول پاسخ در این حالت به نحوه پرامپتنویسی شما بستگی دارد: درخواست ساختار خاص، تعداد بخشها یا سطح جزئیات مشخصی را داشته باشید. مقدار num_predict را فقط زمانی افزایش دهید که done_reason با مقدار length برگردد.