mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-07-09 05:12:12 +02:00
196 lines
14 KiB
Markdown
196 lines
14 KiB
Markdown
|
|
# מפענח מסמכים אוניברסלי
|
|||
|
|
|
|||
|
|
## כותרת
|
|||
|
|
|
|||
|
|
מפענח מסמכים אוניברסלי המופעל על ידי `unstructured` — קבלת פורמטים נפוצים של מסמכים באמצעות שירות יחיד, עם תיעוד מלא של מקור הנתונים ושילוב עם ספריית ניהול מסמכים, תוך רישום מיקומי המקור כמטא-דאטה של גרף ידע למעקב מקצה לקצה.
|
|||
|
|
|
|||
|
|
## בעיה
|
|||
|
|
|
|||
|
|
ל-TrustGraph כיום יש מפענח ספציפי ל-PDF. תמיכה בפורמטים נוספים (DOCX, XLSX, HTML, Markdown, טקסט רגיל, PPTX וכו') דורשת או כתיבת מפענח חדש לכל פורמט או אימוץ ספריית חילוץ אוניברסלית. לכל פורמט יש מבנה שונה — חלקם מבוססי דפים, חלקם לא — ושרשרת התיעוד חייבת לתעד היכן בכל המסמך המקורי הגיע כל חלק של הטקסט שחולץ.
|
|||
|
|
|
|||
|
|
## גישה
|
|||
|
|
|
|||
|
|
### ספרייה: `unstructured`
|
|||
|
|
|
|||
|
|
יש להשתמש ב-`unstructured.partition.auto.partition()` שמזהה באופן אוטומטי את הפורמט מסוג MIME או סיומת הקובץ ומחלצת אלמנטים מובנים (כותרת, טקסט, טבלה, פריט רשימה וכו'). כל אלמנט מכיל מטא-דאטה, כולל:
|
|||
|
|
|
|||
|
|
- `page_number` (לפורמטים מבוססי דפים כמו PDF, PPTX)
|
|||
|
|
- `element_id` (ייחודי לכל אלמנט)
|
|||
|
|
- `coordinates` (מלבן תחום עבור PDF)
|
|||
|
|
- `text` (תוכן הטקסט שחולץ)
|
|||
|
|
- `category` (סוג אלמנט: כותרת, טקסט, טבלה וכו')
|
|||
|
|
|
|||
|
|
### סוגי אלמנטים
|
|||
|
|
|
|||
|
|
`unstructured` מחלץ אלמנטים מסוגים שונים ממסמכים. לכל אלמנט יש קטגוריה ומטא-דאטה נלווים:
|
|||
|
|
|
|||
|
|
**אלמנטים טקסטואליים:**
|
|||
|
|
- `Title` — כותרות סעיפים
|
|||
|
|
- `NarrativeText` — פסקאות גוף
|
|||
|
|
- `ListItem` — פריטי רשימה/רשימות ממוספרות
|
|||
|
|
- `Header`, `Footer` — כותרות/כותרות שוליים של עמודים
|
|||
|
|
- `FigureCaption` — כיתובים עבור תמונות/גרפיקה
|
|||
|
|
- `Formula` — ביטויים מתמטיים
|
|||
|
|
- `Address`, `EmailAddress` — פרטי התקשרות
|
|||
|
|
- `CodeSnippet` — בלוקי קוד (מ-Markdown)
|
|||
|
|
|
|||
|
|
**טבלאות:**
|
|||
|
|
- `Table` — נתונים טבלאיים מובנים. `unstructured` מספק גם `element.text` (טקסט רגיל) וגם `element.metadata.text_as_html` (תגית HTML מלאה של `<table>` עם שורות, עמודות וכותרות). עבור פורמטים עם מבנה טבלה מוגדר (DOCX, XLSX, HTML), החילוץ אמין מאוד. עבור PDF, זיהוי טבלאות תלוי באסטרטגיית `hi_res` עם ניתוח פריסה.
|
|||
|
|
|
|||
|
|
**תמונות:**
|
|||
|
|
- `Image` — תמונות מוטמעות שזוהו באמצעות ניתוח פריסה (דורש אסטרטגיית `hi_res`). עם `extract_image_block_to_payload=True`, מחזיר את נתוני התמונה כ-base64 ב-`element.metadata.image_base64`. טקסט OCR מהתמונה זמין ב-`element.text`.
|
|||
|
|
|
|||
|
|
### טיפול בטבלאות
|
|||
|
|
|
|||
|
|
טבלאות הן פלט ברמה ראשונה. כאשר המפענח נתקל באלמנט `Table`, הוא שומר על מבנה ה-HTML במקום לפשט לטקסט רגיל. זה נותן למחלץ ה-LLM במעלה הזרם קלט טוב יותר לשליפה של ידע מובנה מנתונים טבלאיים.
|
|||
|
|
|
|||
|
|
הטקסט של העמוד/הסעיף מורכב באופן הבא:
|
|||
|
|
- אלמנטים טקסטואליים: טקסט רגיל, המחוברים עם שורות חדשות.
|
|||
|
|
- אלמנטים של טבלאות: תגית טבלה HTML מ-`text_as_html`, עטופה בתגית `<table>` כך שה-LLM יכול להבחין בין טבלאות לבין טקסט רגיל.
|
|||
|
|
|
|||
|
|
לדוגמה, עמוד עם כותרת, פסקה וטבלה מייצר:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
סקירה פיננסית
|
|||
|
|
|
|||
|
|
ההכנסות גדלו ב-15% שנה אחר שנה, הודות לאימוץ ארגוני.
|
|||
|
|
|
|||
|
|
<table>
|
|||
|
|
<tr><th>רבעון</th><th>הכנסות</th><th>צמיחה</th></tr>
|
|||
|
|
<tr<td>רבעון 1</td><td>$12 מיליון</td><td>12%</td></tr>
|
|||
|
|
<tr<td>רבעון 2</td><td>$14 מיליון</td><td>17%</td></tr>
|
|||
|
|
</table>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
זה שומר על מבנה הטבלה במהלך חלוקה לחלקים ולתוך צינור החילוץ, שבו ה-LLM יכול לחלץ קשרים ישירות מתאים מובנים ולא לנחש על התאמת עמודות מרווח לבן.
|
|||
|
|
|
|||
|
|
### טיפול בתמונות
|
|||
|
|
|
|||
|
|
תמונות מחולצות ומאוחסנות בספריית הניהול כמסמכים משניים עם `document_type="image"` ו-ID `urn:image:{uuid}`. הם מקבלים משולשים של תיעוד מסוג `tg:Image`, המקושרים לעמוד/סעיף האב שלהם באמצעות `prov:wasDerivedFrom`. מטא-דאטה של תמונה (קואורדינטות, מימדים, `element_id`) נרשמים בתיעוד.
|
|||
|
|
|
|||
|
|
**חשוב, תמונות אינן מופצות כפלט של `TextDocument`.** הן מאוחסנות בלבד — אינן נשלחות במעלה הזרם למחלק או לכל צינור עיבוד טקסט. זה מכוון:
|
|||
|
|
|
|||
|
|
1. אין עדיין צינור לעיבוד תמונות (שילוב מודל ראייה הוא עבודה עתידית)
|
|||
|
|
2. העברת נתוני תמונה ב-base64 או פיסות OCR לצינור חילוץ הטקסט תיצור משולשים של גרף ידע "זבל".
|
|||
|
|
|
|||
|
|
תמונות גם אינן נכללות בטקסט העמוד המורכב — כל אלמנטי `Image` מושמטים בשקט כאשר מחברים טקסט של אלמנטים עבור עמוד/סעיף. שרשרת התיעוד רושמת שתמונות קיימות ואיפה שהן הופיעו במסמך, כך שניתן יהיה לשלוף אותן על ידי צינור עיבוד תמונות עתידי מבלי לטעון מחדש את המסמך.
|
|||
|
|
|
|||
|
|
#### עבודה עתידית
|
|||
|
|
|
|||
|
|
- הכוונת ישויות `tg:Image` למודל ראייה לתיאור, פרשנות דיאגרמות או חילוץ נתוני תרשימים.
|
|||
|
|
- אחסון תיאורי תמונה כמסמכים טקסטואליים שמוזנים לצינור החלוקה/חילוץ הסטנדרטי.
|
|||
|
|
- קישור ידע שנחצה חזרה לתמונות מקור באמצעות תיעוד.
|
|||
|
|
|
|||
|
|
### אסטרטגיות סעיפים
|
|||
|
|
|
|||
|
|
לפורמטים מבוססי דפים (PDF, PPTX, XLSX), אלמנטים תמיד מקובצים לפי עמוד/שקופית/גיליון תחילה. עבור פורמטים שאינם מבוססי דפים (DOCX, HTML, Markdown וכו'), למפענח יש אסטרטגיה לחלוקת המסמך לסעיפים. זה מוגדר בזמן ריצה באמצעות `--section-strategy`.
|
|||
|
|
|
|||
|
|
כל אסטרטגיה היא פונקציית קיבוץ על רשימת האלמנטים של `unstructured`. הפלט הוא רשימת קבוצות אלמנטים; שאר הצינור (הרכבת טקסט, אחסון בספריית הניהול, תיעוד, פליטת `TextDocument`) זהים ללא קשר לאסטרטגיה.
|
|||
|
|
|
|||
|
|
#### `whole-document` (ברירת מחדל)
|
|||
|
|
|
|||
|
|
פליטת כל המסמך כסעיף יחיד. תן למחלק במעלה הזרם לטפל בכל החלוקה.
|
|||
|
|
|
|||
|
|
- גישה פשוטה, נקודת התחלה טובה.
|
|||
|
|
- עשויה ליצור `TextDocument` גדול מאוד עבור קבצים גדולים, אך המחלק מטפל בכך.
|
|||
|
|
- הטוב ביותר כאשר אתה רוצה הקשר מרבי לכל סעיף.
|
|||
|
|
|
|||
|
|
#### `heading`
|
|||
|
|
|
|||
|
|
פיצול בכותרות (`Title`). כל סעיף הוא כותרת וכל התוכן עד לכותרת ברמה שווה או גבוהה יותר. כותרות מקוננות יוצרות סעיפים מקוננים.
|
|||
|
|
|
|||
|
|
- מייצר יחידות מגובשות מבחינה נושאית.
|
|||
|
|
- עובד היטב עבור מסמכים מובנים (דוחות, מדריכים, מפרטים).
|
|||
|
|
- נותן למחלץ ה-LLM הקשר של כותרת יחד עם התוכן.
|
|||
|
|
- חוזר ל-`whole-document` אם לא נמצאות כותרות.
|
|||
|
|
|
|||
|
|
#### `element-type`
|
|||
|
|
|
|||
|
|
פיצול כאשר סוג האלמנט משתנה באופן משמעותי — במיוחד, התחלה של סעיף חדש במעברים בין טקסט נרטיבי לטבלאות. אלמנטים עוקבים מאותה קטגוריה רחבה (טקסט, טקסט, טקסט או טבלה, טבלה) נשארים מקובצים.
|
|||
|
|
|
|||
|
|
- שומר על טבלאות כסעיפים עצמאיים.
|
|||
|
|
- טוב למסמכים עם תוכן מעורב (דוחות עם טבלאות נתונים).
|
|||
|
|
- לטבלאות יש תשומת לב חילוץ ייעודית.
|
|||
|
|
|
|||
|
|
#### `count`
|
|||
|
|
|
|||
|
|
קיבוץ מספר קבוע של אלמנטים לכל סעיף. ניתן להגדרה באמצעות `--section-element-count` (ברירת מחדל: 20).
|
|||
|
|
|
|||
|
|
- פשוט וצפוי.
|
|||
|
|
- לא מכבד את מבנה המסמך.
|
|||
|
|
- שימושי כברירת מחדל או לניסויים.
|
|||
|
|
|
|||
|
|
#### `size`
|
|||
|
|
|
|||
|
|
צבירת אלמנטים עד שמגיעים לגבול תווים, ואז התחלת סעיף חדש. מכבד את גבולות האלמנטים — לעולם לא מפצל באמצע אלמנט. ניתן להגדרה באמצעות `--section-max-size` (ברירת מחדל: 4000 תווים).
|
|||
|
|
|
|||
|
|
- מייצר גדלים בערך אחידים של סעיפים.
|
|||
|
|
- מכבד את גבולות האלמנטים (בניגוד למחלק במעלה הזרם).
|
|||
|
|
- פשרה טובה בין שליטה במבנה ובגודל.
|
|||
|
|
- אם אלמנט יחיד חורג מהגבול, הוא הופך לסעיף משלו.
|
|||
|
|
|
|||
|
|
#### אינטראקציה עם פורמטים מבוססי דפים
|
|||
|
|
|
|||
|
|
עבור פורמטים מבוססי דפים, הקיבוץ לפי עמוד תמיד מקבל עדיפות. אסטרטגיות סעיפים יכולות באופן אופציונלי להחיל *בתוך* עמוד אם הוא גדול מאוד (לדוגמה, עמוד PDF עם טבלה עצומה), דבר ששולט על ידי `--section-within-pages` (ברירת מחדל: false). כאשר זה כוזב, כל עמוד תמיד סעיף אחד ללא קשר לגודל.
|
|||
|
|
|
|||
|
|
### זיהוי פורמט
|
|||
|
|
|
|||
|
|
למפענח יש צורך לדעת את סוג MIME של המסמך כדי להעביר ל-`partition()` של `unstructured`. שתי אפשרויות:
|
|||
|
|
|
|||
|
|
- **נתיב ספריית הניהול** (`document_id` מוגדר): אחסון מטא-דאטה של מסמך מהספרייה תחילה — זה נותן לנו את `kind` (סוג MIME) שנרשם בזמן ההעלאה. ואז אחסון תוכן מסמך. שתי קריאות לספריית הניהול, אך אחזור המטא-דאטה קל משקל.
|
|||
|
|
- **נתיב מקומי** (תאימות לאחור, `data` מוגדר): אין מטא-דאטה זמין על ההודעה. השתמש ב-`python-magic` כדי לזהות את הפורמט מתוך בתים של תוכן כגיבוי.
|
|||
|
|
|
|||
|
|
אין צורך בשינויים בסכימת `Document` — ספריית הניהול כבר מאחסנת את סוג ה-MIME.
|
|||
|
|
|
|||
|
|
### ארכיטקטורה
|
|||
|
|
|
|||
|
|
שירות `universal-decoder` יחיד שמבצע את הפעולות הבאות:
|
|||
|
|
|
|||
|
|
1. מקבל הודעת `Document` (מקומית או באמצעות הפניה לספריית הניהול).
|
|||
|
|
2. אם נתיב ספריית הניהול: אחסון מטא-דאטה של מסמך (קבלת סוג MIME), ואז אחסון תוכן. אם נתיב מקומי: זיהוי פורמט מתוך בתים של תוכן.
|
|||
|
|
3. קריאה ל-`partition()` כדי לחלץ אלמנטים.
|
|||
|
|
4. קיבוץ אלמנטים: לפי עמוד עבור פורמטים מבוססי דפים, לפי אסטרטגיית סעיף מוגדרת עבור פורמטים שאינם מבוססי דפים.
|
|||
|
|
5. עבור כל עמוד/סעיף:
|
|||
|
|
- יצירת ID `urn:page:{uuid}` או `urn:section:{uuid}`.
|
|||
|
|
- הרכבת טקסט עמוד: טקסט רגיל, טבלאות כ-HTML, תמונות מושמטות.
|
|||
|
|
- חישוב ההיסט מוחלט של כל אלמנט בתוך טקסט העמוד.
|
|||
|
|
- שמירה בספריית הניהול כתיעוד משני.
|
|||
|
|
- יצירת משולשים של תיעוד עם מטא-דאטה מיקומי.
|
|||
|
|
- שליחת `TextDocument` במעלה הזרם לחלוקה.
|
|||
|
|
6. עבור כל אלמנט תמונה:
|
|||
|
|
- יצירת ID `urn:image:{uuid}`.
|
|||
|
|
- שמירת נתוני תמונה בספריית הניהול כתיעוד משני.
|
|||
|
|
- יצירת משולשים של תיעוד (מאוחסנים בלבד, אינם נשלחים במעלה הזרם).
|
|||
|
|
|
|||
|
|
### טיפול בפורמטים
|
|||
|
|
|
|||
|
|
| פורמט | סוג MIME | מבוסס עמוד | הערות |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| PDF | application/pdf | כן | קיבוץ לפי עמוד |
|
|||
|
|
| DOCX | application/vnd.openxmlformats... | לא | משתמש באסטרטגיית סעיף |
|
|||
|
|
| PPTX | application/vnd.openxmlformats... | כן | קיבוץ לפי שקופית |
|
|||
|
|
| XLSX/XLS | application/vnd.openxmlformats... | כן | קיבוץ לפי גיליון |
|
|||
|
|
| HTML | text/html | לא | משתמש באסטרטגיית סעיף |
|
|||
|
|
| Markdown | text/markdown | לא | משתמש באסטרטגיית סעיף |
|
|||
|
|
| רגיל | text/plain | לא | משתמש באסטרטגיית סעיף |
|
|||
|
|
| CSV | text/csv | לא | משתמש באסטרטגיית סעיף |
|
|||
|
|
| RST | text/x-rst | לא | משתמש באסטרטגיית סעיף |
|
|||
|
|
| RTF | application/rtf | לא | משתמש באסטרטגיית סעיף |
|
|||
|
|
| ODT | application/vnd.oasis... | לא | משתמש באסטרטגיית סעיף |
|
|||
|
|
| TSV | text/tab-separated-values | לא | משתמש באסטרטגיית סעיף |
|
|||
|
|
|
|||
|
|
### מטא-דאטה של תיעוד
|
|||
|
|
|
|||
|
|
כל ישות עמוד/סעיף רושמת מטא-דאטה מיקומי כמשולשים של תיעוד בגרף `GRAPH_SOURCE`, ומאפשרת מעקב מלא מהמשולשים של גרף ידע חזרה למיקומי המסמך המקוריים.
|
|||
|
|
|
|||
|
|
#### שדות קיימים (כבר ב-`derived_entity_triples`)
|
|||
|
|
|
|||
|
|
- `page_number` — מספר עמוד/גיליון/שקופית (מוגדר מ-1, רק עבור פורמטים מבוססי עמודים)
|
|||
|
|
- `char_offset` — היסט מוחלט של תווים של עמוד/סעיף זה בתוך הטקסט המלא של המסמך.
|
|||
|
|
- `char_length` — אורך התווים של הטקסט של עמוד/סעיף זה.
|
|||
|
|
|
|||
|
|
#### שדות חדשים (הרחבת `derived_entity_triples`)
|
|||
|
|
|
|||
|
|
- `mime_type` — פורמט מסמך מקורי (לדוגמה, `application/pdf`)
|
|||
|
|
- `element_types` — רשימה מופרדת בפסיקים של קטגוריות `unstructured` של אלמנטים (לדוגמה, `title, paragraph, table`).
|
|||
|
|
- `provenance` — מידע על מקור הנתונים.
|