4.5 Sémantické vyhľadávanie
Text tejto stránky je spracovaný zo záverečnej správy projektu BIBLIB.AI a nadväzuje na projektové zadanie publikované v tejto dokumentácii.
Súvisiace okruhy
Účel a východiská
Cieľom podsystému pre semantické vyhľadávanie je rozšíriť existujúce bibliografické vyhľadávanie o schopnosť vyhľadávať podľa významovej podobnosti textu. Klasické fulltextové vyhľadávanie pracuje najmä s lexikálnou zhodou, teda s výskytom slov, ich analyzovanými tvarmi, identifikátormi a presnými filtrami. V katalógovom prostredí je tento prístup stále nevyhnutný, pretože používateľ často hľadá podľa názvu, autora, ISBN, roku vydania, typu dokumentu alebo knižnice. Zároveň však existuje veľká skupina dotazov, pri ktorých používateľ nepozná presné slová použité v zázname. Môže formulovať tému prirodzeným jazykom, použiť synonymum, širší opis odboru alebo kombináciu pojmov v inom jazyku. Práve v takýchto prípadoch má význam semantické vyhľadávanie založené na embedding vektoroch.
Cieľom bolo vytvorenie prototypu (a neskôr plná integrácia do všetkých systémov) nad indexom systému INFOGATE s približne 3,96 milióna koreňových dokumentov a viac než 31 miliónov interných dokumentov vrátane nested a join reprezentácií entít. Index obsahuje rozsiahle mapovanie s viac ako stovkou top-level polí a štruktúru parent/child cez pole XRAY. Reálne dáta zahŕňali bibliografické záznamy aj holdingové záznamy, pričom XRAY rozlišovalo hodnoty biblio a holdingbiblio. Táto štruktúra je dôležitá pre návrh semantického vyhľadávania: embedding nemá byť počítaný zo všetkých dokumentov rovnako, ale najmä z obsahových bibliografických textov a pri vyhľadávaní má byť možné filtrovať typ dokumentu, knižnicu, jazyk, rok alebo stav.
Teoretické východiská semantického vyhľadávania
Embedding je číselná reprezentácia textu vo vektorovom priestore. Model strojového učenia transformuje text na usporiadané pole desatinných čísel tak, aby významovo podobné texty ležali v priestore bližšie k sebe ako texty významovo odlišné. Pri vyhľadávaní sa rovnakým modelom zakóduje používateľský dotaz a následne sa porovnáva vzdialenosť alebo podobnosť dotazového vektora s vektormi uloženými pri dokumentoch. Najčastejšie používanými metrikami sú kosínusová podobnosť, skalárny súčin alebo euklidovská vzdialenosť. V projekte sa pracuje s normalizovanými embeddingmi, čo znamená, že veľkosť vektora je upravená na jednotkovú normu. Pri normalizovaných vektoroch je kosínusová podobnosť prirodzenou mierou významovej blízkosti.
Semantické vyhľadávanie nenahrádza fulltext, ale dopĺňa ho. Fulltext je výborný pri presnej zhode názvov, identifikátorov, mien a čísel. Embedding je vhodný pri tematickom alebo významovom dotaze, napríklad keď používateľ hľadá literatúru o umelej inteligencii vo vzdelávaní, aj keď záznam obsahuje formulácie ako strojové učenie, inteligentné výučbové systémy alebo automatizovaná personalizácia výučby. V knižničnom katalógu je preto najvhodnejší hybridný prístup: výsledok vzniká kombináciou lexikálnej relevancie, vektorovej podobnosti a štruktúrovaných filtrov.
Dôležitým teoretickým rozhodnutím je, čo presne reprezentuje jeden embedding. Pri bibliografickom zázname by nebolo vhodné zakódovať iba názov, pretože názov môže byť príliš krátky alebo neinformatívny. Rovnako nie je vždy vhodné zakódovať celý XML alebo všetky polia bez rozlíšenia, pretože by sa do vektora dostali šumy, technické hodnoty alebo lokálne evidenčné údaje. Implementované riešenie preto vytvára reprezentatívny text z vybraných polí: názvy, variantné názvy, kľúčové slová, abstrakt, časti a edície. Tento text je následne vložený do embedding modelu ako jedna konsolidovaná textová reprezentácia bibliografického dokumentu.
Použité technické prostriedky
| Komponent | Použitie v riešení |
|---|---|
| FastAPI | REST rozhranie pre health , readiness , jednotkový výpočet embeddingu a batch výpočet embeddingov . |
| Uvicorn | ASGI server pre spustenie služby v kontajneri na porte 8080. |
| sentence-transformers | Knižnica na načítanie transformačného modelu a generovanie textových embeddingov . |
| paraphrase-multilingual-MiniLM-L12-v2 | Predvolený viacjazyčný model vhodný pre slovenské, české a anglické dotazy; typická dimenzia vektora je 384. |
| NumPy | Efektívna práca s vektormi a konverzia výstupu modelu na float32 zoznamy pre JSON alebo Elasticsearch . |
| Docker | Reprodukovateľné nasadenie služby s cache pre Hugging Face a Torch modely. |
| Elasticsearch | Uloženie katalógových dokumentov, fulltextové vyhľadávanie, filtre a vektorové vyhľadávanie nad poľom vektor. |
Systém podpory sémantického vyhľadávania bol navrhnutý ako samostojaci výkonný systém, ktorý môže slúžiť viacerým databázam a systémom a zároveň je ho možné škálovať pre potrebný výkon. Výsledná REST služba je implementovaná tak, že vie použiť akýkoľvek “sentencetransformer”. Táto vlastnosť je konfigurovateľná, celé riešenie je kontainerizované a použiteľné v Linux aj Windows prostrediach. Aktuálne nasadenie prevádzkujeme v UBUNTU ako jeden z kontainerov. Konfigurovať je možné bezpečnostný kľúč API_KEY, použitý model MODEL_NAME, použité zariadenie DEVICE, system normalizácie hodnôt NORMALIZE, maximálnu podporovanú dĺžku textu pre transformáciu MAX_TEXT_LEN a maximálny počet textov pre transformáciu do vektorov v jednej dávke MAX_BATCH_SIZE. Predvolený model je sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2, normalizácia je zapnutá a predvolené zariadenie je CPU. V prípade dostupnosti GPU možno použiť DEVICE=cuda, pričom aplikačné rozhranie ostáva rovnaké. Podstatnou vlastnosťou riešenia je cache modelu tak, aby sa po každom štarte kontainera nesťahoval nanovo.
Implementácia REST služby
Služba poskytuje štyri základné endpointy. GET /health slúži ako kontrola procesu (vracia stav oka uptime). GET /ready overuje, či je model načítaný, a vracia názov modelu, dimenziu vektora a použité zariadenie. POST /embedding prijíma jeden text a vracia jeden vektor. POST /embeddings prijíma zoznam textov a vracia zoznam vektorov. Oba POST endpointy vyžadujú hlavičku X-API-Key, čím sa zabraňuje neautorizovanému používaniu výpočtovo náročnej služby.
Model sa načítava pri štarte aplikácie cez startup event. To je dôležité pre produkčné použitie, pretože prvá používateľská požiadavka nemusí znášať oneskorenie spôsobené načítaním transformačného modelu. Výstupom je vektor hodnôt podľa použitého modelu vo float32 a JSON serializovateľnom poli.
Validácia vstupu je riešená cez Pydantic modely. Jednotlivý text má minimálnu dĺžku 1 a maximálnu dĺžku MAX_TEXT_LEN, predvolene 4000 znakov. Batchendpoint vyžaduje aspoň jeden text a najviac MAX_BATCH_SIZE položiek, predvolene 128. Texty sa pred spracovaním orezávajú cez trim a prázdne hodnoty sú odmietnuté chybou HTTP 400. Táto kontrola je prakticky dôležitá, pretože prázdny text by síce mohol produkovať technický embedding, ale jeho význam pre vyhľadávanie by bol nulový a mohol by zhoršiť kvalitu indexu.
POST /embeddings
Content-Type: application/json
X-API-Key: <API_KEY>
{"texts":["matematická analýza","medicínske dáta"]}
Výsledkom je JSON obsahujúci názov modelu, dimenziu, príznak normalizácie a pole vectors. Pri predvolenom modeli má každý vektor 384 čísel. Táto dimenzia musí byť totožná s dimenziou poľa v Elasticsearch; ak sa model zmení, nie je možné miešať staré a nové vektory v tom istom poli bez reindexácie alebo nového poľa.
Tvorba textu pre embedding a backfill existujúceho indexu
Okrem univerzálnej služby API ktorej vstupom je text a výstupom je embedding vektor bola vytvorená aj ďalšia služba pre prácu s ElasticSearch indexami vývojovej platformy BIBLIB. Tento skript rieši doplnenie vektorového poľa do existujúcich dokumentov v Elasticsearch. Skript najskôr zistí dimenziu lokálneho embedding modelu pomocou testovacieho textu. Potom načíta mapovanie cieľového indexu a overí, či pole vektor existuje. Ak existuje, skontroluje kompatibilitu dimenzie. Ak neexistuje, pokúsi sa doplniť mapovanie poľa vektor ako dense_vector s príslušnou dimenziou, indexovaním a kosínusovou podobnosťou.
Jadrom procesu je funkcia,ktorá zostavuje text pre embedding z vybraných zdrojových polí indexu: TIT, TITAVA, TITOTH, TITPAR, TITSHT, PTI, KEY, ABS, PART.TIT a SERIE.TIT. Každé pole má vlastný znakový rozpočet. Názvové polia sú obmedzené približne na stovky znakov, kľúčové slová na 1200 znakov a abstrakt na 2200 znakov. Takýto rozpočet má dve funkcie: chráni model pred príliš dlhým vstupom a zároveň dáva vyššiu váhu najrelevantnejším textovým častiam dokumentu.
Pred vložením do modelu sa hodnoty čistia od zalomení riadkov, normalizuje sa medzerovanie, viacnásobné hodnoty sa case-insensitivededuplikujú a extrahujú sa vnorené názvy častí alebo edícií. Výsledný text má formu označených sekcií, napríklad TIT: názov, KEY: kľúčové slová, ABS: abstrakt. Zachovanie názvov sekcií môže modelu pomôcť, pretože text má stabilnú štruktúru a rozlišuje názov od abstraktu alebo kľúčových slov. Ak dokument neobsahuje žiadne vhodné pole, použije sa hodnota N/A; táto sa v produkčnej prevádzke bude monitorovať, pretože vektor z nereprezentatívneho textu nemá vyhľadávaciu hodnotu.
Skript používa scroll vyhľadávanie nad Elasticsearch, predvolene so searchbatchsize 256 a embeddingbatchsize 128. Dotaz vyberá dokumenty podľa XRAY, predvolene biblio, a pokiaľ nie je použitý prepínač force-all, spracúva iba dokumenty, ktorým chýba pole vektor. Aktualizácia prebieha cez Bulk API. Pri parent/child dokumentoch sa zachováva routing z pôvodného hitu, čo je dôležité pre správne uloženie dokumentu v rámci shardov. Po spracovaní sa index refreshne a skript vypíše súhrn počtu dokumentov bez vektora pred a po behu.
Využitie embedding vektorov v Elasticsearch
Elasticsearch podporuje ukladanie hustých vektorov cez typ dense_vector. V moderných verziách Elasticsearch je tento typ určený najmä na k-nearestneighbor vyhľadávanie, teda hľadanie najbližších dokumentových vektorov k vektoru vypočítanému z dotazu vyhľadávania. Oficiálna dokumentácia Elasticsearch rozlišuje približné kNN, ktoré používa indexované vektorové štruktúry a je vhodné pre produkčné rozsiahle dáta, a presné brute-force vyhľadávanie cez script_score, ktoré je presné, ale škáluje horšie a je vhodné najmä nad menšími alebo už filtrovanými množinami dokumentov.
Experimenty boli v začiatkoch realizované nad Elasticsearch 7.6.1. Ide o staršiu verziu, v ktorej sú natívne približné kNN možnosti oproti novším verziám limitované. Experimentovali sme však aj s touto verziou, ale je to dôvod inovovať všetky riešenia na najnovšie verzie 9.X a použiť indexované dense_vector pole a knnquery alebo knn časť search požiadavky s filtrami a hybridným skórovaním.
Pre existujúci INFOGATE cluster je typický dotaz založený na kombinácii bool filtra a script_score. Najskôr sa výsledky obmedzia podľa štruktúrovaných kritérií, napríklad XRAY=biblio, stav záznamu, rok publikovania, jazyk alebo knižnica. Až nad touto množinou sa vypočíta vektorové skóre. Takýto postup je efektívnejší než porovnávanie dotazového vektora so všetkými miliónmi dokumentov.
POST bib_infogate_ostry_f_biblio/_search
{
"size": 20,
"query": {
"script_score": {
"query": { "bool": {
"filter": [
{ "term": { "XRAY": "biblio" } },
{ "range": { "PUBYR": { "gte": 2000 } } }
],
"must": [ { "match": { "all": "umelá inteligencia vo vzdelávaní" } } ]
} },
"script": {
"source": "cosineSimilarity(params.q,
"params": { "q": [/* 384-dim queryvector */] }
}
}
}
}
Pripočítanie hodnoty 1.0 je bežný praktický postup, pretože kosínusová podobnosť môže nadobúdať aj záporné hodnoty, zatiaľ čo Elasticsearch skóre by malo byť nezáporné. Výsledkom je rebríček dokumentov, ktoré zároveň spĺňajú bežné katalógové kritériá a sú významovo blízke dotazu.
V novšej verzii Elasticsearch možno použiť približné kNN nad indexovaným dense_vector poľom. Takýto dotaz pracuje s parametrami field, query_vector, k a num_candidates. Parameter k určuje počet najbližších susedov, ktoré má vektorové vyhľadávanie vrátiť, a num_candidates počet kandidátov skúmaných pri približnom vyhľadávaní. KNN možno kombinovať s filtrom, aby sa hľadali iba dokumenty určitého typu, roku alebo knižnice.
POST bib_infogate_ostry_f_biblio/_search
{
"size": 20,
"knn": {
"field": "vektor",
"query_vector": [/* 384-dim queryvector */],
"k": 100,
"num_candidates": 1000,
"filter": { "bool": { "filter": [
{ "term": { "XRAY": "biblio" } },
{ "terms": { "LAN.SHT": ["slo", "cze", "eng"] } } }
] } }
},
"query": {
"multi_match": {
"query": "umelá inteligencia vo vzdelávaní",
"fields": ["all^2", "TIT^3", "KEY^2", "ABS"]
}
}
}
Tento hybridný vzor kombinuje významovú podobnosť a klasické textové skóre. V novších verziách Elasticsearch sa skóre z knn a query časti kombinuje, pričom je možné použiť boost hodnoty na vyváženie vplyvu lexikálnej a vektorovej relevancie. Pre katalógové vyhľadávanie je to praktické: presný výskyt názvu alebo identifikátora môže mať vyššiu váhu, zatiaľ čo embedding rozširuje výsledky o významovo blízke dokumenty, ktoré by bežný fulltext nezachytil.
Kombinácia s bežnými katalógovými kritériami
Najväčšia hodnota vektorového vyhľadávania vzniká vtedy, keď sa používa spolu s existujúcimi kritériami katalógu. V analyzovanom indexe sú dostupné polia ako TIT, KEY, ABS, ISBN, ISSN, DOI, PUBYR, TYPE, TPE, nested osoby PER, inštitúcie INST, jazyky LAN, holdingy HOL a ďalšie. To umožňuje vytvárať dotazy, ktoré kombinujú význam dotazu s presnými obmedzeniami. Príkladom môže byť vyhľadanie významovo podobných dokumentov k téme medicínske dáta, ale iba v slovenskom alebo anglickom jazyku, iba pre bibliografické záznamy, iba po roku 2015 a iba v knižniciach, ktoré majú dostupný holding.
Pri nested poliach treba rešpektovať pôvodnú štruktúru indexu. Jednoduchý exists dotaz nemusí pre nested objekt fungovať tak, ako pri top-level poli; na polia ako PER, INST alebo LAN je potrebné používať nestedquery alebo nested agregácie. To platí aj pri filtrovaní semantických výsledkov podľa jazyka, osoby alebo inštitúcie. Vektorové skóre by malo hodnotiť bibliografický dokument ako celok, no štruktúrované obmedzenia musia byť vyjadrené spôsobom kompatibilným s mapovaním indexu.
Z používateľského hľadiska možno rozlišovať tri režimy. Prvý režim je klasické vyhľadávanie, pri ktorom sa embedding nepoužije a rozhodujú fulltextové polia a filtre. Druhý režim je semantické vyhľadávanie, pri ktorom dotaz prejde cez embedding službu a výsledky sa zoradia podľa vektorovej podobnosti v rámci povoleného filtra. Tretí režim je hybridné vyhľadávanie, pri ktorom sa použijú obe zložky a výsledné skóre kombinuje presnú textovú relevanciu so sémantickou podobnosťou. Pre produkčný katalóg je najvhodnejší tretí režim, pretože minimalizuje riziko, že vektorové vyhľadávanie uprednostní tematicky blízky, ale bibliograficky menej presný záznam pred presnou zhodou názvu alebo identifikátora.
Prevádzkové a kvalitatívne aspekty
Pri prevádzke podsystému je nutné zabezpečiť stabilitu modelu. Všetky dokumentové vektory a dotazové vektory musia byť generované rovnakým modelom a rovnakým nastavením normalizácie. Zmena modelu znamená zmenu vektorového priestoru; staré a nové vektory už nie sú porovnateľné. Výkonnosť závisí od viacerých faktorov: počtu dokumentov s vektorom, dimenzie vektora, použitej verzie Elasticsearch, shardovania, počet kandidátov, veľkosti filtra a hardvéru. Pri staršom Elasticsearch a script_score prístupe je kľúčové najprv čo najviac zúžiť kandidátnu množinu. Pri novších verziách s približným kNN je vhodné ladiť k, počet kandidátov a boost hodnoty, aby výsledok nebol ani príliš pomalý, ani príliš nepresný.
Kvalita embeddingov závisí aj od pravidiel zostavenia textu. Ak sa do embeddingu vložia prevažne technické identifikátory, lokálne signatúry alebo duplicitné hodnoty, vektor prestane reprezentovať tematický obsah. Naopak, ak sa vynechajú abstrakty a kľúčové slová, záznamy s neurčitým názvom budú ťažšie vyhľadateľné. V implementovanom riešení je vhodne zvolený kompromis: názvy tvoria základ, kľúčové slová a abstrakt poskytujú tematickú hĺbku a časti či edície dopĺňajú kontext.
Záver
Vytvorený podsystém poskytuje technický základ pre semantické vyhľadávanie nad katalógovými dátami BIBLIB. REST služba izoluje výpočet embeddingov od hlavného katalógového systému a poskytuje jednotné API pre jednotlivé aj dávkové požiadavky. Backfill skript umožňuje automaticky a priebežne dopĺňať existujúci Elasticsearch index o pole vektor, pričom rešpektuje štruktúru indexu, typ dokumentu XRAY, batch spracovanie a Bulk API.
Najdôležitejším prínosom je možnosť vytvoriť hybridné vyhľadávanie, ktoré spája presnosť tradičných katalógových kritérií s významovou podobnosťou. Používateľ tak môže nájsť dokumenty aj vtedy, keď nepoužije presné slová zo záznamu, a zároveň si zachová kontrolu nad jazykmi, rokmi, knižnicami, typmi dokumentov a dostupnosťou. Keďže počas riešenia projektu prebehol upgrade Elasticsearch, v riešení sme už pripravili koncept natívneho kNN vyhľadávania nad indexovaným dense_vector poľom v kombinácii s bežnými query a filter kritériami.