LLM Router: למה ספק אחד לא עומד בעומס עבודה
הצמדה קשיחה לספק LLM אחד נשברת באופן צפוי: האפליקציה נתקלת במגבלות בקשות בשיא העומס, וחלק מהפניות מתחילות ליפול עם שגיאה עוד לפני יצירת התשובה.
לאחר מכן נכנס האפקט השני — הספק תחת עומס מתחיל להגיב לאט יותר, ואיכות התשובות יורדת: המודל עובר למצב מצומצם, ואתם מקבלים ירידה באיכות במקום שבו קודם הייתה תוצאה יציבה.
עבור המשתמש זה נראה כמו "השירות נתקע" או "התחיל להגיב בטיפשות", למרות שקוד האפליקציה לא השתנה.
בדיוק את הבעיה הזו פותר LLM Router — שכבת ניתוב של בקשות LLM בין כמה ספקים. הוא מחזיק נקודת כניסה אחידה, מפזר את התעבורה בין המודלים הזמינים, עוקב אחר מגבלות הספק ומעביר את הזרימה לערוץ גיבוי כאשר הערוץ הראשי מיצה את המכסה או מגיב לאט מדי.
עמידות לתקלות של LLM מפסיקה להיות תלויה בספק אחד: כשל או ירידה בביצועים בצד של מסלול אחד לא מפילים את המוצר כולו.
ניתוב בקשות LLM נבנה לא "בסבב", אלא לפי כללים: סוג המשימה, האיכות הנדרשת, ההשהיה המותרת ועלות העיבוד. בקשות פשוטות עוברות למודלים מהירים וזולים, מורכבות — לחזקים, וכאשר המסלול המועדף אינו זמין, הבקשה עוברת אוטומטית למסלול גיבוי תוך שמירה על ההקשר.
כך מגבלות הספק מפסיקות להיות תקרה עבור המוצר, והירידה באיכות התשובות מתוחמת למסלול בודד במקום לכל השירות.
מפרקים כיצד זה נסגר בפועל: אילו כללי ניתוב הגיוניים, כיצד מוגדרת מעבר בעת כשלים ומה נדרש כדי שהמעבר בין ספקים לא ישבור את הלוגיקה של האפליקציה.
מה נותנת ניתוב בקשות בין מודלים
נתב הוא שכבה בין האפליקציה למודלים, אשר עבור כל בקשה מחליטה לאן לשלוח אותה: לאיזה ספק, לאיזה מודל, עם איזה מגבלת זמן ומה לעשות אם התשובה לא הגיעה. בלעדיו האפליקציה קשורה באופן נוקשה לספק אחד, וכל תקלה שלו, זינוק בהשהיה או ירידה באיכות פוגעים ישירות במשתמש.
שכבת הניתוב מפרידה תלויות אלו: כללי בחירת המודל, ספי פסקי זמן, סדר חלופות הגיבוי ותנאי החזרה חיים בקונפיגורציה, ולא בקוד המוצר.
האפקט המדיד הראשון — הפחתת שיעור הכשלים. כאשר עבור כל סוג בקשה מוגדרת שרשרת של ספק ראשי וספק גיבוי, והחזרה מתבצעת רק עבור פעולות אידמפוטנטיות, כשל בודד של ספק מפסיק להפוך לשגיאה אצל המשתמש. בפועל שיעור הפניות הכושלות יורד מאחוזים לעשיריות האחוז — עם אותו קוד אפליקציה.
האפקט השני — השהיה יציבה. הנתב עוקב אחר זמן התגובה בכל כיוון ומעביר את התעבורה כאשר הספק חורג מהסף שהוגדר, במקום להמתין לפסק זמן. זה מסיר את ה"זנבות" בהתפלגות זמן התגובה: החציון כמעט לא משתנה, אך המתנות ארוכות, שמקלקלות את חוויית המוצר, מצטמצמות פי כמה.
האפקט השלישי — איכות תשובות מבוקרת. בקשות מורכבות ניתן לנתב למודל חזק יותר, פשוטות והמוניות — למודל מהיר וזול, ואת בדיקת התשובה להוציא לשלב נפרד. האיכות מפסיקה להיות פשרה ממוצעת: אתם מגדירים אותה בכללים לתרחיש ספציפי ומשנים אותה בלי לשכתב את המוצר.
ולבסוף, זה ניהול עומס. מגבלות לפי כיוונים, תור בזמן שיא ועדיפויות לפעולות קריטיות לא נותנים לתרחיש כבד אחד לקחת את כל רוחב הפס הכולל. זינוק בתעבורה נפרס על פני הקיבולות הזמינות, ולא הופך למפל של כשלים.
מצבי ניתוב: השוואת גישות
הנתב לא "בוחר את המודל הטוב ביותר" — הוא מחיל כלל על כל בקשה. המצבים נבדלים זה מזה בסוג האות המשמשת כבסיס לבחירה: רצף קשיח, חלקים מוגדרים מראש, מחיר הטוקן או הערכת איכות התשובה. להלן כיצד זה נראה בתצורה והיכן כל מצב נשבר.
| מצב | מתי מתאים | מגבלות |
|---|---|---|
| מסלול בעדיפות | ספק ראשי אחד, השאר — לגיבוי בעת כשל | מחזיק רזרבה קרה: בעת מעבר עולה הזמן עד לטוקן הראשון |
| פיזור משוקלל | יש צורך לפזר עומס ולהשוות ספקים על תעבורה חיה | החלקים קבועים, בעת הידרדרות של זרוע אחת ההטיה לא מתאזנת מעצמה |
| לפי עלות | בקשות המוניות אחידות ללא דרישות גבוהות לתשובה | מודל זול יותר נופל לשאילתות חוזרות — החיסכון נאכל על ידי חזרות |
| לפי איכות | משימות שבהן טעות יקרה יותר מהשהיה: ניתוח מסמכים, אנליטיקה | הערכת האיכות מפגרת אחרי הבקשה, נדרש אות משלך |
| מסלול גיבוי | שכבה חובה מעל כל אחד מהמצבים | ללא health-check נותן הפעלות שווא ומעברים מיותרים |
בפועל משלבים מצבים: מסלול בעדיפות עם רזרבה משוקללת ומגבלה על עלות הבקשה. אז כשל של ספק לא מפיל את השירות, ופרץ תעבורה לא הופך לחשבון על טוקנים.
המגבלה בכל המצבים משותפת — איכות אות הקלט. אם health-check בודק רק זמינות ולא נכונות תשובה, הנתב ישלח בקשות באדיקות לזרוע שהידרדרה. לכן כללי הניתוב שלנו תמיד מקושרים למדדי התשובה, ולא רק לקוד המצב.
כיצד אנו מטמיעים את ה-router: שלבי העבודה
הטמעת ה-router אינה מתחילה בהגדרת כללים, אלא במיפוי של מה שכבר קורה בפרודקשן.
אנו אוספים יומני קריאות (logs), מקבצים אותם לפי סוג המשימה, אורך ההקשר והדיוק הנדרש — ורק לאחר מכן מתבהר היכן המסלול "תמיד למודל החזק ביותר" משלם יותר מדי בזמן ובעלות, והיכן מודל זול מספק שיעור שגיאות בלתי מקובל.
שלבי העבודה
- ביקורת קריאות LLM. מנתחים את היסטוריית הבקשות: אילו תרחישים דומיננטיים, כיצד מתפלגים אורכי הפרומפטים, היכן פועלים חזרות ו-cache, ואילו תשובות נשלחות לטיוב. בפלט — מפת עומסים אמיתית, ולא הנחות.
- תכנון סכימת המסלולים. מגדירים מחלקות משימות ולכל אחת — שרשרת מודלים עם תנאי מעבר: לפי סוג הבקשה, נפח ההקשר, דרישות לפורמט התשובה. קובעים כללי נסיגה (fallback) אם הספק הראשי אינו זמין.
- הגדרת כללים וספים. רושמים עדיפויות, מגבלות על אורך ההקשר, התנהגות בשגיאות וב-timeouts. בנפרד מגדירים מה לעשות עם בקשות שלא מתאימות לאף כלל — הן לא אמורות ליפול בשקט.
- בדיקת עומס. מריצים תעבורה הקרובה לזו הייצורית: בודקים כיצד ה-router מתנהג בעומס שיא, בכשל של אחד הספקים ובהדרדרות התשובות. בוחנים את שיעור המעברים המוצלחים ואת זמן התגובה.
- השוואת איכות על נתונים אמיתיים. מריצים את אותה קבוצת משימות דרך מסלולים שונים ומשווים את התוצאה לזו של אמת מידה — כך רואים היכן החיסכון אינו שווה את אובדן הדיוק.
- מסירה לתפעול. מוסרים את הקונפיגורציה, סכימת המסלולים, כללי הניטור והוראות לשינוי הספים. צוות הלקוח יכול לערוך מסלולים בלעדינו.
- ליווי לאחר ההשקה. בשבועות הראשונים עוקבים אחר המדדים ומתקנים את הספים בהתאם להתנהגות בפועל של התעבורה.
כל שלב מסתיים בארטיפקט שניתן לבדוק: מפת עומסים, סכימת מסלולים, דוח בדיקת עומס. זה מאפשר לשנות כללים במודע, ולא באקראי — ולהבין איזה אפקט הביא כל שינוי.
תצורה, מדיניות גישה ותקנות בסיום
הפרויקט אינו מסתיים בהדגמה של ראוטר עובד, אלא במסירת ערכה שלמה שבאמצעותה הצוות שלכם יוכל להפעיל אותו, להרחיב אותו ולהעביר את הידע הלאה. להלן מה שנשאר בידיכם.
- תצורת נתיבים — כללים לבחירת ספק ומודל לפי סוג המשימה, סדרי עדיפויות, מגבלות, זמני המתנה והתנהגות בעת כשל. מוגדרים כקבצים מנוהלי גרסאות, ולא כהגדרות "בממשק אצל המהנדס".
- מדיניות גישה — תפקידים, מפתחות, מכסות לפי צוותים ותרחישים, הגבלות על נתונים רגישים ויומן של מי שינה מה.
- סכמת אינטגרציה — כיצד הראוטר משולב בשירותים שלכם: נקודות כניסה, פורמטים של בקשות ותגובות, טיפול בשגיאות, נתיבי גיבוי בעת אי-זמינות של הספק.
- תיעוד — תיאור הארכיטקטורה, מדריך פרמטרים של התצורה, הוראות לשינויים טיפוסיים וניתוח תקלות נפוצות.
- תקנות הפעלה — סדר הוספת ספק חדש, כללים לעדכון מודלים, בקרת עלויות ואיכות תגובות, נוהל חזרה לתצורה קודמת.
- ניטור והתראות — מערכת מדדים לזמן השהיה, שיעור שגיאות ועלות בקשה עם ספי הפעלה מוגדרים.
- תוכנית פיתוח — מה הוצא במכוון מהשלב הראשון ובאיזה סדר חוזרים לכך.
כל ארטיפקט אנו עוברים יחד עם המהנדסים שלכם במסירה, כדי שהתצורה והתקנות לא יישארו פורמליות בלבד. תארו את המשימה — נחזור עם הערכה ותוכנית.
מקרה בוחן: כיצד ניתוב הסיר מחלקת כשלים בעומס שיא
הלקוח — שירות עם ממשק דיאלוגי וזרימת פניות של עשרות אלפים ביום. הבקשות נשלחו ישירות לספק מודל אחד: כל עוד הוא הגיב ביציבות, הכל עבד, אך בשיא הערב שיעור השגיאות הגיע עד 9%, ובמהלך עבודות מתוכננות אצל הספק השירות היה מושבת לחלוטין — השחזור ארך עד 40 דקות בהחלפות ידניות.
LLM Router הצבנו כשכבה נפרדת בין האפליקציה לספקים. הנתב מחזיק מאגר של מספר מודלים, בודק את זמינותם בבקשות בדיקה קצרות ומפזר את התעבורה לפי כללים: ספק בעדיפות, ספק גיבוי, ענף נפרד לתשובות ארוכות.
אם שיעור השגיאות או ההשהיה חורגים מהסף, התעבורה עוברת אוטומטית למודל הגיבוי, והאפליקציה אפילו לא יודעת על כך.
מה השתנה במספרים
| מדד | לפני | אחרי |
|---|---|---|
| שיעור הכשלים בשיא | עד 9% | 0.4% |
| השהיית תגובה בשיא | עלייה פי 3 | עלייה פי 1.3 |
| זמן שחזור לאחר תקלת ספק | עד 40 דקות | 20-30 שניות |
| החלפות ידניות בעת תקלה | כל אחת | אין |
מחלקת הכשלים "הספק אינו זמין" יצאה מכלל שימוש: ההחלפה אורכת שניות ומתרחשת ללא מעורבות תורן. בנפרד הוגדר rollback — אם מודל חדש בענף הגיבוי מספק איכות לא יציבה, הכלל מחזיר את התעבורה לקודם בתיקון קונפיגורציה אחד, ללא בנייה מחדש ושחרור.
נמדד לא רק זמינות, אלא גם איכות: לוגי הניתוב מראים איזה חלק מהבקשות עבר לגיבוי ומדוע. זה אפשר לבחון מחדש את הספים — חלק מההחלפות היו מיותרות ויצרו עומס על ספק הגיבוי.
במה שונה ניתוב לפי איכות ממיתוג גיבוי
אלו שני מנגנונים שונים שלעיתים קרובות מבלבלים ביניהם, מכיוון ששניהם חיים באותו שכבה — LLM Router. מיתוג גיבוי פותר את בעיית הזמינות: הספק הראשי החזיר שגיאה, פג זמן או נתקל במגבלה — הנתב חוזר על הבקשה לספק הבא ברשימה. הקריטריון כאן הוא אחד: חיוניות.
הבקשה נשלחת לשם שהשירות עונה, ולא לשם שהתשובה תהיה טובה יותר. ניתוב לפי איכות פותר בעיה אחרת — הוא בוחר מודל עבור בקשה ספציפית עוד לפני השליחה, בהתבסס על תוכן הבקשה.
ההבדל בא לידי ביטוי ברגע בחירת המודל. במיתוג גיבוי מודל ברירת המחדל הוא אחד, והוא משתנה רק בעקבות כשל — כלומר איכות התשובה נשארת תוצר לוואי של תקלה. בניתוב לפי איכות הנתב תחילה מסווג את הבקשה: שאלה עובדתית קצרה, ניתוח ארוך של מסמך, יצירת קוד, עבודה עם תמונה.
לאחר מכן פועלים קריטריוני הבחירה — סוג המשימה, אורך ההקשר הנדרש, השהיה מותרת, עלות הטוקן. רק לאחר מכן הבקשה נשלחת למודל המתאים, ומיתוג גיבוי נשאר כשכבת ביטחון מעל החלטה זו.
באופן מעשי זה נראה כך: החלפת ספק פועלת ברמת התעבורה ואינה יודעת על מה הייתה הבקשה. ניתוב לפי איכות פועל ברמת המשמעות ואינו מציל מכשל — אם הספק הנבחר אינו זמין, ללא מנגנון חזרה נפרד הבקשה פשוט תיכשל.
לכן בתצורה עובדת הם אינם מתחרים, אלא משלימים זה את זה: תחילה בחירת מודל לפי קריטריונים, לאחר מכן שרשרת ספקי גיבוי למקרה של כשל.
טעות — לבנות רק מיתוג גיבוי ולקרוא לזה ניתוב. אז בקשה פשוטה נשלחת למודל יקר, ובקשה מורכבת — לזול, ואיכות התשובה משתנה מבקשה לבקשה. הטעות ההפוכה — לנתב לפי איכות ללא גיבוי: כל אי-זמינות של ספק מפילה את כל השירות, מכיוון שלא נ� предусмотрена החלפה.
ספקות טכניים לפני הטמעה
לפני פיילוט כמעט תמיד עולות אותן ארבע שאלות: כיצד הנתב ישתלב בסטאק הקיים, האם זמן התגובה יגדל, מי יתחזק אותו ומה לעשות אם הספק ייפול. להלן תשובות קצרות לכל אחת מהן, בלי שיווק.
האם צריך לשכתב קוד של אפליקציות עבור הנתב?
לא. הנתב עולה כשירות נפרד ומספק ממשק HTTP תואם OpenAI — אותו פורמט בקשה ותגובה כמו בפניות ישירות לספק. באפליקציה משתנים ה-base_url והמפתח, לוגיקת הקריאות, הפרומפטים וניתוח התגובות נשארים כשהיו. אם בסטאק כבר קיים לקוח SDK, הוא ממשיך לעבוד ללא שינויים.
בכמה יגדל זמן התגובה?
מתווסף הופ רשת אחד בין האפליקציה לספק — יחידות של מילישניות על ניתוב, דבר שאינו מורגש על רקע יצירת התגובה על ידי המודל. הזמן העיקרי מושקע באינפרנס עצמו, ולא בבחירת הספק. אם מופעלות חזרות בעת שגיאה, זמן התגובה גדל רק ברגע הכשל — וזה משתלם יותר מאשר להציג למשתמש שגיאה.
בכמה מורכב לתחזק את הנתב?
התצורה היא קובץ דקלרטיבי: כללי ניתוב, מגבלות, עדיפויות ספקים, מפתחות. משתנה ללא בנייה מחדש של השירות. העבודה העיקרית בתחזוקה היא לעדכן את רשימת המודלים ולעקוב אחר מכסות, ולא לתקן קוד. מדדים עבור כל ספק (שיעור שגיאות, זמן תגובה, צריכת טוקנים) נאספים אוטומטית.
מה יקרה אם הספק אינו זמין או החזיר שגיאה?
הנתב מעביר את הבקשה לספק גיבוי לפי כלל מוגדר — לפי קוד שגיאה, טיימאאוט או מיצוי מכסה. האפליקציה מקבלת תגובה ואינה יודעת על הכשל. אם כולם אינם זמינים, מוחזרת שגיאה מובנת עם ציון הסיבה, ולא בקשה "תקועה".
האם יש מגבלות שכדאי לדעת מראש?
ספקים נבדלים בתמיכה בתכונות: לא כולם יודעים לבצע קריאות לכלים, העברה בזרימה או עבודה עם תמונות. יש לבנות את כללי הניתוב בהתחשב בהבדלים אלה, אחרת חלק מהבקשות יגיעו למקום שבו התכונה הנדרשת אינה נתמכת. זה נפתר בשלב ההגדרה, אך דורש תיאור מפורש של הדרישות לכל מודל.
בואו נדון במשימת הניתוב שלכם
כדי לחזור עם הערכה ותוכנית, ולא עם מילים כלליות, אנחנו צריכים להבין את סכימת הניתוב הנוכחית שלכם ואת המגבלות שבתוכן היא פועלת. תארו את המשימה בצורה חופשית — לאחר מכן נשאל שאלות הבהרה ונאסוף את נתוני המקור. ככל שהנתונים הראשוניים מדויקים יותר, כך ההערכה של לוחות הזמנים והיקף העבודה תהיה מדויקת יותר.
מה שמועיל לצרף לתיאור המשימה:
- הסכימה הנוכחית של קריאות למודלים: אילו ספקים מעורבים, לפי איזה מאפיין נבחר המודל עבור הבקשה;
- כיצד כיום מטופלים כשלים וחריגה ממכסות — האם יש ניסיונות חוזרים, מעבר לספק גיבוי, תור;
- דרישות לזמן השהיה ולעלות: מה קריטי יותר לכל סוג של בקשות, היכן מותר להמתין;
- כללים לגבי נתונים: אילו בקשות אסור לשלוח לספקים חיצוניים, האם יש דרישות לאחסון ולתיעוד;
- פרופיל העומס הצפוי: בקשות שיא בדקה, שיעור הפניות הכבדות והקלות, עונתיות;
- נקודות אינטגרציה: מאיפה מגיעות הבקשות, אילו שירותים וצוותים מעורבים;
- מגבלות בתשתית ובהרשאות גישה: היכן נפרס הנתב, מי הבעלים של התצורה.
לפי הנתונים האלה אנחנו מעריכים את ההיקף: האם נדרש שכבה נפרדת של ניתוב או שמספיק לשפר את הקיימת, אילו כללי עמידות בכשלים אנחנו קובעים, כיצד נארגן את הנראות והחזרה לאחור. אנחנו חוזרים עם תוכנית שלבים, לוחות זמנים ומה שיידרש מצדכם. הצעד הבא — שיחה קצרה לעניין: תארו את המשימה, ואנחנו נחזור עם הערכה ותוכנית.







