LLM‑alapú dokumentumdaraboló modul
A modul Python alapú szolgáltatásként valósult meg, amelyet egy FastAPI-alapú REST API tesz elérhetővé.
Input:
- A szolgáltatás egyetlen bemeneti paraméterként egy dokumentumfájlt vár, amely
.pdfvagy.docxformátumban érkezhet. - A beérkező fájlt egy POST kérés keretében kell elküldeni az alábbi végpontra:
/api/llm-based-document-chunking- A fájlt a FastAPI automatikusan bytes típusra alakítja, amelyet a MainOrchestrator továbbít a teljes feldolgozási pipeline-nak.
Output:
- A válasz egy JSON objektum, amely a következő két elemet tartalmazza:
chunks: A létrehozott szövegrészletek listájaDataChunkDTOformátumban. Minden elem egyetlen Markdown chunkot tartalmaz (chunk: str).totalTokenUsage: Ez tartalmazza az LLM-hívások során felhasznált tokenek számát (pl.prompt_tokens,completion_tokens,total_tokens).
1. Bevezetés
Ez a dokumentáció egy LLM alapú dokumentumfeldolgozó és -daraboló rendszer működését mutatja be. A modul fő célja, hogy különböző formátumú dokumentumokból (PDF, DOCX) strukturált, szemantikailag értelmes és könnyen kezelhető szövegrészleteket, ún. „chunkokat“ hozzon létre.
A folyamat kulcsa egy hierarchikus struktúrát építő prompt. Ez a prompt mondja meg az LLM-nek, hogy: - Mi legyen a végső kimenet: egy többszintű JSON struktúra, ahol minden elem (chunk) egy címsort (title), annak aktuális szinjét (level), a kezdősor számát (start_line) és az alárendelt elemek listáját (children) tartalmazza. - Hogyan ismerje fel az eltérő chunkokba tartozó szövegrészleteket: ne csak a Markdown szintaxisra ( #, ## stb.) támaszkodjon, hanem a tipikus tipográfiai és szemantikai jelekre is (nagybetűs sor, számozott bekezdés, egy új szekció szemantikai értelemben vett kezdete).
Ezzel a hierarchia‑vezérelt prompttal a rendszer képes: - Logikai szerkezetet építeni a dokumentum belső tematikus tagolásából, még akkor is, ha az eredeti forrás nem tartalmaz formális címsorjelölést. - Egyértelműen hozzárendelni az egyes albekezdéseket a megfelelő szülő‑elemhez. - Token‑takarékosan működni, mivel a prompt minden futásnál csak a hierarchikus JSON struktúrát adja vissza, így elkerülhető a teljes dokumentum output-ként való visszaadása.
A hierarchiadetektáló promptra épülve a feldolgozás egy többlépcsős pipeline‑ban valósul meg, amely magában foglalja a fájlok konverzióját, általános és gránit specifikus előfeldolgozási logikákat, az LLM által vezérelt hierarchiafelismerést, a modell által generált struktúra javítását, és végül a dokumentum feldarabolását.
2. Fő komponensek
A teljes munkafolyamat a bejövő API kéréstől a kész chunkok visszaadásáig a következő főbb lépésekre bontható:
| Fájl | Fő osztály / függvény | Rövid leírás |
|---|---|---|
llm_auto_chunking_api.py |
FastAPI router | REST végpont /api/llm-based-document-chunking. |
orchestrator.py |
MainOrchestrator |
A teljes pipeline koordinátora. |
base.py |
BaseInitializer |
Globális konfigurációk betöltése, LLM‑kliens és spaCy inicializálás, segédobjektumok központi létrehozása. |
text_to_md.py |
MarkdownConverter |
Többféle megoldással (Azure, docling) konvertál különböző formátumú dokumentumokat (PDF, DOCX) Markdownra. |
base_preprocessor.py |
BasePreProcessor |
Általános előfeldolgozás az egységes struktúra kialakításának érdekében (HTML‑táblák, Markdown-táblák). |
custom_preprocessor.py |
CustomPreProcessor |
A BasePreProcessor kiterjesztése, amely az ügyfélspecifikus előfeldolgozási szabályok megvalósítását teszi lehetővé. |
llm_document_processor.py |
LLMDocumentProcessorWith* PromptOutput/StructuredOutput |
Iteratív LLM hívások (Gemini-output: prompt‑alapú, OpenAI-output: Pydantic‑struktúrált), részleges vagy csonka JSON‑válaszok javítása és egyesítése. |
fix_json_structure.py |
JSONFixer |
Az LLM JSON output logikájának a javítása különböző szabályrendszerek mentén. |
base_chunker.py |
BaseChunker |
A végső chunk objektum kialakítása az alapértelmezett feldolgozások mentén. |
custom_chunker.py |
CustomChunker |
A BaseChunker kiterjesztése, amely az ügyfélspecifikus darabolási szabályok megvalósítását teszi lehetővé. |
3. Részletes folyamatleírás
3.1 Konvertálás - MarkdownConverter (text_to_md.py)
Ez a rész felelős azért, hogy a különböző bemeneti fájlokat egységes Markdown szöveggé alakítsa.
- Funciók:
- A
.pdfés.docxformátumokat támogatja.- Többféle konverziós „backendet“ képes használni, melyek a konfigurációban választhatók ki:
docling: Egy nyílt forráskódú könyvtár (markdown alapú táblázatok).azure: Az Azure Document Intelligence szolgáltatásprebuilt-layoutmodelljét használja. Különösen hatékony a táblázatok és komplex elrendezések értelmezésében (HTML alapú táblázatok).
- Ideiglenes fájlok kezelése::
- A konverzióhoz a fájlt lemezre kell menteni, mert mind a
docling, mind azazurefájlútvonalon keresztül dolgozik, nembytesobjektumokkal. Ezért aMarkdownConverterideiglenes fájlokat hoz létre, amelyeket a feldolgozás végén automatikusan töröl. - A jövőben szükség esetén átalakítható, hogy közvetlenül
bytesalapon működjön. - Azure oldal-limit:
- Az Azure-alapú konverzió során a
max_input_pageparaméter határozza meg, hány oldalt lehet feldolgozni egy dokumentumból. Ez védi a rendszert a túl nagy dokumentumoktól, illetve a költségek optimalizálását szolgálja. - PDF → DOCX konverzió két lépésben (Azure előfeldolgozás):
- A DOCX fájlok oldalainak számlálásához a rendszer PDF-formátumba konvertálja a dokumentumot, mert az DOCX nem tárolja az oldalak számozását. Ehhez két különböző konverter is rendelkezésre áll:
- LibreOffice (
soffice) – előnyben részesített megoldás a szerveren történő futtatás miatt. docx2pdf– fallback opció Windows és macOS rendszereken, ha a LibreOffice nem elérhető vagy hibát jelez.- Elméletileg macOS‑en is futnia kellene, a gyakorlatban azonban több alkalommal hibát tapasztaltunk, ezért macOS alatt célszerű a LibreOffice‑alapú megoldást választani. Ügyelj arra, hogy a LibreOffice soffice (futtatható programfájlja) szerepeljen a PATH környezeti változóban.
- Alternatív megoldás a PATH kihagyására:
pdf_docx_to_md_azurefüggvény soffice command-ját írd át erre:"/Applications/LibreOffice.app/Contents/MacOS/soffice"
- Többféle konverziós „backendet“ képes használni, melyek a konfigurációban választhatók ki:
3.2 Előfeldolgozás - CustomPreProcessor & BasePreProcessor (custom_preprocessor.py & base_preprocessor.py)
Az előfeldolgozó komponens két rétegből áll össze:
- BasePreProcessor:
- Univerzális pipeline, amely minden bemeneti Markdownon lefut.
- Biztosítja, hogy a további lépések (LLM, chunker) konzisztens, zajmentes inputot kapjanak – függetlenül a dokumentum struktúrájától.
- Feladatai:
- HTML Táblázat Tisztítás (HTMLTableCleaner): Kifejezetten az Azure által generált Markdown-ra optimalizálva. Eltávolítja az ismétlődő élőfejeket és élőlábakat, összevonja a több oldalra tört táblázatokat, és javítja a hibás HTML táblázat-struktúrákat.
- Markdown Táblázat Tisztítás (MarkdownTableCleaner): Normalizálja a Markdown táblázatok elválasztó sorait és eltávolítja a felesleges szóközöket a cellákból.
- Sorszámozás: Minden sort egy egyedi, lineXXXXXX: előtaggal lát el. Ez a sorszámozás szükséges a sorok azonosításához.
- CustomPreProcessor:
- A BasePreProcessor kiterjesztése, ahol ügyfélspecifikus szabályok foglalnak helyet.
- Lehetővé teszi, hogy a rendszer az általános tisztításon túl reagáljon egyedi üzleti logikákra
- Feladatai:
- Jelenleg kizárólag a táblázatokra (Markdown és HTML formában) koncentrál és két fő területet érint:
- Strukturális szintek bejelölése (LEVEL:N):
- Az eredeti DOCX fájlokban gyakran előfordulnak olyan cellák, amelyek vizuálisan (lila háttérszínnel) kiemeltek, és szemantikailag címként értelmezhetők.
- felismeri ezeket a cellákat,
- kiolvassa a bal oldali behúzás mértékét
- és a hozzájuk tartozó sorokat ellátja egy LEVEL:N előtaggal (ahol N a hierarchikus szintet jelöli),
- Ez a lépés segít explicit szerkezeti jeleket adni az LLM‑nek, így jelentősen javítja a címfelismerés és az alárendeltségi viszonyok pontosságát.
- Táblázatok újrarendezése:
- Egyes dokumentumtípusoknál az egyes kiemelt sorok nem mindig logikai sorrendben szerepelnek a táblázatban. A CustomPreProcessor felismeri ezeket a DOCX táblázatsorokat:
- külön gyűjti és elemzi,
- az átalakított Markdown/HTML táblákban újrapozicionálja úgy, hogy azok logikailag összetartozó szakaszok után kerüljenek.
3.3 LLM alapú hierarchia építés - LLMDocumentProcessorWithStructuredOutput & LLMDocumentProcessorWithPromptOutput (llm_document_processor.py)
A dokumentumhierarchia felismerése a rendszer egyik központi feladata: a cél az, hogy a sorszámozott Markdown szövegből egy LLM segítségével strukturált, többszintű JSON készüljön.
A rendszer ehhez két külön osztályt használ, attól függően, hogy melyik LLM-et alkalmazzuk:
- LLMDocumentProcessorWithStructuredOutput - OpenAI-hoz optimalizálva:
- Kihasználja a modell azon képességét, hogy közvetlenül Pydantic modelleknek megfelelő, garantáltan helyes JSON struktúrát adjon vissza. Ez a megközelítés megbízhatóbb.
- Kezeli azokat az eseteket is, amikor a modell a maximális token-hossz miatt megszakítja a generálást (LengthFinishReasonError), és megpróbálja a részleges eredményt is feldolgozni.
- LLMDocumentProcessorWithPromptOutput - Geminihez optimalizálva:
- A Gemini API ezzel szemben nem támogatja az önmagukra hivatkozó Pydantic modellek közvetlen visszaadását. Ezért ott prompt-alapú, szöveges JSON generálásra van szükség.
A két osztály közös működési elvei: - javítja a befejezetlen vagy hibás JSON-t, - iteratív feldolgozás, csak a még nem feldolgozott sorokat küldi el újra az LLM-nek, - az LLM részleges válaszait egyesíti, amíg a teljes struktúra össze nem áll.
Példa a várt JSON-kimenetre (HierarchicalChunk struktúrában):
[
{
"title": "1. Bevezetés",
"level": 1,
"start_line": "line000005",
"has_children": "Y",
"children": [
{
"title": "1.1 Célkitűzések",
"level": 2,
"start_line": "line000010",
"has_children": "N",
"children": []
},
{
"title": "1.2 Fogalmak",
"level": 2,
"start_line": "line000020",
"has_children": "Y",
"children": [
{
"title": "1.2.1 Alapfogalmak",
"level": 3,
"start_line": "line000025",
"has_children": "N",
"children": []
}
]
}
]
}
]
3.4 Hierarchia javítás - JSONFixer (fix_json_structure.py)
Az LLM által generált hierarchia tartalmazhat felesleges vagy logikailag pontatlan elemeket. A JSONFixer feladata ezeknek a hibáknak a szabályalapú korrekciója.
- Funkciók:
- Szintek korrekciója (
fix_hierarchy_and_levels): Biztosítja, hogy a beágyazási szintek és alevelattribútumok konzisztensek legyenek. Két lépésben dolgozik:- Újrahierarchizálás: Az elemeket újraosztja, hogy a megfelelő szintű elemek valóban a megfelelő elem alá kerüljenek.
- Szintkorrekció: A szinteket újraszámolja, hogy azok valóban tükrözzék a hierarchia mélységét.
- Felesleges elemek eltávolítása (
postprocess_json): Különböző szabályok alapján eltávolít olyan elemeket, amelyek nem valódi címsorok. - Kezdő elem létrehozása: Ha a dokumentum nem címsorral kezdődik, egy „dummy“ elemet szúr be az elejére
line000001-re, hogy a dokumentum legelején lévő szöveg se vesszen el.
3.5 Chunk létrehozás - CustomChunker & BaseChunker (custom_chunker.py és base_chunker.py)
Az utolsó lépésben a letisztított hierarchia és a sorszámozott szöveg alapján létrejönnek a végső szövegdarabok.
A daraboló komponens két rétegből áll össze:
- BasePreProcessor:
- Univerzális pipeline, amely minden bemeneten lefut.
- Feladatai:
- ChunkProcessor: A beágyazott hierarchiát lineáris listává bontja, hogy minden egyes elem önállóan feldolgozható legyen.
- ChunkModifier:
- Fejlécek generálása: Minden chunk elején automatikusan létrehoz egy több szintből álló fejlécet (dokumentumcím → fejezet → alfejezet), amely kontextust biztosít a chunkhoz.
- Tábla-kezelés: Az Azure HTML-alapú tábláit <table> tagekkel egészíti ki, a Markdown-alapú táblákhoz pedig hiányzó elválasztó sorokat illeszt be.
- Szűrés: Kizárja a valódi tartalom nélküli chunkokat.
- ChunkLengthControl:
- Méretkontroll: Gondoskodik arról, hogy egy chunk ne haladja meg a megadott max_chunk_size értéket.
- Szegmentálás: Ha szükséges, tovább darabolja a chunkot:
- A táblázatokat egyben hagyja, nem vágja szét.
- A szöveget mondathatárok mentén darabolja, spaCy vagy HuSpaCy modell segítségével.
- CustomPreProcessor:
- A BaseChunker kiterjesztése, ahol ügyfélspecifikus szabályok foglalnak helyet.
- Lehetővé teszi, hogy a rendszer az általános tisztításon túl reagáljon egyedi üzleti logikákra
- Feladati:
- Jelenleg csak egy extra szűrési lépés található benne a Markdown típusú táblázatokra vonatkozóan