بنية الذكاء الاصطناعي · البحث المتجهي

ترحيل Embeddings في Qdrant من دون تعطيل البحث

خطة إنتاجية لترحيل نموذج Embeddings جديد: Named Vectors أوBlue/Green، وDual Write وBackfill وتقييم ظل وCutover وRollback.

المسار المرتبطالذكاء الاصطناعي وRAG والبحث المتجهي
رسم تحريري تصوري لنقاط مستندات تنتقل بين فضاءين متجهيين مختلفين عبر مساري Dual Write وBackfill مع مفتاح Cutover مضبوط؛ وليس واجهة Qdrant أوترحيلًا حقيقيًا.
تصوّر بصري للفكرة — يتبعه شرح ومخطط تنفيذي داخل المقال.

تغيير نموذج Embeddings هو ترحيل بيانات، وليس تعديل Configuration. قد يغيّر النموذج الجديد أبعاد Vector وسلوك التشابه وQuery/Document Prompting ونوع البيانات وLatency وجودة الترتيب. يحافظ ترحيل Qdrant الآمن على مسار البحث القديم، ويكتب المحتوى الجديد إلى الوجهتين، وينقل النقاط التاريخية بصورة Idempotent، ويقارن النظامين على Queries ضمن Tenant Scope نفسه، ثم يحول Traffic ذريًا مع نافذة Rollback مختبرة.

توثق Qdrant آليتين صحيحتين: Blue/Green تبني Collection ثانية وتحول Alias، أو—في Qdrant 1.18 وما بعده—ترحيل Named Vector يضيف فضاءً متجهيًا إلى Collection موجودة. يشكل دليل الترحيل الرسمي الأساس الواقعي لهذه القدرات. أما Release Gates والمراقبة وقواعد التعافي أدناه فهي توصيات هندسية على مستوى التطبيق.

لماذا قد يكسر تغيير Embedding الاسترجاع؟

لا تشترك Vectors من نموذجين مختلفين في فضاء ذي معنى لمجرد أن طولها متساوٍ. لا تضمّن Query بالنموذج الجديد وتبحث في Document Vectors قديمة، إلا إذا وثق المزود صراحة Cross-model Compatibility. وحتى داخل عائلة متوافقة، خزّن النموذج الدقيق وOutput Dimension ودور الإدخال وTruncation وNormalization ضمن عقد محدد الإصدار.

الأبعاد جزء من Qdrant Vector Schema. توضح وثائق Collections أن Vectors داخل Named Space واحدة تشترك في Dimension وDistance Metric، بينما يمكن لـNamed Vectors حمل أبعاد ومقاييس مختلفة. لذلك يحتاج الانتقال من 1024 إلى 512 بُعدًا Named Vector جديدة أوCollection جديدة، لا استبدالًا مباشرًا للفضاء القديم.

تؤثر معاملات المزود أيضًا في المعنى. تميز Embeddings API لدى Voyage بين `input_type: document` و`input_type: query`، وتدعم أبعادًا محددة وأنواع Float أوInteger أوBinary في النماذج المؤهلة. تعامل معها كجزء من `embedding_contract_version` لا كخيارات Request عرضية. وقد يغيّر Silent Truncation ما يمثله Chunk؛ سجله وقِسه.

اختر Named Vectors أوBlue/Green Collections

استخدم Named Vectors عندما تستخدم Collection الحالية Named Vectors أصلًا، ويعمل Qdrant 1.18 أوأحدث، وتريد إبقاء Payload وPoint IDs في مكان واحد، وتستطيع تحمل تخزين Vector ثانية لكل Point مؤقتًا. أضف Vector Name جديدة بحجمها وDistance الخاصة، واملأها، ووجّه البحث عبر `using`، ثم احذف الاسم القديم فقط بعد انتهاء نافذة التراجع.

استخدم Blue/Green عندما لا تتأهل Source Collection لمسار Named Vector، أويتغير Schema أوSharding بصورة كبيرة، أوتريد فصلًا ماديًا، أوتحتاج ضبط HNSW وQuantization وStorage بصورة مستقلة قبل Cutover. ابنِ `documents_v2` بينما يستخدم Traffic الـAlias المستقرة، ثم انقل Alias ذريًا من v1 إلى v2.

الفرق تشغيلي. تقلل Named Vectors تكرار Payload وتبسط Per-point Updates، لكن Collection تحمل فهرسين أثناء الترحيل ويصبح Cleanup غير قابل للتراجع عند حذف الاسم القديم. تستهلك Blue/Green Collection ثانية وتتطلب Writes متسقة إلى الاثنين، لكن Rollback مجرد Alias Switch وتبقى Collection القديمة سليمة.

ثبّت عقد Embedding أولًا

قبل Backfill اكتب Migration Manifest تضم Source وTarget Collection أوVector Name، والمزود، والنموذج الدقيق، وOutput Dimension، وData Type، وDistance Metric، ودوري Query وDocument، وChunking Version، وNormalization، وTenant Filter Version، وخوارزمية Text Hash. أعطِ Manifest معرف ترحيل ثابتًا.

{
  "migration_id": "emb-2026-10-v2",
  "source": {"collection": "docs_v1", "vector": "dense_v1"},
  "target": {"collection": "docs_v2", "vector": "dense_v2"},
  "embedding": {
    "model": "approved-model-snapshot",
    "dimension": 1024,
    "document_input_type": "document",
    "query_input_type": "query"
  },
  "chunking_version": "chunk-v4"
}

هذه Application Manifest وليست Response من Qdrant أوVoyage. يمنع تثبيتها Workers من إنتاج Target Vectors غير متوافقة تحت الاسم نفسه. خزّن Model Revision وContract Version مع كل Checkpoint، ولا تضع Secrets أوSource Text داخل Manifest.

قرر هل هذا Embedding Migration فقط. إذا تغيرت Chunk Boundaries أيضًا فقد تتغير Point IDs ودقة النتائج، فتصبح المقارنة الثنائية أصعب. فضّل ترحيل متغير مستقل واحد، أوعامل العمل صراحة كإعادة بناء كاملة لـRetrieval Index مع Relevance Labels خاصة بها.

تصل الكتابات الجديدة إلى نسختي Embedding بينما تنقل Worker قابلة للاستئناف النقاط القديمة؛ تقارن Shadow Queries الاسترجاع قبل تحويل Atomic، ويبقى المسار القديم متاحًا للتراجع.
تصل الكتابات الجديدة إلى نسختي Embedding بينما تنقل Worker قابلة للاستئناف النقاط القديمة؛ تقارن Shadow Queries الاسترجاع قبل تحويل Atomic، ويبقى المسار القديم متاحًا للتراجع. اضغط لعرض أكبر

ابدأ Dual Writes قبل Backfill التاريخي

حدّث Ingestion أولًا كي تصل كل Create وUpdate وDelete إلى Target القديم والجديد. اشتق Point IDs ثابتة من Source Document وهوية Chunk. استخدم Outbox أوDurable Job Record كي لا يترك Timeout من مزود Embeddings الفهرس الجديد متأخرًا دائمًا عن Source of Truth.

في Named Vectors يمكن لـUpsert حمل Vector القديمة والجديدة لنقطة واحدة. وفي Blue/Green نفّذ Upserts قابلة للتكرار من Document Revision نفسها. لا تعتمد على استدعاءين شبكيين Best-effort داخل Request. خزّن Target States المطلوبة وأعد محاولة كل واحدة بصورة مستقلة.

ضع في Payload لكل Point حقول `tenant_id` و`document_id` و`content_revision` و`content_hash` و`chunking_version` و`embedding_contract_version`. حافظ على Tenant Filter نفسها في البحث القديم والجديد والـBackfill والتقييم. النموذج الأفضل لا يعوض Authorization Boundary مفقودة.

يجب أن تسلك Deletes المسار المزدوج نفسه. قد يعيد ترحيل ينسخ النقاط التاريخية لكنه يفوّت Delete محتوى سريًا أوقديمًا عند Cutover. احتفظ بـTombstones أوDelete Revisions حتى تؤكد الوجهتان استلامها.

نفّذ Backfill قابلة للاستئناف ومحدودة المعدل

اقرأ Source Documents من قاعدة البيانات المرجعية إن أمكن، ولا تعامل Stored Vectors كنص قابل للاستعادة. وإذا حملت Qdrant Payload النص المرجعي المعتمد، تدعم Points API الـScrolling وBatch Operations؛ اطلب حقول Payload الضرورية فقط واستبعد Vectors القديمة لتقليل النقل.

قسّم العمل حسب Tenant ونطاقات Point ID ثابتة. تقرأ كل Job Batch محدودة، وتتحقق من Current Document Revision، وتنتج Embedding بالعقد المثبت، وتنفذ Upsert، ثم تخزن Checkpoint. عند Retry تجعل Point ID وContract Version الثابتتان الكتابة Idempotent. أضف Exponential Backoff مع Jitter لـRate Limits، وضع الأعطال الحتمية مثل Source Text غير صالحة في Quarantine.

لا تعلن الاكتمال من `indexed_vectors_count`؛ توثق Qdrant أن عدادات Points وIndexed Vectors الداخلية قد تكون تقريبية أثناء Optimizations. استخدم Exact Count API مع Filter على Target Contract Version، وقارنها بعدد المصادر المؤهلة المرجعي، وخذ عينات من Point IDs بحثًا عن Revisions مفقودة أوقديمة. انتظر استقرار بناء Index والـOptimization قبل قياس Tail Latency.

حدد المعدل وفق Token Limits للمزود وQdrant Write Latency وOptimizer Pressure وCPU وMemory وDisk Headroom. Backfill حمل إنتاجي. الترحيل الذي يحفظ Availability لكنه يستهلك Disk أويرفع p99 Search Latency إلى مستوى غير مقبول ليس Zero-downtime.

قيّم الاسترجاع في الظل لا عدد الصفوف فقط

يثبت الاكتمال وجود Vectors، ولا يثبت أنها تسترجع Evidence مفيدة. ابنِ Evaluation Set ثابتة من Query Shapes حقيقية مع Relevance Judgments وTenant وFilter Context واللغة ونوع المستند وHard Negatives. ضمّن كل Query بعقد Query المطابق لكل Candidate Index.

قارن Recall@k وnDCG@k وMRR وZero-result Rate وصحة Filters وCitation Coverage وقبول الإجابة المؤرضة. وقِس Embedding Latency وQdrant p50/p95/p99 وعدد Candidates وكلفة Payload Hydration والكلفة لكل إجابة مقبولة. اعرض Metrics حسب Cohort؛ فقد يخفي تحسن إجمالي تراجعًا في العربية أوCode أوTables أومجال Tenant بعينها.

شغّل Shadow Queries بصورة Async كي يبقى User Latency مرتبطًا بالمسار القديم. سجّل IDs وScores فقط وفق Data Policy؛ قد يكشف تحليل الصلة Document Identifiers حتى من دون النص. لا تسمح لنتائج الظل بتنفيذ Side Effects أوالوصول للمستخدم.

قد يتغير Score Scale بين النماذج، فلا تنقل Similarity Threshold بصورة عمياء. أعد ضبط Minimum Scores وCandidate Depth وReranker Inputs على التوزيع الجديد. وعندما يتبع Reranker الاسترجاع قيّم Pre-rerank Recall وجودة الترتيب النهائية.

نفّذ Cutover ذريًا وأبقِ Rollback دافئًا

في Blue/Green صُممت Qdrant Collection Aliases لتحويل إصدارات Vector بلا إيقاف Concurrent Requests. أرسل Delete للـAlias القديمة وCreate للجديدة داخل Alias Update واحدة كي يكون الانتقال Atomic. وفي Named Vectors غيّر Versioned Route Configuration واحدة تحتوي Embedding Model واسم `using` معًا؛ تغيير أحدهما فقط يصنع Cross-space Query Bug.

نفّذ Canary قبل Cutover كامل عندما يستطيع التطبيق توجيه Tenant أوRequest Cohort ثابت مباشرة إلى Target. قارن النتائج المرئية وOperational Metrics، ثم انقل Shared Route. سجّل Route Version وCollection أوVector Name الفعلية وEmbedding Contract وIndex Build Revision في كل Trace.

احتفظ بـDual Writes والمسار القديم طوال Observation Window. ارجع عند Critical Relevance Regression أوAuthorization/Filter Mismatch أوTarget Lag أوارتفاع Zero-result Rate أوp99 Latency أوError Rate أوCost per Accepted Answer. يغير Rollback المسار، ولا يجب أن يطلب Backfill جديدة.

تشرح وثائق الاتساق كلفة Availability عند تشديد Write Ordering وRead Consistency في Replicated Clusters. اختر الإعدادات وفق Conflict Model للتطبيق بدل تفعيل أقوى خيار تلقائيًا. يبقى Durable Ingestion Ledger الدليل على استلام الوجهتين لـDocument Revision.

لا تحذف المسار القديم قبل الدليل

أوقف Dual Writes فقط بعد أن يستخدم كل Traffic المسار الجديد، ويصبح Lag صفرًا، وتبقى Evaluation Gate خضراء خلال مدة ممثلة، وتجرب Snapshot أوAuthoritative Re-embedding Path. في Named Vectors يحذف Old Vector Name الـSchema والبيانات؛ ويسميه دليل الترحيل نقطة اللاعودة دون Re-embedding.

في Blue/Green احذف Collection القديمة بعد انتهاء Retention وRollback Policy. تحقق أولًا أن لا Alias أوWorker أوDashboard أوReplay Job تشير إليها. يحرر الحذف الموارد لكنه يزيل أسرع Rollback، فاجعله عملية معتمدة صراحة لاCleanup تلقائية عند نجاح Deployment.

متى لا ترحّل؟

لا ترحّل لأن Public Benchmark واحد رتّب نموذجًا أعلى. إذا كان الاسترجاع الحالي يحقق Product SLO ولم يحسن النموذج الجديد Workload-shaped Evaluations بما يكفي لتبرير Embedding Cost وStorage والمخاطر التشغيلية وLock-in المستقبلي، فاحتفظ بالعقد الحالي.

قد يكون Lexical Search أوSQL أفضل عندما يحتاج المستخدم IDs دقيقة أوTotals أوRanges أوDeterministic Filters. وقد يكون Hybrid Search أفضل عندما تفوّت Dense Embeddings المعرفات والمصطلحات النادرة؛ يظل هذا النمط مطبقًا على Dense Branch بينما تُحدد Sparse Branch بإصدار مستقل. وإذا كانت المشكلة Chunking سيئة أوSource Data ناقصة فلن يصلح تغيير النموذج Evidence Boundary.

قائمة تنفيذ الإنتاج

اختر Migration Shape، وثبّت Embedding Contract كاملة، وفعّل Durable Dual Writes بما فيها Deletes، وشغّل Tenant-scoped Backfill قابلة للاستئناف، وتحقق من Exact Coverage، وانتظر Indexing، وقيّم Retrieval وجودة الإجابة، ونفّذ Canary لحزمة التوجيه كاملة، وحوّل ذريًا، وراقب مع Rollback دافئ، ولا تحذف المسار القديم قبل اعتماد صريح.

الترحيل الأكثر أمانًا ممل عمدًا: لكل انتقال Checkpoint، وكل مقارنة تستخدم Authorization Filters نفسها، ولا Cleanup قبل انتفاء الحاجة إلى التراجع. اربط هذا المسار مع دليل Hybrid Search في Qdrant وخط إنتاج RAG لإبقاء عقود الفهرسة والاسترجاع والتوليد قابلة للاختبار مستقلًا.

المراجع الرسمية

تدعم هذه المراجع سلوك الأدوات المذكورة. الأمثلة وقرارات التصميم توضيحية، ويجب تكييفها مع متطلبات المشروع وإصداراته.

إعداد: Noor Yasser

من القرار إلى التنفيذ

تعمل على تحدٍ تقني مشابه؟

أساعد الفرق على تحويل القرار المعماري إلى نطاق واضح وتنفيذ يمكن تشغيله ومراجعته بثقة.

احجز لقاءً لمدة ٣٠ دقيقةالخدمة المرتبطةتكاملات الذكاء الاصطناعي وأنظمة RAGمشروع من الأعمالمُرشد