Knowledge Ingestion Pipelines: איך בונים צינור נתונים אמין למערכות RAG וסוכני AI
מאת צוות מדיה דיל · 01.08.2026 · Data Engineering · 10 דק׳
מדריך ארכיטקטוני לבניית Knowledge Ingestion Pipeline שמזין מערכות RAG וסוכני AI בנתונים איכותיים, עדכניים ומאובטחים — מ-Connectors ועד Indexing.
ארגון טיפוסי שמנסה להטמיע עוזר AI פנימי מגלה מהר מאוד שהבעיה האמיתית היא לא ה-LLM. הבעיה היא שהמידע הרלוונטי מפוזר על פני Confluence, Google Drive, SharePoint, מערכת Ticketing, מאגר PDF-ים ישנים ותיקיית Slack שאף אחד לא מנקה. כשהצוות בונה POC מהיר עם כמה מסמכים, הכל עובד להפליא. ברגע שמנסים להזין את כל בסיס הידע הארגוני — מתגלה שאין באמת "פייפליין", יש רק סקריפט אד-הוק שרץ פעם אחת ולא שורד עדכון אחד במקור. Knowledge Ingestion Pipeline הוא בדיוק התשתית שסוגרת את הפער הזה: המנגנון שאחראי לזהות, לשלוף, לנרמל, לחלק ולהעשיר מידע ממקורות הטרוגניים, כך שמערכת ה-Retrieval שמאחורי ה-RAG תקבל קלט איכותי ועדכני באופן שוטף, לא חד-פעמי.
למה זו בעיה הנדסית ולא רק בעיית אינטגרציה
ה-אינטואיציה הראשונית היא שמדובר ב"עוד אינטגרציית API": מתחברים למקור, מושכים מסמכים, שולחים ל-Embedding Model, שומרים ב-Vector DB. בפועל, כל אחד מהשלבים האלה מסתיר מורכבות משמעותית. מקורות שונים מחזירים פורמטים שונים לגמרי — HTML עם טבלאות מקוננות, PDF סרוק שדורש OCR, מסמכי Word עם הערות שוליים, קבצי Markdown עם קוד מוטבע. כל אחד מהם דורש לוגיקת extraction שונה כדי לשמר את המבנה הסמנטי של המסמך ולא להפוך אותו לגוש טקסט חסר הקשר.
מעבר לכך, מקורות הידע משתנים כל הזמן: מסמכים נמחקים, עמודי Confluence מתעדכנים כמה פעמים ביום, קבצים עוברים בין תיקיות עם הרשאות שונות. פייפליין שלא בנוי מלכתחילה כמערכת מתמשכת עם מעקב אחר שינויים — ולא כסקריפט חד-פעמי — יצטרך full re-index בכל פעם, מה שהופך בלתי אפשרי כבר במאות אלפי מסמכים.
ארכיטקטורת הצינור: שכבות ותפקידים
פייפליין בשל בנוי משכבות מופרדות עם חוזה ברור ביניהן. שכבת ה-Connectors אחראית על תקשורת עם כל מקור — API של Confluence, Google Drive API, S3, מסד נתונים פנימי — ומחזירה ייצוג אחיד של "מסמך גולמי" עם metadata בסיסי (מקור, מזהה, זמן עדכון אחרון). שכבת ה-Extraction ממירה את הפורמט הגולמי לטקסט מובנה: parsing של HTML לעץ סמנטי, OCR למסמכים סרוקים, חילוץ טבלאות כמבנה נפרד ולא כטקסט שטוח. שכבת ה-Chunking מפצלת את המסמך ליחידות קטנות שמתאימות ל-Embedding, תוך שמירה על גבולות סמנטיים — לא חיתוך אמצע משפט או אמצע טבלה. שכבת ה-Enrichment מוסיפה metadata חיוני: כותרות היררכיות, תגיות ACL, קטגוריה, תאריך תוקף. ולבסוף שכבת ה-Embedding & Indexing ממירה כל chunk לוקטור ומכניסה אותו ל-Vector DB יחד עם ה-metadata.
הפרדה כזו מאפשרת להחליף רכיב בודד — למשל להחליף ספק Embedding — בלי לגעת בשאר הצינור. היא גם מאפשרת להריץ שלבים מקבילית: extraction של מסמך אחד לא תלוי ב-extraction של מסמך אחר, כך שניתן להשתמש בתשתית עבודה מבוזרת (Celery, Temporal, Airflow) כדי לעבד אלפי מסמכים במקביל בלי לחכות לשרשור סדרתי.
Batch מול Streaming: החלטת התזמון
שאלת מפתח היא באיזו תדירות הפייפליין רץ. גישת Batch מריצה crawl מלא או חלקי במרווחי זמן קבועים — פעם בשעה, פעם ביום. היא פשוטה להטמעה ולדיבוג, אבל יוצרת פער עדכניות: מסמך שהשתנה יופיע במערכת רק אחרי הריצה הבאה. גישת Streaming מתחברת ל-Webhooks או Change Data Capture של המקור (למשל Confluence Webhooks, Google Drive Push Notifications) ומעדכנת כמעט מיידית. Streaming מורכב יותר להטמעה — צריך לטפל ב-out-of-order events, ב-deduplication וב-retry logic — אבל הוא הכרחי כשמדובר במידע שהעדכניות שלו קריטית, כמו מדיניות פנימית או תמחור.
בפרויקטים שאנחנו בונים במדיה דיל אנחנו נוטים להתחיל עם Batch יומי כ-baseline אמין, ולהוסיף Streaming רק למקורות שבהם יש הוכחה שהעדכניות משפיעה על התוצאה העסקית — לא כברירת מחדל גורפת.
Chunking: הפרמטר שמכריע איכות Retrieval
גודל ה-chunk הוא אחת ההחלטות המשפיעות ביותר על איכות המערכת כולה, ולעיתים קרובות היא נעשית בלי מחשבה — "512 טוקנים כי זה מה שכתוב במדריך". Chunk קטן מדי (100-150 טוקנים) מייצר וקטורים ממוקדים אך מאבד הקשר: משפט בודד בלי הפסקה הקודמת עלול להיות חסר משמעות. Chunk גדול מדי (1500+ טוקנים) שומר הקשר אבל "מדלל" את הוקטור — הוא מייצג יותר מדי רעיונות בו-זמנית, מה שפוגע בדיוק ה-similarity search. Overlap בין chunks (בדרך כלל 10-20%) עוזר לצמצם את בעיית "החיתוך באמצע רעיון", במחיר של כפילות אחסון.
הגישה הבשלה יותר היא Structure-Aware Chunking: להשתמש במבנה המסמך עצמו — כותרות, פסקאות, טבלאות — כגבולות טבעיים לחיתוך, במקום לספור טוקנים עיוורת. מסמך עם כותרות H1/H2 ברורות מתחלק הרבה יותר טוב כשה-chunker מכבד את ההיררכיה, ואז מוסיף metadata של "תחת איזו כותרת נמצא ה-chunk" — מידע שמאפשר גם re-ranking וגם מתן הקשר טוב יותר ל-LLM בזמן ה-generation.
Deduplication, Idempotency וניהול גרסאות
בלי מנגנון דדופליקציה, אותו מסמך שמופיע בכמה מקורות (למשל PDF שגם הועלה ל-Drive וגם צורף כקישור ב-Confluence) ייכנס פעמיים למאגר, מה שמטה את תוצאות ה-Retrieval לטובתו. הפתרון הוא content hashing: כל chunk מקבל hash על בסיס התוכן שלו, וה-pipeline בודק מול ה-hash הקיים לפני יצירת embedding חדש — חוסך גם כסף (קריאות API) וגם זמן עיבוד. בנוסף, לכל מסמך צריך document version — hash של המסמך כולו, כך שכשהוא מתעדכן, ה-pipeline יודע להחליף רק את ה-chunks שהשתנו ולא לעבד את המסמך מחדש במלואו. הנושא הזה מורחב במאמר שלנו על אינדוקס אינקרמנטלי ל-RAG, שמתמקד ספציפית בעדכון מדורג של האינדקס. באופן פשטני, לוגיקת ההשוואה נראית כך:
def should_reindex(chunk, existing_index):
content_hash = sha256(chunk.text + str(chunk.metadata))
existing = existing_index.get(chunk.doc_id, chunk.chunk_id)
if existing and existing.hash == content_hash:
return False # אין שינוי, מדלגים על embedding מחדש
return True
ההיגיון הזה נשמע טריוויאלי, אבל הוא זה שקובע אם ריצת ingestion שגרתית תיקח דקות בודדות (כי רוב המסמכים לא השתנו) או שעות ארוכות ועלות מיותרת של אלפי קריאות API. צוותים רבים מגלים את החשיבות שלו רק אחרי שהחשבון החודשי של ספק ה-Embedding קופץ פי כמה בלי סיבה ברורה — וכשבודקים מגלים שכל ריצה יוצרת embedding מחדש לכל מסמך במערכת, כולל כאלה שלא נגעו בהם חודשים.
טעויות נפוצות בפרודקשן
הטעות הראשונה והנפוצה ביותר: התעלמות ממחיקות. פייפליין שרק מוסיף מסמכים חדשים ולעולם לא מסיר וקטורים של מסמכים שנמחקו במקור, יוצר "vector rot" — המערכת ממשיכה להחזיר מידע שכבר לא קיים, ולעיתים כבר לא נכון. הפתרון דורש mechanism של Tombstoning או Soft Delete שמסונכרן מול המקור. הטעות השנייה היא הזנחת error handling ברמת מסמך בודד: אם מסמך אחד גורם לשגיאת parsing, כל ה-batch לא אמור ליפול — יש לבודד כשלים ולתעד אותם ב-Dead Letter Queue לבדיקה ידנית. טעות שלישית היא אי-שמירה על metadata של הרשאות (ACL) בזמן ה-ingestion, מה שמוביל לדליפת מידע רגיש דרך תשובות ה-RAG — נושא שמורחב במאמר על בקרת גישה ב-RAG. טעות רביעית היא היעדר observability: בלי מטריקות על שיעור הצלחה, זמן עיבוד ממוצע וכמות מסמכים שעודכנו, אי אפשר לדעת שהפייפליין "נשבר בשקט" — תופעה נפוצה כשמקור API משנה סכמה או מחזיר rate limit.
מתי כדאי להשקיע בפייפליין מלא ומתי לא
אם מדובר בבסיס ידע קטן וסטטי — כמה עשרות מסמכים שמתעדכנים לעיתים רחוקות — פייפליין מלא הוא overengineering. אפשר להסתפק בסקריפט ידני שרץ מדי פעם. אבל ברגע שיש יותר ממקור אחד, יותר מכמה מאות מסמכים, או קצב שינויים שוטף — היעדר פייפליין מסודר יהפוך במהרה לצוואר בקבוק תפעולי: מישהו יצטרך "לתקן ידנית" את בסיס הידע כל שבוע. הסימן המובהק שהגיע הזמן להשקיע: כשמשתמשים מתחילים לדווח שהתשובות של המערכת "לא מעודכנות" או "חסרות מידע שבטוח קיים במקום כלשהו". סימן נוסף, פחות מדובר אך חשוב לא פחות, הוא כשצוות הפיתוח מוצא את עצמו מריץ סקריפטים ידניים כדי "לתקן" את הנתונים — אם ingestion דורש התערבות אנושית תדירה, זה כבר לא סקריפט עזר אלא מערכת ייצור שלא הוכרה ככזו, וכדאי להתייחס אליה בהתאם מבחינת תשתית, בדיקות ותקציב תחזוקה.
בחירת כלי אורקסטרציה: Airflow, Temporal או פתרון פנימי
שאלה נפוצה היא אם צריך מנוע אורקסטרציה ייעודי או שאפשר להסתפק בקוד פשוט עם cron. התשובה תלויה בהיקף. עד כמה עשרות אלפי מסמכים וכמה מקורות, cron job עם תור עבודות (Redis Queue, SQS) מספיק לגמרי ופשוט הרבה יותר לתחזוקה. כשמספר המקורות גדל, כשיש תלות בין שלבים (retry ברמת שלב, לא ברמת כל הפייפליין), וכשצריך visibility ברור על אילו מסמכים עברו איזה שלב — כלים כמו Airflow או Dagster נותנים DAG-based orchestration עם ניטור מובנה. Temporal מתאים במיוחד כשיש תהליכים ארוכי טווח עם צורך ב-durable execution — למשל עיבוד מסמך שדורש קריאה חוזרת ל-API חיצוני עם delay של דקות. הטעות הנפוצה היא לקפוץ ישר לכלי הכבד ביותר "כי זה מה שכולם משתמשים בו", ולשלם מחיר תחזוקה גבוה על מורכבות שלא נחוצה בשלב המוקדם של הפרויקט.
עלויות נסתרות: Embedding API ו-Rate Limits
היבט שלעיתים קרובות מתגלה רק בפרודקשן הוא העלות התפעולית של יצירת embeddings. עיבוד מחדש של מיליון chunks בכל פעם שמישהו משנה את פרומפט ה-enrichment, או בכל פעם שמחליטים לנסות מודל embedding חדש, יכול לעלות אלפי דולרים ולקחת שעות ארוכות. לכן שכבת ה-caching של embeddings — לפי content hash כפי שתואר למעלה — היא לא רק אופטימיזציית ביצועים אלא שיקול תקציבי ממשי. בנוסף, כמעט כל ספקי ה-Embedding API מטילים rate limits, ופייפליין שלא מטמיע backoff אקספוננציאלי ותור עם concurrency מוגבל ייתקל בכשלים אקראיים תחת עומס — בדיוק כשצריך להריץ ingestion גדול לאחר מיגרציה או הוספת מקור חדש.
סיכום
Knowledge Ingestion Pipeline הוא לא שכבת תשתית שוליים — הוא הבסיס שקובע אם מערכת ה-RAG שלכם תיתן תשובות מדויקות ועדכניות, או תשובות חלקיות ומיושנות. ההשקעה בארכיטקטורה נכונה — הפרדת שכבות, chunking מודע-מבנה, דדופליקציה ו-observability — משתלמת הרבה יותר מהשקעה נוספת ב-prompt engineering או במודל גדול יותר. אצלנו במדיה דיל, כמעט כל פרויקט RAG ארגוני מתחיל דווקא כאן, לפני שמדברים בכלל על בחירת LLM.
תגיות: Knowledge Ingestion · RAG · Data Pipeline · Chunking · Vector Database · Embeddings · Data Engineering