Adatréteg
Qdrant
A Qdrant nyílt forrású vektoradatbázis: kollekciókban tárolja a pontokat, HNSW indexszel gyorsítja a hasonlósági keresést, a payload szűrők pedig szűkítik a találatokat.
A Qdrant egy nyílt forrású vektoradatbázis hasonlósági keresésre: a sokdimenziós vektorhalmazban nem feltételes szűréssel, hanem geometriai közelség alapján találja meg a releváns rekordokat. A beágyazásmodell úgy tanul, hogy a való világban hasonló objektumok közel kerüljenek egymáshoz a vektortérben: a keresés bemenete egy vektor, kimenete a legközelebbi pontok pontszám szerint rendezett listája.
Nálunk a Qdrant Docker konténerként fut a saját szerveren, és a retrieval funkciók mögötti vektorkeresést szolgálja ki. A 6333-as porton fut a REST API és a webes irányítópult, a 6334-esen a gRPC API, az adat pedig kötetben marad, amit a Docker stack tart rendben.
Kollekciók, pontok és nevesített vektorok
A kollekció névvel ellátott ponthalmaz, amelyen belül keresünk. Egy kollekció minden pontjának vektora ugyanakkora dimenziószámú, és egyetlen metrikával hasonlítjuk össze őket. Ha egy objektumhoz több beágyazás tartozik, nevesített vektorokat használunk: minden vektornévhez saját dimenzió és saját metrika tartozhat.
A pont a rekord: azonosítóból, vektorokból és opcionális payloadból áll. Az azonosító 64 bites egész szám vagy UUID, a payload tetszőleges JSON: karakterláncok, számok, logikai értékek, tömbök, geo pontok és időbélyegek. Sűrű vektort ad a legtöbb beágyazásmodell, ritka vektor a kulcsszavas egyezést szolgálja, multi-vektor pedig a late interaction modellekből származik.
- A feltöltés idempotens: azonos azonosítóval a meglévő pont felülíródik.
- A módosítás előbb a write-ahead logba kerül, onnantól áramszünet sem viszi el, majd a szegmensekbe íródik.
- Sok pontot egyetlen hívásban érdemes tölteni, párhuzamos feltöltéssel.
Távolságmetrikák
Négy dokumentált metrika közül választhatunk: pontszorzat (Dot), koszinusz hasonlóság (Cosine), euklideszi távolság (Euclid) és Manhattan távolság.
- Cosine a legtöbb szövegbeágyazásnál jó választás: a vektort beszúráskor normalizáljuk, így a keresés pontszorzattá egyszerűsödik, amit a processzor SIMD utasításokkal gyorsít.
- Dot akkor hasznos, ha a vektorok nincsenek normalizálva, és a hossz is hordoz jelentést.
- Euclid és Manhattan akkor kerül elő, amikor a skála vagy a taxicab jellegű távolság számít.
A metrika a kollekció létrehozásakor rögzül, később nem váltható át.
Payload szűrés és indexek
A beágyazás nem tartalmaz mindent, ami üzletileg számít: készletet, felhasználói helyet, árat vagy dátumot. A keresés ezért feltételt kaphat a payloadra és az azonosítóra is. A feltételek rekurzívan egymásba ágyazhatók: a must az ÉS, a should a VAGY, a must_not a tagadás megfelelője.
A szűrés gyorsasága két dolgon múlik. Egyrészt a payload indexen: kulcsszó, egész, valós, logikai, geo, dátum és szöveg típushoz külön index építhető, index nélkül a gép a teljes kollekciót pásztázza. Másrészt a lekérdezés tervezésén: a becsült szelektivitás alapján a Qdrant a payload indexből indul ki, a szűrhető HNSW gráfot járja be, vagy küszöb alatt teljes pásztázásra vált.
- A payload indexet az adatbetöltés előtt érdemes létrehozni, mert a szűrhető HNSW csak akkor kap feltételre szabott éleket, ha az index már létezett az építéskor; utólag létrehozott indexnél a HNSW indexet újra kell építeni.
- Szigorú módban a szűretlen mezőre irányuló lekérdezés hibával elutasítható, így a hiányzó index nem csendes lassulás, hanem hiba.
- Több bérlőnél egyetlen kollekció és bérlő kulcsú payload index a javasolt út sok kis kollekció helyett.
HNSW index és az API felület
A gyors vektorkeresést a HNSW gráf adja: minden pont legfeljebb m éllel kapcsolódik a szomszédaihoz, a keresés pedig rétegenként lefelé haladva, mohó lépésekkel közelíti meg a lekérdezésvektort. Az m és az ef_construct építési paraméter, a hnsw_ef lekérdezésenként állítható.
Az index nem épül meg minden szegmensben automatikusan: az optimalizáló a pontszám és a konfiguráció alapján dönt, a küszöb alatt teljes pásztázás fut.
Az API két felületen érhető el. A REST API a 6333-as porton dolgozik, a dokumentált lekérdezési végpont a POST /collections/{collection_name}/points/query. A gRPC API a 6334-es porton fut, és a nagy átbocsátású, kötegelt betöltést szolgálja; a Rust, Java, C# és Go kliens kifejezetten ezt használja.
- A vektorkeresés közelítő: az exact=true teljes pásztázást kényszerít ki pontos eredményért.
- Az indexed_only kihagyja az index nélküli szegmenseket, de részleges eredményt adhat.
Amire figyelni kell
- Az index építése időbe telik, és az m, az ef_construct vagy a payload_m növelése az építési időt és a memóriaigényt is növeli; érdemes figyelni a kollekció állapotát, amíg az optimalizálás fut.
- A memóriaigényt elsődlegesen a vektorok adják: egy dimenzió négy bájt. Ehhez jön a gráf és a payload indexek igénye. A vektorok mindig memóriába leképezett fájlban vannak: a cached szint betölti őket a RAM-ba, a cold szint nem.
- A kvantálás 4-szeres (skalár), akár 32-szeres (bináris) vagy 64-szeres (szorzat) tömörítést ad, de közelítési hibát visz be; a visszakeresés a pontosság nagy részét helyreállítja.
- A találatok közelítőek: a pontosság az m, az ef_construct és a hnsw_ef értékétől, valamint a kvantálástól függ, ezért valós lekérdezésmintán kell ellenőrizni.
- Az index nélküli mezőn szűrés lassabb, és a klaszter többi lekérdezésének késleltetését is rontja.
Tovább olvasás
A CyberElectrónál a Qdrant a retrieval réteg vektorkeresője: egy Docker stack, saját kollekciókkal és payload indexekkel. A forrásrekordok a PostgreSQL adatbázisban élnek.