הקמת LiteLLM כ-gateway עצמאי לניהול מודלי שפה
למדו כיצד להריץ LiteLLM על שרת VPS כדי לרכז את כל פניות ה-API שלכם. פתרון המאפשר ניהול מפתחות וירטואליים, הגדרת תקציבים לכל משתמש, ומנגנוני Fallbacks אוטומטיים.
מה עושה שער LLM באירוח עצמי
LiteLLM הוא שער LLM בקוד פתוח שניתן לארח באופן עצמאי: נקודת קצה (endpoint) אחת מסוג HTTP שכל היישומים שלכם פונים אליה, והיא בתורה מעבירה כל בקשה לספק המתאים שיענה עליה. LLM הוא מודל שפה גדול (Large Language Model). השער מדבר בפורמט ה-API של OpenAI chat completions, כך שכל ספריית לקוח שכבר עובדת מול OpenAI תעבוד מולו לאחר שני שינויים בלבד: ה-base URL והמפתח.
שכבת התיווך הזו היא העיקר. היישומים שלכם מפסיקים להחזיק בפרטי הזיהוי של הספקים. החלפת מודל הופכת לשורה אחת בקובץ הגדרות בשרת, במקום שינוי קוד בחמישה שירותים שונים. ומכיוון שכל קריאה עוברת דרך תהליך אחד, יש לכם מקום מרכזי להגדרת תקציב ולתיעוד ההוצאות.
להלן מה שמתקבל ברגע שהשירות רץ:
- נקודת קצה אחת. יישומים פונים ל-
https://gateway.example.com/v1ומבקשים שם מודל שהמצאתם, כגוןbulkאוstrong. - מפתחות וירטואליים. כל יישום מקבל מפתח משלו עם רשימת מודלים מורשים ותקרת הוצאות משלו. ניתן לבטל מפתח אחד מבלי להשפיע על האחרים.
- מנגנוני גיבוי (Fallbacks). קריאה שנכשלה או prompt גדול מדי מבוצעים שוב מול מודל אחר באופן אוטומטי.
- תיעוד מלא. כל בקשה רושמת שורה הכוללת את העלות שלה, כך שתמיד יש תשובה לשאלה "איזה יישום ביצע את ההוצאה הזו".
למה להריץ את ה-gateway בעצמך
נתב מנוהל הוא בעל מבנה זהה, אך עם תהליך של גורם חיצוני שיושב באמצע כל בקשה. הרצה עצמית של ה-gateway שומרת את מפתחות הספק ואת טקסט ה-prompt שלך על שרת שנמצא בשליטתך. למחיר הזה יש משמעות: כעת אתה מנהל את הרכיב שכל יישום תלוי בו. החלק האחרון במדריך זה עוסק במחיר הזה, כיוון שזהו החלק שרוב המדריכים נוטים להשמיט.
דרישות קדם
- שרת VPS המריץ Ubuntu 24.04, עם Docker ותוסף Compose מותקנים.
- שם מתחם (domain name) המצביע אל השרת, אם מכונות מחוץ לשרת יתחברו ל־gateway באמצעות TLS (אבטחת שכבת תעבורה).
- מפתח API של ספק אחד לפחות.
ה־gateway אינו מבצע הסקה (inference). הוא מעביר בקשות ומזרים תשובות בחזרה, לכן עומס ה־CPU שלו תואם לנפח הבקשות ולא לגודל המודל. שרת עם 1 vCPU מסוגל להריץ מספר יישומים פנימיים ללא קושי. מה שגדל הוא מסד הנתונים, כיוון שה־gateway כותב שורת הוצאה עבור כל בקשה.
יצירת config.yaml תחילה
קובץ התצורה קובע אילו מודלים רשאי הלקוח לבקש. ארבעה סעיפים ברמה העליונה הם הקובעים: model_list, litellm_settings, router_settings ו-general_settings.
model_list:
- model_name: bulk
litellm_params:
model: anthropic/claude-haiku-4-5
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: strong
litellm_params:
model: anthropic/claude-sonnet-5
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: strong
litellm_params:
model: openai/gpt-5.5
api_key: os.environ/OPENAI_API_KEY
litellm_settings:
num_retries: 2
request_timeout: 120
allowed_fails: 3
cooldown_time: 30
json_logs: true
set_verbose: false
router_settings:
fallbacks: [{"bulk": ["strong"]}]
context_window_fallbacks: [{"bulk": ["strong"]}]
general_settings:
background_health_checks: true
health_check_interval: 300model_name הוא השם שהלקוחות שלכם שולחים. litellm_params.model הוא המודל האמיתי, הנכתב כ-provider/model. תנו למודלים שלכם שמות לפי התפקיד שלהם ולא לפי הספק. יישום המבקש את bulk ימשיך לעבוד גם כאשר תחליטו בחודש הבא ש-bulk צריך להיות מודל אחר.
api_key: os.environ/ANTHROPIC_API_KEY מורה ל-LiteLLM לקרוא את המשתנה בזמן הריצה. המפתח המילולי לעולם אינו מופיע בקובץ, וזה חשוב מכיוון ש-config.yaml הוא הקובץ שאתם מבצעים לו commit.
שתי רשומות חולקות את השם strong, וזאת בכוונה. כאשר יותר מפריסה אחת נושאת את אותו model_name, ה-router מתייחס אליהן כניתנות להחלפה ומנסה את השנייה כאשר הראשונה נכשלת. כך strong שורד מצב שבו ספק חווה שעה לא טובה.
num_retries: 2 מבצע ניסיונות חוזרים (retries) על אותה פריסה במקרה של שגיאה שניתן לנסות שוב. מנגנון fallback מופעל רק לאחר שנוצלו כל הניסיונות הללו. allowed_fails: 3 עם cooldown_time: 30 מוציא פריסה מהסבב למשך 30 שניות לאחר שנכשלה 3 פעמים, כך שספק שמחזיר שגיאות 500 מפסיק לקבל ניסיונות בכל בקשה ובקשה.
ל-fallbacks ול-context_window_fallbacks יש טריגרים שונים, והשני הוא השימושי שאנשים נוטים לדלג עליו.
fallbacksמופעל כאשר הקריאה הראשית נכשלת.context_window_fallbacksמופעל כאשר הספק דוחה את הבקשה בטענה שהיא ארוכה מחלון ההקשר (context window) של אותו מודל, כך ש-prompt גדול מדי מועבר למודל עם מקום פנוי במקום להחזיר שגיאה למבצע הקריאה.
קיים גם content_policy_fallbacks, עבור ספק שמסרב לבקשה מטעמי מדיניות תוכן. הגדירו אותו רק אם יש לכם יעד הגיוני לשלוח אליו את הקריאות הללו.
פריסת LiteLLM על שרת VPS באמצעות Docker Compose
צרו תיקייה המכילה שלושה קבצים: config.yaml, docker-compose.yml ו-.env. המדריך המהיר הרשמי מושך את התגית latest. עדיף לקבע תגית גרסה ספציפית, כך ש-docker compose up -d בחודש הבא תספק לכם את אותו ה-gateway שקיבלתם היום, מה שמאפשר ביצוע rollback בשורת פקודה אחת.
services:
litellm:
image: ghcr.io/berriai/litellm:v1.95.0
restart: unless-stopped
command: ["--config", "/app/config.yaml", "--num_workers", "1"]
ports:
- "127.0.0.1:4000:4000"
volumes:
- ./config.yaml:/app/config.yaml:ro
env_file: .env
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: litellm
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
POSTGRES_DB: litellm
healthcheck:
test: ["CMD-SHELL", "pg_isready -U litellm"]
interval: 5s
timeout: 5s
retries: 10
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:הכלי Compose קורא את .env פעמיים במקרה זה. פעם אחת כדי להחליף את ${POSTGRES_PASSWORD} בתוך קובץ ה-compose עצמו, ופעם שנייה דרך env_file כדי להעביר את כל המשתנים לתוך המכולה.
v1.95.0 הייתה הגרסה העדכנית באוגוסט 2026. בדקו את דף ה-releases של הפרויקט וקבעו את הגרסה העדכנית ביותר בעת הפריסה. כל גרסה מפורסמת עם חתימה, כך שניתן לאמת את ה-image לפני שנותנים בו אמון:
cosign verify --key https://raw.githubusercontent.com/BerriAI/litellm/v1.95.0/cosign.pub ghcr.io/berriai/litellm:v1.95.0שורת ה-port היא 127.0.0.1:4000:4000, אשר מפרסמת את הפורט על ממשק ה-loopback בלבד. אם תכתבו 4000:4000 במקום זאת, ה-gateway שלכם יהיה נגיש מכל רחבי האינטרנט, כיוון ש-Docker מוסיפה חוקים משלה ל-chain בשם FORWARD ב-iptables, וחוקים אלו מוערכים לפני החוקים של ufw, לכן ufw deny 4000 לא יחסום זאת. זו הדרך הנפוצה ביותר שבה gateway מאוחסן עצמית נחשף בטעות: ראו כיצד Docker מפרסמת פורט של מכולה תוך עקיפת ufw. תעבורה מבחוץ צריכה להגיע דרך ה-reverse proxy בלבד.
שמירה על מפתחות הספק מחוץ ל-image
הקובץ .env מכיל את כל הסודות. הוא מוזרק כמשתני סביבה בזמן הריצה, לכן הוא לעולם אינו מוטמע בתוך ה-image ולעולם אינו נשמר ב-commit.
LITELLM_MASTER_KEY=sk-REPLACE_ME
LITELLM_SALT_KEY=sk-REPLACE_ME_TOO
POSTGRES_PASSWORD=REPLACE_ME_AS_WELL
DATABASE_URL=postgresql://litellm:REPLACE_ME_AS_WELL@db:5432/litellm
STORE_MODEL_IN_DB=True
LITELLM_MODE=PRODUCTION
LITELLM_LOG=ERROR
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-proj-...צרו את שני המפתחות של LiteLLM באמצעות אקראיות אמיתית, ולאחר מכן הגבילו את ההרשאות לקובץ:
printf 'sk-%s\n' "$(openssl rand -hex 32)"
chmod 600 .envLITELLM_MASTER_KEY הוא פרט הזיהוי של מנהל המערכת. הוא מאמת את ה-API של הניהול ומשמש כסיסמה עבור ה-Admin UI בכתובת /ui. אף יישום לא אמור להחזיק בו.
LITELLM_SALT_KEY מצפין את פרטי הזיהוי של הספקים המאוחסנים במסד הנתונים. הגדירו אותו פעם אחת והשאירו אותו כפי שהוא. אם תשנו אותו מאוחר יותר, לא ניתן יהיה לפענח את פרטי הזיהוי שכבר אוחסנו; במצב כזה ה-gateway יעלה כרגיל, אך כל קריאה לאותם ספקים תיכשל בשלב האימות.
STORE_MODEL_IN_DB=True מאפשר לכם להוסיף ולערוך מודלים מתוך ה-Admin UI מבלי לגעת בקובץ config.yaml. זה נוח, אך זה מפצל את מקור האמת שלכם לשניים. החליטו איזה מהם הוא הסמכותי ותעדו את ההחלטה לצד ה-config.
ההיגיון ששומר על מפתחות מחוץ לקובץ התצורה הוא אותו היגיון ששומר עליהם מחוץ לכלים שאתם מעבירים לסוכן (agent). המאמר שמירה על סודות ספק מחוץ לסוכני AI מכסה את התבנית הזו, ו-קבצי env וסודות ב-Docker Compose מכסה את ההיבטים הטכניים.
העלו את השירות ועקבו אחר האתחול הראשון:
docker compose up -d
docker compose logs -f litellmבדיקת תקינות הפעולה
קיימות שתי בדיקות ללא אימות ובדיקה אחת עם אימות, והן נכשלות מסיבות שונות.
curl -s http://127.0.0.1:4000/health/liveliness
curl -s http://127.0.0.1:4000/health/readiness/health/liveliness אינו דורש אימות ומשיב "I'm alive!" כל עוד התהליך רץ. גם /health/readiness אינו דורש אימות. הוא מחזיר אובייקט JSON עם "status": "healthy" ושדה db, או קוד שגיאה 503 כאשר מסד הנתונים אינו נגיש. כוונו את מערכת הניטור שלכם אל ה-readiness, כיוון שה-liveliness נשאר תקין גם ב-gateway שאינו מסוגל לאתר מפתח וירטואלי בודד.
הבדיקה המאומתת היא זו שמתקשרת עם הספקים:
curl -s http://127.0.0.1:4000/health \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"היא משיבה עם מערכים של healthy_endpoints ו-unhealthy_endpoints. מודל שנמצא ב-unhealthy_endpoints עם שגיאת אימות מעיד על כך שמפתח הספק ב-.env שגוי או חסר; זהו הכשל שאתם מחפשים כעת. מכיוון ש-background_health_checks: true מוגדר, ה-proxy מריץ את הבדיקות הללו בעצמו בכל health_check_interval שניות, ו-/health מחזיר את התוצאה האחרונה, כך שביצוע polling לא שולח בקשת בדיקה לספקים שלכם בכל פעם מחדש.
מפתחות וירטואליים ותקציבים לכל מפתח
כל יישום מקבל מפתח משלו, המונפק מול מפתח האב.
curl -s http://127.0.0.1:4000/key/generate \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H 'Content-Type: application/json' \
-d '{
"key_alias": "nightly-summariser",
"models": ["bulk"],
"max_budget": 5,
"budget_duration": "30d",
"rpm_limit": 60,
"tpm_limit": 200000
}'התגובה מכילה שדה key המתחיל ב-sk-. מחרוזת זו היא מה שהיישום מקבל, וזהו הדבר היחיד שהיישום יקבל אי פעם.
modelsהוא רשימה מאושרת (allowlist) של מה שמפתח זה רשאי לבקש. המפתח לעיל יכול לבקש רקbulkולא שום דבר אחר.max_budget: 5עםbudget_duration: "30d"מגדיר תקציב של חמישה דולרים לכל 30 יום מתגלגלים, ולאחר מכן המפתח מפסיק לעבוד.rpm_limitו-tpm_limitמגבילים את מספר הבקשות לדקה ואת מספר הטוקנים לדקה עבור מפתח זה בלבד.key_aliasהוא מה שתזהו ביומן ההוצאות שישה שבועות לאחר מכן. הגדירו זאת תמיד.
כאשר התקציב נגמר, הקריאה נכשלת עם שגיאת HTTP 401 וגוף תגובה במבנה הבא:
ExceededBudget: Current spend for token: 7.2e-05; Max Budget for Token: 2e-07קוד הסטטוס הוא מה שהופך את העניין למבלבל. ספריית לקוח מדווחת על 401 כבעיית אימות, לכן המפתח שקורא את ה-stack trace מתחיל לבדוק האם המפתח תקין. רשמו ביומן את גוף התגובה לצד קוד הסטטוס, אחרת מיצוי תקציב ייראה בכל פעם כבעיה בפרטי הזיהוי.
ניתן לבדוק ולהתאים מפתחות דרך אותו ממשק ניהול (management API):
curl -s "http://127.0.0.1:4000/key/info?key=sk-..." \
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
curl -s -X POST http://127.0.0.1:4000/key/update \
-H "Authorization: Bearer $LITELLM_MASTER_KEY" \
-H 'Content-Type: application/json' \
-d '{"key": "sk-...", "max_budget": 25}'תקציב שנאכף בשער (gateway) נשאר בתוקף גם כאשר הגורם שהשתבש הוא הסוכן (agent) עצמו, וזו הסיבה שהוא מהווה את עמוד השדרה של בקרת עלויות עבור סוכני AI על גבי VPS.
שליחת עבודה מרוכזת למודל זול
הפנו את הלקוח (client) אל ה-gateway. הגדירו את ה-Base URL, את ה-key ואת שם המודל:
curl -s http://127.0.0.1:4000/v1/chat/completions \
-H "Authorization: Bearer sk-<the virtual key>" \
-H 'Content-Type: application/json' \
-d '{
"model": "bulk",
"messages": [{"role": "user", "content": "Say hello in five words."}]
}'כל ספריית לקוח של OpenAI מתנהגת באותו אופן: הגדירו את base_url ל-https://gateway.example.com/v1 ואת api_key למפתח הווירטואלי.
מדיניות הניתוב מתוך config.yaml חלה כעת מבלי שהקוד הקורא יהיה מודע לכך. בקשה עבור bulk מופנית למודל הזול. אם קריאה זו נכשלת לאחר הניסיונות החוזרים שלה, הבקשה מבוצעת שוב מול strong. אם ה-prompt ארוך מדי עבור bulk, המערכת context_window_fallbacks תשלח אותו ל-strong במקום להחזיר שגיאה. עבודה מרוכזת, כגון סבב סיווג או סיכום של backlog, רצה כברירת מחדל בעלות נמוכה, ורק בקשות מורכבות עולות יותר.
זהו גם המקום שבו ה-gateway מוכיח את ערכו עבור סוכנים (agents) המשתמשים בכלים. ניתן להפנות גם שרת MCP (model context protocol) על אותו VPS וגם את הסוכן שמפעיל אותו לאותה נקודת קצה (endpoint), כך שהמודל שמאחוריהם משתנה ללא צורך בפריסה מחדש של אף אחד מהם.
כיצד ניתן לדעת שהתרחש fallback?
זהו מצב כשל שגורם להפסדים כספיים, כיוון שכלפי חוץ נראה שהכול תקין. fallback מוצלח מחזיר HTTP 200 עם גוף תגובה רגיל. המודל הזול שלכם יכול להיות מושבת במשך יום שלם, כאשר כל בקשה מוגשת בשקט על ידי המודל היקר, והסימן הראשון לכך יהיה החשבונית.
הראיות קיימות בתוך ה-response headers. בקשו אותם:
curl -s -D - -o /dev/null http://127.0.0.1:4000/v1/chat/completions \
-H "Authorization: Bearer sk-<the virtual key>" \
-H 'Content-Type: application/json' \
-d '{"model":"bulk","messages":[{"role":"user","content":"ping"}]}' \
| grep -i '^x-litellm'x-litellm-model-groupהוא המודל שהלקוח ביקש.x-litellm-model-idהוא ה-deployment שענה בפועל. כאשר השניים אינם תואמים, התרחש fallback.x-litellm-attempted-fallbacksו-x-litellm-attempted-retriesסופרים אותם. בבקשה תקינה, שניהם יהיו 0.x-litellm-response-costהוא העלות של אותה בקשה בדולרים.x-litellm-call-idהוא המזהה שבו אתם משתמשים כדי לאתר את אותה בקשה בלוגים שלכם.
תעדו את x-litellm-attempted-fallbacks בכל בקשה והגדירו התראה כאשר הערך אינו 0. מספר זה הוא ההבדל בין מדיניות ניתוב תקינה לבין מדיניות שהפכה בשקט ל"השתמש תמיד במודל היקר".
הגרסה המלאה של תהליך זה היא tracing, והיא דורשת הגדרה עצמאית: אירוח עצמי של Langfuse למעקב אחר קריאות סוכן. LiteLLM כולל את ה-callback, לכן חיבורו דורש שתי שורות קוד בלבד בתוספת פרטי הזדהות.
litellm_settings:
success_callback: ["langfuse"]
failure_callback: ["langfuse"]LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...
LANGFUSE_HOST=https://langfuse.example.comהגדירו את failure_callback וגם את success_callback. אם תדלגו על כך, ה-traces היחידים שיישמרו יהיו אלו שבהם לא התרחשה שגיאה. בנפרד מכל זה, LiteLLM כותב שורת הוצאה לכל בקשה לתוך Postgres, וממשק הניהול ב-/ui קורא את הטבלה הזו. הטבלה גדלה בהתאם לתעבורה, לכן יש לנטר אותה במידה והדיסק קטן.
הצבת ה-gateway מאחורי reverse proxy
שום גורם מחוץ לשרת לא אמור להגיע לפורט 4000. בצעו TLS termination ב-nginx או ב-Caddy והעבירו את התעבורה לכתובת ה-loopback.
location / {
proxy_pass http://127.0.0.1:4000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_read_timeout 600s;
}שתיים מהשורות הללו הן אלו שאנשים נוטים להשמיט. proxy_buffering off חשוב מכיוון ש-streaming completion הוא רצף של server-sent events, וכאשר ה-buffering פעיל, nginx מחזיק את הנתונים עד לסיום התגובה, כך שהלקוח ממתין בשקט ואז מקבל את כל המידע בבת אחת. proxy_read_timeout 600s חשוב מכיוון שיצירת תוכן ארוכה עשויה להימשך מעבר לזמן ברירת המחדל של nginx, העומד על 60 שניות; כאשר זה קורה, הלקוח מקבל שגיאת 504 בעוד לוג השגיאות מתעד upstream timed out (110: Connection timed out) while reading response header from upstream.
עבור התעודה, Certbot עם Let's Encrypt על nginx הוא הדרך הקצרה ביותר. אם השרת כבר מריץ כמה מכולות, Traefik לפני כמה יישומי Compose יטפל בניתוב ובתעודות במקום אחד.
ה־gateway הפך לנקודת כשל מרכזית
היו כנים לגבי מה שבניתם. כל יישום שבבעלותכם תלוי כעת במכולה אחת על שרת VPS אחד. כל עוד היא מושבתת, שום דבר לא יכול לקרוא לאף מודל, גם לא לספקים שמתפקדים בצורה מושלמת. ארבעה דברים נובעים מכך.
- תצורה שגויה משביתה את הכל בבת אחת.
restart: unless-stoppedמבצע הפעלה מחדש במקרה של קריסה, והוא יפעיל מחדש מכולה שלא מצליחה לפענח את config.yaml, שוב ושוב. קראו אתdocker compose logs litellmלאחר כל שינוי בתצורה, ובצעו שינויים כאלו רק כשיש לכם זמן להשגיח עליהם. - Postgres נמצא בנתיב הבקשה. חיפוש מפתח וירטואלי ותיעוד הוצאות משתמשים בו שניהם.
/health/readinessשמחזיר 503 הוא האזהרה שלכם לכך שה־gateway פועל אך אינו מסוגל לבצע אף אחד מהם. - בצעו Scale על ידי הוספת מופעים, לא על ידי הגדלת מופע קיים. ההנחיה של הפרויקט עצמו היא worker אחד לכל מופע (
--num_workers 1) כאשר כמה מופעים חולקים מסד נתונים אחד. שני gateways קטנים מאחורי load balancer מסירים את המכולה הבודדת מהמשוואה. הם לא מסירים את מסד הנתונים. - גבו את מה שאינכם יכולים לשחזר. מדובר ב-
config.yamlוב-.env, יחד עםpg_dumpשל מסד הנתונים. אובדן שלLITELLM_SALT_KEYהופך את אישורי הספק המוצפנים בתוך ה-dump הזה לחסרי תועלת, לכן קובץ ה-env וה-dump שייכים לאותה משימת גיבוי: גיבויי restic לאחסון חיצוני.
שדרוג מתבצע על ידי עריכת תגית ה-image והרצת docker compose up -d. LiteLLM מריץ prisma migrate deploy בעת העלייה כברירת מחדל, לכן המכולה החדשה מבצעת מיגרציה לסכימת מסד הנתונים בהפעלה הראשונה שלה. בצעו dump לפני שינוי התגית, כיוון שהחזרת ה-image הישן לא מבטלת מיגרציה שכבר בוצעה.
FAQ
האם LiteLLM מוסיף השהיה (latency) מורגשת לכל קריאה?
הפרויקט מפרסם נתון של 8 ms באחוזון ה-95 תחת עומס של 1000 בקשות בשנייה, כפי שצוין ב-README שלו באוגוסט 2026. יש להתייחס לנתון זה כאל נתון של ספק. המספר שמשפיע בפועל על ההשהיה שלכם הוא המרחק ברשת בין היישומים שלכם לבין ה-gateway, כיוון שהוספתם סבב תקשורת (round trip) אחד לכל קריאה. הריצו את ה-gateway באותו אזור (region) שבו נמצאים היישומים שקוראים לו, ולאחר מכן מדדו את ה-overhead שלכם באמצעות ה-header x-litellm-overhead-duration-ms על תגובה אמיתית.
מדוע הזרמת נתונים (streaming) הפסיקה לעבוד לאחר שהצבתי את nginx בחזית?
מכיוון ש-nginx מבצע buffering לתגובות מה-upstream כברירת מחדל, ו-streaming completion הוא רצף של אירועים שנשלחים מהשרת (server-sent events). כאשר proxy_buffering מופעל, nginx אוסף את ה-chunks ומשחרר אותם רק בסיום התגובה, כך שהלקוח ממתין בשקט ואז מקבל את כל התשובה בבת אחת. הגדירו proxy_buffering off; בתוך בלוק ה-location. העלו את הערך של proxy_read_timeout באותו בלוק, שכן יצירת טקסט ארוכה עלולה לחרוג ממגבלת ברירת המחדל של nginx העומדת על 60 שניות, מה שיגרום ללקוח לקבל שגיאת 504.
מה קורה כאשר ל-virtual key נגמר התקציב?
הקריאה נכשלת עם שגיאת HTTP 401 וגוף תגובה במבנה ExceededBudget: Current spend for token: 7.2e-05; Max Budget for Token: 2e-07. ה-401 הוא המוקש: ספריית לקוח מדווחת על כך ככשל אימות, ולכן אנשים מתחילים לבדוק אם המפתח תקין במקום לקרוא את ההודעה. תעדו את גוף התגובה לצד קוד הסטטוס. אשרו את המיקום האמיתי של המפתח מול ה-master key באמצעות /key/info?key=sk-..., והעלו את התקרה באמצעות /key/update אם התקציב הוגדר נמוך מדי.
האם ה-gateway יכול לנתב למודל מקומי בנוסף למודלים מאוחסנים?
כן, וזו כניסה נוספת ב-model_list. השתמשו בקידומת ollama_chat/ עם api_base, לדוגמה model: ollama_chat/llama3.1 לצד api_base: http://ollama:11434. מתוך מכולה, localhost מצביע על אותה מכולה, לכן השתמשו בשם שירות ה-Compose או בכתובת המארח ברשת ה-Docker, לעולם לא ב-127.0.0.1. הקמת המודל המקומי היא משימה נפרדת: ראו אירוח עצמי של LLM עם Ollama על גבי VPS.