Vector Databases

إطلاق قوة pgvector: البحث المتجهي المتقدم في PostgreSQL

على مدى سنوات، فرض نمط "التخزين متعدد اللغات" (Polyglot Persistence) أن أنواع البيانات تتطلب محركات تخزين مختلفة. كانت البيانات المعاملية تعيش في قواعد البيانات العلائقية، بينما ذهبت السجلات غير المهيكلة إلى مخازن المستندات. لكن صعود الذكاء الاصطناعي التوليدي والنماذج اللغوية الكبيرة (LLMs) قدّم نوعًا جديدًا من البيانات يتحدى هذا النموذج: المتجهات. ومع اعتماد التطبيقات بشكل متزايد على البحث الدلالي ومطابقة التشابه، أصبح إدارة المصفوفات عالية الأبعاد أمرًا بالغ الأهمية. هنا يأتي دور pgvector، وهو امتداد قوي لـ PostgreSQL يجلب البحث الأصلي عن تشابه المتجهات إلى قاعدة البيانات العلائقية الأكثر شيوعًا في العالم.

لماذا pgvector؟

غالبًا ما يواجه المطورون معضلة عند تنفيذ البحث المتجهي: هل يقدمون قاعدة بيانات متجهية متخصصة مثل Pinecone أو Weaviate، مما يضيف تعقيدًا تشغيليًا وتكلفة مزامنة البيانات، أم يلتزمون ببنيتهم التحتية الحالية؟ يحل pgvector هذه المشكلة من خلال السماح لك بتخزين المتجهات والبحث عنها مباشرة داخل بياناتك العلائقية.

تشمل المزايا الرئيسية ما يلي:

  • الامتثال لمبدأ ACID: بيانات المتجهات معاملية (Transactional). يمكنك تحديث متجه والتراجع عن التغييرات إذا فشلت الإدراج، وهي ميزة غالبًا ما تكون مفقودة في مخازن المتجهات غير العلائقية (NoSQL).
  • إمكانية الدمج (Join): يمكنك دمج نتائج البحث المتجهي مع منطق الأعمال الآخر (مثل ملفات المستخدمين، والصلاحيات) في استعلام SQL واحد.
  • البساطة التشغيلية: إذا كنت تستخدم بالفعل PostgreSQL، فلا تحتاج إلى الحفاظ على عناقيد (Clusters) منفصلة. تبقى استراتيجيات النسخ الاحتياطي، والمراقبة، والتوسع متسقة.

البدء: تصميم المخطط (Schema)

إعداد pgvector بسيط. أولاً، تأكد من تثبيت الامتداد على مثيل PostgreSQL الخاص بك (يُنصح بالإصدار 13 أو أحدث). ثم، أنشئ الامتداد وحدد جدولك:

CREATE EXTENSION vector;

CREATE TABLE embeddings (
    id BIGSERIAL PRIMARY KEY,
    metadata JSONB,
    embedding VECTOR(384) -- بافتراض متجه ذي 384 بُعدًا
);

لاحظ نوع VECTOR(384). يجب أن يتطابق البعد مع حجم المخرج لنموذج التضمين (Embedding) الخاص بك (على سبيل المثال، ينتج text-embedding-ada-002 من OpenAI متجهات ذات 1536 بُعدًا، بينما تنتج بعض النماذج المحلية 384 بُعدًا). ستؤدي الأبعاد غير المتطابقة إلى حدوث خطأ أثناء الإدراج.

استراتيجيات الفهرسة: HNSW مقابل IVFFlat

المسح بالقوة الغاشمة (Brute-force) قابل للتطبيق للمجموعات الصغيرة (أقل من 10 آلاف صف)، لكن الأداء يتدهور خطيًا مع نمو البيانات. للتوسع، يجب عليك استخدام فهرس. يدعم pgvector خوارزميتين رئيسيتين:

1. IVFFlat (فهرس الملف المعكوس مع التكميم المسطح)

يقوم IVFFlat بتجميع المتجهات في عدد ثابت من القوائم باستخدام k-means. وقت الاستعلام، يبحث فقط في أقرب العناقيد (Probes). إنه فعال من حيث الذاكرة ومناسب جدًا لأحمال العمل التي يهيمن عليها القراءة وللمجموعات الكبيرة.

2. HNSW (العالم الصغير القابل للتنقل الهرمي)

يبني HNSW بنية رسومية من المتجهات. يوفر استرجاعًا أعلى وأوقات استعلام أسرع، لكنه يتطلب ذاكرة عشوائية (RAM) كبيرة بشكل ملحوظ أثناء كل من الفهرسة والاستعلام. لمعظم تطبيقات الذكاء الاصطناعي الحديثة حيث تكون زمن الاستجابة حرجًا، يُعد HNSW الخيار المفضل.

إليك كيفية إنشاء فهرس HNSW:

CREATE INDEX ON embeddings 
USING hnsw (embedding vector_cosine_ops);

ملاحظة: فئة المشغل vector_cosine_ops تحدد مقياس المسافة. يمكنك أيضًا استخدام vector_l2_ops (إقليدي) أو vector_ip_ops (الجداء الداخلي). اختر بناءً على تطبيع مخرج نموذجك.

إجراء البحث الدلالي

بمجرد الفهرسة، يبدو إجراء بحث التشابه مثل استعلام SQL قياسي. افترض أن لديك متجه استعلام للمستخدم: [0.1, 0.5, ...] (384 بُعدًا). يمكنك العثور على أفضل 10 سجلات الأكثر تشابهًا باستخدام مشغل المسافة الجيبية (<=>).

SELECT 
    id, 
    metadata, 
    embedding <=> '[0.1, 0.5, ...]' AS distance
FROM 
    embeddings
ORDER BY 
    distance
LIMIT 10;

يتم ترتيب النتيجة حسب المسافة. بالنسبة للتشابه الجيبي، يعني مسافة 0 متجهات متطابقة، بينما يعني 2 متجهات متعاكسة. يفضل العديد من المطورين إرجاع درجة التشابه بدلاً من ذلك. يمكنك تحقيق ذلك عن طريق تحويل المسافة إلى درجة تشابه:

SELECT 
    id, 
    metadata, 
    1 - (embedding <=> '[0.1, 0.5, ...]') AS similarity
FROM 
    embeddings
ORDER BY 
    embedding <=> '[0.1, 0.5, ...]'
LIMIT 10;

نصائح لضبط الأداء

  • اختر المقياس الصحيح: إذا كانت تضميناتك (Embeddings) مُطبَّعة إلى طول وحدة، فإن التشابه الجيبي والمسافة الإقليدية مكافئان رياضيًا. في هذه الحالة، استخدم L2 (<->) لأنه غالبًا ما يكون أسرع في الحساب. إذا لم تكن مُطبَّعة، التزم بالجيبي (<=>) لدقة دلالية أفضل.
  • اضبط معاملات HNSW: يتحكم معامل m في عدد الاتصالات لكل عقدة (أعلى = أكثر دقة لكن فهرس أكبر). يتحكم معامل ef_search في عدد المرشحين الذين يتم النظر فيهم أثناء البحث (أعلى = أبطأ لكن أكثر دقة). ابدأ بالقيم الافتراضية (m=16) وزد ef_search إذا وجدت أن نسبة الاسترجاع تنخفض عن المستويات المقبولة.
  • التقسيم (Partitioning): للتطبيقات متعددة المستأجرين، فكر في تقسيم جدولك حسب معرّف المستأجر. هذا يضمن أن عمليات البحث المتجهي تمسح فقط الأقسام ذات الصلة، مما يقلل بشكل كبير من استخدام الإدخال/الإخراج والذاكرة.

الخلاصة

نضج pgvector من امتداد متخصص ليصبح حلاً جاهزًا للإنتاج للتطبيقات المدعومة بالذكاء الاصطناعي. إنه يسد الفجوة بين البيانات العلائقية التقليدية والبحث الدلالي الحديث، مما يوفر للمطورين منصة موحدة آمنة وقابلة للتوسع وسهلة الصيانة. في حين أن قواعد البيانات المتجهية المتخصصة قد لا تزال تقدم تحسينات للحالات الحدية للمجموعات الضخمة بمقياس المليارات، يبقى pgvector الخيار الأفضل لمعظم تطبيقات الذكاء الاصطناعي، حيث يوفر التوازن المثالي بين الأداء والمرونة والبساطة التشغيلية.

Share: