--- layout: default title: "מקור המידע בזמן החילוץ: שכבת המקור" parent: "Hebrew (Beta)" --- # מקור המידע בזמן החילוץ: שכבת המקור > **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta. ## סקירה כללית מסמך זה מתעד הערות על מקור המידע בזמן החילוץ לצורך עבודה עתידית על מפרטים. מקור המידע בזמן החילוץ מתעד את "שכבת המקור" - מאיפה הנתונים הגיעו במקור, וכיצד הם חולצו ועובדו. זה נפרד ממקור המידע בזמן השאילתה (ראה `query-time-provenance.md`) אשר מתעד את הנימוקים של המערכת. ## הצהרת בעיה ### יישום נוכחי כיום, מקור המידע פועל באופן הבא: מטא-נתונים של מסמכים מאוחסנים כמשולשים RDF בגרף הידע. מזהה מסמך מקשר בין מטא-נתונים למסמך, כך שהמסמך מופיע כצומת בגרף. כאשר קשרים (יחסים/עובדות) מחולצים ממסמכים, קשר `subjectOf` מקשר את הקשר המחולץ בחזרה למסמך המקור. ### בעיות בגישה הנוכחית 1. **טעינת מטא-נתונים חוזרת:** מטא-נתונים של מסמכים מקובצים ונטענים שוב ושוב עם כל אצווה של משולשים המחולצים ממסמך זה. זה בזבוז ומיותר - אותם מטא-נתונים מועברים כחלק מהפלט בכל חילוץ. <<<<<<< HEAD 2. **מקור מידע שטחי:** הקשר `subjectOf` הנוכחי מקשר רק עובדות ישירות למסמך הראשי. אין נראות לגבי שרשרת השינויים - מאיזו עמוד הגיעה העובדה, מאיזה חלק, באיזו שיטת חילוץ נעשה שימוש. ======= 2. **מקור מידע שטחי:** הקשר `subjectOf` הנוכחי מקשר רק עובדות ישירות למסמך הראשי. אין נראות לגבי שרשרת השינויים - מאיזו עמוד הגיעה העובדה, מאיזה חלק, באיזו שיטת חילוץ השתמשו. >>>>>>> 82edf2d (New md files from RunPod) ### מצב רצוי 1. **טעינת מטא-נתונים פעם אחת:** מטא-נתונים של מסמכים צריכים להיטען פעם אחת ולהיות מחוברים לצומת המסמך הראשי, ולא לחזור על עצמם עם כל אצווה של משולשים. <<<<<<< HEAD 2. **גרף מקור מידע עשיר:** לתפוס את שרשרת השינויים המלאה ממסמך המקור דרך כל הארטיפקטים הביניים ועד לעובדות המחולצות. לדוגמה, טרנספורמציה של מסמך PDF: ======= 2. **גרף מקור מידע עשיר:** לתפוס את שרשרת השינויים המלאה מהמסמך המקור דרך כל הארטיפקטים הביניים ועד לעובדות המחולצות. לדוגמה, טרנספורמציה של מסמך PDF: >>>>>>> 82edf2d (New md files from RunPod) ``` PDF file (source document with metadata) → Page 1 (decoded text) → Chunk 1 → Extracted edge/fact (via subjectOf) → Extracted edge/fact → Chunk 2 → Extracted edge/fact → Page 2 → Chunk 3 → ... ``` 3. **אחסון מאוחד:** גרף המוצא (provenance DAG) מאוחסן באותו גרף ידע כמו הידע שחולץ. זה מאפשר שאילתת מוצא באותה צורה כמו שאילתת ידע - מעקב אחר קשרים לאחור בשרשרת מכל עובדה למיקום המקור המדויק שלה. 4. **מזהים יציבים:** לכל ארטיפקט ביניים (עמוד, מקטע) יש מזהה יציב כצומת בגרף. 5. **קישור הורה-ילד:** מסמכים נגזרים מקושרים להוריהם עד למסמך המקור העליון באמצעות סוגי קשרים עקביים. 6. **הקצאת עובדות מדויקת:** הקשר `subjectOf` בקשרים שחולצו מצביע על ההורה המיידי (מקטע), ולא על מסמך המקור העליון. ניתן לשחזר את כל המוצא על ידי מעבר ב-DAG. ## תרחישי שימוש <<<<<<< HEAD ### UC1: הקצאת מקור בתגובות GraphRAG ======= ### תרחיש שימוש 1: הקצאת מקור בתגובות GraphRAG >>>>>>> 82edf2d (New md files from RunPod) **תרחיש:** משתמש מריץ שאילתה של GraphRAG ומקבל תגובה מהסוכן. **תהליך:** 1. משתמש מגיש שאילתה לסוכן GraphRAG. 2. הסוכן שולף עובדות רלוונטיות מגרף הידע כדי לנסח תגובה. 3. בהתאם למפרט המוצא בזמן השאילתה, הסוכן מדווח אילו עובדות תרמו לתגובה. 4. כל עובדה מקושרת למקטע המקור שלה באמצעות גרף המוצא. 5. מקטעים מקושרים לעמודים, עמודים מקושרים למסמכי מקור. **תוצאה עבור המשתמש:** הממשק מציג את תגובת מודל השפה הגדול (LLM) יחד עם הקצאת מקור. המשתמש יכול: לראות אילו עובדות תמכו בתגובה. לעבור ממקטעים → עמודים → מסמכים. לעיין במסמכי המקור המקוריים כדי לאמת טענות. להבין בדיוק מאיפה במסמך (איזה עמוד, איזה חלק) עובדה מסוימת הגיעה. **ערך:** משתמשים יכולים לאמת תגובות שנוצרו על ידי AI מול מקורות ראשוניים, ובכך לבנות אמון ולאפשר בדיקת עובדות. <<<<<<< HEAD ### UC2: ניפוי באגים של איכות חילוץ עובדה נראית שגויה. ניתן לעקוב אחורה דרך מקטע → עמוד → מסמך כדי לראות את הטקסט המקורי. האם זו הייתה שגיאת חילוץ, או שהמקור עצמו היה שגוי? ### UC3: חילוץ חוזר מצטבר מסמך מקור מתעדכן. אילו מקטעים/עובדות נגזרו ממנו? לבטל ולחדש רק את אלה, ולא לעבד הכל מחדש. ### UC4: מחיקת נתונים / הזכות להיות נשכח יש להסיר מסמך מקור (GDPR, סיבות משפטיות וכו'). יש לעבור ב-DAG כדי למצוא ולהסיר את כל העובדות הנגזרות. ### UC5: פתרון קונפליקטים שתי עובדות סותרות אחת את השנייה. ניתן לעקוב אחורה לשני המקורות שלהן כדי להבין מדוע ולהחליט איזו עובדה לתת לה עדיפות (מקור סמכותי יותר, עדכני יותר וכו'). ### UC6: שקלול סמכות מקור למקורות מסוימים יש סמכות רבה יותר מאחרים. ניתן לשקלל או לסנן עובדות בהתאם לסמכות/איכות מסמכי המקור שלהן. ### UC7: השוואת צינורות חילוץ ======= ### תרחיש שימוש 2: ניפוי באגים של איכות חילוץ עובדה נראית שגויה. ניתן לחזור אחורה דרך מקטע → עמוד → מסמך כדי לראות את הטקסט המקורי. האם זו הייתה שגיאת חילוץ, או שהמקור עצמו שגוי? ### תרחיש שימוש 3: חילוץ חוזר מצטבר מסמך מקור מתעדכן. אילו מקטעים/עובדות נגזרו ממנו? לבטל ולחדש רק את אלה, ולא לעבד הכל מחדש. ### תרחיש שימוש 4: מחיקת נתונים / הזכות להימחק יש להסיר מסמך מקור (GDPR, סיבות משפטיות וכו'). יש לעבור ב-DAG כדי למצוא ולהסיר את כל העובדות הנגזרות. ### תרחיש שימוש 5: פתרון קונפליקטים שתי עובדות סותרות אחת את השנייה. ניתן לחזור לשתי העובדות למקורות שלהן כדי להבין מדוע ולהחליט איזו מהן לתת לה עדיפות (מקור סמכותי יותר, עדכני יותר וכו'). ### תרחיש שימוש 6: שקלול סמכות מקור למקורות מסוימים יש סמכות רבה יותר מאחרים. ניתן לשקלל או לסנן עובדות בהתאם לסמכות/איכות מסמכי המקור שלהן. ### תרחיש שימוש 7: השוואת צינורות חילוץ >>>>>>> 82edf2d (New md files from RunPod) השוואת תוצאות משיטות/גרסאות חילוץ שונות. איזה מחלץ הפיק עובדות טובות יותר מאותו מקור? ## נקודות אינטגרציה ### ספרן רכיב הספרן כבר מספק אחסון מסמכים עם מזהי מסמכים ייחודיים. מערכת המקור משתלבת בתשתית הקיימת. #### יכולות קיימות (שיושמו כבר) **קישור מסמכים הורה-ילד:** `parent_id` שדה ב-`DocumentMetadata` - מקשר מסמך ילד למסמך הורה `document_type` שדה - ערכים: `"source"` (מקור) או `"extracted"` (נגזר) `add-child-document` API - יוצר מסמך ילד עם `document_type = "extracted"` אוטומטי `list-children` API - שולף את כל ילדי מסמך הורה מחיקה מדורגת - הסרת מסמך הורה מוחקת אוטומטית את כל מסמכי הילד **זיהוי מסמכים:** מזהי מסמכים מוגדרים על ידי הלקוח (לא נוצרים אוטומטית) מסמכים מאוחסנים לפי מפתח מורכב `(user, document_id)` ב-Cassandra מזהי אובייקטים (UUIDs) נוצרים באופן פנימי עבור אחסון בלובים **תמיכה במטא-נתונים:** `metadata: list[Triple]` שדה - משולשים RDF עבור מטא-נתונים מובנים `title`, `comments`, `tags` - מטא-נתונים בסיסיים של מסמך `time` - חותמת זמן, `kind` - סוג MIME **ארכיטקטורת אחסון:** מטא-נתונים מאוחסנים ב-Cassandra (מרחב מפתחות `librarian`, טבלה `document`) תוכן מאוחסן ב-MinIO/S3 blob storage (דלי `library`) העברת תוכן חכמה: מסמכים קטנים מ-2MB משובצים, מסמכים גדולים יותר מועברים #### קבצים מרכזיים `trustgraph-flow/trustgraph/librarian/librarian.py` - פעולות ליבה של הספרן `trustgraph-flow/trustgraph/librarian/service.py` - מעבד שירות, טעינת מסמכים `trustgraph-flow/trustgraph/tables/library.py` - חנות טבלאות Cassandra `trustgraph-base/trustgraph/schema/services/library.py` - הגדרות סכימה #### פערים לטיפול ל-ספרן יש את אבני הבניין, אך כרגע: 1. קישור הורה-ילד הוא בעומק של רמה אחת - אין עזרי מעבר DAG מרובי רמות 2. אין אוצר מילים סטנדרטי לסוגי יחסים (לדוגמה, `derivedFrom`, `extractedFrom`) 3. מטא-נתונים של מקור (שיטת חילוץ, רמת אמון, מיקום מקטע) אינם סטנדרטיים 4. אין API שאילתה למעבר על שרשרת המקור המלאה מעובדה חזרה למקור ## תכנון זרימת עבודה מקצה לקצה כל מעבד בצינור עוקב אחר דפוס עקבי: מקבל מזהה מסמך מהשורה העליונה שולף תוכן מהספרן מייצר ארטיפקטים ילדים עבור כל ילד: שומר בספרן, פולט קצה לגרף, מעביר מזהה לשורה התחתונה ### זרימות עיבוד ישנן שתי זרימות בהתאם לסוג המסמך: #### זרימת מסמכי PDF ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ Librarian (initiate processing) │ │ 1. Emit root document metadata to knowledge graph (once) │ │ 2. Send root document ID to PDF extractor │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ PDF Extractor (per page) │ │ 1. Fetch PDF content from librarian using document ID │ │ 2. Extract pages as text │ │ 3. For each page: │ │ a. Save page as child document in librarian (parent = root doc) │ │ b. Emit parent-child edge to knowledge graph │ │ c. Send page document ID to chunker │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Chunker (per chunk) │ │ 1. Fetch page content from librarian using document ID │ │ 2. Split text into chunks │ │ 3. For each chunk: │ │ a. Save chunk as child document in librarian (parent = page) │ │ b. Emit parent-child edge to knowledge graph │ │ c. Send chunk document ID + chunk content to next processor │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ Post-chunker optimization: messages carry both chunk ID (for provenance) and content (to avoid librarian round-trip). Chunks are small (2-4KB). ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Knowledge Extractor (per chunk) │ │ 1. Receive chunk ID + content directly (no librarian fetch needed) │ │ 2. Extract facts/triples and embeddings from chunk content │ │ 3. For each triple: │ │ a. Emit triple to knowledge graph │ │ b. Emit reified edge linking triple → chunk ID (edge pointing │ │ to edge - first use of reification support) │ │ 4. For each embedding: │ │ a. Emit embedding with its entity ID │ │ b. Link entity ID → chunk ID in knowledge graph │ └─────────────────────────────────────────────────────────────────────────┘ ``` #### זרימת מסמכי טקסט מסמכי טקסט עוקפים את מודל החילוץ של PDF ועוברים ישירות למקטע: ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ Librarian (initiate processing) │ │ 1. Emit root document metadata to knowledge graph (once) │ │ 2. Send root document ID directly to chunker (skip PDF extractor) │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Chunker (per chunk) │ │ 1. Fetch text content from librarian using document ID │ │ 2. Split text into chunks │ │ 3. For each chunk: │ │ a. Save chunk as child document in librarian (parent = root doc) │ │ b. Emit parent-child edge to knowledge graph │ │ c. Send chunk document ID + chunk content to next processor │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Knowledge Extractor │ │ (same as PDF flow) │ └─────────────────────────────────────────────────────────────────────────┘ ``` הגרף המכוון (DAG) המתקבל הוא ברמה אחת קצרה יותר: ``` PDF: Document → Pages → Chunks → Triples/Embeddings Text: Document → Chunks → Triples/Embeddings ``` העיצוב מתאים לשני המקרים מכיוון שהמקטע (chunker) מטפל בקלט שלו באופן כללי - הוא משתמש בכל מזהה מסמך שהוא מקבל כאב, ללא קשר לשאלה האם מדובר במסמך מקור או בעמוד. ### סכימת מטא-נתונים (PROV-O) מטא-נתונים של מקור (Provenance) משתמשים באונטולוגיה W3C PROV-O. זה מספק אוצר מילים סטנדרטי ומאפשר חתימה/אימות עתידי של תוצרי חילוץ. #### מושגים מרכזיים ב-PROV-O | סוג PROV-O | שימוש ב-TrustGraph | |-------------|------------------| | `prov:Entity` | מסמך, עמוד, מקטע, טריפל, הטמעה | | `prov:Activity` | מופעים של פעולות חילוץ | | `prov:Agent` | רכיבי TG (תוכנת חילוץ PDF, מקטע, וכו') עם גרסאות | #### קשרים ב-PROV-O | פרידיקט | משמעות | דוגמה | |-----------|---------|---------| <<<<<<< HEAD | `prov:wasDerivedFrom` | ישות שמקורה בישות אחרת | עמוד היה-מבוסס-על מסמך | | `prov:wasGeneratedBy` | ישות שנוצרה על ידי פעילות | עמוד נוצר-על-ידי פעולת חילוץ PDF | | `prov:used` | פעילות השתמשה בישות כקלט | פעולת חילוץ PDF השתמשה במסמך | | `prov:wasAssociatedWith` | פעילות בוצעה על ידי סוכן | פעולת חילוץ PDF הייתה-קשורה ל-tg:PDFExtractor | ======= | `prov:wasDerivedFrom` | ישות שמקורה בישות אחרת | עמוד wasDerivedFrom מסמך | | `prov:wasGeneratedBy` | ישות שנוצרה על ידי פעילות | עמוד wasGeneratedBy PDFExtractionActivity | | `prov:used` | פעילות השתמשה בישות כקלט | PDFExtractionActivity used Document | | `prov:wasAssociatedWith` | פעילות בוצעה על ידי סוכן | PDFExtractionActivity wasAssociatedWith tg:PDFExtractor | >>>>>>> 82edf2d (New md files from RunPod) #### מטא-נתונים בכל רמה **מסמך מקור (נפלט על ידי הספרן):** ``` doc:123 a prov:Entity . doc:123 dc:title "Research Paper" . doc:123 dc:source . doc:123 dc:date "2024-01-15" . doc:123 dc:creator "Author Name" . doc:123 tg:pageCount 42 . doc:123 tg:mimeType "application/pdf" . ``` <<<<<<< HEAD **עמוד (נפלט על ידי מופשט PDF):** ======= **עמוד (נפלט על ידי מחלץ PDF):** >>>>>>> 82edf2d (New md files from RunPod) ``` page:123-1 a prov:Entity . page:123-1 prov:wasDerivedFrom doc:123 . page:123-1 prov:wasGeneratedBy activity:pdf-extract-456 . page:123-1 tg:pageNumber 1 . activity:pdf-extract-456 a prov:Activity . activity:pdf-extract-456 prov:used doc:123 . activity:pdf-extract-456 prov:wasAssociatedWith tg:PDFExtractor . activity:pdf-extract-456 tg:componentVersion "1.2.3" . activity:pdf-extract-456 prov:startedAtTime "2024-01-15T10:30:00Z" . ``` **חלק (נפלט על ידי מודול החלוקה):** ``` chunk:123-1-1 a prov:Entity . chunk:123-1-1 prov:wasDerivedFrom page:123-1 . chunk:123-1-1 prov:wasGeneratedBy activity:chunk-789 . chunk:123-1-1 tg:chunkIndex 1 . chunk:123-1-1 tg:charOffset 0 . chunk:123-1-1 tg:charLength 2048 . activity:chunk-789 a prov:Activity . activity:chunk-789 prov:used page:123-1 . activity:chunk-789 prov:wasAssociatedWith tg:Chunker . activity:chunk-789 tg:componentVersion "1.0.0" . activity:chunk-789 tg:chunkSize 2048 . activity:chunk-789 tg:chunkOverlap 200 . ``` **משולש (נפלט על ידי מפיק ידע):** ``` # The extracted triple (edge) entity:JohnSmith rel:worksAt entity:AcmeCorp . # Subgraph containing the extracted triples subgraph:001 tg:contains <> . subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . subgraph:001 prov:wasGeneratedBy activity:extract-999 . activity:extract-999 a prov:Activity . activity:extract-999 prov:used chunk:123-1-1 . activity:extract-999 prov:wasAssociatedWith tg:KnowledgeExtractor . activity:extract-999 tg:componentVersion "2.1.0" . activity:extract-999 tg:llmModel "claude-3" . activity:extract-999 tg:ontology . ``` **הטמעה (מאוחסנת במאגר וקטורים, ולא במאגר משולשות):** הטמעות מאוחסנות במאגר הווקטורים עם מטא-נתונים, ולא כמשולשות RDF. כל רשומה של הטמעה מכילה: | שדה | תיאור | דוגמה | |-------|-------------|---------| | וקטור | וקטור ההטמעה | [0.123, -0.456, ...] | | ישות | מזהה צומת שההטמעה מייצגת | `entity:JohnSmith` | | מזהה_קטע | קטע מקור (מקור) | `chunk:123-1-1` | | מודל | מודל הטמעה ששימש | `text-embedding-ada-002` | | גרסת_רכיב | גרסת הטמעת TG | `1.0.0` | השדה `entity` מקשר את ההטמעה לגרף הידע (מזהה צומת). השדה `chunk_id` מספק מידע על המקור חזרה לקטע המקור, ומאפשר מעבר במבנה ה-DAG אל המסמך המקורי. #### הרחבות מרחב השמות של TrustGraph פרדיקטים מותאמים אישית תחת מרחב השמות `tg:` עבור מטא-נתונים ספציפיים לחילוץ: | פרדיקט | תחום | תיאור | |-----------|--------|-------------| | `tg:contains` | תת-גרף | מצביע על משולש הכלול בתת-גרף החילוץ הזה | | `tg:pageCount` | מסמך | מספר כולל של עמודים במסמך המקור | | `tg:mimeType` | מסמך | סוג MIME של המסמך המקור | | `tg:pageNumber` | עמוד | מספר עמוד במסמך המקור | <<<<<<< HEAD | `tg:chunkIndex` | קטע | אינדקס של קטע בתוך הורה | | `tg:charOffset` | קטע | התאמה אופסט בטקסט הורה | | `tg:charLength` | קטע | אורך הקטע בתווים | | `tg:chunkSize` | פעילות | גודל קטע מוגדר | | `tg:chunkOverlap` | פעילות | חפיפה מוגדרת בין קטעים | | `tg:componentVersion` | פעילות | גרסת רכיב TG | ======= | `tg:chunkIndex` | קטע | אינדקס של קטע בתוך ההורה | | `tg:charOffset` | קטע | התאמה אופסט בטקסט ההורה | | `tg:charLength` | קטע | אורך הקטע בתווים | | `tg:chunkSize` | פעילות | גודל קטע מוגדר | | `tg:chunkOverlap` | פעילות | חפיפה מוגדרת בין קטעים | | `tg:componentVersion` | פעילות | גרסה של רכיב TG | >>>>>>> 82edf2d (New md files from RunPod) | `tg:llmModel` | פעילות | מודל LLM ששימש לחילוץ | | `tg:ontology` | פעילות | אונטולוגיה ששימשה להכוונת החילוץ | | `tg:embeddingModel` | פעילות | מודל ששימש להטמעות | | `tg:sourceText` | הצהרה | הטקסט המדויק ממנו חולצה משולשת | <<<<<<< HEAD | `tg:sourceCharOffset` | הצהרה | התאמה אופסט בתוך קטע שבו מתחיל הטקסט המקור | ======= | `tg:sourceCharOffset` | הצהרה | התאמה אופסט בתוך הקטע שבו מתחיל הטקסט המקור | >>>>>>> 82edf2d (New md files from RunPod) | `tg:sourceCharLength` | הצהרה | אורך הטקסט המקור בתווים | #### אתחול אוצר מילים (לכל אוסף) <<<<<<< HEAD גרף הידע הוא ניטרלי אוטולוגי ומתחיל ריק. בעת כתיבת נתוני provenance של PROV-O לאוסף בפעם הראשונה, יש לאתחל את אוצר המילים עם תגיות RDF עבור כל מחלקות ופרדיקטים. זה מבטיח תצוגה קריאה על ידי בני אדם בשאילתות ובממשק המשתמש. ======= גרף הידע הוא ניטרלי מבחינת אונטולוגיה ומתחיל ריק. בעת כתיבת נתוני provenance של PROV-O לאוסף בפעם הראשונה, יש לאתחל את אוצר המילים עם תגיות RDF עבור כל מחלקות ופרדיקטים. זה מבטיח תצוגה קריאה על ידי בני אדם בשאילתות ובממשק המשתמש. >>>>>>> 82edf2d (New md files from RunPod) **מחלקות PROV-O:** ``` prov:Entity rdfs:label "Entity" . prov:Activity rdfs:label "Activity" . prov:Agent rdfs:label "Agent" . ``` **נשואים של PROV-O:** ``` prov:wasDerivedFrom rdfs:label "was derived from" . prov:wasGeneratedBy rdfs:label "was generated by" . prov:used rdfs:label "used" . prov:wasAssociatedWith rdfs:label "was associated with" . prov:startedAtTime rdfs:label "started at" . ``` **משפטי TrustGraph:** ``` tg:contains rdfs:label "contains" . tg:pageCount rdfs:label "page count" . tg:mimeType rdfs:label "MIME type" . tg:pageNumber rdfs:label "page number" . tg:chunkIndex rdfs:label "chunk index" . tg:charOffset rdfs:label "character offset" . tg:charLength rdfs:label "character length" . tg:chunkSize rdfs:label "chunk size" . tg:chunkOverlap rdfs:label "chunk overlap" . tg:componentVersion rdfs:label "component version" . tg:llmModel rdfs:label "LLM model" . tg:ontology rdfs:label "ontology" . tg:embeddingModel rdfs:label "embedding model" . tg:sourceText rdfs:label "source text" . tg:sourceCharOffset rdfs:label "source character offset" . tg:sourceCharLength rdfs:label "source character length" . ``` <<<<<<< HEAD **הערה בנושא יישום:** אוצר המילים הזה צריך להיות בעל תכונה של אידמפוטנטיות - בטוח להפעיל אותו מספר פעמים מבלי ליצור כפילויות. ניתן להפעיל אותו בפעם הראשונה בעיבוד מסמך באוסף, או כשלב נפרד של אתחול אוסף. #### מקור של חלקים קטנים (שאפתני) לצורך מעקב מקור מדויק יותר, יהיה שימושי לתעד בדיוק מאיפה בתוך חלק קטן נשלפה טריפלט. זה מאפשר: ======= **הערה בנושא יישום:** אוצר המילים הזה צריך להיות בעל תכונה של "אידמפוטנטיות" - בטוח להפעיל אותו מספר פעמים מבלי ליצור כפילויות. ניתן להפעיל אותו בפעם הראשונה בעיבוד מסמך באוסף, או כשלב נפרד של אתחול אוסף. #### מקור (Provenance) של תת-קטע (שאיפה) לצורך מעקב מדויק יותר, יהיה מועיל לתעד בדיוק מאיפה בתוך קטע נשלפה טריפלט. זה מאפשר: >>>>>>> 82edf2d (New md files from RunPod) הדגשת הטקסט המדויק ממנו נשלף הטריפלט בממשק המשתמש אימות דיוק החילוץ מול המקור ניפוי באגים באיכות החילוץ ברמת המשפט **דוגמה עם מעקב מיקום:** ``` # The extracted triple entity:JohnSmith rel:worksAt entity:AcmeCorp . # Subgraph with sub-chunk provenance subgraph:001 tg:contains <> . subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . subgraph:001 tg:sourceCharOffset 1547 . subgraph:001 tg:sourceCharLength 46 . ``` **דוגמה עם טווח טקסט (חלופה):** ``` subgraph:001 tg:contains <> . subgraph:001 prov:wasDerivedFrom chunk:123-1-1 . subgraph:001 tg:sourceRange "1547-1593" . subgraph:001 tg:sourceText "John Smith has worked at Acme Corp since 2019" . ``` **שיקולי יישום:** <<<<<<< HEAD חילוץ מבוסס מודל שפה גדול (LLM) עשוי שלא לספק באופן טבעי מיקומי תווים. ניתן לבקש מה-LLM להחזיר את המשפט/הביטוי המקורי יחד עם הטריפלים החילוצים. לחלופין, ניתן לבצע עיבוד לאחר החילוץ כדי להתאים את הישויות החילוצות בחזרה לטקסט המקור. איזון בין מורכבות החילוץ ובין רמת הפירוט של מקור המידע. ייתכן שיהיה קל יותר להשיג זאת באמצעות שיטות חילוץ מובנות מאשר חילוץ חופשי מבוסס LLM. זה מסומן כשאיפה - יש ליישם תחילה את מקור המידע ברמת החלקים, כאשר מעקב אחר תת-חלקים הוא שיפור עתידי אם אפשרי. ### מודל אחסון כפול גרף מקור המידע נבנה בהדרגה ככל שהמסמכים עוברים דרך הצינור: | אחסון | מה מאוחסן | מטרה | |-------|---------------|---------| | ספרן (Librarian) | תוכן מסמך + קישורים הורה-ילד | אחזור תוכן, מחיקה מדורגת | | גרף ידע (Knowledge Graph) | קצוות הורה-ילד + מטא-נתונים | שאילתות מקור מידע, ייחוס עובדות | שני האחסונים שומרים על מבנה גרף זהה. הספרן שומר על התוכן; הגרף שומר על קשרים ומאפשר שאילתות מעבר. ### עקרונות עיצוב מרכזיים 1. **מזהה מסמך כיחידת זרימה** - מעבדים מעבירים מזהים, לא תוכן. התוכן נשאב מהספרן בעת הצורך. 2. **פליטה חד-פעמית במקור** - מטא-נתונים נכתבים לגרף פעם אחת בתחילת העיבוד, ולא חוזרים על עצמם במעלה הצינור. 3. **תבנית מעבד עקבית** - כל מעבד פועל לפי אותה תבנית של קבלה/שאילתא/יצירה/שמירה/פליטה/העברה. 4. **בניית גרף הדרגתית** - כל מעבד מוסיף את השכבה שלו לגרף. שרשרת מקור המידע השלמה נבנית בהדרגה. 5. **אופטימיזציה לאחר חלוקה לחלקים** - לאחר חלוקה לחלקים, הודעות נושאות גם מזהה וגם תוכן. החלקים קטנים (2-4KB), כך שכלול התוכן מונע מעברים מיותרים לספרן תוך שמירה על מקור המידע באמצעות המזהה. ======= חילוץ מבוסס מודל שפה גדול (LLM) עשוי שלא לספק באופן טבעי מיקומי תווים ניתן לבקש מה-LLM להחזיר את המשפט/הביטוי המקורי יחד עם הטריפלים החולצים לחלופין, ניתן לבצע עיבוד לאחר החילוץ כדי להתאים את הישויות החולצות בחזרה לטקסט המקור פשרה בין מורכבות החילוץ וגרנולריות המקור ייתכן שיהיה קל יותר להשיג זאת באמצעות שיטות חילוץ מובנות מאשר חילוץ LLM חופשי זה מסומן כשאיפה - יש ליישם תחילה את המקור הבסיסי ברמת החלקים, כאשר מעקב אחר תת-חלקים הוא שיפור עתידי אם זה אפשרי. ### מודל אחסון כפול גרף המקור נבנה בהדרגה ככל שהמסמכים עוברים דרך הצינור: | חנות | מה מאוחסן | מטרה | |-------|---------------|---------| | ספרן | תוכן מסמך + קישורים הורה-ילד | אחזור תוכן, מחיקה מדורגת | | גרף ידע | קצוות הורה-ילד + מטא-נתונים | שאילתות מקור, הקצאת עובדות | שתי החנויות שומרות על מבנה גרף זהה. הספרן מחזיק בתוכן; הגרף מחזיק ביחסים ומאפשר שאילתות ניווט. ### עקרונות עיצוב מרכזיים 1. **מזהה מסמך כיחידת זרימה** - מעבדים מעבירים מזהים, לא תוכן. תוכן נשאב מהספרן בעת הצורך. 2. **פליטה פעם אחת במקור** - מטא-נתונים נכתבים לגרף פעם אחת כאשר עיבוד מתחיל, ולא חוזרים על עצמם במורד הזרם. 3. **דפוס מעבד עקבי** - כל מעבד עוקב אחר דפוס קבלה/שאילתא/יצירה/שמירה/פליטה/העברה זהה. 4. **בניית גרף הדרגתית** - כל מעבד מוסיף את השכבה שלו לגרף. שרשרת המקור השלמה נבנית באופן מצטבר. 5. **אופטימיזציה לאחר חלוקה לחלקים** - לאחר חלוקה לחלקים, הודעות נושאות גם מזהה וגם תוכן. החלקים קטנים (2-4KB), כך שכלול התוכן נמנע ממסעות הלוך ושוב מיותרים לספרן תוך שמירה על המקור באמצעות המזהה. >>>>>>> 82edf2d (New md files from RunPod) ## משימות יישום ### שינויים בספרן #### מצב נוכחי <<<<<<< HEAD מתחיל עיבוד מסמכים על ידי שליחת מזהה מסמך למעבד הראשון. אין חיבור למאגר טריפלים - מטא-נתונים נכללים בפלט החילוץ. `add-child-document` יוצר קישורים הורה-ילד ברמה אחת. `list-children` מחזיר רק ילדים מיידיים. ======= מתחיל עיבוד מסמכים על ידי שליחת מזהה מסמך למעבד הראשון אין חיבור למאגר טריפלים - מטא-נתונים מקובצים עם פלטי חילוץ `add-child-document` יוצר קישורים הורה-ילד חד-שכבתיים `list-children` מחזיר רק ילדים מיידיים >>>>>>> 82edf2d (New md files from RunPod) #### שינויים נדרשים **1. ממשק חדש: חיבור למאגר טריפלים** <<<<<<< HEAD הספרן צריך לפלוט קצוות מטא-נתונים של מסמכים ישירות לגרף הידע בעת התחלת העיבוד. הוספת לקוח/מפרסם של מאגר טריפלים לשירות הספרן. בעת התחלת עיבוד: פליטת מטא-נתונים של מסמך השורש כקצוות גרף (פעם אחת). **2. אוצר מילים של סוגי מסמכים** סטנדרטיזציה של ערכים `document_type` עבור מסמכי ילד: `source` - מסמך שהועלה במקור. `page` - עמוד שחולץ מהמקור (PDF, וכו'). `chunk` - חלק טקסט שמקורו בעמוד או במקור. #### סיכום שינויים בממשק | ממשק | שינוי | |-----------|--------| | מאגר טריפלים | חיבור יוצא חד - פליטת קצוות מטא-נתונים של מסמכים | | התחלת עיבוד | פליטת מטא-נתונים לגרף לפני העברת מזהה מסמך | ======= הספרן צריך לפלוט קצוות מטא-נתונים של מסמכים ישירות לגרף הידע בעת התחלת עיבוד. הוסף לקוח/מפרסם של מאגר טריפלים לשירות הספרן בעת התחלת עיבוד: פלט מטא-נתונים של מסמך שורש כקצוות גרף (פעם אחת) **2. אוצר מילים של סוגי מסמכים** תקנן ערכים של `document_type` עבור מסמכי ילד: `source` - מסמך שהועלה במקור `page` - עמוד שחולץ מהמקור (PDF, וכו') `chunk` - חלק טקסט שמקורו בעמוד או במקור #### סיכום שינויי ממשק | ממשק | שינוי | |-----------|--------| | מאגר טריפלים | חיבור יוצא חד - פלט קצוות מטא-נתונים של מסמכים | | התחלת עיבוד | פלט מטא-נתונים לגרף לפני העברת מזהה מסמך | >>>>>>> 82edf2d (New md files from RunPod) ### שינויים בחולץ PDF #### מצב נוכחי <<<<<<< HEAD מקבל תוכן מסמך (או זורם מסמכים גדולים). מחלץ טקסט מעמודי PDF. מעביר תוכן עמוד לחולץ חלקים. אין אינטראקציה עם הספרן או מאגר הטריפלים. ======= מקבל תוכן מסמך (או זורם מסמכים גדולים) מחלץ טקסט מעמודי PDF מעביר תוכן עמוד לחולץ אין אינטראקציה עם הספרן או מאגר הטריפלים >>>>>>> 82edf2d (New md files from RunPod) #### שינויים נדרשים **1. ממשק חדש: לקוח ספרן** חולץ PDF צריך לשמור כל עמוד כמסמך ילד בספרן. <<<<<<< HEAD הוספת לקוח ספרן לשירות חולץ PDF. עבור כל עמוד: קריאה ל-`add-child-document` עם מזהה הורה = מזהה מסמך השורש. ======= הוסף לקוח ספרן לשירות חולץ PDF עבור כל עמוד: התקשר ל-`add-child-document` עם parent = מזהה מסמך שורש >>>>>>> 82edf2d (New md files from RunPod) **2. ממשק חדש: חיבור למאגר טריפלים** חולץ PDF צריך לפלוט קצוות הורה-ילד לגרף הידע. <<<<<<< HEAD הוספת לקוח/מפרסם של מאגר טריפלים. עבור כל עמוד: פליטת קצה המקשר עמוד מסמך למסמך הורה. **3. שינוי פורמט פלט** פלט חוזה (יש לעקוב בדיוק אחר הפורמט הבא). ======= הוסף לקוח/מפרסם של מאגר טריפלים עבור כל עמוד: פלט קצה המקשר את מסמך העמוד למסמך הורה **3. שנה פורמט פלט** פלט חוזה (יש לעקוב אחר הפורמט המדויק). >>>>>>> 82edf2d (New md files from RunPod) במקום להעביר ישירות את תוכן העמוד, יש להעביר את מזהה המסמך של העמוד. ה-Chunker ישלוף את התוכן מה-librarian באמצעות המזהה. #### סיכום שינויים בממשק | ממשק | שינוי | |-----------|--------| | Librarian | יציאה חדשה - שמירת מסמכים ילדים | | Triple store | יציאה חדשה - פליטת קשרים הורה-ילד | | הודעת פלט | שינוי מתוכן למזהה מסמך | ### שינויים ב-Chunker #### מצב נוכחי מקבל תוכן עמוד/טקסט מחלק לחלקים מעביר את תוכן החלק למעבדים downstream אין אינטראקציה עם ה-librarian או ה-triple store #### שינויים נדרשים **1. שינוי טיפול בקלט** <<<<<<< HEAD לקבל מזהה מסמך במקום תוכן, לשלוף מה-librarian. להוסיף לקוח librarian לשירות ה-chunker לשלוף תוכן עמוד באמצעות מזהה מסמך **2. ממשק חדש: לקוח Librarian (כתיבה)** לשמור כל חלק כמסמך ילד ב-librarian. עבור כל חלק: לקרוא לפונקציה `add-child-document` עם parent = מזהה מסמך העמוד **3. ממשק חדש: חיבור ל-Triple store** לפלוט קשרים הורה-ילד לגרף הידע. להוסיף לקוח/מפרסם triple store עבור כל חלק: לפלוט קשר המקשר בין מסמך החלק למסמך העמוד **4. שינוי פורמט פלט** להעביר גם את מזהה מסמך החלק וגם את תוכן החלק (אופטימיזציה לאחר ה-chunker). מעבדים downstream מקבלים מזהה לצורך מעקב מקור + תוכן לעבודה איתו ======= יש לקבל מזהה מסמך במקום תוכן, ולשלוף אותו מה-librarian. יש להוסיף לקוח librarian לשירות ה-chunker יש לשלוף את תוכן העמוד באמצעות מזהה המסמך **2. ממשק חדש: לקוח Librarian (כתיבה)** יש לשמור כל חלק כמסמך ילד ב-librarian. עבור כל חלק: יש לקרוא ל-`add-child-document` עם parent = מזהה מסמך העמוד **3. ממשק חדש: חיבור ל-Triple store** יש לפלוט קשרים הורה-ילד לגרף הידע. יש להוסיף לקוח/מפרסם triple store עבור כל חלק: יש לפלוט קשר המקשר בין מסמך החלק למסמך העמוד **4. שינוי פורמט פלט** יש להעביר גם את מזהה מסמך החלק וגם את תוכן החלק (אופטימיזציה לאחר חלוקה). מעבדים downstream מקבלים מזהה לצורך מעקב מקור + תוכן לעבודה >>>>>>> 82edf2d (New md files from RunPod) #### סיכום שינויים בממשק | ממשק | שינוי | |-----------|--------| | הודעת קלט | שינוי מתוכן למזהה מסמך | | Librarian | יציאה חדשה (קריאה + כתיבה) - שליפת תוכן, שמירת מסמכים ילדים | | Triple store | יציאה חדשה - פליטת קשרים הורה-ילד | <<<<<<< HEAD | הודעת פלט | שינוי מתוכן בלבד ל-ID + תוכן | ======= | הודעת פלט | שינוי מתוכן בלבד ל-מזהה + תוכן | >>>>>>> 82edf2d (New md files from RunPod) ### שינויים ב-Knowledge Extractor #### מצב נוכחי <<<<<<< HEAD מקבל תוכן חלק ======= מקבל תוכן של חלק >>>>>>> 82edf2d (New md files from RunPod) מחלץ טריפל ו-embeddings פולט ל-triple store ול-embedding store `subjectOf` הקשר מצביע למסמך ברמה העליונה (ולא לחלק) #### שינויים נדרשים **1. שינוי טיפול בקלט** <<<<<<< HEAD לקבל מזהה מסמך חלק יחד עם התוכן. להשתמש במזהה החלק לצורך קישור מעקב מקור (תוכן כלול כבר בהתאם לאופטימיזציה) **2. עדכון מעקב טריפל** לקשר טריפל מחולץ לחלק (ולא למסמך ברמה העליונה). להשתמש ב-reification ליצירת קשר המצביע לקשר `subjectOf` הקשר: טריפל → מזהה מסמך חלק ======= יש לקבל מזהה מסמך של חלק יחד עם התוכן. יש להשתמש במזהה החלק לצורך קישור מעקב מקור (תוכן כלול כבר בהתאם לאופטימיזציה) **2. עדכון מעקב טריפל** יש לקשר טריפל מחולץ לחלק (ולא למסמך ברמה העליונה). יש להשתמש ב-reification ליצירת קשר המצביע לקשר `subjectOf` קשר: טריפל → מזהה מסמך של חלק >>>>>>> 82edf2d (New md files from RunPod) שימוש ראשון בתמיכה קיימת ב-reification **3. עדכון מעקב embedding** <<<<<<< HEAD לקשר מזהי ישויות embedding לחלק. לפלוט קשר: מזהה ישות embedding → מזהה מסמך חלק ======= יש לקשר מזהי ישויות embedding לחלק. יש לפלוט קשר: מזהה ישות embedding → מזהה מסמך של חלק >>>>>>> 82edf2d (New md files from RunPod) #### סיכום שינויים בממשק | ממשק | שינוי | |-----------|--------| | הודעת קלט | מצפים למזהה חלק + תוכן (ולא רק תוכן) | <<<<<<< HEAD | Triple store | להשתמש ב-reification למעקב טריפל → חלק | | מעקב embedding | לקשר מזהה ישות → מזהה חלק | ======= | Triple store | שימוש ב-reification למעקב טריפל → חלק | | מעקב embedding | קישור מזהה ישות → מזהה חלק | >>>>>>> 82edf2d (New md files from RunPod) ## הפניות מעקב בזמן שאילתה: `docs/tech-specs/query-time-provenance.md` תקן PROV-O למודל מעקב מקור מטא-נתונים קיימים ממקור בגרף הידע (דורש ביקורת)