30 վայրկյանում
Վեկտորային բազան պահում է embedding-ներ՝ թվերի ցուցակներ, որոնք արտահայտում են տեքստի, պատկերների կամ այլ տվյալների իմաստը, և գտնում է հարցմանը ամենանման ցուցակները։ Այն օգտագործում է approximate nearest neighbour (ANN) ինդեքսներ, ինչպիսին HNSW-ն է, որպեսզի միլիոնավոր վեկտորների մեջ որոնի միլիվայրկյանների ընթացքում։ Սա ապահովում է սեմանտիկ որոնում, առաջարկություններ և retrieval AI օգնականների համար (RAG)։ Կարող եք օգտագործել առանձին engine կամ pgvector-ի նման extension։
Իմ ամենօրյա stack-ում չէ․ գիտեմ հիմնական գաղափարները և մանրամասները կսովորեմ, երբ նախագիծը դա պահանջի։
Ինչու է սա կարևոր
- Keyword որոնումը ձախողվում է, երբ մարդիկ նույն բանի համար տարբեր բառեր են օգտագործում։ Embedding-ները «cheap flights»-ը համընկեցնում են «low-cost airfare»-ի հետ, և հենց դրա համար է սեմանտիկ որոնումն ավելի խելացի թվում։
- Retrieval-augmented generation-ը (RAG) կախված է դրանից․ LLM-ը պատասխանում է ձեր փաստաթղթերից միայն այն դեպքում, եթե կարողանում եք արագ գտնել ճիշտ հատվածները։
- Թիմերն ընտրում են գոյություն ունեցող բազային վեկտորներ ավելացնելու (pgvector, Elasticsearch, Redis) և առանձին engine աշխատեցնելու միջև․ ճիշտ ընտրությունը կախված է մասշտաբից, ֆիլտրերից և թիմի հմտություններից։
- Այն լրացնում է, ոչ թե փոխարինում keyword որոնմանը, ինչպիսիք են Algolia-ն կամ Elasticsearch BM25-ը․ լավագույն համակարգերը երկուսը համադրում են hybrid որոնման մեջ։
Ինչպես է աշխատում
01Embedding-ներ՝ իմաստը որպես կոորդինատներ
Embedding մոդելը կոնտենտի կտորը վերածում է վեկտորի, օրինակ՝ 1,024 թվի։ Պատկերացրեք հսկայական քարտեզ, որտեղ նման իմաստները մոտ են միմյանց․ «dog»-ը մոտ է «puppy»-ին և հեռու «invoice»-ից։ Մոդելը վարժեցված է այնպես, որ այս քարտեզի վրա հեռավորությունն արտացոլի նմանությունը։ Դուք մեկ անգամ embed եք անում ձեր փաստաթղթերը և պահում վեկտորները․ հարցման ժամանակ նույն մոդելով embed եք անում հարցը և փնտրում ամենամոտ հարևաններին։ Նմանությունը չափվում է cosine similarity-ով (վեկտորների միջև անկյունը), dot product-ով կամ Euclidean (L2) հեռավորությամբ։ Տեքստային մոդելների մեծ մասը արտադրում է նորմալացված վեկտորներ, այնպես որ cosine-ը և dot product-ը նույն կերպ են դասակարգում։
- Չափողականություն (dimension)՝ քանի թիվ ունի յուրաքանչյուր վեկտոր (օրինակ՝ 384, 768, 1024, 1536, 3072)։
- Փաստաթղթերի և հարցումների համար միշտ օգտագործեք նույն մոդելը․ տարբեր մոդելների վեկտորները համեմատելի չեն։
- Մոդելը փոխելը նշանակում է ամեն ինչ վերա-embed անել, այնպես որ յուրաքանչյուր վեկտորի հետ գրանցեք մոդելի անունը և տարբերակը։
02Ինչո՞ւ ճշգրիտ որոնումը չի մասշտաբավորվում, և ինչպես է օգնում ANN-ը
Ճշգրիտ որոնումը հարցումը համեմատում է յուրաքանչյուր պահված վեկտորի հետ։ 10,000 վեկտորի համար դա լավ է, իսկ 1,024 չափողականությամբ 50 միլիոնի համար՝ չափազանց դանդաղ։ Approximate nearest neighbour (ANN) ինդեքսները մի փոքր ճշգրտություն փոխանակում են հսկայական արագության հետ։ HNSW-ն (Hierarchical Navigable Small World) կառուցում է շերտավոր գրաֆ․ վերին շերտերը նոսր մայրուղիներ են, ստորին շերտերը՝ խիտ տեղական փողոցներ։ Որոնումը սկսվում է վերևից, ագահաբար շարժվում դեպի հարցումը և իջնում։ IVF-ը (inverted file) վեկտորները կլաստերավորում է և որոնում միայն ամենամոտ կլաստերներում։ Recall-ը չափում է որակը՝ իրական ամենամոտ հարևանների այն մասը, որը վերադարձնում է ինդեքսը։ Լավ կարգավորումները մի քանի միլիվայրկյանում հասնում են 95–99% recall-ի։
- HNSW՝ recall/արագություն լավագույն փոխզիջումը, ավելի շատ հիշողություն, ավելի դանդաղ կառուցում։
- IVF՝ ավելի քիչ հիշողություն և ավելի արագ կառուցում, պահանջում է վարժեցում տվյալների վրա և probe-երի կարգավորում։
- Quantization՝ վեկտորների պահում ավելի քիչ բիթերով (int8, binary)՝ հիշողությունը կրճատելու համար, ճշգրտության համար rescoring-ով։
03Սկսել pgvector-ով PostgreSQL-ում
Եթե արդեն աշխատեցնում եք PostgreSQL, pgvector-ը հաճախ ամենապարզ սկիզբն է․ վեկտորներն ապրում են ձեր տողերի կողքին, անվճար ստանում եք տրանզակցիաներ, join-եր, backup-ներ և access control, իսկ ֆիլտրերը սովորական SQL են։ Extension-ն ավելացնում է vector տիպը (և halfvec՝ 16-բիթանոց պահման համար), հեռավորության օպերատորներ (<->՝ L2-ի համար, <=>՝ cosine distance-ի համար, <#>՝ բացասական inner product-ի համար) և HNSW ու IVFFlat ինդեքսներ։ Օգտագործեք ձեր հեռավորությանը համապատասխանող operator class․ vector_cosine_ops-ով կառուցված ինդեքսն օգնում է միայն այն հարցումներին, որոնք դասավորում են <=>-ով։ Բարձրացրեք hnsw.ef_search-ը ավելի լավ recall-ի համար՝ latency-ի որոշակի գնով։
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE doc_chunks (
id bigserial PRIMARY KEY,
doc_id bigint NOT NULL,
tenant_id int NOT NULL,
content text NOT NULL,
embedding vector(1024) NOT NULL
);
CREATE INDEX ON doc_chunks USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
SET hnsw.ef_search = 100;
SELECT id, content, 1 - (embedding <=> $1) AS similarity
FROM doc_chunks WHERE tenant_id = 7
ORDER BY embedding <=> $1 LIMIT 10;
04Առանձին վեկտորային բազաներ
Առանձին engine-ները, ինչպիսիք են Qdrant-ը, Weaviate-ը, Milvus-ը և Pinecone-ը, կառուցված են vector որոնման շուրջ։ Դրանք առաջարկում են արագ ֆիլտրված որոնում, quantization, sharding node-երի միջև, multi-tenancy ֆունկցիաներ, sparse վեկտորներ hybrid որոնման համար և կառավարվող ամպային տարբերակներ։ Դուք պահում եք point-եր, որոնք բաղկացած են ID-ից, մեկ կամ մի քանի վեկտորից և payload-ից (մետատվյալներ), որով ֆիլտրում եք։ Փոխզիջումը ևս մեկ համակարգ է, որը պետք է աշխատեցնել, պաշտպանել և սինքրոն պահել ձեր հիմնական բազայի հետ։ Գործնական կանոն՝ մի քանի միլիոն վեկտորից ցածր և չափավոր թրաֆիկի դեպքում pgvector-ը կամ ձեր գոյություն ունեցող որոնման շարժիչը սովորաբար բավարար են․ տասնյակ միլիոնավոր վեկտորների, ծանր ֆիլտրման կամ latency-ի խիստ թիրախների դեպքում առանձին engine-ն արդարացնում է իրեն։
# Qdrant: create a collection and search with a filter (HTTP API)
curl -X PUT http://localhost:6333/collections/docs -H 'Content-Type: application/json' \
-d '{ "vectors": { "size": 1024, "distance": "Cosine" } }'
curl -X POST http://localhost:6333/collections/docs/points/query \
-H 'Content-Type: application/json' -d '{
"query": [0.01, 0.12, 0.03],
"filter": { "must": [ { "key": "tenant_id", "match": { "value": 7 } } ] },
"limit": 10, "with_payload": true
}'
05Hybrid որոնում և reranking
Վեկտորները հիանալի են իմաստի հարցում, բայց թույլ են ճշգրիտ token-ների հարցում՝ ապրանքների կոդեր, անուններ, սխալի հաղորդագրություններ։ Keyword որոնումը (BM25) հակառակն է։ Hybrid որոնումն աշխատեցնում է երկուսն էլ և միավորում ցուցակները, ամենից հաճախ reciprocal rank fusion-ով (RRF), որտեղ յուրաքանչյուր փաստաթուղթ յուրաքանչյուր ցուցակում ստանում է 1 / (k + rank) score, և գումարները որոշում են վերջնական հերթականությունը։ RRF-ը score-ի նորմալացում չի պահանջում, և հենց դրա համար է հանրաճանաչ։ Միավորելուց հետո cross-encoder reranker-ը կարող է վերագնահատել top 50–100 թեկնածուներին՝ կարդալով հարցումը և փաստաթուղթը միասին․ այն ավելի դանդաղ է, բայց շատ ավելի ճշգրիտ, այնպես որ աշխատում է միայն կարճ ցուցակի վրա։
-- Hybrid in PostgreSQL: full-text + vector, merged with RRF (k = 60)
WITH kw AS (
SELECT id, row_number() OVER (ORDER BY ts_rank(tsv, q) DESC) AS r
FROM doc_chunks, websearch_to_tsquery('english', $2) q
WHERE tsv @@ q ORDER BY r LIMIT 50
), vec AS (
SELECT id, row_number() OVER (ORDER BY embedding <=> $1) AS r
FROM doc_chunks ORDER BY embedding <=> $1 LIMIT 50
)
SELECT id, sum(1.0 / (60 + r)) AS score
FROM (SELECT * FROM kw UNION ALL SELECT * FROM vec) s
GROUP BY id ORDER BY score DESC LIMIT 10;
Օգտագործեք, երբ
- Սեմանտիկ որոնում փաստաթղթերում, help center-ներում, տիկետներում կամ ապրանքների նկարագրություններում։
- Retrieval RAG օգնականների համար, որոնք պետք է պատասխանեն ձեր սեփական կոնտենտից։
- Առաջարկություններ և «նման ապրանքներ»՝ կոնտենտի կամ վարքագծի embedding-ների հիման վրա։
- Գրեթե նույնական տեքստերի կամ պատկերների դեդուպլիկացիա և կլաստերավորում։
Մի՛ օգտագործեք, երբ
- Ճշգրիտ lookup-ներ ըստ ID-ի, SKU-ի կամ ֆիլտրի պայմանների․ սովորական ինդեքսն ավելի արագ և ճշգրիտ է։
- Մի քանի հազար տարրից բաղկացած փոքր հավաքածուներ, որտեղ հիշողության մեջ կամ PostgreSQL-ում ճշգրիտ որոնումը բավարար է։
- Երբ օգտատերերը հիմնականում որոնում են ճշգրիտ անուններ և կոդեր․ լավ keyword որոնումը նրանց ավելի լավ կծառայի։
Այլընտրանքներ
- pgvector (PostgreSQL)
Վեկտորներ ռելյացիոն տվյալների կողքին՝ SQL ֆիլտրերով և տրանզակցիաներով․ շատ թիմերի համար ամենապարզ սկիզբը։
- Qdrant / Weaviate / Milvus
Open-source առանձին engine-ներ՝ ուժեղ ֆիլտրմամբ, quantization-ով և մասշտաբավորմամբ, սեփական սերվերի վրա կամ կառավարվող։
- Pinecone
Ամբողջովին կառավարվող serverless վեկտորային բազա․ առանց operations աշխատանքի, օգտագործման վրա հիմնված գնով։
- Elasticsearch / OpenSearch / Redis
Ավելացրեք vector որոնում այն engine-ին, որը գուցե արդեն աշխատեցնում եք՝ ներկառուցված keyword որոնմամբ hybrid-ի համար։
Լավագույն պրակտիկաներ
- Embedding մոդելն ընտրեք՝ գնահատելով այն ձեր սեփական հարցումների վրա, ոչ միայն leaderboard-ի դիրքով։
- Յուրաքանչյուր վեկտորի հետ պահեք մոդելի անունը և տարբերակը և պլանավորեք ամբողջական վերա-embedding։
- Ինդեքսի operator class-ը կամ մետրիկը համապատասխանեցրեք այն հեռավորությանը, որը սպասում է ձեր մոդելը (սովորաբար cosine)։
- Չափեք recall-ը ճշգրիտ որոնման դեմ նմուշի վրա՝ մինչև ef_search-ի նման պարամետրերը կարգավորելը։
- Օգտագործեք hybrid որոնում (keyword գումարած vector) և reranker վերջնական top արդյունքների համար։
- Tenant-ի և թույլտվությունների ֆիլտրերը կիրառեք vector հարցման ներսում, երբեք միայն retrieval-ից հետո։
- Ճշմարտության աղբյուրը պահեք ձեր հիմնական բազայում և վեկտորները սինքրոնացրեք ասինխրոն և idempotent կերպով։
Տարածված սխալներ
- Երկու embedding մոդելների վեկտորները մեկ ինդեքսում խառնել, ինչը լուռ անիմաստ դասակարգումներ է տալիս։
- Ամբողջական երկար փաստաթղթերը embed անել որպես մեկ վեկտոր, այնպես որ իմաստը մշուշվում է, և retrieval-ը բաց է թողնում մանրամասները։
- Արդյունքները ֆիլտրել top-10 vector որոնումից հետո՝ ընտրողական ֆիլտրերի դեպքում թողնելով զրո արդյունք։
- Ենթադրել, որ vector որոնումը ճշգրիտ է, և ընդհանրապես չչափել recall-ը կամ relevance-ը։
- Մոռանալ, որ ինդեքսի հիշողությունն աճում է չափողականությունը բազմապատկած վեկտորների քանակով, և պրոդակշնում RAM-ը սպառել։
Խորը վերլուծություն
06HNSW-ի կարգավորում՝ m, ef_construction, ef_search
m-ը յուրաքանչյուր node-ի կապերի քանակն է։ Ավելի բարձր m-ը բարելավում է recall-ը բարձր չափողականությամբ տվյալների վրա, բայց մեծացնում է հիշողությունը և կառուցման ժամանակը․ 16-ը տարածված լռելյայն արժեք է, 32–64՝ բարդ dataset-երի համար։ ef_construction-ը թեկնածուների ցուցակի չափն է կառուցման ժամանակ․ ավելի բարձրը նշանակում է ավելի լավ գրաֆ և ավելի դանդաղ insert-ներ (64–200-ը բնորոշ է)։ ef_search-ը թեկնածուների ցուցակն է հարցման ժամանակ և runtime-ի հիմնական կարգավորիչը․ ավելի բարձրը նշանակում է ավելի լավ recall և ավելի շատ latency, և այն պետք է առնվազն LIMIT-ի չափ լինի։ Կարգավորեք էմպիրիկ կերպով․ վերցրեք 1,000 նմուշային հարցում, sequential scan-ով հաշվեք ճշգրիտ հարևաններին, ապա փոփոխեք ef_search-ը և գծեք recall at 10-ն ընդդեմ p95 latency-ի։ HNSW-ի կառուցումը հիշողություն է ուտում․ PostgreSQL-ում կառուցման համար բարձրացրեք maintenance_work_mem-ը և max_parallel_maintenance_workers-ը։
-- Build faster with more memory and workers (PostgreSQL)
SET maintenance_work_mem = '4GB';
SET max_parallel_maintenance_workers = 7;
CREATE INDEX CONCURRENTLY idx_chunks_emb
ON doc_chunks USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 128);
-- Filtered queries: keep scanning until enough rows match (pgvector 0.8+)
SET hnsw.iterative_scan = relaxed_order;
07Հիշողություն, quantization և rescoring
1,024 չափողականությամբ float32 վեկտորը զբաղեցնում է 4 KB։ Դրանցից տաս միլիոնը մոտ 40 GB է՝ մինչև ինդեքսի overhead-ը, և HNSW-ն ուզում է, որ տաք մասը լինի RAM-ում։ Quantization-ը փոքրացնում է սա։ Half precision-ը (halfvec pgvector-ում) կիսով չափ կրճատում է չափը՝ գրեթե առանց recall-ի կորստի։ Scalar quantization-ը դեպի int8 կրճատում է չորս անգամ։ Binary quantization-ը պահում է մեկ բիթ յուրաքանչյուր չափողականության համար՝ 32 անգամ ավելի փոքր, և զարմանալիորեն լավ է աշխատում շատ ժամանակակից embedding մոդելների վրա, երբ համադրվում է rescoring-ի հետ․ կոմպակտ ինդեքսում որոնեք, ասենք, top 200 թեկնածուներին, ապա վերադասակարգեք նրանց ամբողջական ճշգրտության վեկտորներով։ Qdrant-ի, Milvus-ի և Elasticsearch-ի նման engine-ները իրականացնում են այս պատերնը native կերպով․ pgvector-ում կարող եք ինդեքսավորել binary արտահայտություն և rescore անել SQL-ում։
-- pgvector: binary-quantized index with full-precision rescoring
CREATE INDEX ON doc_chunks USING hnsw
((binary_quantize(embedding)::bit(1024)) bit_hamming_ops);
SELECT id FROM (
SELECT id, embedding FROM doc_chunks
ORDER BY binary_quantize(embedding)::bit(1024) <~> binary_quantize($1)
LIMIT 200
) candidates
ORDER BY embedding <=> $1 LIMIT 10;
08Վեկտորները թարմ պահել՝ ingestion և վերա-embedding
Վեկտորները ածանցյալ տվյալներ են։ Embedding-ը դիտարկեք որպես pipeline․ երբ փաստաթուղթը փոխվում է, իրադարձությունը (outbox տող կամ queue job) գործարկում է chunking և embedding, և արդյունքը upsert է արվում կայուն ID-ով, ինչպիսին doc_id-ն է գումարած chunk-ի համարը՝ ջնջելով նույն փաստաթղթի հնացած chunk-երը։ Job-երը դարձրեք idempotent և rate-limited, քանի որ embedding API-ներն ունեն quota-ներ։ Մոդելի upgrade-ներին պետք է միգրացիոն պլան․ ստեղծեք նոր սյունակ կամ կոլեկցիա նոր մոդելի համար, backfill արեք ֆոնում, գնահատեք կողք կողքի, ընթերցումները փոխարկեք flag-ի հետևում, ապա ջնջեք հին վեկտորները։ HNSW ինդեքսները մի փոքր վատանում են ծանր update-ներից և delete-ներից․ պլանավորեք պարբերական reindex (REINDEX CONCURRENTLY PostgreSQL-ում) կամ ապավինեք engine-ի optimiser-ին։
09Embedding-ների անվտանգություն և գաղտնիություն
Embedding-ները անանուն չեն։ Հետազոտությունները ցույց են տվել, որ տեքստը կարող է մասնակիորեն վերականգնվել իր embedding-ից, այնպես որ վեկտորներին վերաբերվեք նույն զգայունությամբ, ինչ աղբյուր կոնտենտին։ Access control-ը պարտադրեք հարցման ժամանակ՝ tenant-ի և թույլտվությունների ֆիլտրեր որոնման ներսում, row-level security PostgreSQL-ում կամ առանձին կոլեկցիաներ խիստ մեկուսացման համար։ Կոնտենտն արտաքին embedding API ուղարկելիս ստուգեք տվյալների մշակման պայմանները և խուսափեք գաղտնիքներ կամ ավելորդ անձնական տվյալներ ուղարկելուց։ Փաստաթուղթը ջնջելը պետք է ջնջի նաև նրա վեկտորները, ինչը կարևոր է GDPR ջնջման համար։ Վերջապես, RAG-ում օգտագործելիս retrieved կոնտենտը կարող է պարունակել prompt injection, այնպես որ prompt-ում retrieved տեքստը դիտարկեք որպես անվստահելի տվյալ։
Իրական իրավիճակներ
Սեմանտիկ որոնում help center-ի համար
Խնդիր
SaaS help center-ն ունի 3,000 հոդված։ Օգտատերերը որոնում են իրենց բառերով, և keyword որոնումը հարցումների կեսի համար ոչինչ չի վերադարձնում։
Ինչպես լուծել
Սկսեք պարզից․ միացրեք pgvector-ը գոյություն ունեցող PostgreSQL-ում։ Հոդվածները բաժանեք մի քանի հարյուր token-անոց chunk-երի՝ պահպանելով վերնագրերը, embed արեք դրանք մեկ մոդելով և պահեք doc_id-ն, chunk-ի տեքստը և մոդելի տարբերակը։ Ստեղծեք HNSW ինդեքս cosine օպերատորներով։ Կառուցեք hybrid որոնում՝ PostgreSQL full-text search գումարած vector որոնում՝ միավորված RRF-ով, ինչպես դասում է։ Որոնման լոգերից հավաքեք 100 իրական հարցում, պիտակավորեք ճիշտ հոդվածները և համեմատեք zero-result rate-ը և recall at 5-ը առաջ և հետո։ Փոփոխված հոդվածները վերա-embed արեք queue job-ով՝ հրապարակման ժամանակ։ Այս չափի դեպքում նոր բազա պետք չէ։
Ֆիլտրված որոնումը չափազանց քիչ արդյունք է վերադարձնում
Խնդիր
Marketplace-ը որոնում է 20 միլիոն հայտարարության embedding-ներում՝ քաղաքի և կատեգորիայի ֆիլտրերով։ Փոքր քաղաքների համար հարցումները հաճախ վերադարձնում են երկու կամ երեք արդյունք՝ քսանի փոխարեն։
Ինչպես լուծել
ANN ինդեքսը նախ վերադարձնում է ամենամոտ թեկնածուներին, և ֆիլտրը հետո հեռացնում է նրանց մեծ մասը։ pgvector 0.8+-ում միացրեք iterative scan-ները SET hnsw.iterative_scan = relaxed_order-ով և անհրաժեշտության դեպքում բարձրացրեք hnsw.max_scan_tuples-ը։ Շատ ընտրողական ֆիլտրերի համար թողեք, որ planner-ը օգտագործի B-tree ինդեքս քաղաքի վրա և ճշգրիտ հեռավորություն հաշվի փոքր ենթաբազմության վրա, կամ ստեղծեք partial HNSW ինդեքսներ յուրաքանչյուր մեծ կատեգորիայի համար։ Առանձին engine-ում, ինչպիսին Qdrant-ն է, ստեղծեք payload ինդեքսներ քաղաքի և կատեգորիայի վրա, որպեսզի ֆիլտրումը տեղի ունենա գրաֆի traversal-ի ընթացքում։ Հաստատեք recall թեստերով փոքր քաղաքների հարցումների վրա, ոչ միայն գլոբալ միջիններով։
Embedding մոդելի upgrade
Խնդիր
Թիմը ուզում է անցնել ավելի նոր embedding մոդելի՝ ավելի լավ բազմալեզու որակով։ Նրանք ունեն 8 միլիոն chunk՝ embed արված հին մոդելով, և որոնումը պետք է շարունակի աշխատել։
Ինչպես լուծել
Ավելացրեք նոր սյունակ (կամ կոլեկցիա) նոր մոդելի վեկտորների համար՝ իր չափողականությամբ և ինդեքսով․ երբեք մի խառնեք դրանք։ Backfill արեք ֆոնում rate-limited worker-ով՝ սկզբում ամենանոր և ամենադիտված կոնտենտը։ Backfill-ի ընթացքում նոր և փոփոխված փաստաթղթերը ստանում են երկու embedding-ն էլ։ Աշխատեցրեք offline գնահատում պիտակավորված հարցումների հավաքածուի վրա և shadow համեմատություն live հարցումների վրա։ Երբ նոր մոդելը հաղթում է, ընթերցումները փոխարկեք feature flag-ի հետևում, հետևեք click-through-ին և zero-result rate-ին, հին վեկտորները պահեք rollback պատուհանի համար, ապա ջնջեք հին սյունակը և ինդեքսը՝ հիշողություն ազատելու համար։
Արագ ուղեցույց
- Միացնել pgvector-ը
CREATE EXTENSION IF NOT EXISTS vector;- Cosine HNSW ինդեքս
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);- Ամենամոտերը ըստ cosine distance-ի
SELECT id FROM items ORDER BY embedding <=> $1 LIMIT 10;- Ավելի բարձր recall հարցման ժամանակ
SET hnsw.ef_search = 100;- Ֆիլտրված հարցումները շարունակում են սկանավորել
SET hnsw.iterative_scan = relaxed_order;- Half-precision պահում
embedding halfvec(1024) -- index with halfvec_cosine_ops- RRF score մեկ ցուցակի համար
score = 1.0 / (60 + rank)- Qdrant կոլեկցիա
PUT /collections/docs { "vectors": { "size": 1024, "distance": "Cosine" } }- Ճշգրիտ baseline recall թեստերի համար
SET enable_indexscan = off; -- then run the same ORDER BY query
Հարցեր և պատասխաններ
Q1Ի՞նչ է embedding-ը։
Embedding-ը ֆիքսված երկարությամբ թվերի ցուցակ է, որը ներկայացնում է որոշ կոնտենտի իմաստը և ստեղծվում է վարժեցված մոդելի կողմից։ Մոդելը նման տարրերը տեղադրում է իրար մոտ այս վեկտորային տարածության մեջ, այնպես որ «reset my password»-ը և «I forgot my login»-ը հայտնվում են իրար մոտ՝ նույնիսկ առանց ընդհանուր բառերի։ Embedding-ները համեմատում եք cosine similarity-ով, dot product-ով կամ Euclidean հեռավորությամբ։ Embedding-ները համեմատելի են միայն այն դեպքում, երբ գալիս են նույն մոդելից և տարբերակից։ Դրանք կամուրջ են չկառուցվածքավորված կոնտենտի և արագ մաթեմատիկական որոնման միջև, և ապահովում են սեմանտիկ որոնում, առաջարկություններ, կլաստերավորում և RAG։
Q2Արդյո՞ք ինձ պետք է առանձին վեկտորային բազա։
Սկզբում հաճախ՝ ոչ։ Եթե արդեն օգտագործում եք PostgreSQL, pgvector-ը աշխատում է միլիոնավոր վեկտորների հետ՝ HNSW ինդեքսներով, SQL ֆիլտրերով, տրանզակցիաներով և ձեր գոյություն ունեցող backup-ներով։ Elasticsearch-ը, OpenSearch-ը և Redis-ը նույնպես աջակցում են vector որոնում։ Առանձին engine, ինչպիսիք են Qdrant-ը, Milvus-ը, Weaviate-ը կամ Pinecone-ը, իմաստ ունի տասնյակ կամ հարյուրավոր միլիոնավոր վեկտորների, ծանր ֆիլտրված որոնման, բարձր concurrency-ի դեպքում խիստ latency-ի կամ այնպիսի ֆունկցիաների դեպքում, ինչպիսիք են առաջադեմ quantization-ը և multi-vector որոնումը։ Գինը ևս մեկ համակարգ է, որը պետք է շահագործել և սինքրոն պահել։ Ես կսկսեի եղածից, կչափեի և կտեղափոխվեի, երբ թվերը դա արդարացնեն։
Q3Ինչպե՞ս է աշխատում HNSW-ն։
HNSW-ն կառուցում է բազմաշերտ գրաֆ, որտեղ յուրաքանչյուր վեկտոր node է՝ կապված իր մոտ հարևանների հետ։ Վերին շերտերը պարունակում են քիչ node-եր երկար կապերով, ինչպես մայրուղիները․ ստորին շերտերը պարունակում են ավելի շատ node-եր կարճ կապերով, ինչպես տեղական փողոցները, իսկ ամենաներքևի շերտը պարունակում է բոլոր վեկտորները։ Որոնումը սկսվում է վերին շերտի entry point-ից, ագահաբար շարժվում դեպի հարցմանը ամենամոտ հարևանը, ապա իջնում մեկ շերտ և կրկնում՝ ավարտվելով ներքևի շերտում տեղական որոնմամբ։ m (կապեր յուրաքանչյուր node-ի համար) և ef_construction պարամետրերը կառավարում են կառուցման որակը և հիշողությունը, իսկ ef_search-ը կառավարում է recall-ն ընդդեմ արագության հարցման ժամանակ։
Q4Ի՞նչ է hybrid որոնումը, և ինչո՞ւ օգտագործել այն։
Hybrid որոնումը համադրում է keyword որոնումը, սովորաբար BM25-ը, vector similarity-ի հետ և միավորում արդյունքները։ Յուրաքանչյուր մեթոդ տարբեր կերպ է ձախողվում․ վեկտորները հասկանում են վերաձևակերպումները, բայց կարող են բաց թողնել ճշգրիտ term-եր, ինչպիսիք են ապրանքների կոդերը կամ անունները, իսկ keyword որոնումը համընկնում է ճշգրիտ token-ների հետ, բայց բաց է թողնում հոմանիշներն ու մտադրությունը։ Երկուսն էլ աշխատեցնելը և reciprocal rank fusion-ով միավորելը գնահատումների մեծ մասում տալիս է ավելի կայուն արդյունքներ, քան յուրաքանչյուրը առանձին։ Շատ engine-ներ աջակցում են դա native կերպով՝ Elasticsearch-ը և OpenSearch-ը, Weaviate-ը, Qdrant-ը sparse վեկտորներով, կամ PostgreSQL-ը՝ full-text-ը և pgvector-ը մեկ հարցման մեջ համադրելով։ Միավորված top արդյունքների վրա reranker-ը ավելի է բարելավում precision-ը։
Q5Ինչպե՞ս եք աշխատում ֆիլտրերի հետ, օրինակ՝ ըստ tenant-ի տվյալների, vector որոնման մեջ։
Ֆիլտրը պետք է լինի որոնման մաս, ոչ թե կիրառվի հետո։ Եթե վերցնում եք top 10 ամենամոտ վեկտորները և ապա հեռացնում այլ tenant-ների արդյունքները, կարող եք մնալ ոչնչով։ Առանձին engine-ները payload ֆիլտրերը կիրառում են գրաֆի traversal-ի ընթացքում և դրա համար ինդեքսավորում են payload դաշտերը։ pgvector-ում օգտագործեք WHERE clause․ 0.8 տարբերակից iterative index scan-ները (hnsw.iterative_scan) շարունակում են որոնել, մինչև բավարար տողեր անցնեն ֆիլտրը, իսկ շատ ընտրողական ֆիլտրերի համար B-tree ինդեքսը կամ յուրաքանչյուր tenant-ի համար partial ինդեքսը կարող է ավելի լավ լինել։ Խիստ մեկուսացման համար տարբերակ են առանձին կոլեկցիաները կամ partition-ները յուրաքանչյուր tenant-ի համար՝ ավելի շատ օբյեկտների գնով։
Q6Ինչպե՞ս ընտրել embedding մոդել։
Սկսեք պահանջներից՝ լեզուներ, կոնտենտի տիպ (կոդ, իրավական, ապրանքային տվյալներ), մուտքի առավելագույն երկարություն, հոսթինգ (API կամ սեփական՝ գաղտնիության համար) և արժեք։ Կազմեք մի քանի մոդելի կարճ ցուցակ՝ օգտագործելով հանրային benchmark-ներ, ինչպիսին MTEB-ն է, ապա գնահատեք ձեր սեփական տվյալների վրա․ հավաքեք 50-ից 200 իրական հարցում այն փաստաթղթերով, որոնք պետք է գտնվեն, և յուրաքանչյուր մոդելի համար չափեք recall at 10 և MRR։ Հաշվի առեք չափողականությունը․ ավելի մեծ վեկտորները կարող են ավելի ճշգրիտ լինել, բայց հիշողություն են արժենում․ շատ ժամանակակից մոդելներ աջակցում են ավելի կարճ կրճատված վեկտորներ (Matryoshka embeddings)՝ որակի փոքր կորստով։ Ինչ էլ ընտրեք, պահեք մոդելի տարբերակը, որպեսզի հետագայում կարողանաք միգրացիա անել։
Սենիոր մակարդակի հարցեր
S1pgvector, թե՞ առանձին վեկտորային բազա 50 միլիոն վեկտորի համար։
pgvector-ով դա հնարավոր է, բայց փոխզիջումները սրվում են։ 1,024 չափողականությամբ 50 միլիոն float վեկտորը մոտ 200 GB raw է․ halfvec-ով կամ binary quantization-ով գումարած rescoring-ով ինդեքսը կարող է տեղավորվել մեծ մեքենայի RAM-ում, և պահպանում եք SQL-ը, տրանզակցիաները և մեկ backup պատմություն։ Բայց HNSW-ի կառուցումը ժամեր է տևում, գրառումների բարձր տեմպը դժվարացնում է սպասարկումը, և PostgreSQL-ը մասշտաբավորվում է ուղղահայաց, այնպես որ հարցումների շատ բարձր concurrency-ն նշանակում է read replica-ներ։ Առանձին engine-ը ավտոմատ shard է անում, ֆիլտրում է traversal-ի ընթացքում payload ինդեքսներով և ունի ներկառուցված quantization ու tiered storage՝ երկրորդ համակարգի և sync pipeline-ի գնով։ Ես երկուսն էլ benchmark կանեի իրական տվյալների վրա՝ իրատեսական ֆիլտրերով և թիրախային p95 latency-ով ու recall-ով, ապա կորոշեի արժեքի և օպերացիոն համապատասխանության հիման վրա։
S2Ինչպե՞ս գնահատել retrieval համակարգը end to end։
Տարանջատեք retrieval-ի որակը generation-ի որակից։ Retrieval-ի համար կազմեք իրական հարցումների պիտակավորված հավաքածու՝ համապատասխան chunk-երով, և յուրաքանչյուր կոնֆիգուրացիայի համար չափեք recall at k, MRR կամ nDCG՝ chunk-ի չափ, embedding մոդել, hybrid կշիռներ, reranker։ Ինդեքսի recall-ը չափեք առանձին՝ ճշգրիտ որոնման դեմ, որպեսզի իմանաք՝ բացթողումները գալիս են ANN ինդեքսից, թե embedding-ներից։ Հետևեք latency-ին p95-ում և p99-ում և մեկ հարցման արժեքին։ Online-ում մոնիտորինգ արեք zero-result rate-ը, click-through-ը կամ պատասխանի ընդունումը և վերանայման համար ընտրեք ձախողումների նմուշներ։ Գնահատման հավաքածուն պահեք version control-ում և աշխատեցրեք այն CI-ում ցանկացած փոփոխության դեպքում, որպեսզի մոդելի կամ chunking-ի փոփոխությունը չկարողանա լուռ վատացնել արդյունքները։
S3Ինչպե՞ս կնախագծեիք multi-tenant vector որոնում՝ խիստ մեկուսացմամբ։
Կա երեք մակարդակ։ Ընդհանուր ինդեքսը tenant ֆիլտրով ամենաարդյունավետն է՝ մեկ HNSW գրաֆ, tenant_id-ն որպես ինդեքսավորված payload կամ WHERE clause, և row-level security-ն որպես երկրորդ պաշտպանություն։ Այն արտահոսքի ռիսկ ունի միայն այն դեպքում, եթե ֆիլտրերը բացակայում են, այնպես որ պարտադրեք դրանք data-access շերտում և թեստավորեք։ Partition արված պահոցը, ինչպիսիք են PostgreSQL partition-ները յուրաքանչյուր մեծ tenant-ի համար կամ Qdrant-ի tenant-aware sharding-ը, յուրաքանչյուր tenant-ի գրաֆը պահում է ավելի փոքր, իսկ ֆիլտրումը՝ ավելի էժան։ Կոլեկցիա կամ բազա յուրաքանչյուր tenant-ի համար տալիս է ամենաուժեղ մեկուսացումը և հեշտ ջնջում, բայց հազարավոր փոքր ինդեքսները հիշողություն են վատնում և բարդացնում շահագործումը։ Տարածված դիզայնն է ընդհանուր պահոց փոքր tenant-ների համար և առանձին partition-ներ կամ կոլեկցիաներ մեծ կամ կարգավորվող tenant-ների համար։
Բառարան
- Embedding
- Կոնտենտի իմաստը ներկայացնող թվերի ցուցակ՝ ստեղծված վարժեցված մոդելի կողմից։
- Cosine similarity
- Նմանություն՝ չափված երկու վեկտորների միջև անկյունով․ 1-ը նշանակում է նույն ուղղություն։
- ANN
- Approximate nearest neighbour որոնում՝ արագ որոնում, որը կարող է բաց թողնել մի քանի իրական հարևանի։
- HNSW
- Շերտավոր գրաֆային ինդեքս ANN որոնման համար՝ գերազանց արագությամբ և recall-ով։
- Recall
- Իրական ամենամոտ հարևանների այն մասը, որը ինդեքսն իրականում վերադարձնում է։
- Quantization
- Վեկտորների պահում ավելի քիչ բիթերով՝ հիշողություն խնայելու համար, սովորաբար ճշգրտության փոքր կորստով։
- Hybrid որոնում
- Keyword և vector որոնման արդյունքների համադրում մեկ դասակարգված ցուցակում։
- Reranker
- Մոդել, որը վերագնահատում է թեկնածուների կարճ ցուցակը՝ կարդալով հարցումը և փաստաթուղթը միասին։
- Chunking
- Փաստաթղթերի բաժանում ավելի փոքր հատվածների, որպեսզի յուրաքանչյուր embedding արտահայտի կենտրոնացված իմաստ։
Շարունակեք սովորել
Պրոդուկտի գաղափար ունե՞ք։Եկեք ստեղծենք այն։
Պատմեք ձեր գաղափարի, պրոդուկտի կամ թիմի մասին։ Սովորաբար պատասխանում եմ մեկ աշխատանքային օրվա ընթացքում։