💡 Tam çalışan örnek GitHub’da mevcuttur:
document-to-markdown-rag-chunks-java

İddia Masası Sorunu: Neden RAG Alımı Gerçek Dosyalarda Bozulur

Yerinde bir RAG alım hattı, bir ekibin zaten sahip olduğu dosyaları üçüncü bir tarafa göndermeden aranabilir, alıntılanabilir metne dönüştüren bir belge ayrıştırma katmanıdır. Sigorta operasyonları bunun neden önemli olduğunu gösterir. Bir iddia sorumlusu iç asistanına “bu poliçedeki su hasarı hakkında düzenleyici ne söylemişti?” diye sorar ve cevap geçen Mart ayındaki bir e-postada, ona eklenmiş bir PDF raporunda, “Findings” (Bulgular) başlığı altında bulunur. Asistan, alım ekşi okur, başlığı korur ve raporun hangi e-postayla geldiğini hatırlarsa bunu bulabilir.

Çoğu alım işi bu üç unsurdan birini yanlış yapar. Düz metin çıkarıcı e-posta gövdesini döndürür ve eki görmez. Sabit 512‑token bölücü raporu “Findings” başlığının ortasından keser. Ve barındırılan ayrıştırıcı ikisini de çözer, ancak iddia dosyası, kişisel ve tıbbi detaylarıyla, bir başkasının sunucularına yüklendikten ve sayfa başına faturalandırıldıktan sonra.

Ekibin ihtiyacı dar ve somut: Java hizmeti içinde Word, PDF, EML ve ZIP dosyalarını okuyabilmek, yapılarını Markdown olarak koruyabilmek, yazarın başlıklarında bölmek ve her parçaya kaynak ve üst öğeyi eklemek.

Piyasa anlık görüntüsü: İncelediğimiz 2026 “RAG için belge ayrıştırma” kılavuzları, açık kaynak Python ayrıştırıcılarını sayfa başına faturalandırılan bulut API’leriyle karşılaştırıyor. Kendi donanımınızda çalışan bir Java kütüphanesi bu konuşmadan büyük ölçüde eksik.

Neden RAG Boru Hatları Düz Metin Yerine Markdown’a İhtiyaç Duyar?

Markdown, bir alıcının bir fikrin nerede bittiğini ve bir sonrakinin nerede başladığını gösteren belge parçalarını korur. Başlıklar # satırları haline gelir, tablolar satır ve sütun olarak kalır, listeler öğelerini saklar. Bir parçalama aracı bu başlıklarda bölünebilir ve parçayı okuyan bir LLM, bir kişinin göreceği aynı taslağı görür. Düz metin bu taslağı atar, bölme için tek sinyal olarak yalnızca boyutu bırakır.

Neden Genel Çözümler Burada İşe Yaramaz

Takımlar, uygun bir alım katmanı inşa etmeden önce genellikle üç şeyden birini dener:

  • Düz metin çıkarımı artı token bölücü: kurması hızlıdır, ancak parçalar bölümleri karıştırır ve alıntılayacağınız başlığı kaybeder.
  • Bulut ayrıştırma API’si: iyi yapı sağlar, ancak dosyalar ağ üzerinden çıkar ve her yeniden indeksleme sayfasıyla fatura artar.
  • Format başına ev yapımı ayrıştırıcı: DOCX için bir kütüphane, PDF için bir diğeri, e-posta için bir MIME ayrıştırıcı ve arşivler için java.util.zip, her biri kendi kenar durumlarıyla.

GroupDocs.Parser for Java, tek bir Parser sınıfı altında tüm dört formatı kapsar ve aynı süreç içinde çalışır.

Çözüm: İddia Alımı İş Akışında GroupDocs.Parser

GroupDocs.Parser for Java bir belgeyi okur ve getFormattedText aracılığıyla metnini Markdown olarak döndürebilir. E-postalar ve arşivler, öğeleri yeni Parser örnekleri olarak açan kapsayıcılar olarak sunulur; böylece bir e-postaya eklenmiş PDF, diskteki bir PDF gibi işlenir. Örnek proje bunu altı statik metoda sarar ve sonucu JSON Lines olarak yazar; bu, herhangi bir gömme işi ya da vektör deposu tarafından yüklenebilir. Hiçbir RAG çerçevesi dahil edilmez; çıktı formatı entegrasyon noktasını oluşturur.

İlerlemek için şunlara ihtiyacınız var:

  • pom.xml için JDK 11 veya üzeri (kod kendisi Java 8 özelliklerine bağlıdır)
  • GroupDocs.Parser for Java 26.10 (geçici lisans alın)
  • Bir avuç DOCX, PDF, EML veya ZIP dosyası

Projenin pom.xml dosyası https://releases.groupdocs.com/java/repo/ deposunu ve tek bağımlılığı bildirir, bu yüzden bir yapı bir komutla yapılır:

mvn compile exec:java

Alım Katmanını Adım Adım Uygulama

Aşağıdaki adımlar, bir iddia dosyasını gelen kutusundan indekse kadar izler. Her adım, RagChunksDemo.java içinde bir ya da iki metoda karşılık gelir. Bunları kasıtlı olarak düz statik metodlar olarak tuttuk, böylece herhangi birini mevcut bir işçiye alıp geri kalanını benimsemeden kullanabilirsiniz.

Adım 1 – Her Dosyayı Aç ve Yönlendir

Yüklenen her dosya kendi Parser’ına sahiptir. Dosya adı kaynak kimliği olur ve üst‑seviye dosyanın üst öğesi yoktur.

// One call per uploaded claim document
String sourceId = new File(path).getName();
try (Parser parser = new Parser(path)) {
    return chunkParser(parser, sourceId, null, 0);  // null parent: top-level file
} catch (UnsupportedDocumentFormatException ex) {
    // An unknown format is logged and skipped, the batch keeps going
    System.out.println("skipped (unsupported format): " + sourceId);
    return new ArrayList<>();
}

chunkParser ardından gövdeyi çıkarır, parçalar ve ekleri derinlik 2’nin altında olduğu sürece altına iner.

Adım 2 – Markdown İste, Düz Metin Kabul Et

Çıkarma adımı, uzantı listesini sabit kodlamak yerine formatın ne desteklediğini sorgular.

if (parser.getFeatures().isFormattedText()) {
    // Headings, lists and tables survive as Markdown
    FormattedTextOptions options =
            new FormattedTextOptions(FormattedTextMode.Markdown);
    try (TextReader reader = parser.getFormattedText(options)) {
        if (reader != null) {
            return new ExtractedText("markdown", reader.readToEnd());
        }
    } catch (IOException ex) {
        throw new RuntimeException(ex);
    }
}
try (TextReader reader = parser.getText()) {
    if (reader != null) {  // fallback for formats without formatted text
        return new ExtractedText("plain", reader.readToEnd());
    }
} catch (IOException ex) {
    throw new RuntimeException(ex);
}
return new ExtractedText("none", "");  // e.g. a photo with no OCR

Bu ayarların iddia verileri için önemi:

  • FormattedTextMode.Markdown: düzenleyicinin “Findings” başlığı, parçalama aracına ## Findings olarak ulaşır, böylece bir bölme noktası ve alıntı olur.
  • isFormattedText(): örnek çalıştırmada DOCX ve e-posta Markdown olarak dönerken PDF düz metne geri döner ve format alanı ne olduğunu kaydeder.
  • none sonucu: ZIP içindeki iddia fotoğrafları OCR olmadan parça üretmez; bu dürüst ve izlenmesi kolaydır.

Adım 3 – Düzenleyicinin Başlıklarında Böl

Parçalayıcı, altı Markdown seviyesinin her birinde mevcut başlığı tutan bir yığın kullanır. Yeni bir başlık, önceki bölümü kapatır ve seviyesinin altındaki her şeyi sıfırlar.

for (String line : markdown.split("\\r?\\n", -1)) {
    Matcher heading = HEADING.matcher(line);   // "#" to "######" + title
    if (heading.matches()) {
        // Close the previous section under the old path
        addSection(chunks, section.toString(), sourceId, parentId, path, format);
        section.setLength(0);
        int level = heading.group(1).length();
        stack[level - 1] = heading.group(2).trim();
        for (int i = level; i < stack.length; i++) {
            stack[i] = null;                     // forget deeper headings
        }
        path = joinPath(stack);                  // "Heading 1 > Heading 1.2"
    }
    section.append(line).append('\n');
}

1500 karakteri aşan bölümler paragraf sonlarında kesilir, böylece uzun bir bulgu bölümü aynı başlık yolunu paylaşan birkaç parçaya dönüşür. Paketlenmiş Word dosyasında bu, Heading 1 > Heading 1.2 > Heading 1.2.1 gibi yollar üretir.

Adım 4 – Ekleri Takip Et ve JSON Lines Yaz

Bu, bir iddia masasının en çok önem verdiği adımdır. getContainer() e‑posta eklerini ve ZIP girdilerini listeler; her öğe bir alt belge olarak açılır ve üst öğenin kimliğini devralır.

Iterable<ContainerItem> items = parser.getContainer();
if (items == null) {
    return chunks;                    // not an email or archive
}
for (ContainerItem item : items) {
    // "claim-0412.eml/report.pdf" style ids keep the lineage readable
    String childId = sourceId + "/" + item.getFilePath();
    try (Parser child = item.openParser()) {
        chunks.addAll(chunkParser(child, childId, sourceId, depth + 1));
    } catch (UnsupportedDocumentFormatException ex) {
        System.out.println("skipped (unsupported format): " + childId);
    }
}

writeJsonl ardından her parçayı id, source, parent, heading_path, format ve text alanlarıyla UTF‑8 bir satır olarak yazar. Dört örnek girdiyle çalıştırma 22 satır üretir. Örnek e‑postanın ekinden gelen parça email-with-attachment.eml/attachment.txt#0 ve parentı email-with-attachment.eml olur. Bu çift, asistanın “14 Mart e‑postasına ekli rapordan” demesini, “bir yerden” demesini engeller.

Gerçek İş Akışı: Haftalık İddiaların Yeniden İndekslenmesi

Haftanın kapanan iddia posta kutularını her Cuma EML dosyaları ve destekleyici belgelerin ZIP paketleri olarak dışa aktaran bir iddia operasyon ekibini hayal edin. Bir Java işçisi bu dışa aktarmaları belge deposuna zaten taşıyor. Alım eklemek, her dosya için chunkDocument çağırmak ve JSON Lines çıktısını gömme kuyruğuna eklemek demektir.

Adım 4, raporun e‑postaya ekli olduğu izini korur. Adım 3, asistan “Findings” alıntıladığında alıntının dosya ve başlık adını, yalnızca bir parça numarasını değil, göstermesini sağlar. Bu tür bir indeks için benim kuralım şudur: bir parça dosya ve başlığa geri alıntılanamıyorsa, indeksde bulunmamalıdır.

İş Etkisi: Bu Değişiklik Ne Sağlar

Özellik Önceki tipik kurulum GroupDocs.Parser boru hattı ile
Dosyaların nerede ayrıştırıldığı Üçüncü‑taraf uç noktası Kendi JVM’nizde
Ayrıştırma maliyet modeli Sayfa başına, her yeniden indekslemede Sayfa başına bulut ücreti yok
Parça sınırları Sabit token pencereleri Yazarın başlıkları, 1500 karakter sınırı
E‑posta ekleri Çoğunlukla atlanır veya düzleştirilir Alt belgeler olarak ayrıştırılır
Alıntı verileri En iyi dosya adı source, parent ve heading_path
Çalışma zamanı bağımlılıkları SDK + ağ erişimi Tek Maven artefaktı

Bileşik etki, uyum ekibinin onaylayabileceği bir indeks ve yanıtları gerçek belge ve bölüme yönlendiren bir asistan yaratır.

GroupDocs.Parser’ın Uygun Olduğu Diğer Sigorta Senaryoları

Alım katmanı kurulduktan sonra aynı kod diğer belge‑ağır işler için de kullanılabilir:

  • Poliçe metni araması: Bölüm başlıklarıyla bölünmüş Word poliçeleri, yanıtların tam bölümü alıntılamasını sağlar.
  • Broker başvuruları: Karışık PDF ve elektronik tablo içeren ZIP yüklemeleri, her bir üye ayrı ayrı indekslenir ve başvuru ile ilişkilendirilir.
  • Şikayet yönetimi: Müşteri e‑postaları ve ekleri birlikte indekslenir, e‑posta her ek parçasının üst öğesi olur.

İddia Ortamınızda Başlamak

Örneği klonlayın, kendi dışa aktardığınız birkaç e‑posta üzerinde çalıştırın ve output/chunks.jsonl dosyasını açarak başlık yollarını ve üst kimlikleri gömme işine bağlamadan önce kontrol edin. Aşama‑aşama mimari notları, bu boru hattı için belgelendirme kullanım senaryosu içinde ve hangi biçimlerin korunduğunu listeleyen Markdown çıktı referansı içinde bulunur.

Kaynaklar