Skanerlangan PDF Pipeline
Vazifa
Real oqim: foydalanuvchi PDF yuklaydi. U digital yoki skanerlangan bo'lishi mumkin — oldindan bilmaymiz. 200 sahifalik hujjat bo'lishi mumkin. Pipeline nima qilishi kerak?
PDF keldi | v [Text layer bormi?] ---- HA ---> pdfplumber bilan matnni olamiz | (bepul, tez, 100% aniq) YO'Q | v [Har sahifani rasmga aylantirish] pdf2image, 300 DPI | v [Preprocessing] 3-bobdagi funksiya | v [OCR] Tesseract (tez) | v [Confidence tekshiruv] -- past --> VLM bilan qayta o'qish | v [Tozalash] -> chunking -> embedding (RAG pipeline davom etadi)
Text layer ni aniqlash
Eng muhim optimizatsiya: skanerlanmagan PDF ga OCR qilmaslik. Digital PDF dan matn olish bepul va 100% aniq — OCR esa sekin va xatoli. Farqlash usuli:
import pdfplumber def is_scanned(pdf_path, min_chars=100): """PDF da matn qatlami bormi? Birinchi 3 sahifa yetarli.""" with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages[:3]: text = page.extract_text() or "" if len(text.strip()) >= min_chars: return False # matn bor — digital PDF return True # 3 sahifada ham matn yo'q — skanerlangan
Ikki amaliy detal:
- Faqat birinchi 3 sahifa — 200 sahifani ochib chiqish shart emas. RAG qo'llanmasi 5-bobidagi extractor kabi: avval arzon tekshiruv, keyin qimmat ish.
min_chars=100— ba'zi skanerlangan PDF larda sahifa raqami yoki shtamp matn sifatida bo'ladi. 5-10 belgi "matn bor" degani emas.
Ehtiyot bo'ling: aralash PDF ham uchraydi — asosiy qismi digital, oxirida skanerlangan ilova. Production versiyada (10-bob) tekshiruvni sahifama-sahifa qilamiz.
PDF → rasm
OCR kutubxonalari PDF bilan ishlamaydi — ularga rasm kerak:
sudo apt install poppler-utils # pdf2image ning motori pip install pdf2image
from pdf2image import convert_from_path # Har sahifa PIL Image bo'lib qaytadi pages = convert_from_path("scanned.pdf", dpi=300) print(f"{len(pages)} sahifa")
dpi=300 — 3-bobdagi qoida. Kattaroq DPI = kattaroq rasm = sekinroq, lekin aniqroq. 300 — muvozanat nuqtasi.
Xotira haqida: 200 sahifali PDF ni birdan ochsangiz — RAM tugaydi. Production da sahifalarni bo'lib-bo'lib oching:
from pdf2image import pdfinfo_from_path, convert_from_path info = pdfinfo_from_path(pdf_path) total = info["Pages"] for start in range(1, total + 1, 10): # 10 sahifadan pages = convert_from_path(pdf_path, dpi=300, first_page=start, last_page=min(start + 9, total)) for page_img in pages: process(page_img) # OCR + saqlash
To'liq funksiya
import pdfplumber import pytesseract from pdf2image import convert_from_path def extract_pdf_text(pdf_path): """PDF -> matn. Digital bo'lsa to'g'ridan-to'g'ri, bo'lmasa OCR.""" if not is_scanned(pdf_path): with pdfplumber.open(pdf_path) as pdf: return "\n\n".join(p.extract_text() or "" for p in pdf.pages) pages = convert_from_path(pdf_path, dpi=300) texts = [] for i, page_img in enumerate(pages, 1): text = pytesseract.image_to_string(page_img, lang="rus+uzb") texts.append(text) print(f"Sahifa {i}/{len(pages)} OCR qilindi") return "\n\n".join(texts)
Gibrid strategiya — reranking printsipi
RAG qo'llanmasi 8-bobini eslang: arzon usul hammani saralaydi, qimmat usul faqat qiyinlarini. Retrieval 15 nomzod topadi, reranker faqat shularni chuqur baholaydi.
OCR da xuddi shu dizayn:
Hamma sahifa -> Tesseract (~1 s, bepul, confidence beradi)
|
conf >= 60 | conf < 60
ishlatamiz | Qwen2.5-VL ga yuboramiz
| (~10 s, kuchli, qiyin sahifalar uchun)
Natija: 100 sahifalik hujjatda odatda 5-10 sahifa VLM ga tushadi. Tezlik deyarli Tesseract darajasida, sifat deyarli VLM darajasida. Bu dizayn 10-bobdagi production modulning yadrosi.
Xulosa
| Tushuncha | Asosiy fikr |
|---|---|
| Avval tekshir | Text layer bor PDF ga OCR qilish — isrof va sifat yo'qotish |
| is_scanned | Birinchi 3 sahifa, min_chars=100; aralash PDF larni unutmang |
| pdf2image | 300 DPI; katta PDF ni 10 sahifadan bo'lib oching (RAM!) |
| Gibrid | Tesseract hammaga, VLM faqat conf < 60 sahifalarga — reranking printsipi |
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.