# تشغيل البحث الهجين والإجابات الموثّقة

> فهرسة التوثيق المنشور في Qdrant، وتقييم حركة الظل، والانتقال الآمن، وتشغيل إجابات الذكاء الاصطناعي الموثّقة اختيارياً.

يدعم Nibleaf v0.2 البحث الهجين في المحتوى العربي والإنجليزي والمختلط باستخدام
BM25 والمتجهات الكثيفة، مع فرض نطاق المستأجر والصلاحيات في الخادم. يبقى وضع
نتائج البحث متاحاً من دون نموذج إجابة، وتحتاج الإجابات الموثّقة إلى تفعيل صريح
على مستوى النسخة والموقع.

## حدود المكوّنات

تتولى الحزمة `@nibleaf/search` التجزئة الواعية باللغة والتطبيع والمتجهات المتناثرة
وتحقق الاستشهادات وحماية المطالبة وعقد أحداث التحليلات ذي الإصدار. وتتولى
`@nibleaf/qdrant` المجموعة ذات الإصدار والفهارس والاسم المستعار والعمليات
المفلترة عبر حزمة Qdrant الرسمية لجافاسكربت. يشتق الخادم إلزامياً المشروع والنشر
والإصدار واللغة والخصوصية ومنح الصفحات؛ ولا يستطيع العميل إرسال هذا النطاق.
يستدعي القارئ دوال خادم TanStack Start عبر خطافات TanStack Query، وتصل دالة
الخادم وحدها إلى Hono RPC مع إبقاء سياق الطلب وفحوص الصلاحيات في الخادم.

اسم المجموعة هو
`<QDRANT_COLLECTION_ALIAS>_<QDRANT_COLLECTION_VERSION>_<dimensions>`، بينما
يبقى الاسم المستعار ثابتاً. معرّفات المقاطع حتمية، لذلك تكون إعادة المحاولة
آمنة. تُحسب إحصاءات IDF ضمن المستأجر والصلاحيات نفسها المستخدمة في الاستعلام.

## إعداد المزوّدين

ابدأ من `.env.production.example` واترك `SEARCH_RUNTIME=shadow` أثناء الفهرسة
والتقييم. اضبط `OPENROUTER_API_KEY` وثبّت `SEARCH_EMBEDDING_MODEL`؛ تستخدم
التضمينات حزمة OpenRouter الرسمية لـ TypeScript، والنموذج الافتراضي هو
`openai/text-embedding-3-small`. يجب أن تساوي الأبعاد `QDRANT_VECTOR_SIZE`،
ويتطلب تغيير النموذج أو الأبعاد أو نص إدخال التضمين إصدار مجموعة جديداً.

أضف ملف بحث v0.2 إلى كل أمر Compose في بيئة الإنتاج المحمولة:

```bash
docker compose -f docker-compose.prod.yml -f docker-compose.search.yml up -d
```

يبقى الملف منفصلاً حتى لا تتغير أصول الاستضافة الذاتية الموقعة للإصدار v0.1.2.
ويتضمن إعداد Coolify وبيئة التطوير Qdrant مباشرة.

للإجابات، فعّل `SEARCH_ANSWER_ENABLED` وثبّت `SEARCH_ANSWER_MODEL`. تستخدم
الإجابات بيانات اعتماد OpenRouter نفسها عبر حزمة TypeScript الرسمية من
OpenRouter والمخرجات البنيوية الأصلية.
بعدها يفعّل المسؤول **Grounded AI answers** لكل موقع مقصود. الحصة اليومية ذرية
لكل مشروع في Redis، ويوجد حد منفصل لكل عنوان IP ومهلة وإلغاء للطلب. عند تعطل
Redis يفشل فحص الحصة بصورة مغلقة وآمنة.

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

## الفهرسة والتقييم

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

شغّل الاختبارات والتقييم القابل للتكرار:

```bash
pnpm --filter @nibleaf/search test
pnpm --filter @nibleaf/search eval:rag
```

يقرأ التقييم حالات عربية وإنجليزية ومختلطة من
`packages/search/eval/rag-answer-fixtures.json`، ويتحقق من معرّفات النماذج عبر
دليل OpenRouter الحي، ويسجل جودة الاستشهاد والتأسيس وعدم الإجابة واللغة والمهلة
والرموز والتكلفة التي يبلغ عنها المزوّد. لا يحوّل البيانات المفقودة إلى أصفار.

## الانتقال والتراجع

1. ارفع `QDRANT_COLLECTION_VERSION` عند تغيير المخطط أو التجزئة أو النموذج أو الأبعاد.
2. املأ المجموعة الجديدة وتحقق من الأعداد ضمن كل مشروع ونشر وإصدار ولغة وصلاحية.
3. اختبر حالات الرفض للمواقع العامة والخاصة والقارئ محدود الصفحات بالعربية والإنجليزية.
4. بدّل الاسم المستعار صراحة بعد تأكيد اسمي المجموعتين. مثلاً بعد ضبط
   `QDRANT_COLLECTION_VERSION=v2` وأبعاد 1536:

   ```bash
   QDRANT_PREVIOUS_COLLECTION=nibleaf_search_active_v1_1536 \
   QDRANT_SWITCH_TO=nibleaf_search_active_v2_1536 \
   pnpm --filter @nibleaf/qdrant alias:switch
   ```

   ثم اضبط `SEARCH_RUNTIME=hybrid` وراقب الأخطاء والمهلة وجودة الإجابات.
5. احتفظ بالمجموعة السابقة إلى نهاية فترة المراقبة.

للتراجع الفوري اضبط `SEARCH_RUNTIME=legacy`. وللتراجع عن ترحيل المجموعة، أعد
الاسم المستعار إلى المجموعة السابقة مع نموذج التضمين وأبعاده المطابقة. يؤدي
تعطيل `SEARCH_ANSWER_ENABLED` إلى إزالة الإجابات فقط ولا يوقف نتائج البحث.

## إعدادات المشروع والتشخيص الآمن للخصوصية

يمكن لمسؤول المشروع ضبط **1–50 نتيجة** لكل بحث (الافتراضي **12**) وإظهار مرشحي
اللغة والإصدار أو إخفائهما بصورة مستقلة (كلاهما مفعّل افتراضياً). الإجابات
الموثّقة معطّلة افتراضياً والاختصار الافتراضي `⌘K`. يعود النص النائب الفارغ إلى
نسخة Paraglide المترجمة للغة القارئ النشطة؛ ويعود تخصيص اللغة أولاً إلى قيمة
المشروع ثم إلى النسخة المترجمة.

يحدّث الحفظ `Project.config.search` فقط عبر مقارنة وتبديل مقيد بالمؤسسة، ويحافظ
على أقسام الإعداد المتزامنة. يبطل الحفظ النسخة المحلية فوراً وتتقارب بقية نسخ
API خلال مهلة 15 ثانية الموثقة. حذف المفاتيح يعيد القيم الافتراضية.

يفحص العضو المخول المراجعة الجاهزة الحالية فقط. يستخدم التشخيص أعداداً وواجهات
facets دقيقة ومقيدة بالمشروع والنشر وصفحة بيانات وصفية محدودة، ولا يمسح المجموعة
كاملة. تعرض النتيجة المعرفات المنطقية والأعداد والتوزيع والرموز الثابتة وعينة
محدودة من معرف الصفحة والترتيب واللغة والإصدار والحالة. لا تعرض المحتوى أو
العنوان أو المسار أو البصمة أو المتجه أو السر أو اسم المجموعة أو حمولة المزوّد.
غياب المزوّد يعني غير متاح وأعداداً غير معروفة. مؤشرات الصفحات موقعة ومقيدة
بالمستأجر والمراجعة.

جدول `SearchIndexRun` إضافي ومصغّر. يفرض فهرس فريد تشغيلًا نشطًا واحدًا للمشروع،
وتستخدم العمال مطالبات متجددة أطول من مهلة أي مزوّد، وتستعيد التشغيل نفسه بعد
التعطل، وتعيد الحالة النهائية بصورة حتمية، ولا تستعيد إلا مطالبة منتهية. لا تعاد
تضمينات المقاطع غير المتغيرة.

يمكن لتراجع التطبيق ترك الجدول. لتراجع المخطط، أوقف API والعمال ثم نفّذ
`packages/database/prisma/migrations/20260823180000_search_configuration_diagnostics/rollback.sql`؛
يحذف سجل التشخيص ولا يغيّر بيانات Qdrant.

## حذف البيانات

يرسل حذف المشروع عملية حذف مفلترة بالمشروع عبر كل المجموعات المحتفظ بها تحت
بادئة الاسم المستعار المضبوط، ويستخدم `delete-deployment` المسح نفسه لتنظيف نشر
بعينه. تحقق من أن العدد الدقيق للمشروع أصبح صفراً قبل تطبيق سياسة الاحتفاظ
بالنسخ الاحتياطية، ولا تحذف مجموعة يخدمها الاسم المستعار.
