השתמשתי בצינור ה-RAG שלי כמו ב"קופסה שחורה". embeddings נכנסו, תשובות יצאו, ובאיזשהו שלב באמצע, חשבון הענן שלי גדל. כמו רוב המפתחים ששוחחתי איתם, הנחתי שמודלים של וקטורים צפופים (dense vector models) הם הנבלים. הם נשמעו יקרים. המרה של אלף עמודים לערכי float בממדים גבוהים הרגישה כמו תהליך ייצור כבד, אז התייחסתי אליה בזהירות תואמת. אפילו בניתי שכבת caching במיוחד כדי להימנע מביצוע embedding מחדש לנתונים שכבר עיבדתי. הייתי גאה באופטימיזציה הזו. ואז פתחתי את החשבונית ועשיתי את החישוב.

אופטימיזציה של הדבר הלא נכון לחלוטין.

מלכודת ה-Embedding

הנה המספר שערער על ההנחות שלי: embedding של מסמך בן 1,000 עמודים עולה בערך שמונה עשרה סנט. זו לא טעות הקלדה. בפחות ממחיר של כוס קפה ברוב הערים, אתם יכולים לבצע וקטוריזציה לספר שלם. חשוב מכך, העלות הזו מופיעה פעם אחת בלבד, בזמן ה-ingestion. לאחר המעבר הראשוני, הווקטורים הללו יושבים באחסון ומחכים. הם לא צוברים עמלות לפי שימוש בכל פעם שמשתמש פותח את האפליקציה שלכם. זוהי הוצאה הונית (capital expense), לא הוצאה שוטפת.

ובכל זאת, המיתוס נמשך. חלק מהבלבול הוא מבני. תהליך ה-ingestion הוא המקום שבו מהנדסים משקיעים את האנרגיה הראשונית שלהם. אתם כותבים את ה-chunker, נלחמים עם ה-tokenizer, וצופים בסרגלי ההתקדמות זוחלים על הטרמינל. המאמץ הנראה הזה יוצר אשליה של פרופורציה. זה מרגיש כמו החלק היקר כי זה החלק עתיר העבודה. אך עבודה ועלות אינן אותו דבר, וב-RAG הן לעיתים קרובות קשורות ביחס הפוך.

שלושה חשבונות שונים בתכלית

ברגע שהפרדתי את העלויות לפי שלבים במקום לאחד אותן יחד, התמונה התבהרה. מערכת RAG פועלת על שלושה מודלים כלכליים נפרדים, והבנת ההבדל ביניהם חיונית אם אתם רוצים לשמור על תקציב שפוי.

Embeddings הם עלות ייצור חד-פעמית. אתם משלמים כדי להפוך מסמכים לווקטורים, ואז אתם מסיימים. אם המסמכים שלכם סטטיים, סעיף זה בקושי יופיע בחשבון החודשי שלכם.

מסדי נתונים וקטוריים (Vector databases) הם שכר דירה לתשתית. אתם משלמים כדי לשמור על המערכת פעילה מסביב לשעון. אתם משלמים על ה-SSDs שמחזיקים מיליוני chunks, על ליבות ה-CPU שמתחזקות אינדקסים, ועל הרשת שמספקת חיפושים של פחות מ-100 מילי-שניות. העלות הזו אמיתית, והיא גדלה עם נפח הנתונים, אך היא בדרך כלל צפויה. היא מתנהגת כמו מנוי לחדר כושר. בין אם תבצעו שאילתה פעם אחת או עשרת אלפים פעמים, עלות התשתית הבסיסית נשארת בערך זהה.

מודלי שפה גדולים (LLMs) הם מיסי צריכה. כל שאלת משתמש מפעילה חשבונית. כל token שיוצא משכבת השליפה (retrieval layer) שלכם ונכנס ל-prompt עולה כסף. כל שלב של הסקה (reasoning), כל הוראת פורמט, כל ציטוט שאתם מבקשים מהמודל לייצר מוסיפים משקל מיקרוסקופי. אך המיקרו-חיובים הללו מוכפלים במספר הסשנים, ומספר הסשנים נוטה לעלות. כאן השיהוי (latency) מצטבר עם ההוצאות. שאילתה איטית היא לא רק מעצבנת עבור המשתמש; היא שורפת מזומנים באופן פעיל בזמן שהמשתמש ממתין.

אלו אינן וריאציות של אותה בעיה. אלו שלוש בעיות נפרדות. אי אפשר לפתור בעיית הוצאות בזמן שאילתה על ידי הפיכת ה-ingestion לזול יותר. זה כמו לכוון את מנוע המכונית שלכם כדי לחסוך כסף בחניה.

לאן הכסף באמת הולך

אם אתם מריצים אפליקציית RAG בסביבת ייצור, פתחו את ה-cost explorer שלכם וסננו לפי סוג שימוש (usage type). אני מוכן להתערב שפעולת ה-embedding שלכם היא קו ישר פעם ביום, בעוד שנקודת הקצה (endpoint) של ה-LLM שלכם נראית כמו פעימת לב שקופצת עם התנועה. התבנית הזו מספרת את כל הסיפור. הווקטורים שלכם ישנים; המודל שלכם מתעורר בכל פעם שיש למשתמש שאלה.

התובנה הזו שינתה את הדרך שבה אני מתעדף עבודה הנדסית. הפסקתי לשאול איך להפוך את ה-ingestion לזול יותר והתחלתי לשאול איך להפוך כל שאלה לזולה יותר. השינוי הזה נשמע מובן מאליו, אך רוב הצוותים עדיין פועלים על תחושות בטן. הם בונים לוגיקת deduplication מסובכת לשלב ה-embedding ואז מזינים חלונות הקשר (context windows) נפוחים ולא ממוקדים ל-LLM בלי לחשוב פעמיים. הם מלטשים את הרצפה בזמן שהגג דולף.

איך לחסוך בעלויות מבלי לשבור את ה-Pipeline שלכם

חיסכון בכסף במערכת RAG דורש התאמה של הטקטיקה למודל העלות. הנה מה שעובד באמת.

בצעו Deduplication לפני העיבוד

רוב מאגרי הידע הארגוניים נעים לאט. מדיניות, מדריכים, קובצי PDF של מחקרים ודוחות מאוחסנים נותרים ללא מגע במשך חודשים. בזרמי עבודה (pipelines) רבים, כ-80% ממסמכי המקור נותרים זהים בין הרצות הזנה (ingestion). למרות זאת, מערכות רבות מוחקות את כל הקורפוס ובונות מחדש את האינדקס מאפס על בסיס לוח זמנים קבוע. אל תעשו זאת. בנו שער בכניסה ל-pipeline שלכם. בצעו hashing לקבצים הנכנסים. השוו חותמות זמן של "שינוי אחרון" (last-modified). אם מסמך לא השתנה, דלגו עליו לחלוטין. עיבוד מחדש של קבצים סטטיים הוא בזבוז מוחלט. זה גובה כוח מחשוב, שוחק כונני SSD ללא צורך, ומנפח את לוגי ההזנה (ingestion logs) שלכם בפעילות כוזבת.

בפועל, שמרו מניפסט (manifest) קל הממפה נתיבי קבצים ל-checksums. כאשר המתזמן (scheduler) מתעורר, תנו לו לבדוק קודם כל את המניפסט. רק המיעוט של הקבצים שהשתנו אמור להגיע ל-chunker.

עדכנו מסמכים (Patch), אל תחליפו אותם

כאשר מסמך אכן משתנה, התנגדו ליצר להתייחס אליו כאל קובץ חדש לגמרי. מפרט טכני בן חמישים עמודים עשוי לקבל עדכון של שני פסקאות בסעיף ארבעה. אם ה-pipeline שלכם מחליף את הקובץ כולו, תבצעו re-chunking ו-re-embedding לארבעים ותשע עמודים מצוינים ללא סיבה.

במקום זאת, השוו את הגרסה החדשה לישנה. זהו את הדילטה (delta). לאחר מכן, בצעו re-chunking ו-re-embedding רק לסעיפים שהשתנו. השתמשו במטא-דאטה כמו מספרי עמודים, מזהי סעיפים (section IDs), עוגני כותרות או טווחי פסקאות כדי לעקוב אחר הגבולות. אם אסטרטגיית ה-chunking שלכם מכבדת את מבנה המסמך, זה פשוט מאוד. אם לא, תיקון ה-chunker שלכם הוא השקעה טובה יותר מאשר קניית אשכול (cluster) הסקה (inference) גדול יותר. עלות ההנדסה של תחזוקת pipeline המודע להבדלים (diff-aware) מחזירה את עצמה תוך שבועות ברגע שמספר המסמכים שלכם גדל.

התמודדו ישירות עם העלויות החוזרות

מכיוון שקריאות LLM מתבצעות בכל שאילתה, חיסכון אפילו בכמה טוקנים או שמירה בזיכרון (caching) של קומץ תגובות יוצרים תשואה גבוהה במיוחד. התחילו עם prompt caching. אם משתמש אחד שואל על מדיניות ההחזרים שלכם ומשתמש אחר שואל את אותו הדבר עשר דקות מאוחר יותר, אין סיבה לפנות למודל פעמיים. שמרו זוגות של שאילתה-תגובה אחרונים עם התאמה מבוססת דמיון סמנטי. כאשר שאלה חדשה נוחתת בתוך סף דמיון (similarity threshold) של שאלה שמורה, החזירו את התשובה השמורה ישירות. אין יצירת טוקנים, אין הוצאת דולרים.

לאחר מכן, בחנו היטב את איכות השליפה (retrieval) שלכם. retriever רשלן מאלץ את ה-LLM לקרוא ערימת שחת כדי למצוא מחט. אם אתם דוחסים לתוך ה-prompt עשרים קטעים (chunks) לא רלוונטיים כי חיתוך ה-top-k שלכם רחב מדי, אתם משלמים למודל כדי שיסרוק רעש. הידקו את השליפה. צמצמו את ה-top-k שלכם. דחסו את ה-chunks לפני השליחה. הסירו כותרות ותחתית עמודים קבועות (boilerplate) במהלך ההזנה כדי שהן לעולם לא יגיעו ל-prompt. כל טוקן שאתם מסירים מחלון ההקשר (context window) הוא שבריר של סנט שנחסך, והשברים הללו מצטברים לאורך אלפי שאילתות יומיות.

שליפה טובה יותר משפרת גם את השיהוי (latency), שהוא צורה נוספת של עלות. משתמשים נוטשים ממשקים איטיים. תשובה מהירה יותר היא גם זולה יותר לייצור וגם טובה יותר לשימור משתמשים (retention).

השורה התחתונה האמיתית

הפסיקו לייעל את מה שמרגיש יקר והתחילו לייעל את מה שהחשבונית שלכם אומרת שהוא יקר. מדדו כל שלב בנפרד. סביר להניח שתגלו שה-embeddings הם החלק הזול, אחסון הוקטורים (vector storage) הוא החלק היציב, וה-LLM inference הוא החלק שגורם לדליפת כספים. רכזו את האנרגיה שלכם ביעילות בזמן שאילתה, עדכונים אינקרמנטליים והסרת כפילויות מדויקת (surgical deduplication). בנו עבור שאלת המשתמש האלף, לא עבור העלאת המסמך החמישים. צוואר הבקבוק הוא לעיתים רחוקות איפה שאתם חושבים שהוא נמצא.

מקור: Where Does RAG Actually Cost You Money? I Decided to Stop Guessing

הצטרפו לדיון ב-GyaanSetu AI learning community.