Free lesson · GenAI Data Engineering
அனைத்து extraction வெளியீடுகளையும் இயல்பாக்கும் ஒருங்கிணைந்த document model-ஐ வடிவமைக்கவும்
Typed content blocks மற்றும் extraction method metadata கொண்ட, format-agnostic document schema-வை உருவாக்கவும். Docling, VLM மற்றும் Document AI வெளியீடுகளுக்கான adapters-ஐ உருவாக்கவும்.
Course: GenAI Data Pipelines · Chapter 1 · Document Ingestion with VLMs
Free to read — no subscription required.
அறிமுகம்
Docling, Document AI மற்றும் ஒரு vision-language model ஆகியவற்றிலிருந்து உள்ளடக்கத்தை இழுக்கும் ஒரு ingestion pipeline-ஐ நீங்கள் உருவாக்கும்போது, ஒவ்வொரு backend-உம் தனக்கே உரிய வடிவத்தில் உள்ளடக்கத்தைத் திருப்பித் தருகிறது — இங்கே bounding boxes, அங்கே page hierarchies, வேறொரு இடத்தில் freeform JSON — மேலும் ஒவ்வொரு downstream consumer-உம் if extractor == "docling": … என்று கிளைபிரிந்து, இறுதியில் codebase extractor பெயர்களைச் சுற்றி புதைபடிவமாக உறைந்துவிடுகிறது. ஒருங்கிணைந்த ஆவண மாதிரியைத் தவிர்க்கும் குழுக்கள், ஒவ்வொரு புதிய extractor வெளியாகும்போதும் chunkers, embedders மற்றும் search indexers-ஐ மீண்டும் எழுதுவதில் அடுத்த காலாண்டைச் செலவிடுகின்றன. இப்பாடத்தின் முடிவில், discriminated-union content blocks, provenance metadata மற்றும் ஒரு நிலையான adapter எல்லையுடன் கூடிய canonical document schema-வை வடிவமைக்க உங்களால் முடியும், இதனால் எந்த extractor அதை உருவாக்கியிருந்தாலும் downstream அமைப்புகள் ஒரே வடிவத்தைப் பயன்படுத்துகின்றன.
முக்கிய சொற்கள்
- ஒருங்கிணைந்த ஆவண மாதிரி (Unified document model): ஒவ்வொரு extractor adapter-உம் இலக்காகக் கொள்ளும் ஒரே canonical schema (இங்கே,
UnifiedDocument), இதனால் downstream chunkers, embedders மற்றும் indexers extractor பெயரின் அடிப்படையில் கிளைபிரிவதற்குப் பதிலாக ஒரே வடிவத்தைப் பயன்படுத்துகின்றன. - Discriminated union: ஒவ்வொரு variant-உம் ஒரு literal
block_typetag-ஐ (எ.கா.TableBlock-இல்Literal["table"]) கொண்டிருக்கும் polymorphic content-block பிரதிநிதித்துவம்; Pydantic இதைப் பயன்படுத்தி கலப்பு block பட்டியல்களைத் தெளிவின்மை இல்லாமல் deserialize செய்கிறது. - Provenance metadata: எந்த extractor அந்த block-ஐ உருவாக்கியது என்பதை block அளவில் கண்காணிப்பது (பெயர், பதிப்பு, பக்கம், bounding box, confidence,
quality_flags), block-இலேயே வைக்கப்படுவதால் quality-aware processing downstream-இல் வடிகட்டவோ மறு-வழிப்படுத்தவோ முடியும். - Extraction adapter: ஒரு extractor-இன் native output-ஐ
UnifiedDocument-ஆக மொழிபெயர்ப்பது மட்டுமே வேலையாகக் கொண்ட தனிமைப்படுத்தப்பட்ட class (எ.கா.DoclingAdapter); இது ingestion-ஐ extractor தேர்விலிருந்து பிரிக்கும் நிலையான எல்லையை உருவாக்குகிறது.
கருத்துகள்
இப்பாடம் ஒரே வடிவமைப்பாக ஒன்றிணையும் மூன்று யோசனைகளைக் கற்பிக்கிறது.
ஒரே canonical schema, பல adapters. UnifiedDocument மாதிரி என்பது ஒவ்வொரு downstream consumer-உம் சார்ந்திருக்கும் ஒப்பந்தம்; DoclingAdapter மற்றும் எதிர்கால DocumentAIAdapter / VLMAdapter ஆகியவை தங்கள் backend-இன் native output-ஐ அந்த ஒப்பந்தத்திற்கு மாற்றுவதற்காக மட்டுமே இருக்கின்றன. புதிய extractor-ஐச் சேர்ப்பது schema-வையோ எந்த consumer-ஐயோ ஒருபோதும் மாற்றாது — அது ஒரு adapter class-ஐச் சேர்க்கிறது, வேறு எதையும் அல்ல.
Free-form JSON-க்குப் பதிலாக discriminated unions. உண்மையான ஆவணங்கள் பத்திகள், தலைப்புகள், அட்டவணைகள், படங்கள் மற்றும் பட்டியல்களைக் கலந்து கொண்டிருக்கின்றன. ஒவ்வொன்றையும் literal block_type tag-உடன் கூடிய Pydantic மாதிரியாகக் குறியிடுவது, list[ContentBlock | TableBlock] சரியாக deserialize ஆக அனுமதிக்கிறது, அதே நேரத்தில் TableBlock.headers அல்லது ContentBlock.level போன்ற variant-குறிப்பிட்ட புலங்களுக்கு typed அணுகலையும் வழங்குகிறது. Free-form dicts அதே தரவை உருவாக்கினாலும் validation மற்றும் IDE ஆதரவை இழக்கின்றன.
Provenance என்பது முதன்மைப் புலம், sidecar log அல்ல. ஒவ்வொரு block-உம் தனக்கே உரிய Provenance-ஐ (extractor, version, page, bbox, confidence, quality_flags) கொண்டிருப்பதால், downstream code ஒவ்வொரு block-க்கும் தனித்தனியாக முடிவுகளை எடுக்க முடியும் — குறைந்த confidence கொண்ட VLM output-ஐ நீக்குவது, flag செய்யப்பட்ட blocks-ஐ மதிப்பாய்வுக்கு மறு-வழிப்படுத்துவது, RAG பதிலில் citations-ஐ இணைப்பது — இவை அனைத்தும் வெளிப்புற metadata store-உடன் மீண்டும் join செய்யாமலேயே. கீழே உள்ள Code Walkthrough, இந்த மூன்று யோசனைகளில் ஒவ்வொன்றும் schema-வில் எப்படித் தோன்றுகிறது என்பதையும், DoclingAdapter அவற்றை எப்படி உருவாக்குகிறது என்பதையும் துல்லியமாகக் காட்டுகிறது.
Code Walkthrough
Pydantic Schema-வை வரையறுத்தல்
ஆவண உள்ளடக்கத்தின் polymorphic தன்மையைக் கையாள discriminated unions-உடன் Pydantic மாதிரிகளைப் பயன்படுத்துங்கள்:
Code snippetpython
1from pydantic import BaseModel, Field 2from typing import Literal, Optional 3from datetime import datetime 4from enum import Enum 5 6class BlockType(str, Enum): 7 PARAGRAPH = "paragraph" 8 HEADING = "heading" 9 TABLE = "table" 10 FIGURE = "figure" 11 LIST_ITEM = "list_item" 12 CODE = "code" 13 14class Provenance(BaseModel): 15 extractor: str 16 extractor_version: str 17 page_number: Optional[int] = None 18 bbox: Optional[tuple[float, float, float, float]] = None 19 confidence: Optional[float] = None 20 quality_flags: list[str] = Field(default_factory=list) 21 22class TableCell(BaseModel): 23 text: str 24 row_span: int = 1 25 col_span: int = 1 26 27class TableBlock(BaseModel): 28 block_type: Literal["table"] = "table" 29 headers: list[str] 30 rows: list[list[TableCell]] 31 provenance: Provenance 32 33class ContentBlock(BaseModel): 34 block_type: BlockType 35 text: str 36 level: Optional[int] = None 37 children: list["ContentBlock"] = Field(default_factory=list) 38 provenance: Provenance 39 40class DocumentPage(BaseModel): 41 page_number: int 42 blocks: list[ContentBlock | TableBlock] 43 44class UnifiedDocument(BaseModel): 45 document_id: str 46 source_uri: str 47 schema_version: str = "1.0" 48 format: str 49 page_count: int 50 extraction_timestamp: datetime 51 pages: list[DocumentPage] 52 metadata: dict = Field(default_factory=dict)
- வரிகள் 6-12:
BlockTypeenum உங்கள் pipeline கையாளும் அனைத்து உள்ளடக்க வகைகளையும் வரையறுக்கிறது. Free-form strings-க்குப் பதிலாக enum-ஐப் பயன்படுத்துவது validation நேரத்தில் எழுத்துப் பிழைகளைப் பிடிக்கிறது மற்றும் downstream processors-இல் முழுமையான pattern matching-ஐ சாத்தியமாக்குகிறது. - வரிகள் 14-20:
Provenanceமாதிரி ஒவ்வொரு block-ஐயும் எந்த extractor உருவாக்கியது என்பதைக் கண்காணிக்கிறது.quality_flagsபட்டியல் extraction-இன் போது கண்டறியப்பட்ட சிக்கல்களைப் பதிவு செய்கிறது —"low_confidence","possible_hallucination","truncated"— இது downstream-இல் quality-aware processing-ஐ சாத்தியமாக்குகிறது. - வரிகள் 28-31:
TableBlockblock_type: Literal["table"]-உடன் discriminated union pattern-ஐப் பயன்படுத்துகிறது, இதனால் Pydantic கலப்பு content block பட்டியல்களைச் சரியாக deserialize செய்ய முடியும். Headers மற்றும் rowsrow_spanமற்றும்col_spanவழியாக இணைக்கப்பட்ட cells-ஐ ஆதரிக்கும்TableCellobjects-ஐப் பயன்படுத்துகின்றன. - வரிகள் 33-37:
ContentBlockchildrenபுலம் வழியாக recursive nesting-ஐ ஆதரிக்கிறது, இது பிரிவுகள் துணைப்பிரிவுகளைக் கொண்டிருக்கும், அவை பத்திகளைக் கொண்டிருக்கும் உண்மையான ஆவணங்களின் படிநிலை அமைப்பைப் பிரதிபலிக்கிறது. - வரிகள் 43-52: மேல்-நிலை
UnifiedDocumentஆவண-நிலை metadata, ஒவ்வொன்றும் blocks-ஐக் கொண்ட பக்கங்களின் பட்டியல், மற்றும் பரிணாம வளர்ச்சிக்கானschema_versionஆகியவற்றைப் பிடிக்கிறது.
Extraction Adapters-ஐ உருவாக்குதல்
ஒவ்வொரு adapter-உம் extractor-குறிப்பிட்ட output-ஐ ஒருங்கிணைந்த மாதிரியாக மாற்றுகிறது:
Code snippetpython
1class DoclingAdapter: 2 EXTRACTOR_NAME = "docling" 3 EXTRACTOR_VERSION = "2.0" 4 5 def to_unified_document( 6 self, result, source_uri: str 7 ) -> UnifiedDocument: 8 doc = result.document 9 pages = [] 10 11 current_page_blocks = [] 12 current_page = 1 13 14 for item, level in doc.iterate_items(): 15 page_num = item.prov[0].page_no if item.prov else current_page 16 17 if page_num != current_page and current_page_blocks: 18 pages.append(DocumentPage( 19 page_number=current_page, 20 blocks=current_page_blocks, 21 )) 22 current_page_blocks = [] 23 current_page = page_num 24 25 provenance = Provenance( 26 extractor=self.EXTRACTOR_NAME, 27 extractor_version=self.EXTRACTOR_VERSION, 28 page_number=page_num, 29 bbox=item.prov[0].bbox.as_tuple() if item.prov else None, 30 confidence=None, 31 ) 32 33 class_name = item.__class__.__name__ 34 if class_name == "SectionHeaderItem": 35 block = ContentBlock( 36 block_type=BlockType.HEADING, 37 text=item.text, 38 level=item.level, 39 provenance=provenance, 40 ) 41 elif class_name == "TableItem": 42 df = item.export_to_dataframe() 43 block = TableBlock( 44 headers=list(df.columns), 45 rows=[ 46 [TableCell(text=str(cell)) for cell in row] 47 for _, row in df.iterrows() 48 ], 49 provenance=provenance, 50 ) 51 else: 52 block = ContentBlock( 53 block_type=BlockType.PARAGRAPH, 54 text=item.text if hasattr(item, "text") else "", 55 provenance=provenance, 56 ) 57 58 current_page_blocks.append(block) 59 60 if current_page_blocks: 61 pages.append(DocumentPage( 62 page_number=current_page, 63 blocks=current_page_blocks, 64 )) 65 66 return UnifiedDocument( 67 document_id=self._generate_id(source_uri), 68 source_uri=source_uri, 69 format=str(result.input.format), 70 page_count=len(doc.pages) if hasattr(doc, "pages") else len(pages), 71 extraction_timestamp=datetime.utcnow(), 72 pages=pages, 73 ) 74 75 def _generate_id(self, uri: str) -> str: 76 import hashlib 77 return hashlib.sha256(uri.encode()).hexdigest()[:16]
- வரிகள் 1-3: ஒவ்வொரு adapter-உம் தனது extractor அடையாளத்தை class constants-ஆக அறிவிக்கிறது, இதனால் இந்த adapter செயலாக்கும் அனைத்து ஆவணங்களிலும் நிலையான provenance கண்காணிப்பு உறுதி செய்யப்படுகிறது.
- வரிகள் 14-23: Content blocks-ஐ பக்க எண்ணின் அடிப்படையில் குழுவாக்குங்கள். Docling-இன்
iterate_items()உறுப்புகளை வாசிப்பு வரிசையில் தருகிறது, ஆனால் பக்க மாற்றங்களை provenance metadata-விலிருந்து கண்டறிய வேண்டும். - வரிகள் 25-31: Docling-இன் output-இலிருந்து extractor பெயர், பதிப்பு, பக்க எண் மற்றும் bounding box-உடன் ஒவ்வொரு block-க்கும்
Provenanceobjects-ஐ உருவாக்குங்கள். - வரிகள் 33-52: Docling உறுப்பு வகைகளை ஒருங்கிணைந்த மாதிரியின் block வகைகளுக்கு map செய்யுங்கள்.
SectionHeaderItemஅதன் level பாதுகாக்கப்பட்ட தலைப்பாக மாறுகிறது.TableItemஒரு DataFrame-ஆக export செய்யப்பட்டு, பின்னர் சரியானTableCellobjects-உடன் canonicalTableBlockவடிவத்திற்கு மாற்றப்படுகிறது. மற்ற அனைத்து உறுப்புகளும் இயல்பாகப் பத்திகளாக மாறுகின்றன. - வரிகள் 65-72: Source URI-இலிருந்து பெறப்பட்ட deterministic ID-உடன் இறுதி
UnifiedDocument-ஐ உருவாக்குங்கள், இதனால் idempotent மறு-extraction ஒரே ஆவண ID-ஐ உருவாக்குவது உறுதி செய்யப்படுகிறது.
Adapter pattern உங்கள் pipeline-ஐ எந்த ஒரு extraction backend-இலிருந்தும் பிரிக்கிறது. புதிய extractor-ஐச் சேர்ப்பதற்கு, எந்த downstream consumer code-ஐயும் மாற்றாமல் ஒரு புதிய adapter class-ஐ எழுதுவது மட்டுமே தேவை.
துறைசார் பயன்பாடு
செய்ய வேண்டியவை மற்றும் செய்யக்கூடாதவை
இப்போது நீங்கள் செயலாக்கத்தை முழுமையாகப் பார்த்துவிட்டீர்கள்; கீழே உள்ள நடைமுறைகள் நீடித்த அணுகுமுறையை உடையக்கூடிய அணுகுமுறையிலிருந்து பிரித்துக் காட்டுகின்றன.
செய்ய வேண்டியவை
- ஒவ்வொரு content-block variant-ஐயும்
Literal["..."]block_type-உடன் tag செய்யுங்கள், இதனால் Pydantic கலப்புlist[ContentBlock | TableBlock]உள்ளடக்கத்தைத் தெளிவின்மை இல்லாமல் deserialize செய்ய முடியும், மேலும் consumers அந்த tag-இன் அடிப்படையில் dispatch செய்ய முடியும். - ஒவ்வொரு block-இலும்
Provenance-ஐ கட்டாயமாக்குங்கள் — extractor பெயர், பதிப்பு, பக்க எண், கிடைக்கும் இடங்களில் bbox, மற்றும்quality_flags— இதனால் downstream re-ranking, debugging மற்றும் citation பாதைகள் ஒருபோதும் வெளிப்புற metadata store-உடன் மீண்டும் join செய்ய வேண்டியதில்லை. - நீங்கள் ஒரு block வகையைச் சேர்க்கும்போதோ அல்லது ஒரு புலத்தின் பொருளை மாற்றும்போதோ
UnifiedDocument-இல்schema_version-ஐ உயர்த்துங்கள், மேலும் consumers-ஐ version-இன் அடிப்படையில் கிளைபிரியக் கற்றுக்கொடுங்கள் (ஒருபோதும் extractor-இன் அடிப்படையில் அல்ல).
செய்யக்கூடாதவை
if extractor == "docling"கிளைபிரிவை adapter எல்லையைத் தாண்டிக் கசிய விடாதீர்கள் — ஒருUnifiedDocumentஉருவாகிவிட்டால், எந்த chunker, embedder அல்லது indexer-உம் எந்த backend அதை உருவாக்கியது என்பதை அறிந்திருக்கக் கூடாது.- அறியப்படாத extractor உறுப்பு வகைகளை free-form
dictblobs-இல் போட்டுவிடாதீர்கள்; அவற்றை மிக நெருக்கமான canonicalBlockType-க்கு map செய்யுங்கள் (இயல்பாகPARAGRAPH), இதனால் discriminated union முழுமையாகவும் validation பொருள் உள்ளதாகவும் இருக்கும். Provenance-ஐ optional ஆக்கவோ அல்லது sidecar log-இல் சேமிக்கவோ வேண்டாம் — normalization-க்குப் பிறகு quality-aware processing செயல்படுவதற்கான முழுக் காரணமே block-local provenance தான்.
3 hands-on labs come with this lesson — real code, in a cloud IDE. Create a free account to run them. No card.
Free account · no card · straight to the labs
Or get the full path — from
Listen to this lesson
Audio overviews of this lesson's labs and its chapter, from GenBodha Bytes.
More free lessons in GenAI Data Pipelines
- Ch 1Extract documents using Docling's unified multi-format parser
- Ch 1Use Google Document AI for managed OCR and layout parsing
- Ch 1Design a unified document model normalizing all extraction outputsYou are here
- Ch 1Build a routing system selecting the optimal extraction method
- Ch 2Implement content quality scoring with NeMo Curator filters
- Ch 3Build Anthropic's Contextual Retrieval pattern
- Ch 4Extract structured metadata using Instructor with Pydantic schemas