Ollama: הגבלת אורך פלט עם num_predict
למדו כיצד להגביל את מספר ה-tokens בתגובות Ollama באמצעות num_predict. המדריך מסביר היכן להגדיר את הפרמטר, איזו הגדרה קובעת וכיצד לזהות done_reason בתגובה כשהמכסה מוצתה.
מה עושה num_predict ב-Ollama
num_predict הוא הפרמטר ב-Ollama המגביל את מספר ה-tokens שהמודל רשאי לייצר בתגובה אחת. הוא סופר רק את ה-tokens של הפלט, כך שה-prompt לעולם אינו נכלל במכסה זו. כאשר המודל מגיע למגבלה, יצירת הטקסט נעצרת בנקודה שבה הוא נמצא, לעיתים באמצע מילה, והתגובה חוזרת כאשר done_reason מוגדר כ-length.
זוהי תמצית התכונה. הקושי נובע מכך ש-Ollama מאפשר להגדיר את הערך בשלושה מקומות שונים, וההגדרה הקרובה ביותר לבקשה היא זו שקובעת. כמעט כל דיווח על כך ש-"num_predict לא עושה כלום" נובע משכבה אחת שדורסת בשקט הגדרה בשכבה אחרת.
num_predict אינו num_ctx
שתי האפשרויות הללו הן המבלבלות ביותר ב-Ollama, ובלבול זה גוזל זמן יקר בפתרון תקלות.
num_ctx הוא כמות הטקסט שהמודל יכול לקרוא. זהו גודל חלון ההקשר (context window), המכיל את ה-prompt ואת כל מה שהופק עד כה. הגדלת ערך זה צורכת זיכרון, כיוון שמטמון ה-key/value שהמודל שומר עבור ה-tokens הללו גדל בהתאם לחלון. קביעת גודל num_ctx עבור החומרה שלך היא משימה נפרדת עם דפוסי כשל משלה.
num_predict הוא כמות הטקסט שהמודל יכתוב. זהו כלל עצירה, לא הקצאת משאבים. הגדלת ערך זה צורכת זמן עיבוד (wall-clock time) ולא זיכרון RAM, ושום דבר אינו משוריין מראש.
הם נפגשים בנקודה אחת. ה-tokens המופקים נכנסים לתוך חלון ההקשר ככל שהם נוצרים, לכן תשובה יכולה להיעצר גם בגלל שהחלון התמלא, ולא רק בגלל שהגעת למכסה שהגדרת. 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 מדפיסה את ההגדרה המלאה, וזו גם הדרך המהירה ביותר להעתיק את הפרמטרים שעימם מגיע מודל קיים. יצירת מודל מוגבל בדרך זו כמעט אינה צורכת שטח דיסק נוסף, כיוון שהרשומה החדשה עושה שימוש חוזר ב-blobs של המשקולות שהורדו עבור מודל הבסיס במקום להעתיק אותם. כדאי לדעת היכן Ollama שומר את ה-blobs האלו לפני שדיסק ה-root של ה-VPS מתמלא.
זוהי השכבה הנכונה עבור ערך שאתם רוצים שכל קורא יירש. זוהי השכבה השגויה אם אתם מצפים שהערך יהיה סופי, כיוון שהוא אינו כזה.
הגדרת הערך לפי בקשה באובייקט האפשרויות
כל נקודת קצה (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 עם אותה משמעות. ערך שמוגדר כאן חל על קריאה זו בלבד ואינו משפיע על שום דבר אחר. זוהי השכבה שבה הכלים שלכם משתמשים: ממשק צ'אט, סקריפט, עטיפת 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 מקבל גם ערכים שליליים, ואלו משמשים כסימני בקרה (sentinels) ולא כמונים. ערך שלילי אחד משמעותו "אל תגביל, המשך ביצירה". ערך אחר שימש בעבר לציון "מלא את ההקשר הנותר". נכון לאוגוסט 2026, התיעוד של Ollama Modelfile מציין את ברירת המחדל כ--1, יצירה אינסופית, וגרסאות מוקדמות יותר של אותה טבלה ציינו גם את -2 עבור מילוי ההקשר.
התייחסו לכל אלו כנתונים התלויים בגרסה, כיוון שהם השתנו. התיעוד הציג את ברירת המחדל כ-128 במשך זמן רב לפני שהערך תוקן בסוף 2024, לכן מדריכים רבים עדיין חוזרים על המספר הישן. קראו את ה-Modelfile parameter reference עבור הגרסה שאתם מריצים בפועל, ולאחר מכן אשרו את ההתנהגות באמצעות בדיקת ה-eval_count שלעיל. ערך שאימתתם בעצמכם על השרת שלכם עדיף על ערך שקראתם בכל מקום אחר, כולל בפוסט זה.
מדוע אורך הפלט הוא העלות העיקרית בשרת VPS מבוסס CPU בלבד
תהליך היצירה מורכב משני שלבים בעלי מהירויות שונות בתכלית. אסימוני (tokens) ה-prompt מוערכים במקבצים, רבים בבת אחת. אסימוני הפלט מופקים אחד בכל פעם, וכל אחד מהם דורש מעבר מלא על משקולות המודל. בשרת VPS מבוסס CPU בלבד, מעבר זה מוגבל על ידי רוחב הפס של הזיכרון, ולכן אסימון פלט אחד עולה הרבה יותר מאסימון prompt אחד. מכיוון שהמעבר מחייב קריאה של כל משקולת, מספר הבייטים שכל משקולת תופסת קובע את התקרה לקצב האסימונים שלכם; זו הסיבה ש-גרסת q4 מפענחת מהר יותר מאותו מודל ב-q8 או ב-fp16.
בקשו תגובה ללא הזרמה (streaming) והמספרים יהיו גלויים לעין:
"prompt_eval_count": 26,
"prompt_eval_duration": 107345000,
"eval_count": 237,
"eval_duration": 4289432000משכי הזמן מצוינים בננו-שניות. בבלוק זה, המהווה את תגובת הדוגמה שפורסמה בתיעוד ה-API של Ollama ולא מדידה של שרת ספציפי, 26 אסימוני prompt ארכו כ-0.1 שניות, בעוד 237 אסימוני פלט ארכו כ-4.3 שניות. קצב היצירה האישי שלכם הוא eval_count חלקי eval_duration מומר לשניות, ו-מדידת אסימונים לשנייה על החומרה שלכם היא פעולה שכדאי לבצע פעם אחת לפני שמבצעים כוונון אחר. קצב זה תלוי במודל לא פחות מאשר במכונה, לכן אם תשובות ארוכות הן העלות האמיתית, מודל שנבנה לפענוח מהיר כמו Nemotron 3.5 Lightning ב-VPS מחזיר חלק מהזמן שמגבלה נמוכה נועדה להגן עליו.
החשבון עושה את השאר. בקצב של 8 אסימונים לשנייה, תשובה של 2,000 אסימונים תופסת את המכונה ליותר מארבע דקות, ולמודל אין מושג שרציתם רק פסקה. מודל הסקה (reasoning model) מקצה חלק מהתקציב הזה לחשיבה לפני שהוא כותב מילה אחת שביקשתם, וחשיבה זו מופקת אסימון אחד בכל פעם כמו כל דבר אחר, לכן מאמץ ההסקה שאתם מבקשים הוא מנוף נוסף על אותה עלות. חלק מהמודלים גם נכנסים ללולאה, וחוזרים על ביטוי עד שמשהו עוצר אותם. ללא הגבלה, בקשה בודדת כזו תעסיק ליבה עד שחלון ההקשר (context window) יתמלא. num_predict הוא ההגדרה שקובעת את הגבול, וזה חשוב במיוחד ב-שרת VPS מארח עצמי של Ollama קטן, שבו בקשה ארוכה אחת תופסת את כל משאבי המכונה.
פלט קטוע נובע בדרך כלל ממגבלת אורך, לא מכשל במודל
התסמינים נראים כמו כשל של המודל. תשובה שנעצרת באמצע משפט. JSON שלא ניתן לפענח, כיוון שסוגר ה־brace הסוגר מעולם לא הגיע. הרפלקס הראשוני הוא להאשים את המודל או את ה־quantisation. קראו תחילה את התגובה.
done_reason עונה על השאלה ישירות. stop מציין שהמודל סיים את עבודתו באופן עצמאי, בין אם על ידי פליטת ה־token המציין סוף רצף (end-of-sequence) ובין אם על ידי התאמה לאחת המחרוזות באופציה stop שלכם. length מציין שהיצירה נקטעה כיוון שנגמר המקום. כאשר אתם רואים length, השוו את eval_count למגבלה (cap) שהגדרתם: התאמה מדויקת פירושה ש-num_predict עצר את התהליך, ומספר קטן יותר פירושו שחלון ההקשר (context window) התמלא קודם לכן.
כאשר אתם מבצעים streaming, השדות הללו מגיעים בנתח (chunk) האחרון, זה שנושא את "done": true. ספריות לקוח רבות משליכות את הנתח הזה ומעבירות לקוד שלכם רק את הטקסט; זו הסיבה שאותה קטיעה נראית בלתי מוסברת בתוך יישום, אך ברורה תחת curl. אם ספרייה מסתירה זאת, שלחו בקשה אחת עם curl כדי לגלות מה השרת באמת אמר.
נקודה נוספת עשויה לחסוך לכם אחר צהריים מבוזבז. העלאת num_predict לא גורמת למודל לכתוב יותר. היא רק מסירה תקרה. אם תשובה מסתיימת ב-200 tokens עם done_reason מתוך stop, המודל החליט שהוא סיים, ומגבלה גדולה יותר לא תשנה דבר. תשובות קצרות עם stop הן בעיית prompting. תשובות קצרות עם length הן בעיית מגבלה (cap).
בחירת ערך
- עבור צ'אט אינטראקטיבי, השאירו את הערך ללא הגבלה ולחצו על Ctrl+C כדי לעצור תגובה שיוצאת משליטה. ממילא אתם צופים במסך.
- עבור כל תהליך מתוסרט (scripted), הגדירו את הערך. יצירת טקסט ללא הגבלה בתוך לולאה היא הסיבה לכך שמשימת batch שאמורה להימשך עשר דקות עדיין רצה למחרת בבוקר.
- עבור פלט מובנה, הגדירו את המכסה מעל למסמך התקין הגדול ביותר שאתם מצפים לו, ואז התייחסו ל-
done_reasonמתוךlengthכשגיאה חמורה ובצעו ניסיון חוזר במקום לנסות לעבד את מה שהתקבל. - עבור סוכן תכנות (coding agent), הערך שייך להגדרות של הסוכן עצמו, כיוון שהסוכן שולח את האפשרויות שלו בכל בקשה. הפניית סוכן תכנות ל-Ollama מפרט היכן הגדרות אלו נמצאות.
המכסה סופרת אסימונים (tokens), לא מילים ולא תווים, לכן אל תנסו להעריך אותה. צרו תשובה מייצגת אחת ללא מכסה, קראו את eval_count, והגדירו את המגבלה בערך גבוה בנוחות מעל לערך זה. משפחות מודלים מבצעות טוקניזציה באופן שונה, כך שערך שמתאים למודל Llama עלול לקטוע את אותה תשובה מ-מודל Qwen 3 על אותו VPS.
FAQ
מה ההבדל בין num_ctx לבין num_predict ב-Ollama?
num_ctx הוא הגודל של חלון ההקשר (context window), והוא קובע כמה המודל יכול לקרוא: ה-prompt בתוספת כל מה שנוצר עד כה. הוא צורך זיכרון, כיוון שזיכרון המטמון של ה-key/value גדל בהתאם. num_predict קובע כמה אסימונים (tokens) המודל רשאי לכתוב בתגובה אחת. הוא צורך זמן ולא זיכרון, ושום דבר לא מוקצה מראש עבורו. אסימונים שנוצרו נספרים כנגד שניהם, לכן תגובה עלולה להיקטע בגלל כל אחד מהם.
מדוע נראה שהגדרת ה-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 קטן יותר, חלון ההקשר התמלא קודם לכן. בעת הזרמת נתונים (streaming), שני השדות מגיעים בנתח האחרון עם "done": true, שספריות לקוח רבות משליכות לפני שהקוד שלכם מספיק לראות אותם.
מהו ערך ברירת המחדל של num_predict?
קראו אותו מההתקנה שלכם במקום ממאמר. נכון לאוגוסט 2026, תיעוד ה-Modelfile של Ollama מציין את ברירת המחדל כ--1, מה שאומר שהיצירה אינה מוגבלת; ערך זה תוקן בסוף 2024 לאחר שנים של תיעוד 128. ערכים שליליים הם סימני בקרה (sentinels) ולא ספירות, וגרסאות ישנות יותר של אותה טבלה ציינו גם את -2 למילוי ההקשר הנותר. בדקו את התיעוד של פרמטרי Modelfile עבור הגרסה שלכם, ואז אשרו זאת עם ollama show --parameters ובקשת curl אחת.
האם העלאת num_predict גורמת למודל לכתוב תשובות ארוכות יותר?
לא. היא רק מסירה תקרה. אם תגובה מסתיימת ב-done_reason מתוך stop, המודל החליט שהוא סיים, ומכסה גדולה יותר לא תשנה דבר. האורך במקרה כזה הוא עניין של הנחיה (prompting): בקשו מבנה ספציפי, מספר סעיפים, או רמת פירוט מוגדרת. העלו את num_predict רק כאשר done_reason חוזר כ-length.