
يشارك هذا المقال تنفيذ Q&A بصفر هلوسة في قارئنا بالذكاء الاصطناعي: الإجابات مبنية بدقة على نص الكتاب المفتوح، ويمكن تتبع الادعاءات الرئيسية بنقرة واحدة إلى المقطع الدقيق. إن كنت تبني قراءة بالذكاء الاصطناعي أو Q&A للمستندات أو تطبيقات شبيهة بـ RAG، نأمل أن تفيد ثلاث تكرارات من الدروس والبنية النهائية.
I. التطور في ثلاث مراحل
لم يُصمَّم Q&A بصفر هلوسة بشكل مثالي من اليوم الأول. تطور تحت توتر بين التكلفة والزمن والدقة. فيما يلي عرض زمني لثلاث مراحل—سياق مفيد لفهم شكل البنية الحالية.
المرحلة 1: إدخال الكتاب كاملًا في السياق (الأبسط—والأول الذي ينكسر)
النهج: عندما يفتح المستخدم كتابًا ويسأل، وضع كل النص المستخرج في System Prompt أو رسالة المستخدم ودع نموذج المحادثة يجيب. إن تجاوز الكتاب نحو 400 ألف حرف، قصّ صارم—يُحفظ البداية فقط؛ الفصول اللاحقة غير مرئية للنموذج.
المزايا:
- تكلفة تنفيذ منخفضة جدًا؛ بدون معالجة مسبقة تقريبًا؛
- يعمل بشكل معقول على كتب قصيرة ومستندات بسيطة—النموذج «رأى الكتاب كاملًا» فعلًا؛
- تجربة بسيطة: اسأل واحصل على إجابة، دون «انتظر التحليل».
العيوب (تصبح سريعًا غير مقبولة):
- استجابات بطيئة: كل سؤال يعيد إرسال حمولة ضخمة؛ زمن أول token والزمن الكلي ينمو مع طول الكتاب؛
- تكلفة tokens عالية: تدفع إدخال الكتاب كاملًا في كل سؤال؛
- الكتب الطويلة تتشوه: بعد 400 ألف حرف، النصف الثاني والملاحق والخلاصات كأنها غير موجودة—والواجهة غالبًا لا توضح أن هناك قصًا؛
- حبيبية استرجاع صفرية: على النموذج «إيجاد إبرة في كومة قش» عبر مئات الآلاف من الأحرف—سهل تفويت التفاصيل وأسهل إنتاج ملخصات مقنعة بلا أساس—ما يجب على تطبيقات القراءة تجنبه.
المرحلة 1 مناسبة لـ MVP، لا لمنتج بجودة.
المرحلة 2: LLM أخف لاستخراج جمل رئيسية (ضغط السياق—لكن بشدة زائدة)
النهج: قبل Q&A (أو عند الفتح الأول)، تشغيل نموذج أرخص على النص: تقسيم حسب فصل Spine (أو تقسيم الكتاب)، استخراج جمل رئيسية، الإبقاء على علامات موضع مثل [fملف-بداية-نهاية]، ثم دمج مقتطفات في سياق أقصر لـ Q&A لاحق.
خط أنابيب نموذجي: Extract → Cache → Chat. استخراج مرة (offline أو عند الطلب)، تخزين «حزمة جمل رئيسية»، إعادة استخدامها في كل سؤال—نفس فكرة كثير من نماذج Q&A للمستندات.
المزايا:
- كل سؤال يرسل نصًا أقل بكثير؛ استهلاك tokens لكل طلب ينخفض مقارنة بالمرحلة 1؛
- يمكن تخزين المعالجة المسبقة مؤقتًا؛ لا إعادة استخراج لكل سؤال على نفس الكتاب؛
- علامات الموضع تمهّد للاستشهادات.
العيوب (ما زالت تفشل على الكتب الطويلة):
- فقدان تفاصيل كبير: «الجمل الرئيسية» يختارها النموذج؛ المحددات والأمثلة المضادة وسلاسل الحجة تُسقط غالبًا—إجابات «صحيحة لكن من جانب واحد»؛
- السياق ما زال كبيرًا في الكتب الطويلة: حتى حزم الجمل الرئيسية للأعمال الكبيرة ضخمة—الزمن والتكلفة يُخفَّفان لا يُحلَّان؛
- خطأ LLM مزدوج: الاستخراج قد يفوت؛ Q&A قد يقرأ المقتطفات خطأ—الأخطاء تتراكم؛
- سياق ثابت: سواء سأل المستخدم عن فصل أو بنية الكتاب، النموذج يحصل دائمًا على نفس الكتلة المستخرجة مسبقًا—لا تضييق ديناميكي حسب السؤال.
الدرس: المسألة ليست «هل نضغط»، بل «هل الضغط عند الطلب وهل يمكن العودة للنص المصدر».
المرحلة 3: فهرس مقاطع + Tool retrieval عند الطلب + إرجاع النص المصدر (الحالي)
النهج: مستوحى من PageIndex. مقارنة بالمرحلة 2، ثلاث تحولات أساسية:
- المعالجة المسبقة تنتج فهرسًا منظمًا (ملخصات على مستوى جدول المحتويات + spans أحرف دقيقة)، لا مقتطفات كسياق Q&A مباشرة؛
- كل سؤال يستخدم Tool Calling للاسترجاع عند الطلب، ثم يسحب نصًا مصدرًا بعلامات موضع للإجابة؛
- System Prompt + الواجهة يفرضان تنسيق الاستشهاد ويدعمان القفز بالنقر والتمييز في القارئ.
مقارنة المراحل الثلاث:
| البعد | المرحلة 1 (إدخال كامل) | المرحلة 2 (جمل رئيسية) | المرحلة 3 (الحالي) |
|---|---|---|---|
| السياق لكل سؤال | الكتاب كامل (أو النصف الأمامي المقصوص) | جمل رئيسية مستخرجة مسبقًا | مقتطفات مصدر فقط ذات صلة بالسؤال |
| دقة الكتب الطويلة | ينهار بعد ~400k حرف | يعتمد على الاستخراج؛ يفقد تفاصيل | استرجاع حسب TOC/span؛ لا قصّ صارم للكتاب كاملًا |
| سرعة الاستجابة | بطيئة | أفضل قليلًا؛ الكتب الطويلة ما زالت بطيئة | استرجاع + سياق قصير—أسرع بوضوح |
| تكلفة tokens | عالية جدًا | متوسطة-عالية | معالجة مسبقة مُطَفَّأة + دفع عند الحاجة |
| قابلية التتبع | ضعيفة | علامات موجودة لكن المحتوى مُصفّى مسبقًا | الحواشي تطابق spans مصدر حقيقية |
| تعقيد هندسي | منخفض | متوسط | مرتفع |
لماذا توقفنا عند المرحلة 3: في القراءة، صفر هلوسة ليس «إظهار أكبر قدر من النص للنموذج»، بل «قبل الإجابة، جلب دليل مصدر للسؤال». المرحلتان 1–2 قاتلتا حجم السياق؛ المرحلة 3 تقسم الخط إلى فهرس (معالجة مسبقة) → استرجاع (Tool) → دليل (مصدر) → إجابة (توليد مقيد)—توازن الدقة والتكلفة وقابلية التتبع.
فيما يلي تفاصيل المرحلة 3.
II. تعريف المشكلة: في Q&A للكتب، الهلوسة أخطر من الدردشة العامة
المستخدمون يغفرون أخطاء عرضية في روبوت دردشة عام. في Q&A للكتب، التكلفة أعلى:
- يسألون ماذا تقول هذا الكتاب—لا ما في الذاكرة البارامترية للنموذج؛
- «رأي من الكتاب» مقنع قد يضلل الملاحظات والاقتباسات وإعادة المشاركة؛
- بلا مصادر لا يمكن التحقق—الثقة صعبة البناء.
إذن «صفر هلوسة» تصبح ثلاث قواعد قابلة للتنفيذ:
- أسئلة الكتاب يجب أن تستعلم الكتاب أولًا: أي شيء قد يخص الكتاب المفتوح يمر عبر الاسترجاع (Tool) قبل الإجابة؛
- الإجابات يجب أن تكون قابلة للتتبع: ادعاءات رئيسية بعلامات موضع يمكن للواجهة تحليلها والقفز إليها؛
- قل عندما لا تجد: إن لم يكن في الكتاب، قل ذلك—لا تلبس المعرفة العامة ثوب «ما يقوله الكتاب».
الباقي يتبع تدفق بيانات المرحلة 3 وكيف تُنفَّذ القواعد.
III. البنية: معالجة مسبقة → Tool retrieval → توليد مقيد → استشهادات قابلة للنقر
الفكرة الأساسية: لا تدع النموذج «يجيب من الذاكرة»—أجبره على «جمع الدليل، الإجابة، ووسم المصادر».
IV. المعالجة المسبقة: تحويل الكتاب كاملًا إلى فهرس مقاطع قابل للبحث
إن استخدم كل سؤال سياق الكتاب الكامل من المرحلة 1، الكتب الطويلة تفجر ميزانية tokens والاسترجاع خشن جدًا. المرحلة 3: عند أول محادثة AI لكتاب، تشغيل مهمة ملخص مقاطع في الخلفية—تقسيم حسب TOC أو طول النص إلى Segments، تلخيص كل واحد، تخزين في IndexedDB محلي.
كل Segment يحمل ملخصًا وموضعًا فيزيائيًا في النص:
| الحقل | المعنى |
|---|---|
startFileIndex / endFileIndex | فهرس ملف Spine (PDF: ملف لكل صفحة) |
startOffset / endOffset | بداية/نهاية بالأحرف |
sequence | ترتيب القراءة الخطي |
title | عنوان TOC |
التقسيم يوازن الدقة والتكلفة: إن كان نص عقدة TOC أقل من ~20KB، لخّص تلك العقدة فقط؛ الأشقاء قد يُدمَجون في دفعات (15–20KB) قبل استدعاءات LLM؛ كتل طويلة بلا بنية تُقسَّم في نطاقات ~30–40 ألف حرف.
System Prompt للملخص يطلب الإبقاء على علامات موضع inline ([fرقم-رقم-رقم]) ليتوافق المصدر من Tool مع إزاحات Spine. قيد أساسي:
إن ارتبط الملخص بمقطع، أبقِ علامة الموضع في النهاية [fرقم-رقم-رقم] (مثل [f1-90-109]).
العلامات ذرية—لا تغيّر أو تدمج أو تحذف أي حرف أو رقم.
بعد المعالجة المسبقة، Q&A يعتمد على فهرس مقاطع منظم لا سياق الكتاب كاملًا—شرط هندسي لصفر هلوسة في الكتب الطويلة.
V. نظام علامات الموضع: ترميز «أين» في النص
صفر هلوسة يتطلب محتوى من المصدر و مصدرًا قابلًا للتحليل آليا والقفز في الواجهة. نستخدم علامات inline:
[f{fileIndex}-{startChar}-{endChar}]
مثال: [f5-123-165] = ملف Spine 5 (أساس 0)، أحرف 123–165.
5.1 كيف تُكتب العلامات في النص
طبقة الاستخراج تضيف [f{fileIndex}-{start}-{end}] في نهاية المقاطع:
const position = `[f${fileIndex}-${absOffset}-${absOffset + segment.length}]`;
fileLines.push(segment.text.trim() + position);
سواء ملخصات المعالجة المسبقة أو مقتطفات Tool، المواضع تتماشى مع إزاحات أحرف Spine—لا أرقام صفحات يخمّنها النموذج.
5.2 قيود على مخرجات النموذج
System Prompt يتضمن Position Citation Rules—خمس نقاط أساسية:
- تنسيق قياسي: يجب استخدام
[f_fileIndex-startChar-endChar]؛ الأجزاء الثلاثة الرقمية مطلوبة؛ - نسخ من المصادر الحالية فقط: الحواشي حرفيًا من رسائل system/user أو مرتجعات Tool لهذه الجولة؛
- لا اختلاق: لا تحسب أو تعدّل أو تخترع مواضع؛
- تفضيل الإغفال: إن لم توجد علامة صالحة في السياق، أجب عاديًا—لا تخرج علامات موضع؛
- inline مع الادعاء: العلامات تتبع الجملة ذات الصلة؛ لا قوائم استشهاد في النهاية.
الواجهة أيضًا ترشّح علامات جزئية غير صالحة أحيانًا (مثل [f1-293]) قبل العرض.

VI. Tool Calling: استرجع أولًا، أجب ثانيًا
عند ربط المحادثة بكتاب (resourceId موجود، chatType === 'chat')، نسجّل أداتين مع executors قبل كل توليد—حلقة function calling متوافقة مع OpenAI.
6.1 get_related_segment_summaries — بحث مقاطع موجّه
لـ: مفاهيم، شخصيات، حبكة، تفاصيل فصول—نية استرجاع واضحة.
التدفق:
- النموذج يعيد صياغة كلام المستخدم إلى مصطلحات مرجحة في الكتاب («Optimize Search Queries» في System Prompt)؛
- استدعاء Tool مع
question؛ - تجميع كل ملخصات المقاطع حسب ميزانية tokens (~30k tokens لكل دفعة، بحد أقصى 5)؛
- كل دفعة: طلب LLM منفصل يختار معرفات مقاطع ذات صلة (بحد أقصى 5) من
{ id, title, summary }، JSON مثل{"Thinking":"...","answer":["1","3"]}؛ - للمقاطع المختارة، سحب نص مصدر بعلامات من Spine—لا ملخصات—كنتيجة Tool.
تصميم أساسي: Tool يعيد المصدر لا الملخصات. النموذج يجيب من فقرات حقيقية مع [f…] inline، متجنبًا انحراف «ملخص → إعادة تلخيص».
6.2 get_full_book_segment_summaries — نظرة عامة على الكتاب
لـ: «لخّص الكتاب»، «راجع هذا الكتاب»، «البنية/الموضوعات العامة»—رؤية شاملة.
دمج كل حقول summary للمقاطع بترتيب القراءة—تجنب فقدان فصول رئيسية بالاعتماد على الصلة لكل جزء فقط.
6.3 System Prompt: الكتاب أولًا، الأدوات أولًا
مع كتاب مربوط، يُطبَّق Core Principles for Reading Assistant:
1. Book First, Tool First
- أي سؤال قد يخص الكتاب يجب أن يستدعي الأدوات أولًا؛
- الإجابات يجب أن تعتمد أساسًا على الاسترجاع—لا تختلق «محتوى الكتاب» بلا استرجاع.
2. General Knowledge as Fallback Only
- فقط لـ: دردشة عادية / المستخدم يتخطى الكتاب صراحة / الأدوات بلا نتيجة؛
- إن لم يكن في الكتاب، قل «غير مذكور في هذا الكتاب» قبل المعرفة العامة.
3. Direct Style
- اذهب للموضوع—تجنب «بناءً على المواد المقدمة…» وما شابه.
التوليد يشغّل حلقة الأدوات: tool_calls → تنفيذ → إضافة role: tool → متابعة حتى النص النهائي. مع تفعيل الأدوات، قناة thinking تُغلق لتجنب تعارض البروتوكول.
VII. تتبع الواجهة: من الحاشية إلى التمييز
مخرجات النموذج [f5-123-165] لا تُعرض خامًا؛ طبقة العرض تحوّلها لاستشهادات قابلة للنقر.
7.1 عرض الحواشي
تطبيع العلامات لروابط Markdown مثل [1]([f5-123-165])، عرض كحواشي مرقمة؛ إزالة تكرار نفس الموضع.
7.2 تفاعل النقر
- أول نقرة: تحليل
[f…]→ fileIndex + offsets → استخراج نص Spine → معاينة (عنوان TOC اختياري)؛ - نفس الحاشية مرة أخرى: إغلاق المعاينة؛
- تأكيد القفز: فتح عرض القراءة، تمييز نطاق الأحرف.
من علامة النموذج المنسوخة إلى المصدر الذي يراه المستخدم، السلسلة لا تمر باستدعاء LLM آخر—حتمية وقابلة لإعادة الإنتاج.
VIII. حالات حدية وتدهور صادق
صفر هلوسة ≠ «دائمًا هناك إجابة»—يعني بلا دليل، بلا اختلاق:
| السيناريو | السلوك |
|---|---|
| ملخصات المقاطع غير جاهزة | استخراج النص الكامل والتلخيص أولًا |
| Tool لا يجد شيئًا | إرجاع (No relevant segment excerpts found…)؛ النموذج يقول غير موجود في الكتاب |
| علامات جزئية غير صالحة من النموذج | الواجهة ترشّح؛ لا حواشي مكسورة |
| دردشة عادية | System Prompt يسمح بالمعرفة العامة خارج الكتاب |
| تصدير المحادثة | الحواشي قد تصبح deep links للقارئ للمشاركة/الأرشفة |

IX. مقايضة التصميم: لماذا ليس «vector RAG»؟
زملاء في Q&A للمستندات يسألون: إن كنتم تفعلون retrieval-augmented generation، لماذا ليس Embedding + vector DB Top-K؟
نحن نفعل RAG—استرجاع قبل التوليد. الفرق: «RAG» في خطاب المجتمع غالبًا يعني تشابه متجهات؛ مرحلتنا 3 هي فهرس مقاطع + Tool لسحب المصدر عند الطلب—بلا طبقة متجهات عن قصد. فيما يلي أسباب معمارية، دون إنكار قيمة vector RAG.
النطاق: ليس «بلا استرجاع»، بل «بلا استرجاع متجهات»
- RAG واسع: استرجاع → توليد → نفعل هذا؛
- Vector RAG: استدعاء عبر تشابه embedding → ليس في هذا الإصدار.
المعالجة المسبقة تبني فهرس ملخصات مقاطع؛ النموذج يختار مقاطع عبر Tools ويحصل على نص مصدر. الاسترجاع موجود بلا نموذج embedding منفصل ولا صيانة فهرس متجهات.
السبب 1: مزودو LLM مخصصون—إبقاء سطح التكامل صغيرًا
يمكن للمستخدمين ربط مفاتيح API الخاصة، عناوين base مخصصة، أو Ollama محلي—نموذج المحادثة اختيارهم؛ التكلفة ومسار البيانات تحت السيطرة.
vector RAG النموذجي يوسّع التكامل:
- إلى جانب نموذج المحادثة، غالبًا تحتاج نموذج embedding (اسم آخر، أحيانًا endpoint آخر)؛
- Ollama المحلي يحتاج نموذج embedding منفصل وتوافق الأبعاد/API؛
- أوضاع فشل أكثر: المحادثة تعمل لكن استرجاع فارغ—embedding أو الفهرس أو الأبعاد غير متسقة؛ أصعب تشخيصًا من مزود واحد من طرف لطرف.
هنا، اختيار المقاطع والإجابة يشاركان إعداد المزود نفسه—لا «محادثة على A وفهرس على B». لتطبيقات LLM قابلة للتوصيل، ذلك غالبًا أهم من نقاط recall إضافية.

السبب 2: Embeddings مربوطة بالفهرس—تبديل المزود مكلف
في vector RAG، المتجهات ليست تنسيقًا وسيطًا عالميًا—إنها إحداثيات تحت نموذج embedding واحد. فهرسة بـ A واستعلام بـ B: التشابه عادة غير قابل للمقارنة—غالبًا إعادة تضمين كاملة، والأبعاد (768 / 1024 / 1536 …) تقفل مخطط التخزين.
المرحلة 3 تخزّن ملخصات منظمة + spans أحرف، لا متجهات؛ تبديل نموذج المحادثة لا يعيد بناء الفهرس؛ سلسلة الدليل (مواضع المصدر) ثابتة—متوافق مع «جرّب LLMs مختلفة في أي وقت».
السبب 3: التوجيه المنظم يكفي غالبًا للمستندات الطويلة الغنية بـ TOC
الكتب الإلكترونية وPDF لها عادة بنية فصول؛ المعالجة المسبقة تنتج عناوين مقاطع + ملخصات. لـ «ماذا يقول الفصل X» أو «كيف يعرّف الكتاب Y»، الاختيار من الكتالوج ثم سحب المصدر يعمل جيدًا عمليًا؛ Tool يعيد مصدرًا مع [f…]، صفر هلوسة يثبت على spans أحرف.
المتجهات تساعد في دلالات ضبابية وتعدد لغات وعدم تطابق حرفي لامتدادات طويلة؛ لقراء بـ TOC + معالجة مسبقة + تتبع قوي، الاستثمار في Tool + إرجاع المصدر + قواعد الاستشهاد غالبًا ROI أعلى.
المستقبل: استدعاء هجين، لا إعادة كتابة
قد نضيف استدعاء متجهات خشن (embedding فقط لـ Top-N فصول مرشحة)، ما زال ينتهي بـ اختيار مقطع → مصدر → تتبع قابل للنقر—قواعد صفر هلوسة دون تغيير. إن أُضيف: embedding اختياري، تنبيهات إعادة فهرسة صريحة عند تغيير النماذج—تجنب استرجاع خاطئ صامت.
حتى ذلك الحين: أي API محادثة متوافقة مع OpenAI تعمل؛ تغيير نموذج المحادثة لا يعيد بناء الفهرس المحلي.
X. ملخص
| الخطوة | الأسلوب | الدور |
|---|---|---|
| معالجة مسبقة | تقسيم TOC/طول + cache ملخصات | كتب طويلة قابلة للبحث والتحديد |
| علامات موضع | [fملف-بداية-نهاية] في المصدر | مصدر قابل للتحليل آليا |
| Tool retrieval | مقاطع لكل سؤال / ملخصات الكتاب، إرجاع المصدر | إجبار الدليل قبل الإجابة |
| System Prompt | الكتاب أولًا، لا علامات مزيفة، قل عند الغياب | تقييد التوليد |
| الواجهة | حاشية → معاينة → قفز وتمييز | المستخدم يتحقق من الدليل |
| بلا استرجاع متجهات | مزود واحد؛ تبديل نموذج المحادثة بلا إعادة فهرسة | تكلفة تكامل وترحيل أقل |
«صفر هلوسة» لا يعني أن النموذج لا يخطئ أبدًا—يعني هندسة تقفل المخرجات على سلسلة دليل: بلا استرجاع → لا تتظاهر بمحتوى الكتاب؛ مع استرجاع → أعطِ مواضع مصدر قابلة للتحقق.
إن كنت تبني قراءة بالذكاء الاصطناعي أو Q&A للمستندات، نأمل أن مسار إدخال كامل → جمل رئيسية → Tool-first عند الطلب، مع علامات موضع inline + إرجاع المصدر، يكون تنفيذًا مرجعيًا مفيدًا.
هذه دروس من بناء قارئ Foxycape بالذكاء الاصطناعي—للمرجع فقط. جرّب القارئ في صفحة التحميل.
