Views
No views yet
microsoft/layoutlmv3-base for resume PDF embedding generation in the AppAI recruitment matching pipeline.pdfplumber.| Property | Value |
|---|---|
| Base model | microsoft/layoutlmv3-base |
| Max sequence length | 512 tokens |
| Embedding dimension | 768 |
| Normalisation | L2 (unit norm) |
| Pooling | Mean pooling over last hidden state with attention mask |
| Training objective | Contrastive learning (resume ↔ JD span matching) |
| Bounding box range | [0, 1000] normalised per page |
Resume PDF
→ pdfplumber word extraction + bbox normalisation [0, 1000]
→ Section label assignment (O / EDUCATION / EXPERIENCE / LEADERSHIP)
→ LayoutLMv3TokenizerFast (full resume, single tokenisation pass)
→ word_ids() label propagation to subword tokens
→ Per-label token subsequence extraction
→ LayoutLMv3Model backbone (pixel_values=None)
→ Mean pooling over last hidden state
→ L2 normalisation
→ 768-dim embedding per spanextract_feature_indices_by_label from the training notebook exactly: the full resume is tokenised once, word-level section labels are propagated to subword tokens via word_ids(), then per-label token subsequences are extracted and encoded independently.Smutypi3/applai-sbert — encodes JD text spans (SBERT)Smutypi3/applai-confit — aligns both embedding spaces (ConFiT)pip install torch transformers pdfplumber1from ai_models.preprocessing.resume_preprocessor import preprocess_resume_pdf
2from ai_models.services.layoutlm_service import encode_resume_spans
3
4with open("resume.pdf", "rb") as f:
5 pdf_bytes = f.read()
6
7parsed = preprocess_resume_pdf(pdf_bytes)
8# {"all_words": [{"text": ..., "bbox": [x1,y1,x2,y2]}, ...], "word_labels": [...]}
9
10embeddings = encode_resume_spans(parsed)
11# {"full": [...], "education": [...], "experience": [...], "leadership": [...]}| Label ID | Section |
|---|---|
| 0 | O (Other / header / unclassified) |
| 1 | EDUCATION |
| 2 | EXPERIENCE |
| 3 | LEADERSHIP |
pdfplumber. Per-word bounding boxes are normalised to [0, 1000] per page. Words are grouped into lines by y-coordinate proximity, and short lines (≤ 5 words) containing section header keywords trigger a label change for all subsequent body words.word_ids() propagates word-level labels to subword tokens. Special tokens ([CLS], [SEP]) receive label -100 and are excluded from span extraction — exactly mirroring extract_feature_indices_by_label from the training notebook.zeros(1) input IDs + ones(1) attention mask, matching training exactly.pixel_values are not used at inference (text + layout only), consistent with trainingSmutypi3/applai-sbert and Smutypi3/applai-confit1@software{lucero2025applai_layoutlmv3,
2 author = {Lucero, Jaime Emmanuel},
3 title = {{AppAI LayoutLMv3 Contrastive Learning}: Fine-tuned LayoutLMv3 for Resume PDF Embedding},
4 year = {2025},
5 publisher = {HuggingFace},
6 url = {https://huggingface.co/Smutypi3/applai-layoutlmv3},
7 note = {Part of the AppAI recruitment intelligence pipeline}
8}