Asosiy qismga o'tish

OCR → RAG Integratsiyasi

8-bob 5 kod bloki 690 so'z

Natijalar hali qayta tekshirilmagan

Bu kitobning kodi saytga qo'yishdan oldin qayta ishga tushirilmagan, shuning uchun ayrim natija va raqamlar qo'lda yozilgan bo'lishi mumkin. Kodni o'zingiz ishga tushirib ko'ring — farq topsangiz, Telegramda yozing.

OCR ning pipeline dagi o'rni

RAG qo'llanmasi 5-bobidagi ingestion pipeline ni eslang: scraping → extraction → chunking → embedding → pgvector. OCR bu zanjirga extraction bosqichida ulanadi:

python11 qator
Hujjat manbalari
  |
  +-- web sahifa  -------> BeautifulSoup extractor --+
  |                                                  |
  +-- digital PDF -------> pdfplumber ---------------+--> TOZALASH --> chunking
  |                                                  |    (shu bob)     |
  +-- skanerlangan PDF --> OCR pipeline (7-bob) -----+                  v
  |                                                  |               embedding
  +-- rasm (jpg/png) ----> OCR to'g'ridan-to'g'ri ---+                  |
                                                                        v
                                                                    pgvector

Lekin OCR matni to'g'ridan-to'g'ri chunking ga yuborilmaydi — avval tozalash kerak. Nega?

OCR matni nega "iflos"

Tesseract har vizual qatorni \n bilan tugatadi. Qog'ozda 60-belgilik qatorlar — demak har gap 2-3 bo'lakka bo'linadi:

matn5 qator
OCR chiqishi:                      Bo'lishi kerak edi:

Shartnoma tomonlari o'z zimma-     Shartnoma tomonlari o'z 
siga olgan majburiyatlarni to'-    zimmasiga olgan majburiyatlarni
liq bajarishga kafolat beradi.     to'liq bajarishga kafolat beradi.

RAG qo'llanmasi 4-bobini eslang: paragraph-based chunking paragraf chegaralariga (\n\n) tayanadi. OCR matni esa har 60 belgida \n — chunker "har qator alohida paragraf" deb o'ylaydi va chunk lar mayda-mayda bo'lib ketadi. Embedding sifati ham tushadi: "zimma-" va "siga" alohida so'zlar emas.

Tozalash funksiyasi

To'rt eng muhim tuzatish:

python17 qator
import re

def clean_ocr_text(text):
    # 1. Bo'g'in ko'chirish: "zimma-\nsiga" -> "zimmasiga"
    text = re.sub(r"([\w'])-\n(\w)", r"\1\2", text)

    # 2. Sun'iy qator uzilishi: bitta \n -> bo'shliq
    #    (\n\n paragraf chegarasi sifatida SAQLANADI)
    text = re.sub(r"(?<!\n)\n(?!\n)", " ", text)

    # 3. Ortiqcha bo'shliqlar
    text = re.sub(r"[ \t]{2,}", " ", text)

    # 4. Yolg'iz sahifa raqamlari va kolontitullar
    text = re.sub(r"^\s*-?\s*\d+\s*-?\s*$", "", text, flags=re.MULTILINE)

    return text.strip()

2-qadam eng nozigi: (?<!\n)\n(?!\n) — "oldida ham, orqasida ham \n bo'lmagan \n". Ya'ni yolg'iz qator uzilishi bo'shliqqa aylanadi, \n\n (haqiqiy paragraf) esa tegilmaydi.

Yana bir tez-tez uchraydigan muammo — har sahifada takrorlanadigan kolontitul ("«Nihol» MChJ — Ichki hujjat — Maxfiy"). U har chunk ga kirib, qidiruv natijalarini ifloslaydi. Yechim: sahifalar orasida takrorlangan qatorlarni topib olib tashlash (10-bobdagi kodda bor).

Metadata enrichment

RAG qo'llanmasi 4-bobidagi metadata g'oyasini OCR ma'lumoti bilan boyitamiz:

python7 qator
chunk_metadata = {
    "source_file": "shartnoma_2024.pdf",
    "page": 3,
    "extraction_method": "ocr_tesseract",   # "text_layer" | "ocr_tesseract" | "ocr_vlm"
    "ocr_confidence": 84.2,                  # VLM uchun -1 (confidence bermaydi)
    "language": "rus",
}

Bu metadata uch joyda asqotadi:

  1. Error analysis (RAG guide, 15-bob): foydalanuvchi "javob noto'g'ri" desa — extraction_method va ocr_confidence ga qarang. Ko'pincha muammo retrieval da emas, manba matnning o'zida.
  2. Filtering: "faqat ishonchli manbalardan javob ber" — ocr_confidence > 70 sharti bilan SQL darajasida filtrlash.
  3. Citation: javob manbasini ko'rsatganda "skanerlangan hujjatdan olindi, xato bo'lishi mumkin" ogohlantirishi.

Quality gate — sifat darvozasi

Production tizimda past sifatli OCR ni jimgina bazaga qo'shib yubormaslik kerak. RAGAS (RAG guide, 10-bob) faqat retrieval/generation ni baholaydi — u manba matni buzuqligini ko'rmaydi. Darvoza shunday:

python12 qator
def quality_gate(page_result):
    if page_result.method == "text_layer":
        return "accept"                      # digital matn — ishonchli

    if page_result.method == "ocr_vlm":
        return "accept_with_flag"            # confidence yo'q — belgilab qo'yamiz (6-bob: xatosi ko'rinmaydi)

    if page_result.confidence >= 80:
        return "accept"
    if page_result.confidence >= 60:
        return "accept_with_flag"            # metadata da belgi, keyin tekshiriladi
    return "manual_review"                   # bazaga kirmasin, admin ko'rsin

Admin panelda "manual review" ro'yxati bo'ladi: past confidence li sahifalar odamga ko'rsatiladi. Odam yo qo'lda tuzatadi, yo qayta skanerlashni so'raydi, yo VLM natijasini tasdiqlaydi. Buzuq matn bazaga kirsa, uni topish juda qiyin — darvozada ushlash arzonroq. VLM o'qigan sahifalar ham har doim belgilanadi: ularda confidence yo'q, xatosi esa ko'rinmaydi (6-bob) — yuridik va moliyaviy hujjatlarda ularni odam ko'rib chiqadi.

Xulosa

Tushuncha Asosiy fikr
O'rin OCR = extraction bosqichi; undan keyin har doim tozalash
Tozalash Bo'g'in ko'chirish + yolg'iz \n — busiz chunking buziladi
Kolontitul Takrorlangan qatorlarni olib tashlang — chunk larni ifloslaydi
Metadata extraction_method + ocr_confidence — error analysis va filtering uchun
Quality gate conf < 60 bazaga kirmasin — darvozada ushlash keyin qidirishdan arzon

Bu bobni bepul o'qidingiz.

Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.

Telegramda yozish Narxlar