Table of Contents
Feldolgozás
Jogszabályok feldolgozása és a chunkok előállítása
Jegyzetes:
- Eredeti jogszabály XML -> Köztes fa
- Az eredeti jogszabály lineáris és helyenként hierarchikus XML-ből áll
- Eredmény: szövegi részek tisztán hierarchikus szerkezetben
- A köztes fa előállítása visitorokkal történik:
- feldolgozzák a specifikus XML elemeket (tartalom, attribútumok)
- pl.: táblázatból szöveges vagy markdown formátum
- Minden elem tartalmazhat:
- Context
- minden olyan információ ami az adott content könnyebb megértéséhez és megtalálásához szükséges lehet
- pl.: a törvénynek a címe, a preambulum, a fejezet címe
- Content
- A content pedig minden olyan tartalom ami a keresések megválaszolásához szükséges információkat tartalmazzák
- pl.: egy paragrafus tartalma, egy táblázat szövege
- Context
- A fa bejárása során jönnek létre a chunkok
- Minden context összefűzve addig, amíg nem nem jutunk contentig
- Eredmény:
- Egybefüggő szöveg a szerkezet szerint a kontextusban minden, a tartalomig vezető információval
- Kereshető rész
- HTML/XML elemek eltávolítva
- A chunkokhoz a legközelebbi
jhIdvan hozzárendelve- Fában való felfelé kereséssel van meghatározva
Szöveges:
A jogszabályok xml formátumából lineáris és helyenként hierarchikus szerkezetéből építünk egy egységes köztes fa szerkezetet. Ebben a fában a jogszabály szövegének részei találhatóak tisztán hierarchikus szerkezetben.
Példa:
norma -> dokumentum -> könyv -> rész -> fejezet -> bekezdés -> szakasz
Ezek előállításához visitorok-ba szervezett feldolgozók segítenek amelyek képesek feldolgozni specifikus xml elemeket, azoknak tartalmát és attributumait (pl: táblázatok-ból tudunk előállítani szöveges formátumot, vagy markdown-os szerkezetet).
Minden eleme az általunk épített fának tartalmazhat egy Context-et vagy egy Content-et. A contextben található minden olyan információ ami az adott content könnyebb megértéséhez és megtalálásához szükséges lehet (pl: a törvénynek a címe, a preambulum, a fejezet címe). A content pedig minden olyan tartalom ami a keresések megválaszolásához szükséges információkat tartalmazzák (pl: egy paragrafus tartalma, egy táblázat szövege).
A chunkok ebből a fa szerkezetből épülnek fel, ahogy bejárjuk a fát minden context-et összefűzünk egészen addig amíg nem érkezünk egy olyan levélhez ami content-et tartalmaz. Ezáltal a végén kapunk egy olyan egybefüggő szöveget amiben szerkezet szerint a kontextusban szerepel minden content-ig vezető információ, és a contentben összefűzve az kereshető rész áll elő. A legvégén pedig eltávolítunk minden HMTL/XML elemet a szövegből.
A jhId (NJT-n való anchor linkek előállításához szükséges) hozzárendelése a chunkokhoz egyszerűen a fában való felfele kereséssel lett megoldva, így a chunkhoz legközelebbi jhId-t tudjuk meghatározni.
Keresési találatok szövegkiemelése
A beérkező kérést feldaraboljuk szavakra és eltávolítunk belőle minden nem a magyar ABC-ben szereplő karaktert. Ezeknek a szavaknak megkeressük a szótöveit a Hunspell nevű könyvtárral, majd ezeknek az összegyűjtött szavaknak és szótöveknek megkeressük a szinonimáit egy Thesaurus nevű könyvtárral és ezeket is belerakjuk a lehetséges kiemelendő szavak közé.
A kiemelt szavakat szűrjük egy előre megírt listával ami tartalmazza a kötőszavakat/kérdőszavakat és egyéb szavakat amit nem szeretnénk semmilyen formában látni a kiemelés során.
A folyamat végén pedig megkeressük a szavakat a keresési eredmények között és a szövegben megtalált szavakat kiegészítjük hogy teljes szavakat emeljük ki. (pl adat -> adatok, adatai)
Metadatás keresés évszámos és sorszámos keresések
A keresés több stratégiával is működik, ha a beérkező kérést felismerjük valamilyen minta szerint akkor tudunk a törvények meta-adatai között is keresni. Jelenleg az alábbi stratégiák támogatottak.
Évszámos és Sorszámos keresés
Évszámot és sorszámot is akkor tudunk így is keresni különböző formátumokban.
- A következő formátumok támogatottak:
2016. évi XXXIII. törvény2016 / 332016. 33.2016. XXXIII.2016 33- a fentieknek akár fordított formában is, pl:
33 2016.
Ha nem sikerül jól beazonosítani hogy melyik rész az évszám vagy a sorszám, akkor mindkét verzióban megpróbáljuk.
Évszámos keresés
Ha évszámot adunk meg akkor a jogszabályok évszámában keresünk.
Sorszámos keresés
Ha számot vagy római számot kapunk, akkor a jogszabályok sorszámaiban keresünk.
Keresési kifejezés/kérdés kiegészítése
Lehetőségünk van arra hogy mielőtt a beérkező keresést módosítsuk a jobb találtok érdekében, ez a beérkező kérés elején egy előre meghatározott gyűjteményből tudunk szöveget kicserélni. Így képesek vagyunk olyan kereséseket is finomhangolni ami nem feltétlenül szerepel a jogszabályban és nehezen lenne kereshető. (pl: Mi a chipsadó? -> Mi a Népegészségügyi termékadó?)
Továbbá a chunk építés során gyűjtünk egy listát ami alias-okat tartalmaz, ezt a "továbbiakban" különböző variációinak felismeréséből építjük fel. (pl. NEBEK -> Nemzetközi Bűnügyi Együttműködési Központ)
Keresés
Embedding
Az embedding során egy adott modellel előállítjuk egy chunk szemantikai vektoros reprezentációját, amit később felhasználunk a kereséshez.
Embedding Backendek
Ollama
- hivatalos Docker image
- CPU/GPU support
- GGUF formátum
- egyedi modellarchitektúrák konvertálása alkalom adtán nehézkes lehet (gemma, nv-embed)
Egyedi (SentenceTransformer)
- python alapú szerver, docker konténerben
- egyszerű REST API
- CPU/GPU support
- HF/Transformers modell formátum, a legtöbb modell alapra ebben készül
Spring ONNX integráció
- alkalmazásszerverbe épül be
- CPU/GPU support
- ONNX formátum szükséges, csak támogatott architektúrákkal megy
Embedding Modellek
A vektorok előállításához használt modellek nagyban befolyásolják a keresési találatok minőségét. Jellemzően a kevesebb paraméteres, de specifikusan embedding célra tanított modellek jobban teljesítenek, mint a komplexebb modellek. További előny, ha a modell tanító adathalmaza a célnyelvnek megfelelő szöveget tartalmazott.
Llama 3.2 72B
- Backend: Ollama
- Tapasztalat: Az egyes embeddingek vektorai túl hasonlóak, ezért nem alkalmasak keresésre
gte-Qwen2-7B-instruct
- Backend: Ollama
- A töbnyelvű embedding rangsorban 2. helyezett jelenleg
- Tapasztalat: Ez a modell specifikusan embedding célokra van tanítva, ezért a generált vektorok között nagyobb a távolság, jól kereshető. A kisebb paraméterszám ellenére is jobb találatokat ad, mint a Llama3.2 modell. Ezen felül sokkal gyorsabb a vektorok generálása, az előzetes embedding generálás és a felhasználó keresések során egyaránt.
bge-multilingual-gemma2
- Backend: egyedi (SentenceTransformer)
- A töbnyelvű embedding rangsorban 1. helyezett jelenleg
- Tapasztalat: A Qwen embedding modellhez hasonlóan szintén jól összehasonlítható vektorokat generál.
nv-embed-v2
- Backend: egyedi (SentenceTransformer)
- Új modell (2024. 09.)
- Az embedding modell rangsor élén áll jelenleg
- Tapasztalat:
- Nem generál megfelelő vektorokat 16bit precízió mellett GPU-n, 32bites módban nincs elég VRAM
- Érdemes visszatérni hozzá, amennyiben elterjedtebb lesz és rendelkezésre áll megfelelő tooling, vagy nagyobb hardverkapacitás
Vektoros keresés
A korábban elkészített embedding vektorokat a felhasználó által keresett kifejezésből, hasonlóan képzett vektorokkal hasonlítja össze. A vektorok irányát és/vagy távolságát kiszámítva megállapítható, hogy mely chunk-ok relevánsak a kereséshez.
- Vektor adatbázis: Qdrant
- nagyobb méretű vektorok támogatása
- webes kezelőfelület
- csak az embedding vektort és a szükséges metaadatokat tárolja
- egyéb adatok a normál adatbázisban
- hivatalos Docker image
- Search Score: a beállított algoritmusnak megfelelő, nem biztos, hogy távolság
Reranking
A vektoros keresés eredményeként kapott találatok gyakran az összes relevánsnak tűnő dokumentumot tartalmazzák, de nem relevancia szerinti sorrendben.
A reranking során egy erre tanított modellel az egyes találatokat relevancia szerint súlyozzuk, majd ennek megfelelően rendezzük.
- Egyedi reranker service (FlagReranker)
- python alapú szerver, docker konténerben
- egyszerű REST API
- CPU/GPU support
- HF/Transformers modell formátum, a legtöbb modell alapra ebben készül
- bge-reranker-v2-m3 modell
- a bge-gemma2 és gte-Qwen2 modellekkel jól tud együttműködni
Válaszgenerálás
A keresési találatok alapján LLM segítségével megpróbálunk egy választ adni a felhasználó kérdésére.
Ehhez fontos, hogy a modell rendelkezésére bocsássuk a kérdés megválaszolásához az összes releváns információt.
A találatokhoz tartozó metaadatok segítségével a válasz pontos referenciákat tartalmazhat.
- OpenAI API GPT4-en keresztül generált
- A prompt felépítése:
- instrukciók
- relevánsnak ítélt kontextus
- user query
- Az első két keresési találat chunkjait (és a hozzájuk tartozó contextet) tartalmazza a kérés kontextje
- A kérés REST API-n történik, a válasz egyben van megvárva (nincsen streamelve)
- A felhasználó számára egy elkülönített szövegdobozban jelenik meg