المكتبة المعرفية
المكتبة المعرفية
Section titled “المكتبة المعرفية”المكتبة المعرفية (Knowledge Library) هي مجموعة مُسمّاة ومُدارة من الوثائق المستوعَبة — مثل توثيق Meta WhatsApp Cloud API. تشير كاظمه إلى جذر التوثيق مرة واحدة؛ تزحف الشجرة، تُقسّمها حسب العناوين، تُضمّنها وتفهرسها. بعدها يستدل الوكيل على المحتوى ويذكر المصادر عند الإجابة.
جولة المشغّل (إعادة الفهرسة، الحقن، مفاتيح الإعدادات): الميزات الحديثة.
هذا RAG (توليد معزّز بالاسترجاع) على مجموعة مُنسّقة وقابلة للتحديث — وليس كشطًا حيًا للويب، ولا ضبطًا دقيقًا للنموذج. يصل نص المكتبة إلى الدور بيانات مسيّجة غير موثوقة؛ ولا يُكتب أبدًا في ذاكرة الدردشة.
الاسم العربي للمنتج: Kazma / كاظمه (أو كاظمة). لا تُستخدم كازما.
متى تستخدمها
Section titled “متى تستخدمها”| الهدف | ما تفعله |
|---|---|
| أن يعرف الوكيل واجهة API / مجموعة وثائق بعمق | استيعاب مرة، ثم اسأل — يذكر رابط المصدر + القسم |
| إجابات موثوقة بمصادر | كل نتيجة knowledge_search تحمل رابط مصدرها وقسمها |
| تحديث عند تغيّر الوثائق | حدّث المكتبة؛ تُتخطّى الصفحات غير المتغيّرة |
| الوصول من عدة أماكن | المكتبة نفسها تعمل من صفحة الويب، وTelegram وDiscord وSlack (/kb)، وأدوات الوكيل |
تعمل المكتبة المعرفية على تثبيت بمشغّل واحد. المكتبات والمقاطع ومهام الزحف غير مفصولة لكل مستخدم، لذا يرفض التثبيت الذي فيه مستخدمو منصة (أو KAZMA_MULTI_USER) كل واجهات المعرفة — تجيب واجهة Web API بـ 409 kb_single_operator، وتعرض الصفحة شريط تنبيه، ويردّ /kb وأدوات الوكيل بالسبب — إلى أن تُبنى مكتبات لكل مستخدم.
إن أردت أن يبحث الوكيل في الويب الحي لكل سؤال، انظر البحث على الويب — ميزة مختلفة (نتائج مؤقتة، بلا فهرس ثابت).
جسر ذكاء المستندات ← المكتبة
Section titled “جسر ذكاء المستندات ← المكتبة”يمكنك أيضًا نشر مستند محلي مُعالَج (رفع / document_import) في مكتبة معرفية بعد وصوله إلى حالة ready:
| المسار | الكيفية |
|---|---|
| الويب | صفحة المستندات ← اختر مكتبة ← إضافة إلى المكتبة؛ تعرض الصفحة المكتبات التي ينتمي إليها المستند، ولكل منها زر إزالة (POST /api/documents/{document_id}/unindex) |
| API | POST /api/documents/{document_id}/index مع معرّف المكتبة |
| الوكيل | أداة document_index(document_id, library_id) |
| البحث | document_search / POST /api/documents/search — النتائج مسيّجة كبيانات غير موثوقة |
الفهرسة التلقائية بعد التحليل متوقفة افتراضيًا (فهرسة صريحة فقط). استيعاب المكتبات القائم على الزحف (هذه الصفحة) وفهرسة منصة المستندات يتشاركان معرّفات المكتبات لكنهما مسارا استيعاب مختلفان. حذف مستند يُخرجه أولًا من كل مكتبة تحويه؛ والمكتبة التي يتعذّر عليه مغادرتها توقف الحذف، كي تتمكّن إعادة المحاولة من إكماله. يسجّل مخزن المستندات ما فهرسه وأين: بعد الاستعادة، يعيد كل بدء لعامل نشرَ كل إصدار يسجّله المخزن مفهرسًا لكن مكتبته لم تعد تحويه، ويُبلغ عن مكتبة أو بيان (manifest) مفقود بدل أن يختلق واحدًا (scripts/document_pg_backup.py index يُجري الفحص نفسه يدويًا). المستند الذي يسجّله المخزن محذوفًا وما زالت مكتبة مستعادة تحويه يُخرَج من المكتبة عند ذلك الفحص، مع WARNING وتنبيه التشغيل documents.index_drift. وحذف مكتبة يُبلغ منصة المستندات أيضًا: كل مستند تحويه تُلغى فهرسته منها أولًا. انظر ذكاء المستندات.
كيف يعمل الاستيعاب
Section titled “كيف يعمل الاستيعاب”عند إعطاء كاظمه رابط بذرة (مثل https://developers.facebook.com/docs/whatsapp/cloud-api):
- القبول. يجب أن تكون البذرة رابط http أو https (لا يُخزَّن أبدًا
javascript:أوdata:أو أي مخطط آخر)، وأن يكون مخزن المكتبات دون حصته، وألا يكون زحف آخر للمكتبة نفسها جاريًا. تُرفض بذرة الزحف الواقعة على شبكة خاصة قبل إنشاء أي شيء: فحص العنوان الذي يُجريه الجلب على كل صفحة (كل عنوان يُحَلّ إليه المضيف) يُجرى على البذرة عند القبول، ويُرفض العنوان الخاص أو loopback أو link-local بوصفهsecurity_blocked، والاسم الذي لا يُحَلّ إلى شيء بوصفهconnect_error(تستحق إعادة المحاولة). الزحف المرفوض لا يُنشئ شيئًا: لا تُنشأ مكتبة إلا بعد جلب صفحتها الأولى (صفحة واحدة) أو قبول زحفها. - الاكتشاف (sitemap أولًا). تقرأ كاظمه
robots.txtبحثًا عن توجيهاتSitemap:، ثم تجرّب/sitemap.xmlو/sitemap_index.xmlو/docs/sitemap.xml. تُفلتر الروابط الناتجة إلى نطاق البذرة، فيبقى الزحف داخل شجرة التوثيق. الاحتياطي: سير للروابط بالعرض أولًا (breadth-first) على الصفحة المصيَّرة. - الجلب. تمر كل صفحة عبر سلّم الجلب المشترك. الجلب افتراضيًا محلي فقط: HTTP أولًا، ثم Chromium المحلي للصفحات التي تحتاج JavaScript. لا تُستخدم القارئات المستضافة (Firecrawl، Jina) إلا حين يسمح المشغّل بالجلب البعيد (انظر البحث على الويب). تحصل الصفحات ذات التبويبات على مرور DOM كامل يقرأ اللوحات المخفية أيضًا. الصفحة التي تعيد التوجيه تُخزَّن مرة واحدة، تحت العنوان الذي قُدِّمت منه.
- التقسيم. يُقسَّم Markdown عند عناوين
#/##/###/####مع مسار قسم ("Messages > Send Text Message"). كتل الكود المسيّجة ذرّية — لا تُقسَّم أبدًا. معرّف المقطع يسمّي موضعه في الصفحة، فالصفحة التي تكرّر قسمًا تحتفظ بكل نسخة منه. - النشر. تُنشر الصفحة في معاملة واحدة: تذهب مقاطعها وصفوف فهرس الكلمات المفتاحية القديمة وتصل الجديدة معًا، فيرى البحث الصفحة القديمة أو الجديدة، لا خليطًا منهما أبدًا. الصفحة التي تتعذّر كتابتها تُحسب فاشلة وينتهي الزحف جزئيًا، لا «مكتملًا» أبدًا.
- التضمين. بعد تثبيت الصفحة، تُضمَّن مقاطعها (محليًا
BAAI/bge-m3افتراضيًا، أو أي/embeddingsمتوافق مع OpenAI) في مجموعة المتجهات الخاصة بالمكتبة. المقطع الذي فات مخزنَ المتجهات يضمّنه مرور الصيانة.
حدود الاكتشاف/الجلب: KAZMA_KB_MAX_PAGES (افتراضي 200، سقف صارم 1000)، KAZMA_KB_MAX_DEPTH (افتراضي 10)، KAZMA_KB_DELAY_MS (افتراضي 300)، KAZMA_KB_SCOPE_MODE (tree | prefix | domain | exact، الافتراضي tree).
إعادة الفهرسة والتحديث
Section titled “إعادة الفهرسة والتحديث”| الحالة | السلوك |
|---|---|
| صفحة غير متغيّرة (المقاطع نفسها بالترتيب نفسه) | تُتخطّى: لا يُكتب شيء، وتُحسب غير متغيّرة |
| صفحة متغيّرة أو تقلّصت | تُستبدل في معاملة واحدة (القديمة أو الجديدة، لا خليط أبدًا) |
| رابط غائب عن اكتشاف لاحق | يُحتفظ به. الاكتشاف قليل النتائج أو المحدود بسقف أو الفاشل لا يحذف أبدًا صفحات مفهرسة |
| صفحة تفشل | تُحسب فاشلة؛ وينتهي الزحف جزئيًا ويقول ذلك |
أداة الوكيل knowledge_ingest_site محدودة بسقف أدنى (افتراضيًا 5، وبحد أقصى 15 صفحة) من زحف الويب — استخدم /knowledge أو /kb crawl للأشجار الكبيرة.
مهام الزحف
Section titled “مهام الزحف”كل زحف لموقع وكل تحديث مهمةٌ في سجل الزحف (web_acquire.crawl_jobs)، المصدر الوحيد لحالة الزحف: صفحة الويب و/kb status وkazma acquisition status جميعها تقرؤه.
- صف واحد لكل مهمة. تحديث الصفحة يكتب مهمته وحدها، فلا يجعل زحفٌ كبير منتهٍ الزحفَ التالي يفشل بخطأ “journal is busy”. كل مهمة محدودة (4 MiB) وكذلك السجل كله (16 MiB، وبحد أقصى 24 مهمة، وبحد أقصى 4 جارية). تُطرد المهام المنتهية الأقدم أولًا، بالعدد وبالبايتات، فيبقى للزحف الجديد متسع دائمًا؛ ولا تُطرد مهمة جارية أبدًا. يزيل
kazma acquisition purge-finishedالمهام المنتهية لهذا التثبيت يدويًا. - زحف واحد لكل مكتبة. يُرفض زحف ثانٍ لمكتبة يجري زحفها (
library_busy)؛ ويُرفض كذلك حذف مكتبة أثناء زحفها (crawl_owns_library). - المالكون يُثبَتون ولا يُخمَّنون. تسمّي المهمة الجارية تثبيتها ومضيفها وعمليتها وعقد إيجار يجدّده الزحف (5 دقائق). بعد إعادة التشغيل، تُوسم المهمة التي اختفت عمليتها على هذا المضيف بأنها منقطعة؛ ولا يُستولى على مهمة يملكها مضيف آخر إلا بعد انقضاء عقد إيجارها، وتُرفض الكتابة التالية للمالك القديم. المهام خاصة بهذا التثبيت (
crawl_journal_scope: this_installفيkazma acquisition status): المكتبة المعرفية أحادية التثبيت. - الاستئناف صريح. تُستأنف المهمة المنقطعة من الصفحة، عبر
POST /api/kb/jobs/{job_id}/resume(مسار الاستئناف الوحيد). الصفحات التي كانت نتيجتها غير مؤكدة تُجلب مجددًا؛ والصفحات المكتملة لا تُجلب.
الاسترجاع + الحقن (مكدّس هجين واحد)
Section titled “الاسترجاع + الحقن (مكدّس هجين واحد)”الدردشة لا تدمج المكتبة المعرفية في مخطط الذاكرة. مسار المنتج:
- مرشّحون هجينون — بحث متجهي لكل مكتبة + FTS5 BM25 (
KnowledgeIndex.search_all_sync)؛ يُضمَّن السؤال مرة واحدة، والمقطع الذي وُجد بكلماته وحدها يُقاس بمتجهه المخزَّن أيضًا. - الصلة — لا يعرض البحث إلا ما يخص السؤال. يُحكم على كل مرشّح بالدليل، وهي القاعدة التي يستخدمها استرجاع ذاكرة الدردشة: تشابهه في المعنى فوق خلفية السؤال (ما تبلغه المقاطع غير ذات الصلة له) مضافًا إليه حصة كلمات السؤال التي يحويها، مع طيّ العربية. تحت حدٍّ أدنى لا يُعرض شيء، وتُسقَط النتيجة المتأخرة كثيرًا عن الأفضل؛ وحين لا يوجد متجه يُحكم به، يجب أن يحوي المقطع نصف كلمات السؤال على الأقل. تأتي النتائج الأفضل أولًا بحسب ذلك الدليل، وتُعرض النتيجة الضعيفة بوصفها «ربما ذات صلة». ثمة استثناء واحد: حين يسمّي السؤال شيئًا لا يحويه إلا مقطع واحد (خدمة، أو رمز، أو إصدار) ويحوي ذلك المقطع كل كلمات السؤال، يأتي أولًا، بدليل أفضل نتيجة مُبقاة. فالبحث بالمعنى ضعيف في الأسماء الدقيقة: سأل اختبار الإجهاد (soak) للمعرفة «Which port does zqfmbfjvdv listen on?» مكتبةً تحوي خمسة أسطر متشابهة، فجاءت الإجابة سادسةً. وهذا يغيّر ترتيب ما يُعرض، لا ما يُعرض أبدًا. الأداة و
/kb searchواختبار البحث في الصفحة والحقن التلقائي كلها تستخدمها؛ أما البحث المقيّد بمستند واحد فلا. انظر جودة الاسترجاع لما تقيسه. - البحث الفيدرالي — يعيد
POST /api/memory/v2/federated-searchنتائج الذاكرة ونتائج المعرفة جنبًا إلى جنب. يحتفظ كل مخزن بترتيبه وميزانيته الخاصين (limit_memory،limit_kb)؛ ويقرّرinclude_memory/include_knowledgeهل يُبحث في المخزن أصلًا. - حقن واحد لكل دور — يبني المشرف كتلة المعرفة للدور، مرة واحدة، عند أول استدعاء للنموذج في الدور (
agent/graph_supervisor.py). لم تعد وسائل نقل الدردشة (الويب، الصوت، تطبيقات الدردشة) تحقن نسختها الخاصة. - التسييج — ما كتبته الصفحات يمر عبر
format_untrusted_block(..., source="knowledge"): الصفحة التي تكتب وسم سياج يُحجب وسمها. أسطر كاظمه الخاصة — عدد المقاطع، وأي مكتبة، والتعليمة بالاستشهاد بها — تأتي بعد السياج، خارجه. - سجل الدور — يسرد صف الذاكرة المستخدمة (Memory used) في الدور المقاطعَ التي حُقنت بالضبط.
- مفاتيح الإيقاف —
KAZMA_KB_AUTO_INJECT=0، وmemory.v2.merge_knowledge_into_chat(الإعدادات ← الذاكرة).
الحقن التلقائي يشمل فقط المكتبات غير المؤرشفة التي فُعّل مفتاحها.
البحث الذكي (اختياري): عيّن KAZMA_KB_SMART_SEARCH=1 (أو ConfigStore knowledge.smart_search=true) لاسترجاع المكتبات النشطة ذات المقاطع أيضًا عندما تبدو رسالة المستخدم تقنية (API/توثيق/كيفية)، حتى لو كان الحقن التلقائي لكل مكتبة متوقفًا.
الاستخدام
Section titled “الاستخدام”من واجهة الويب
Section titled “من واجهة الويب”افتح /knowledge → «إضافة مكتبة» → معرّف (مثل shipx_whatsapp_api) واسم ورابط البذرة → اختر:
- استيعاب صفحة واحدة — رابط واحد، الآن. يقول الرد هل خُزّنت الصفحة، أم كانت غير متغيّرة، أم رُفضت، ولماذا.
- زحف شجرة التوثيق كاملة — مهمة خلفية؛ راقب التقدّم الحي (اكتشاف / جلب / استيعاب / فشل). الزحف الذي فيه صفحات فاشلة ينتهي بحالة انتهى مع إخفاقات (Finished with failures)، لا «تم» (Done) أبدًا.
لكل مكتبة يمكنك: اختبار بحث (جرّب استعلامًا داخل الصفحة)، تحديث (إعادة زحف من البذرة)، استعراض المقاطع، أرشفة، حذف. يُعرض الرفض بلغة الصفحة انطلاقًا من رمزه الثابت (knowledge.err.<code>).
من المحادثة (Telegram / Discord / Slack)
Section titled “من المحادثة (Telegram / Discord / Slack)”تجيب البوابة عن /kb بنفسها، دون استدعاء للنموذج. الأوامر التي تغيّر مكتبة مخصّصة لمشرفي البوابة فقط.
| الأمر | للمشرفين فقط | الوظيفة |
|---|---|---|
/kb | لا | قائمة المكتبات + مساعدة |
/kb add <id> <url> | نعم | استيعاب صفحة واحدة الآن؛ يردّ بما خُزّن |
/kb crawl <id> <url> [N] | نعم | زحف شجرة التوثيق في الخلفية؛ يردّ بنتيجة سجل الزحف حين ينتهي |
/kb refresh <id> | نعم | إعادة زحف مكتبة من رابط بذرتها |
/kb search <id> <query> | لا | بحث مباشر (بلا استدعاء للنموذج) |
/kb status <id> | لا | آخر زحف للمكتبة، من سجل الزحف |
/kb delete <id> | نعم | حذف مكتبة وكل ما اشتُق منها |
مثال:
/kb crawl shipx_whatsapp_api https://developers.facebook.com/docs/whatsapp/cloud-api/kb status shipx_whatsapp_apiثم اسأل بشكل طبيعي. يقرّر الوكيل متى يستشير المكتبة عبر أداة knowledge_search. تقرأ الأداة 20 نتيجة كحد أقصى في كل استدعاء.
الحقن التلقائي (سلوك «يعرف مباشرة»)
Section titled “الحقن التلقائي (سلوك «يعرف مباشرة»)”افتراضيًا يستدعي الوكيل knowledge_search عندما يرى أن السؤال يحتاج سياق المكتبة. إن فضّلت طيّ المقاطع ذات الصلة في كل دور تلقائيًا، فعّل الحقن التلقائي على المكتبة (مربع اختيار في صفحة الويب، أو PATCH /api/kb/libraries/{id}).
عند تفعيل الحقن التلقائي تُسترجع المقاطع التي تخص آخر رسالة للمستخدم (أعلى k كحد أقصى، ولا شيء حين لا يوجد في المكتبات ما يخصها) وتُضاف إلى الدور — مسيّجة كبيانات غير موثوقة (<kazma:data source="knowledge" untrusted="true">)، حتى لا تهرّب صفحة توثيق خبيثة تعليمات. المشرف هو الموضع الوحيد الذي يبني هذه الكتلة، مرة لكل دور؛ والدور المُعاد بناؤه من تاريخ المحادثة يُسقط كتلة الدور السابق أولًا.
مفتاح الإيقاف: KAZMA_KB_AUTO_INJECT=0 يعطّل النظام الفرعي كله وقت التشغيل (يُفحص حيًا، لكل دور). ويبقى الاشتراك لكل مكتبة مطلوبًا ومفتاح الإيقاف مفعّل، فالسلوك قائم على الاشتراك الصريح حصرًا.
قابل للضبط: KAZMA_KB_AUTO_INJECT_TOP_K (افتراضي 3، أقصى 10) يتحكم في عدد المقاطع لكل دور.
تذييل الاقتباس
Section titled “تذييل الاقتباس”كل إجابة مبنية على بيانات المكتبة المعرفية تحمل تذييلًا ظاهرًا كي تعرف من أين جاءت المعلومة:
📚 This data is from Knowledge “shipx_whatsapp_api”.
ينطبق هذا على مسار أداة knowledge_search (الصريح) ومسار الحقن التلقائي (الضمني). يسمّي التذييل المكتبة المحددة (أو المكتبات، إن امتد البحث عبر عدة مكتبات). وهو توجيه على مستوى الموجّه: يُطلب من النموذج إلحاقه حرفيًا. في مخرجات الأداة تقع أسطر كاظمه الخاصة (رقم النتيجة، والدرجة، والمكتبة، والتذييل) خارج السياج، وما كتبته الصفحة (رابطها، وعنوانها، وقسمها، ونصها) داخله. وكتلة الحقن التلقائي كذلك: نص الصفحات داخل السياج، والتذييل والتعليمة بالاستشهاد بها بعد السياج (فلو كانا داخله لأخبر السياجُ النموذجَ ألا يطيع شيئًا منهما).
الأرشفة والحذف
Section titled “الأرشفة والحذف”يمكن أرشفة المكتبات — إخفاؤها دون حذف مقاطعها.
- المكتبة المؤرشفة تغادر القائمة النشطة والحقن التلقائي وكل بحث عبر المكتبات. أما البحث الصريح بمعرّفها (
libraryفي الأداة، و/kb search، واختبار البحث في الصفحة) فما زال يقرؤها. - الاستعادة تعيدها؛ الأرشفة قابلة للعكس.
الحذف دائم ويمر عبر مسار واحد لكل الواجهات (kazma-core/kazma_core/stores/knowledge_lifecycle.py): يُرفض أثناء جريان زحف للمكتبة، ويلغي فهرسة كل مستند تحويه المكتبة عبر منصة المستندات (ويُرفض ما دام إبلاغ تلك المنصة متعذرًا)، ثم يزيل متجهات المكتبة، ومقاطعها وصفوف فهرس الكلمات المفتاحية (على دفعات محدودة)، والصفحات المجلوبة المحفوظة معها (<data dir>/knowledge_provenance/<library>). ثم تغادر كلماتها ملفاتِ فهرس الكلمات المفتاحية أيضًا (انظر التخزين)، ويغادر مجلد متجهاتها القرص (انظر متجهات المعنى). لم يحمل كتالوج المتجهات نصها قط؛ والنص الذي خزّنه إصدار أقدم هناك يغادر الملف عند مرور الصيانة التالي.
التخزين
Section titled “التخزين”للمكتبة المعرفية ملف قاعدة بيانات خاص بها، knowledge.db في مجلد البيانات، مُعلَن في سجل المخازن: تحمله النسخ الاحتياطية وkazma migrate. التثبيت الذي كان يحفظ مكتباته في settings.db تُنقل مكتباته إلى knowledge.db عند أول فتح، عبر مخطط المخزن نفسه، وتُحذف الجداول القديمة؛ وحزمة الترحيل المكتوبة قبل النقل تُجهَّز بالطريقة نفسها عند الاستيراد.
- الحصة. صفحات المخزن نفسه محدودة بـ 1 GiB. عند بلوغ الحصة يُرفض أي استيعاب أو زحف جديد قبل جلب أي شيء (
kb_storage_full، HTTP 507)؛ وتستمر القراءة في العمل. تحسب الحصة الصفحات المستخدمة، فحذف مكتبة يفسح المجال لاستيعاب جديد فورًا؛ ويعيد مرور الصيانة المساحة المحرّرة إلى نظام الملفات متى صار 64 MiB على الأقل، أو خُمس الملف، حرًا (PRAGMA incremental_vacuum؛ لاVACUUMأبدًا، فهو يعيد ترقيم الصفوف التي يقوم عليها مفتاح فهرس الكلمات المفتاحية). - فهرس الكلمات المفتاحية. مفتاح فهرس FTS5 هو معرّف الصف، فكتابة مقطع أو حذفه تكلّف الشيء نفسه أيًّا كان حجم الفهرس. يتحقق مرور الصيانة من مطابقته للمقاطع ويعيد بناءه حين لا يطابق، مع WARNING. تحمل قواعد طيّ العربية رقم إصدار يُخزَّن مع الفهرس (يفشل اختبار حين تتغيّر القواعد ولا يتغيّر الرقم)؛ والرقم الجديد يجعل الفتح التالي يعيد بناء الفهرس. يُبلَّغ عن الفهرس المعطوب في صحة كل مكتبة (
keyword_index_ok) وعند مستوى WARNING؛ والاستعلام الذي يتعذّر على الفهرس تحليله لا يعيد نتائج، بهدوء. يسجّل FTS5 الصف المحذوف بعلامة حذف ويحتفظ بكلمات الصف في شرائحه (segments) الأقدم إلى أن يصلها دمج: غير قابلة للبحث، لكنها على القرص. لذلك يُدمج الفهرس بعد حذف مكتبة في شريحة واحدة (KnowledgeStore.purge_search_index، بخطوات من 1,000 صفحة، كل منها معاملتها الخاصة مع تحرير قفل المخزن بينها)، فلا يبقى في الملف شيء من كلمات المكتبة. والدمج وحده لا يكفي: لا يُسقط FTS5 كلمات صف محذوف إلا حين يكتب الدمجُ أقدمَ شريحة في الفهرس، وهو يحكم على ذلك بموضع الشريحة، وحين تقع كل الشرائح على مستوى واحد تحت القمة يدمجها مستوى واحدًا إلى أعلى ويحتفظ بالكلمات. لذا يفحص التطهير الشكل الذي تركه الدمج — شريحة واحدة على المستوى الأخير — وإلا يعيد بناء الفهرس من صفوفه نفسها في معاملة واحدة. كل دفعة من الحذف تسجّل التطهير المستحق عليها في المعاملة نفسها، لذا فالعملية التي تتوقف قبل انتهاء التطهير تتركه للفتح التالي للمخزن أو لمرور الصيانة التالي، اللذين يُتمّانه. ويستخدم «النسيان» (Forget) في الذاكرة وضغطُ كتالوج المتجهات الفحصَ نفسه. الصفحة المستبدلة أو إصدار المستند المستبدل يحتفظ بكلماته القديمة في الشرائح إلى أن تصلها دمجات FTS5 الذاتية؛ ولا تكون قابلة للبحث أبدًا. - الصفحات المجلوبة. يُحفظ نص كل صفحة مجلوبة تحت
<data dir>/knowledge_provenance/<library>/(5,000 ملف كحد أقصى لكل مكتبة) ويُزال مع المكتبة. - المكتبات. يحمل التثبيت 500 مكتبة كحد أقصى، بما فيها المؤرشفة. المكتبة الجديدة بعد ذلك تُرفض قبل جلب أي شيء (
kb_library_limit، HTTP 409، بالإنجليزية والعربية في الصفحة)؛ احذف واحدة لتضيف أخرى. كل مكتبة مجموعة متجهات واحدة، وهذا السقف هو ما تُحجِّم كاظمه مجمّع فهارس Chroma على أساسه (انظر متجهات المعنى). العملية التي لا تستطيع فتح ملفات كافية تحصل على سقف أدنى: الفهرس المحمّل يُبقي 4 ملفات مفتوحة، فعند الافتراضي 512 يكون السقف 92.
متجهات المعنى
Section titled “متجهات المعنى”كل مقطع يحصل على متجه معناه. يُضمَّن المقطع حالما تُثبَّت صفحته. مرور صيانة كل 15 دقيقة (KnowledgeIndex.backfill_vectors، حتى 5 دقائق في كل مرة، وهو الأخير في دورة الصيانة) يجعل متجهات كل مكتبة تطابق مقاطعها: يضمّن أي مقطع بلا متجه من المضمِّن النشط — الأقصر أولًا، عبر كل المكتبات — ويزيل متجهات المقاطع المُحالة إلى التقاعد.
- كل متجه يسمّي المضمِّن الذي صنعه: صنفه، ونموذجه، وحجمه، وخلاصة (digest) لنقطة نهايته، تُقرأ من المضمِّن العامل، لا من الإعدادات أبدًا. النموذج المغيَّر في الإعدادات يسري عند إعادة التشغيل التالية؛ والنموذج البعيد الذي عاد احتياطيًا إلى المحلي يصنع متجهات موسومة بالمحلي. لا تقارن عمليات البحث إلا متجهات المضمِّن النشط، ويعيد المرور تضمين البقية؛ والمجموعة التي لمتجهاتها حجم آخر يُعاد بناؤها أولًا، وإلى ذلك الحين ينتظر الاستعلام بهدوء (سطر INFO واحد).
- لا تستطيع مكتبة واحدة إيقاف الأخريات. المكتبة التي تفشل مجموعتها تُسجَّل فاشلة وتُصلَح البقية؛ ثم يرفع المرور خطأً كي يسجّله منفّذ الصيانة عند مستوى WARNING.
- الانقطاع يُرى. أول مرور يجد مخزن المتجهات غير متاح يسجّل WARNING، وكذلك التعافي؛ وثلاثة مرورات سيئة متتالية ترفع تنبيه التشغيل
knowledge.meaning_search(كل 6 ساعات ما دام الانقطاع قائمًا). يحمل/metricskazma_kb_vector_*وkazma_kb_keyword_index_ok، وتحمل الجاهزية سطرknowledge_vectors(غير حرج أبدًا: فالمكتبة ما زالت تجيب بالكلمات المفتاحية)، ويسرد الملخص اليومي المرور المتدهور تحت “Needs attention”. - الصحة هي ما قيس، على مخزن المتجهات هذا. كل مكتبة في صفحة المعرفة تعرض “Meaning search: N of M” — المقاطع التي صنع المضمِّنُ النشط متجهها — مع حالة: لم يُفحص بعد، أو يُعاد البناء، أو غير متاح، أو فاشل. سرد المكتبات لا يفتح أي مجموعة ولا يحمّل أي نموذج؛ والأرقام هي أرقام المرور الأخير. يسمّي السجل مخزن المتجهات الذي قيس عليه (معرّف محفوظ في
vector_memory/kazma_vector_store_id): يُنسخ knowledge.db احتياطيًا ولا تُنسخ المتجهات، لذا فقاعدة البيانات المستعادة على جهاز ليست عليه متجهاتها تعرض «لم يُفحص بعد» إلى أن يقيس المرور الأول المتجهات الموجودة — ولا تعرض أبدًا تغطية المتجهات التي فقدتها. - فهرس واحد لكل مخزن. تتشارك المكتبة المعرفية ومنصة المستندات فهرس المخزن الواحد، والمجموعة التي أسقطها مقبض آخر يُعاد فتحها بالاسم في الاستدعاء التالي.
تُقارن المتجهات بالزاوية (جيب التمام)، ويُجعل كل منها بطول الوحدة قبل تخزينه أو البحث فيه. يُصنع المتجه من أول 1,500 حرف من مقطعه؛ أما البحث بالكلمات المفتاحية فيقرأ المقطع كاملًا. لا يُخزَّن في مخزن المتجهات إلا المتجه، لا نص المقطع أبدًا. تعيش المتجهات في KAZMA_VECTOR_PATH إن عُيِّن، وإلا في vector_memory/ بجوار قاعدة بيانات المعرفة. حذفُ مكتبة يُسقط مجموعتها. النسخ الاحتياطية تترك المجلد خارجها — فنسخة من قاعدة بيانات Chroma حيّة قد تكون ممزقة — ومرور الصيانة يعيد بناءه بعد الاستعادة أو الترحيل. قياس Chroma عن بُعد (telemetry) متوقف.
ما تفعله كاظمه حول مخزن Chroma المحلي (chromadb 1.5.9، مقيسًا بـ scripts/knowledge_soak.py):
- متجهات المجموعة المُسقطة تغادر القرص. يزيل
delete_collectionفي Chroma صفوف الكتالوج ويُبقي مجلد المجموعة (نحو 40 MB لكل 10,000 مقطع عند 1,024 بُعدًا). تزيل كاظمه كل مجلد لا تملكه أي مجموعة فيchroma.sqlite3: عند بدء العميل، قبل فتح أي مجموعة؛ وفور الإسقاط، حين لا يمسك شيء بالمجلد؛ وفي نهاية كل مرور صيانة. على Windows يبقى المجلد الذي حمّلت هذه العملية فهرسه مفتوحًا إلى أن تُفلته العملية، لذا يغلق المرور حينها عميل المتجهات (بعد الاستدعاءات الجارية، ممسكًا الجديدة في تلك اللحظة)، ويزيل المجلدات، ويدع كل مكتبة تُعيد الفتح في استدعائها التالي؛ وخروج العملية يفعل الشيء نفسه. يحمل/metricskazma_kb_vector_orphan_folders(المجلدات التي لا تزال عملية أخرى تمسك بها). - لا يُطرد أي فهرس. يحفظ Chroma كل فهرس محمّل في مجمّع مقسوم على 64 جزءًا (shard)، يُحجَّم افتراضيًا من حد الملفات المفتوحة (102 مدخل على Windows: واحد أو اثنان لكل جزء)، ولا يكتب الفهرس إلى القرص إلا كل 1,000 سجل. مكتبتان في جزء ممتلئ واحد تطرد إحداهما الأخرى. الفهرس المطرود الذي فيه أقل من 1,000 سجل لم يُكتب قط، فتفشل كل قراءة له حتى إعادة التشغيل (“Nothing found on disk”)؛ والفهرس المطرود الذي فيه 1,000 فأكثر يُعاد تحميله من آخر كتابة له دون السجلات المضافة بعدها، فتفوتها عمليات البحث بلا خطأ حتى الكتابة التالية للمكتبة. تبدأ كاظمه Chroma بمجمّعها الخاص: كل جزء يتسع لكل مكتبة قد توجد (سقف الـ 500 مكتبة، مع بضع احتياطيات)، فلا يمكن لأي جزء أن يفيض، أيًّا كانت الأجزاء التي تقع فيها المكتبات. وترفع حد الملفات المفتوحة أولًا (Windows: حد تدفقات مكتبة C وقت التشغيل إلى 8,192؛ Linux: 10,240 حين يسمح الحد الصارم)، إذ يُبقي كل فهرس محمّل ملفاته الأربعة مفتوحة. القراءة التي لا تزال تجد فهرسًا مفقودًا تجعل Chroma يعيد بناءه من سجل كتابته الخاص، ثم تسأل مجددًا (WARNING، و
kazma_kb_vector_index_reloads_total). - يُعاد تشغيل سجل المكتبة على خيط واحد. أول قراءة لمكتبة بعد بدء Chroma (عند كل إقلاع، وكلما أعاد مرور الصيانة فتح عميل المتجهات) تطبّق سجل كتابة المكتبة على الفهرس الذي يحمّله Chroma من القرص. يفعل Chroma ذلك على خيوط العمل الخاصة به، ولذلك الإدراج المتوازي سباقٌ (race) يُسقط العملية كلها (انتهاك وصول داخل الفهرس، دائمًا عند العنوان نفسه). وقد أصابه اختبار الإجهاد (soak) للمعرفة ثلاث مرات. وفي 2026-10-21 قاس
scripts/chroma_replay_race.pyستة انهيارات في نحو 28,200 بدء للعميل بخيوط Chroma الخاصة، ولا شيء في 28,000 بخيط واحد؛ وإعادة تشغيل مخزن منهار مرة أخرى لم تنهَر قط، فهو سباق لا بيانات تالفة. تضبط كاظمهRAYON_NUM_THREADS=1قبل أن يبدأ Chroma (والقيمة التي تضبطها بنفسك تُحفظ، مع تحذير في السجل). والثمن، مقيسًا عند 1,024 بُعدًا: يُدرَج 20,000 متجه في 60 s بدلًا من 8 s، وأول قراءة لمكتبة بعد الإقلاع تعيد تشغيل ما يصل إلى 999 سجلًا معلّقًا في نحو 6 s بدلًا من 0.7 s. ونموذج التضمين الحقيقي يُنتج نحو 18 مقطعًا في الثانية، فلا تزال سرعة الاستيعاب يحددها النموذج. أعد تشغيل هذا التمرين بعد ترقية chromadb. - لا يُخزَّن نص بجانب المتجه. يُخزَّن المتجه مع وسم المضمِّن الذي صنعه ومعرّفَي مكتبته ومستنده، ولا شيء آخر: المقطع نفسه، وعنوانه، وترويسته، ورابطه تبقى في
knowledge.db، الذي تُقرأ منه كل نتيجة. الإصدارات السابقة لـ 2026-10-15 خزّنت أيضًا معاينة من 2,000 حرف للمقطع مع عنوانه وترويسته ورابطه، لم يقرأها شيء، وSQLite يُبقي بايتات الصف المحذوف في المساحة الحرة للملف: بقيت كلمات المكتبة المحذوفة مقروءة فيchroma.sqlite3(9,429 نسخة من كلمات مجموعة مُسقطة من 3,000 صف في فحص واحد). يعيد مرور الصيانة بناء مثل تلك المجموعة من المتجهات التي تحويها، بلا النص (لا يُعاد تضمين شيء: 12 s لـ 10,000 مقطع). - النص المحذوف يغادر كتالوج المتجهات. حذف صفوف كانت تحمل نصًا (حذف مكتبة، أو صفحة مستبدلة، أو مجموعة أُعيد بناؤها) يَسِم الكتالوج (
vector_memory/kazma_compaction_due)، ونهاية مرور الصيانة التالي تعيد كتابته: يُدمج فهرس النص الكامل في Chroma، ثم يُعاد بناء الملف من صفوفه الحية (VACUUM، كما يفعل أمر Chroma الخاصchroma utils vacuum). لا يمسك المرور استدعاءات المتجهات الجديدة إلا ما دام يعمل، ويُبقي العميل مفتوحًا. عند 10,000 مقطع انتقل الكتالوج من 41.0 MB إلى 3.2 MB في 0.3 s؛ والكتالوج الخالي من النص يستغرق 0.13 s. يحمل/metricskazma_kb_vector_compaction_pending. - لا يطلب البحث مرشّح بيانات وصفية حين لا يحتاجه. المجموعة تحمل مكتبة واحدة، لذا لا يرشّح البحث على وسم المضمِّن إلا ما دامت متجهات مضمِّن آخر موجودة (بعد تبديل النموذج، إلى أن يعيد المرور صنعها)، ويُفحص ذلك مرة لكل مجموعة وعملية. مرشّح البيانات الوصفية في Chroma يكلّف أكثر من البحث نفسه: عند 10,000 متجه استغرق الاستعلام 40 ms مع مرشّح المكتبة والمضمِّن و4 ms من دونه (p95 123 ms و5 ms)؛ وعند 100,000، 353 ms و6 ms (p95 442 ms و10 ms). لم يغيّر المرشّح أي نتيجة: 40 من 40 إجابة مزروعة عند 10,000 في الحالتين، و32 من 40 عند 100,000 في الحالتين (باتساع البحث 256 الذي كان لكل مكتبة آنذاك: الاتساع الآن ينمو مع المكتبة، بعد بندين).
- الفهرس مبني للاستدعاء (recall). تُنشأ المجموعات الجديدة بـ 48 جارًا لكل متجه، واتساع بناء 400 واتساع بحث 256 (افتراضيات Chroma هي 16 و100 و100). على مدوّنة اختبار الإجهاد (soak) عند 10,000 مقطع أعادت الافتراضيات 31-39 من 40 إجابة مزروعة بينما رتّب البحث الدقيق كل واحدة منها أولًا؛ وأعادت هذه الإعدادات 40 من 40 في النص الإنجليزي والعربي والمختلط في 11 من 12 قياسًا، و39 في القياس الآخر (قيس ذلك قبل 2026-10-21، حين كان Chroma لا يزال يبني الفهرس على خيوط متوازية، فاختلف بناءان قليلًا: انظر «يُعاد تشغيل سجل المكتبة على خيط واحد» أعلاه). و256 هو اتساع البحث للمكتبة الصغيرة؛ أما المكتبة الأكبر فيُبحث فيها باتساع أكبر (البند التالي). وللمجموعة المنشأة قبل ذلك، يعيد مرور الصيانة بناء رسمها البياني من المتجهات التي تحويها — دون إعادة تضمين شيء.
- يتّسع البحث كلما كبرت المكتبة. اتساع البحث هو عدد المرشّحين الذين يحتفظ بهم الفهرس وهو يسير في رسمه البياني نحو السؤال. وعند اتساع ثابت قدره 256، وجد البحث بالمعنى إجابات مزروعة أقل كلما كبرت المكتبة — 239 من 240 عند 10,000 مقطع، و218 عند 50,000، و210 عند 100,000، و203 عند 200,000 — بينما رتّب البحث الدقيق كل واحدة منها أولًا؛ وأقل اتساع وجدها كلها نما مع المكتبة، إلى نحو مرشّح واحد لكل 12 مقطعًا (القياسات أدناه). ويُبحث في مجموعة كل مكتبة باتساع بحث 256 تحت 3,072 متجهًا، و384 من 3,072، و512 من 4,608، و768 من 6,144، و1,024 من 9,216، و1,536 من 12,288، و2,048 من 18,432، و3,072 من 24,576، و4,096 من 36,864، و6,144 من 49,152، و8,192 من 73,728، و12,288 من 98,304، و16,384 من 147,456، و24,576 من 196,608، و32,768 من 294,912، و49,152 من 393,216: مرشّح واحد لكل 12 متجهًا، مقرَّبًا صعودًا إلى أقرب هذه القيم التالية. ويُقرأ الحجم من فهرس Chroma نفسه، ويُضبط الاتساع حين تُفتح المجموعة، قبل أن يقرأها أي شيء: فـ Chroma يطبّق الاتساع حين يحمّل فهرس المجموعة، وأي قراءة تحمّله (حتى العدّ)، والفهرس المحمَّل يحتفظ باتساعه ما دام عميل المتجهات حيًّا. والمكتبة التي تتجاوز درجة وفهرسها محمَّل تأخذ الاتساع الجديد في مرور الصيانة التالي، الذي يجعل الفهارس تُحمَّل من جديد (فهو يغلق عميل المتجهات بين الاستدعاءات، كما يفعل للمجلدات المحذوفة؛ وكل مكتبة تحمّل فهرسها عند بحثها التالي). وتحتفظ المكتبة باتساعها حتى تصغر بمقدار الخُمس تحت درجتها، فالمكتبة التي تتأرجح عند درجة لا تغيّره في كل مرور. والمجموعة المعاد بناؤها تُنشأ باتساع حجمها.
البحث بالمعنى على نطاق واسع
Section titled “البحث بالمعنى على نطاق واسع”قيس بالأمر scripts/knowledge_soak.py breadth في 2026-10-15 (chromadb 1.5.9؛ على محطة عمل Windows بـ 24 خيطًا كانت تشغّل اختبارات تحمّل أخرى في الوقت نفسه، لذا أزمنة البحث مرتفعة ولا تُقارَن إلا داخل الصف الواحد). مكتبة واحدة لكل حجم ولغة، تُبنى متجهاتها عبر مخزن المتجهات في المنتج من مدوّنة الحجم (مقاطع مضمَّنة بالتجزئة ذات 1,024 بُعدًا، ورسم كاظمه البياني بـ 48 جارًا واتساع بناء 400) مع 40 سؤالًا مزروعًا بالإنجليزية والعربية والنص المختلط؛ ومدوّنتان (البذرتان 20261015 و7)، أي 240 سؤالًا لكل حجم. يرتّب البحث الدقيق كل إجابة مزروعة أولًا. «وُجدت»: الإجابة بين المرشّحين العشرين الذين تطلبهم طبقة المعنى في بحث المكتبة. ويُضبط كل اتساع قبل تحميل الفهرس، في عملية جديدة، على الرسم البياني نفسه.
| المقاطع | الموجود عند 256 | أقل اتساع وجد الكل (أصعب مدوّنة ولغة) | اتساع كاظمه | الموجود عند اتساع كاظمه | وسيط البحث p50 عند 256 | وسيط البحث p50 عند اتساع كاظمه | تحميل الفهرس عند اتساع كاظمه |
|---|---|---|---|---|---|---|---|
| 10,000 | 239 من 240 | 512 | 1,024 | 240 من 240 | 3.3-3.8 ms | 4.5-5.3 ms | 7-9 ms |
| 50,000 | 218 من 240 | 4,096 | 6,144 | 240 من 240 | 7.5-11.7 ms | 23.5-28.4 ms | 32-37 ms |
| 100,000 | 210 من 240 | 6,144 | 12,288 | 240 من 240 | 17.5-20.9 ms | 51.8-59.5 ms | 62-77 ms |
| 200,000 | 203 من 240 | 16,384 | 24,576 | 240 من 240 | 29.4-33.9 ms | 99.9-113.5 ms | 124-145 ms |
ما تقوله الأرقام:
- الاتساع الثابت يفقد إجابات كلما كبرت المكتبة، وأصعب الإجابات كانت العربية: ففي كل حجم احتاجت المدوّنة العربية أوسع بحث لتجد كل إجاباتها (مفرداتها الحشوية هي الأصغر، 115 كلمة مقابل 166 في الإنجليزية). وأسهل مدوّنة ولغة وجدت كل شيء عند 512 أو أقل في كل حجم.
- مرشّح واحد لكل 12 متجهًا وجد كل إجابة في كل حجم قيس؛ واتساع كاظمه مرشّح واحد لكل 12، مقرَّبًا صعودًا إلى درجته التالية (1.5 ضعفًا على الأكثر): وقد وجد كل إجابة، في كل مدوّنة ولغة، في كل حجم.
- الكلفة زمنُ بحث في المكتبات الكبيرة فقط. عند 10,000 مقطع يستغرق البحث نحو 1.3 ms أكثر؛ وعند 50,000 من 2.5 إلى 3 أضعاف الزمن، وعند 100,000 نحو 3 أضعاف، وعند 200,000 نحو 3.4 أضعاف (عمودا p50، مقيسان على التوالي على الرسوم البيانية نفسها). وتشغيل أهدأ للبحث نفسه في 100,000 مقطع عند 256 استغرق 6 ms (قياس المرشّح أعلاه)، أي ثلث الزمن هنا. وتحميل الفهرس من جديد بعد درجة يكلّف مكتبته بحثًا واحدًا أبطأ: 7-9 ms عند 10,000 مقطع، و124-145 ms عند 200,000، من ذاكرة تخزين مؤقت دافئة للقرص.
- لم يُقَس: ما فوق 200,000 مقطع (حصة المخزن تسمح بنحو 480,000)، ولا الرسوم البيانية لنماذج تضمين حقيقية، وهي أنعم من رسوم الكلمات المجزّأة.
جودة الاسترجاع
Section titled “جودة الاسترجاع”تُقاس جودة الاسترجاع على معيار مُرقَّم الإصدارات (kazma-core/kazma_core/stores/knowledge_benchmark.py، يبنيه scripts/knowledge_bench.py build): أربع مكتبات توثيق، و76 قسمًا، منشورة في مخزن خاص عبر المسار نفسه الذي يسلكه الاستيعاب.
- واجهة API للرسائل، بالإنجليزية.
- مخزن كائنات، بالإنجليزية، تقع موضوعاته بجوار موضوعات الواجهة (المفاتيح، وحدود المعدل، وإعادة المحاولات، والاستدعاءات الراجعة الموقَّعة): الإخفاقات القريبة (near misses).
- مركز مساعدة لمنتج فوترة، بالعربية.
- دليل تشغيل مكتوب بالطريقة التي يكتبه بها فريق خليجي: جمل عربية حول مصطلحات وأوامر إنجليزية.
هناك 72 سؤال ضبط و16 سؤالًا محجوزًا (لم تُستخدم قط لاختيار عتبة)، بالإنجليزية، والعربية (الفصحى والخليجية)، ومزيج منهما، وعبر اللغات (سؤال بلغة عن صفحة باللغة الأخرى). 14 من أسئلة الضبط و4 من المحجوزة تسأل عن شيء لا تحويه أي مكتبة. يمر كل سؤال عبر بحث الأداة (5 نتائج) وعبر الحقن التلقائي (3 مقاطع)، مع تشغيل البحث المعنوي (bge-m3) ومع إيقافه.
تقرير المعيار (مجموعة البيانات v1، 2026-10-15)
Section titled “تقرير المعيار (مجموعة البيانات v1، 2026-10-15)”مع البحث المعنوي:
| بحث الأداة | الحقن التلقائي | بحث الأداة، المحجوزة | الحقن التلقائي، المحجوزة | |
|---|---|---|---|---|
| الإجابات الموجودة (كل أجزائها معروضة) | 55 من 58 (0.95) | 55 من 58 (0.95) | 11 من 12 (0.92) | 11 من 12 (0.92) |
| MRR (مدى علوّ ترتيب أول إجابة) | 0.94 | 0.94 | 0.92 | 0.92 |
| الدقة (حصة ما يُعرض مما يجيب) | 0.71 | 0.72 | 0.79 | 0.79 |
| لا شيء يُعرض حين لا يجيب شيء | 7 من 14 (0.50) | 7 من 14 (0.50) | 1 من 4 | 1 من 4 |
قبل قاعدة الصلة، على المدوّنة نفسها، وجدت الأداة 51 من 58 إجابة (MRR 0.80، الدقة 0.19) والحقن التلقائي 47 من 58 (MRR 0.79، الدقة 0.30). وكلاهما عرض شيئًا لكل واحد من الأسئلة الأربعة عشر التي لا يجيب عنها شيء.
من دون البحث المعنوي (الكلمات المفتاحية فقط)، يجد المساران 31 من 58 إجابة (MRR 0.53، الدقة 0.47) ويتركان 11 من الأربعة عشر فارغة؛ وفي المحجوزة 6 من 12 و4 من 4. ومن دون قاعدة، وجد الدمج 46 ولم يترك أيًّا منها فارغًا.
ما تعنيه الأرقام:
- القاعدة تشتري الامتناع بثمن قليل. نصف الأسئلة التي لا يجيب عنها شيء صار لا يُعرض لها شيء، على المسارين. وتُفقد ثلاث إجابات من 58: إعادة صياغة، وصيغة بالعربية الخليجية، وسؤال عبر اللغات، كلٌّ منها بالكاد فوق ما تبلغه المقاطع غير ذات الصلة.
- ما لا تستطيع رفضه هو الجار. الأسئلة التي ما زالت تُجاب بشيء تسأل عمّا يقع بجوار محتوى مكتبة: تشفير كائنات Orbit بمفاتيحك الخاصة، بجوار أزواج مفاتيح Orbit؛ وسعر خطة، بجوار حد معدلها. والحد الأدنى الأعلى يُفقد إجابات قبل أن يرفض تلك (جُرِّب من 0.04 إلى 0.12).
- الإجابة تأتي أولًا. أعطى الدمجُ أفضلَ مقطع في كل مكتبة الدرجةَ نفسها، فتعادل الإخفاق القريب لمكتبة أخرى مع الإجابة. وبالترتيب على الدليل، يأتي كل إخفاق قريب مسمّى في المعيار تحت إجابته، ويُجاب 5 من الأسئلة الستة عبر اللغات على المسارين (وجدت الأداة 2 من قبل، والحقن التلقائي 1).
- الكلمات وحدها لا تميّز إعادة الصياغة من الجار. من دون البحث المعنوي تطلب القاعدة نصف كلمات السؤال، كما تفعل قاعدة ذاكرة الدردشة. وما لا تستطيع الكلمات تحديد موضعه لا يُخمَّن.
كيف تُثبَّت الدرجات:
- يعيد CI تشغيل المتجهات التي أعادها bge-m3 لهذه النصوص بعينها (
tests/fixtures/knowledge_bench/vectors.npz)، ويقدّمها عميل دقيق داخل العملية. ويعطي chromadb الحقيقي (1.5.9) والنموذج الحي الدرجات نفسها (python scripts/knowledge_bench.py run --chroma،run --real). - الدرجات سقّاطة (ratchet) مختومة بإصدار مجموعة البيانات (
tests/fixtures/knowledge_bench/thresholds.json). يفشلtests/test_knowledge_benchmark.pyعند أي هبوط، وعند ارتفاع لم يثبّته أحد (python scripts/knowledge_bench.py lock). يُثبَّت الإصدار الجديد لمجموعة البيانات بـlock --rebaseline، الذي يُرفض على الإصدار نفسه.
لم يُقَس: المدوّنة صغيرة (76 مقطعًا) ومكتوبة لهذا الغرض، والحجم هو KB-Q01 (معدل الاستيعاب، وزمن البحث، وكلفة الإصلاح عند 10,000 مقطع فأكثر).
واجهة Web API
Section titled “واجهة Web API”لـ /api/kb/* (kazma-ui/kazma_ui/kb_api.py) 16 مسارًا. كل رفض جسمُ JSON {"ok": false, "code": ..., "transient": ..., "error": ...} برمز code ثابت: رمز جلب (invalid_url، robots_disallowed، resource_limit، …) أو أحد رموز المعرفة (kb_single_operator، invalid_request، request_too_large، not_found، library_exists، url_refused، kb_storage_full، library_busy، crawl_owns_library، documents_unavailable، page_not_ingested، no_seed، resume_refused، internal_error). تُسجَّل الرفوض المتوقعة مرة واحدة عند INFO أو WARNING، لا بوصفها ERROR مع تتبّع (traceback) أبدًا. تُقرأ أجسام الطلبات دون 64 KiB ويُتحقق منها: top_k من 1 إلى 20، وquery حتى 2,000 حرف، والاسم والوصف حتى 500، والبذرة حتى 2,048 وhttp(s) فقط، ومعرّف المكتبة يُحوَّل إلى slug من 48 حرفًا كحد أقصى. استيعاب الصفحة الواحدة لا يجيب بـ ok إلا حين تُخزَّن الصفحة.
تنبيهات تقدم الزحف واكتماله
Section titled “تنبيهات تقدم الزحف واكتماله”يحتفظ جرس الإشعارات بتنبيه اكتمال يربط بزحف المعرفة المحفوظ. وللمهام الجزئية والفاشلة والملغاة والمنقطعة تنبيهات منفصلة. يؤدي غياب التقدم المرصود إلى تحذير، ويزيله تقدم فعلي. تتحكم الإعدادات → النظام → جلب الويب في هذه التنبيهات وعتباتها. تقرأ المراقبة الأدلة المحلية المحفوظة دون طلبات للمزوّدين أو إعادة محاولة تلقائية. تعيد زيارة الصفحة حالة المهمة المحفوظة؛ واستأنف المهمة المنقطعة صراحة بعد مراجعة الآثار غير المؤكدة. راجع تنبيهات التقدم والنتائج.
ملاحظات معمارية (للمساهمين)
Section titled “ملاحظات معمارية (للمساهمين)”تميّز نتيجة الجلب المشتركة بين الإخفاقات المصنّفة وشاشات الدخول المرصودة والمحتوى الجزئي والاستخراج الناجح. لا يُعامل المحتوى الذي يبدأ بـ Error: كطلب فاشل. يُرفض المحتوى الجزئي من السلم المشترك قبل الفهرسة. يحافظ ملف المعرفة المشترك على اللوحات المخفية والشيفرة والجداول؛ ويلتقط تفاعل Chromium المحدود كل تبويب مؤجل مدعوم أثناء وجوده. يستخدم اكتشاف الروابط الجلب المصنّف نفسه ضمن النطاق. تُفحص وجهات إعادة التوجيه قبل الإرسال، بما فيها قفزات HTTP في المتصفح. يُرفض الاكتشاف المستضاف حين يعجز المزوّد عن فرض نطاق الزحف. تحتفظ قيم الاستعلام بهوية الصفحة. ضوابط وكيل المنع الأصلي ليست عزلًا للشبكة على مستوى نظام التشغيل. يستخدم الاكتشاف وجلب الصفحة ملفّي استخراج مختلفين، لذا قد تُجلب الصفحة مرتين في زحف واحد.
تعرض الصفحة محاولات الجلب الفعلية وحجوزات الطلبات الخارجية المحدودة وأرصدة المزوّدين المحفوظة. تحديث رصيد Firecrawl صريح ويُحتسب، وتظل الملاحظة حديثة لخمس دقائق وضمن نطاق الحساب. الصفر يعني صفرًا مرصودًا؛ ولا تتحول الأرصدة غير المتاحة أو القديمة ورسوم الطلبات إلى صفر. حصص الطلبات ليست سقوف إنفاق مالي. تستمر جدولة المصادر عبر مخزن الإعدادات المشترك. راجع تقرير التنفيذ للتأهيل المقيس والمحاولات الفاشلة المحفوظة وحدود المنصات.
| الطبقة | الملف | الغرض |
|---|---|---|
| المخزن | kazma-core/kazma_core/stores/knowledge.py | knowledge.db: المكتبات، والمقاطع، وفهرس FTS5، وحالة المتجهات. مصدر الحقيقة؛ مسار نشر واحد لكل صفحة. |
| المقطّع | kazma-core/kazma_core/stores/knowledge_chunker.py | مقسّم بمكتبة Python القياسية وحدها، واعٍ بالعناوين والكود؛ معرّفات مقاطع موضعية. |
| الفهرس | kazma-core/kazma_core/stores/knowledge_index.py | متجهات لكل مكتبة + FTS5، وقاعدة الصلة (الدليل)، ومرور الإصلاح، والصحة، وكتلة الحقن التلقائي. |
| المعيار | kazma-core/kazma_core/stores/knowledge_benchmark.py | معيار الاسترجاع: مخزن خاص، والمساران، مع التقييم (جودة الاسترجاع). |
| الاستيعاب | kazma-core/kazma_core/stores/knowledge_ingest.py | القبول، والاكتشاف، والجلب، والنشر، والصفحات المجلوبة. |
| دورة الحياة | kazma-core/kazma_core/stores/knowledge_lifecycle.py | حذف المكتبة، وقاعدة المشغّل الواحد. |
| سجل الزحف | kazma-core/kazma_core/web_acquire/crawl_jobs.py | مهام الزحف: صف واحد لكل مهمة، والمالكون، وعقود الإيجار، والطرد. |
| الأدوات | kazma-core/kazma_core/agent/tool_builtins/knowledge.py | knowledge_search (مسيّجة)، والسرد، والإنشاء، واستيعاب صفحة / موقع. |
| البوابة | kazma-gateway/kazma_gateway/agent_handler/commands.py _try_kb_command | /kb على كل منصات الدردشة. |
| Web API | kazma-ui/kazma_ui/kb_api.py | موجّه /api/kb/*. |
| صفحة الويب | kazma-ui/kazma_ui/templates/knowledge_base.html + static/js/kb.js | صفحة /knowledge. لا يصير أي رابط مخزَّن رابطًا إلا عبر safeHref (http وhttps). |
لا توجد لوحة للمعرفة في TUI.
لماذا مخزن منفصل (وليس ذاكرة الدردشة)؟ تحتفظ المكتبة المعرفية بقاعدة بياناتها ومجموعات متجهاتها الخاصة (kazma_kb_<library_id>)، بمعزل عن ذاكرة الدردشة (memory_state.db). من دون هذا الفصل، سيُسترجع النص المزحوف كأن المستخدم قاله، ولا تلائم فلترةُ البيانات الوصفية للمكتبات حقائقَ الذاكرة ثنائية الزمن. تعيد المكتبة المعرفية استخدام صنف VectorStore المشترك (memory/vector_store_global.py) والمضمِّن المشترك، في مجموعاتها الخاصة.
اعتماديات اختيارية
Section titled “اعتماديات اختيارية”الاسترجاع المفهرس يحتاج إضافة rag (pip install -e ".[rag]" → chromadb، sentence-transformers، sqlite-vec)؛ وجلب صفحات JS/التبويبات يحتاج إضافة web (pip install -e ".[web]" → playwright، ثم playwright install chromium). بدونهما يتدهور النظام: لا بحث معنوي (FTS5 فقط، والصفحة تقول ذلك)، ولا تصيير لصفحات JS.
حدود وتحفظات صادقة
Section titled “حدود وتحفظات صادقة”- الجلب محلي فقط افتراضيًا. ثبّت إضافة
webوChromium لصفحات JavaScript. تمنع بعض حواجز الروبوتات HTTP وChromium المحلي معًا؛ وتبقى تلك الصفحات إخفاقات ظاهرة. يتطلب Firecrawl/Jina المستضافKAZMA_ACQUISITION_MODE=local_first_with_remote_fallbackوأسماء المزوّدين فيKAZMA_ACQUISITION_REMOTE_PROVIDERS، مع بيانات الاعتماد عند الحاجة. المفاتيح المحفوظة وأعلام Jina القديمة وحدها لا تسمح بالجلب المستضاف. راجع البحث على الويب للسياسة وحدود المحاسبة الحالية. - التحديث يحافظ على الصفحات المحفوظة. عدم اكتشاف رابط، بما فيه الاكتشاف المحدود أو الفاشل أو قليل النتائج، لا يحذف محتواه المفهرس. ينتهي الاستيعاب الذي تفشل جميع صفحاته بخطأ مع حفظ الأسباب.
- فحص robots مفعّل افتراضيًا. يستخدم اكتشاف المعرفة واستيعابها سياسات KazmaBot الخام المحدودة قبل المحتوى وإعادة التوجيه وموارد المتصفح. غياب الملف بـ 404/410 يختلف عن فشل الفحص أو فساد السياسة، اللذين يمنعان الزحف. يُسجل التعطيل الصريح
KAZMA_CRAWL_RESPECT_ROBOTS=0في أدلة الجلب. لا تتجاوز الخدمات المستضافة الفرض؛ وتُرفض بحذر إعادة توجيه ملف التحكم إلى مصدر آخر. راجع البحث على الويب للحدود والتأهيل المتبقي. - ملف Chromium التنفيذي منفصل عن حزمة Python. يثبّت
pip install -e ".[web]"روابط Playwright، ويظلplaywright install chromiumمطلوبًا لتنزيل المتصفح نفسه. يسمّي خطأ المهمة ذلك صراحة: “Chromium binary not installed (run: playwright install chromium)”. - يحتاج Chromium على Linux ضوابط cgroup v2 مفوّضة. يشترك المشغّل والمتصفح في ميزانية ذاكرة ومعالج ومهام إجمالية. يسبب غياب ضوابط الذاكرة أو pids أو CPU أو قتل المجموعة خطأ عدم إتاحة ظاهرًا؛ اضبط تفويض الخدمة أو
KAZMA_BROWSER_CGROUP_ROOT. راجع البحث على الويب للحدود وتنظيف المراقب والتأهيل المتبقي. - قد تقاوم نسبة صغيرة من مواقع توثيق SPA المموّهة بشدة كل ما سبق. تُبلَّغ الصفحات الفاشلة في المهمة لإضافتها يدويًا.
- التضمينات المحلية (
BAAI/bge-m3) مجانية لكنها أبطأ على المعالج؛ والبعيدة مثل NVIDIA NIMnv-embed-v1أسرع وأفضل لكنها مدفوعة. راجعmemory.embedding:فيkazma.yamlأو صفحة الإعدادات → المضمّن. - يُحد الزحف بـ
KAZMA_KB_MAX_PAGES، بسقف صارم 1000 لمنع الانفلات. - تتحول معرّفات المكتبات تلقائيًا إلى slug لتبقى آمنة للمجموعات (
"Meta WhatsApp Docs"→meta_whatsapp_docs، بحد أقصى 48 حرفًا). - لم يُقَس بعد: معدل الاستيعاب وزمن البحث وكلفة الإصلاح عند 100,000 مقطع فأكثر عمل مفتوح (
docs/plans/KNOWLEDGE_INDUSTRIAL_HARDENING_GOAL.md، KB-Q01)؛ أما استدعاء البحث بالمعنى وزمنه في مكتبة واحدة فمقيسان حتى 200,000 مقطع (انظر البحث بالمعنى على نطاق واسع). جودة الاسترجاع مقيسة على معيار صغير: انظر جودة الاسترجاع.

