نماذج التضمين وقواعد البيانات المتجهة
استراتيجيات الفهرسة
فهارس المتجهات تمكّن البحث السريع عن التشابه عبر ملايين المتجهات. فهم أنواع الفهارس يساعدك على موازنة السرعة والدقة والذاكرة.
لماذا الفهرسة مهمة
بدون فهرس، إيجاد متجهات متشابهة يتطلب المقارنة مع كل متجه:
# القوة الغاشمة: O(n) - يفحص كل متجه
def brute_force_search(query: list[float], vectors: list[list[float]], k: int):
distances = [cosine_distance(query, v) for v in vectors]
return sorted(range(len(distances)), key=lambda i: distances[i])[:k]
# مع 1M متجه: ~1 ثانية لكل استعلام
# مع فهرس: ~10ms لكل استعلام
أنواع الفهارس
| الفهرس | السرعة | الدقة | الذاكرة | الأفضل لـ |
|---|---|---|---|---|
| Flat | بطيء | 100% | عالية | < 10K متجه |
| IVF | سريع | 95-99% | متوسطة | 10K-10M متجه |
| HNSW | الأسرع | 95-99% | عالية | أي نطاق، زمن استجابة منخفض |
| PQ | سريع | 90-95% | منخفضة | ذاكرة محدودة |
فهرس Flat (القوة الغاشمة)
بحث دقيق بدون تقريب:
# Pinecone
index = pc.create_index(
name="exact-search",
dimension=1536,
metric="cosine"
# فهرس Flat افتراضياً لمجموعات البيانات الصغيرة
)
# Chroma
collection = client.create_collection(
name="documents",
metadata={"hnsw:space": "cosine"}
# يستخدم بحث flat للمجموعات الصغيرة
)
استخدم عندما: < 10K متجه أو عندما يُطلب استدعاء 100%.
IVF (فهرس الملف المقلوب)
يجمّع المتجهات، يبحث فقط في المجموعات ذات الصلة:
# pgvector مع IVF
cur.execute("""
CREATE INDEX ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100) -- عدد المجموعات
""")
# أثناء البحث، يفحص فقط مجموعة فرعية من المجموعات
# قوائم أكثر = بحث أسرع، استدعاء أقل
# قوائم أقل = بحث أبطأ، استدعاء أعلى
كيف يعمل:
- يجمّع المتجهات في
listsمجموعات أثناء الفهرسة - في وقت الاستعلام، يجد أقرب مراكز المجموعات
- يبحث فقط في المتجهات في تلك المجموعات
ضبط IVF:
| حجم مجموعة البيانات | القوائم | الفحوصات |
|---|---|---|
| 100K | 100 | 10 |
| 1M | 1000 | 50 |
| 10M | 4000 | 100 |
HNSW (العالم الصغير الهرمي القابل للتنقل)
فهرس قائم على الرسم البياني للبحث فائق السرعة:
# Qdrant
from qdrant_client.models import VectorParams, HnswConfigDiff
client.create_collection(
collection_name="documents",
vectors_config=VectorParams(
size=1536,
distance=Distance.COSINE
),
hnsw_config=HnswConfigDiff(
m=16, # الاتصالات لكل عقدة (أعلى = استدعاء أفضل، ذاكرة أكثر)
ef_construct=100 # جودة البناء (أعلى = فهرس أفضل، بناء أبطأ)
)
)
# ضبط وقت الاستعلام
results = client.search(
collection_name="documents",
query_vector=query_embedding,
limit=5,
search_params={"ef": 128} # أعلى = استدعاء أفضل، بحث أبطأ
)
معلمات HNSW:
| المعلمة | التأثير | القيم النموذجية |
|---|---|---|
m |
اتصال الرسم البياني | 8-64 (16 افتراضي) |
ef_construct |
جودة بناء الفهرس | 64-512 (100 افتراضي) |
ef (استعلام) |
جودة البحث | 50-500 |
التكميم المنتج (PQ)
يضغط المتجهات لكفاءة الذاكرة:
# Milvus مع PQ
from pymilvus import Collection, CollectionSchema, FieldSchema, DataType
schema = CollectionSchema([
FieldSchema("id", DataType.INT64, is_primary=True),
FieldSchema("embedding", DataType.FLOAT_VECTOR, dim=1536)
])
collection = Collection("documents", schema)
# إنشاء فهرس PQ
index_params = {
"index_type": "IVF_PQ",
"metric_type": "IP", # الضرب الداخلي
"params": {
"nlist": 1024, # مجموعات IVF
"m": 64, # عدد المكممات الفرعية
"nbits": 8 # البتات لكل مكمم فرعي
}
}
collection.create_index("embedding", index_params)
توفير الذاكرة: 1536-بُعد float32 (6KB) → PQ مع m=64 (64 بايت) = ~99% تخفيض
المقايضة: دقة استدعاء أقل (90-95%) مقابل توفير ذاكرة هائل.
طرق التكميم
| الطريقة | تخفيض الذاكرة | تأثير الدقة |
|---|---|---|
| SQ (قياسي) | 4x | ضئيل |
| PQ (منتج) | 32-64x | معتدل |
| Binary | 32x | كبير |
# تكميم Qdrant القياسي
client.create_collection(
collection_name="documents",
vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
quantization_config={
"scalar": {
"type": "int8",
"quantile": 0.99,
"always_ram": True
}
}
)
اختيار استراتيجية الفهرسة
البداية
│
▼
< 10K متجه؟
│
├─ نعم → Flat (بحث دقيق)
│
▼
ذاكرة محدودة؟
│
├─ نعم → IVF_PQ أو HNSW + تكميم قياسي
│
▼
تحتاج أقل زمن استجابة؟
│
├─ نعم → HNSW (اضبط m و ef)
│
▼
> 10M متجه مع احتياجات متوازنة؟
│
├─ نعم → IVF_HNSW هجين
│
▼
الافتراضي → HNSW (أفضل مقايضة زمن استجابة/استدعاء)
وقت بناء الفهرس مقابل الاستعلام
| الفهرس | وقت البناء | وقت الاستعلام | الذاكرة |
|---|---|---|---|
| Flat | O(n) | O(n) | 1x |
| IVF | O(n log n) | O(log n) | 1.1x |
| HNSW | O(n log n) | O(log n) | 1.5-2x |
| PQ | O(n) | O(log n) | 0.1x |
نصيحة إنتاج: ابدأ مع افتراضيات HNSW. اضبط المعلمات فقط عندما يكون لديك متطلبات محددة لزمن الاستجابة أو الاستدعاء. التحسين المسبق نادراً ما يكون ضرورياً.
التالي، لنستكشف تصفية البيانات الوصفية للتحكم الدقيق بالاسترجاع. :::