استرجاع المعلومات2020متوسط10 دقيقة قراءة
الاسترجاع الكثيف للفقرات للإجابة عن الأسئلة في النطاق المفتوح
Dense Passage Retrieval for Open-Domain Question Answering
Karpukhin, V. · Oğuz, B. · Min, S. · Lewis, P. · Wu, L. · Edunov, S. · Chen, D. · Yih, W. — EMNLP
المشكلة
تحتاج أنظمة الإجابة عن الأسئلة المفتوحة إلى البحث في ملايين المستندات للعثور على الفقرة المناسبة. حتى عام 2020 كان الحلّ السائد هو خوارزمية التي تعود إلى التسعينيات، وتعتمد على مطابقة الكلمات حرفياً. المشكلة أنها تفشل حين تختلف الألفاظ رغم تطابق المعنى: إن كتبتَ «مناخ» لكن الفقرة تقول «طقس» فلن تجدها BM25. المحاولات السابقة لاستخدام التمثيلات الكثيفة كانت إما معقدة أو بطيئة أو أضعف أداءً من BM25 نفسها.
الإسهام
يقدّم DPR بنية بسيطة تستخدم نموذجَي BERT مستقلَّين: أحدهما يرمّز السؤال والآخر يرمّز الفقرة، ويُسقَط كلاهما في فضاء متجهي واحد ذي 768 بُعداً. التشابه بينهما مجرد ضرب نقطي. يُدرَّب النظام بعينات سلبية من داخل الدفعة مع عيّنة صعبة واحدة من BM25 لكل سؤال — وبنحو 59 ألف زوج سؤال-فقرة فقط يحقق نتائج مفاجئة. تُفهرَس 21 مليون فقرة من ويكيبيديا مسبقاً باستخدام FAISS لتمكين استرجاع في أجزاء من الثانية. حقّق DPR دقة %78.4 ضمن أعلى 20 نتيجة على مجموعة Natural Questions متفوقاً على BM25 بفارق 9–19%، وعند دمجه مع نموذج قارئ سجّل أفضل نتائج على عدة معايير مرجعية.
الأثر
أثبت DPR أن يستطيع التفوق حسماً على الطرق المبنية على الكلمات المفتاحية ببنية بسيطة. أصبح الركيزة الأساسية للاسترجاع في نموذج RAG (التوليد المعزّز بالاسترجاع)، وألهم منهج التفاعل المتأخر في ColBERT، ومهّد الطريق للتدريب المسبق غير المُشرَف عليه في Contriever، وغذّى القراءة متعددة الفقرات في FiD. كل أنظمة الاسترجاع الحديثة — من محركات البحث إلى المساعدات الذكية — تعود في أصلها إلى تصميم DPR ثنائي .
فكّر في BM25 كأنها فهرس ورقي في مكتبة: تبحث فيه بالكلمات نفسها الموجودة في سؤالك، فإن وجد بطاقة تطابق كلماتك أعادها لك. لكن لو سألتَ عن «الطاقة الشمسية» وكان أفضل مقال مصنّفاً تحت «الطاقة الكهروضوئية» فلن تجده أبداً.
DPR يستبدل هذا الفهرس بـأمين مكتبة يفهم مقصدك. يقرأ سؤالك ويستوعب ما تريد معرفته، ثم يذهب ويُحضر لك الفقرات الأقرب في المعنى — حتى لو لم تشترك مع سؤالك في كلمة واحدة.
المشكلة: مطابقة الكلمات تفشل حين يكون المعنى هو المهم
تعمل أنظمة الإجابة عن الأسئلة المفتوحة على مرحلتين: أولاً يبحث المسترجِع في ضخمة كويكيبيديا بأكملها ليجد الفقرات المرشحة، ثم يأتي القارئ ليستخرج الإجابة من تلك الفقرات. المسترجِع هو الحلقة الحرجة هنا — إذا لم يعثر على الفقرة الصحيحة فلن يستطيع القارئ فعل شيء.
حتى عام 2020 كانت BM25 هي المسترجِع المهيمن. تعمل هذه الخوارزمية بأسلوب : تحسب عدد كلمات السؤال التي تظهر في الفقرة مع إعطاء وزن أكبر للكلمات النادرة. هذا الأسلوب سريع وفعّال حين تتطابق الكلمات حرفياً، لكن فيه ثغرة جوهرية: التَّرادف. فالسؤال «مَن يرأس الحكومة في ألمانيا؟» وفقرة تقول «المستشار الاتحادي لجمهورية ألمانيا» لا يتشاركان تقريباً أي كلمة، مع أن الفقرة تجيب عن السؤال تماماً.
المحاولات السابقة لبناء استرجاع كثيف اعتمدت على سلاسل معالجة معقدة — تدريب مسبق بمهام مثل الاستنساخ العكسي، أو تدريب متعدد المراحل، أو نماذج متغيرات كامنة. أضافت كل هذه الأساليب تعقيداً كبيراً دون أن تتفوق بشكل ثابت على BM25. كان الوضع محبطاً: الجميع يعلم أن الفهم الدلالي ينبغي أن يتفوق على مطابقة الكلمات، لكن لم ينجح أحد في تحقيق ذلك بطريقة بسيطة وعملية.
الفكرة: مُرمِّزان وفضاء مشترك واحد
ما يميّز DPR هو بساطته الشديدة. الفكرة أن تأخذ نسختين من BERT: واحدة مُرمِّز للأسئلة وأخرى للفقرات. كل مُرمِّز يقرأ مدخله ويضغطه في واحد بـ 768 بُعداً — هو الحالة الخفية الأخيرة لرمز [CLS]. بعد هذه الخطوة يصبح السؤال والفقرة نقطتين في واحد مشترك. قياس التشابه بينهما هو ببساطة : كلما أشار المتجهان في الاتجاه نفسه ارتفعت قيمة الضرب النقطي.
تصوّر الأمر وكأنك تُعطي كل سؤال وكل فقرة إحداثيات GPS في فضاء المعاني. الإحداثيات المتقاربة تعني معاني متقاربة. فالسؤال «متى اكتُشف البنسلين؟» والفقرة «اكتشف ألكسندر فلمنج البنسلين عام 1928» ينبغي أن يقعا بالقرب من بعضهما، رغم أنهما لا يتشاركان إلا كلمة واحدة.
تُعرَف هذه البنية باسم (أو ): مُرمِّزان مستقلان لا يطّلع أحدهما على مُدخَل الآخر، ولا يربطهما سوى الفضاء المتجهي المشترك الذي يُسقطان فيه. هذا الاستقلال هو سرّ سرعة DPR، لأنه يتيح حساب متجهات جميع الفقرات مسبقاً دون اتصال بالإنترنت.
التدريب: فنّ اختيار العيّنات السلبية
يُدرَّب DPR باستخدام : ادفع أزواج السؤال والفقرة الصحيحة لتكون أقرب في الفضاء المتجهي، وادفع الأزواج غير المرتبطة لتكون أبعد. هنا هي السالب اللوغاريتمي لاحتمال الفقرة الصحيحة، أي كأنك تسأل النموذج: «من بين كل الفقرات في هذه الدفعة، هل تستطيع تحديد الفقرة الصحيحة؟»
الملاحظة الجوهرية هنا هي أيّ عيّنات سلبية نختارها للتدريب. جرّب DPR ثلاثة أنواع:
- عيّنات سلبية عشوائية: فقرة عشوائية من المدوّنة. هذه سهلة جداً على النموذج — أسهل مما ينبغي — فبالكاد يتعلم منها شيئاً.
- من BM25: فقرات ترتّبها BM25 في مراتب عالية لكنها لا تحتوي فعلاً على الإجابة. خطورتها أنها تتشارك كلمات مع السؤال فتبدو للنموذج كأنها صحيحة. عيّنة صعبة واحدة لكل سؤال رفعت النتائج بشكل ملحوظ.
- : الفقرات الإيجابية للأسئلة الأخرى في دفعة التدريب نفسها تتحول تلقائياً إلى عيّنات سلبية لهذا السؤال. بحجم دفعة 128 يحصل كل سؤال على 127 عيّنة سلبية مجاناً دون أي حساب إضافي.
الوصفة الناجحة كانت العيّنات السلبية من داخل الدفعة + عيّنة صعبة واحدة من BM25. أما العيّنات السلبية المُعنوَنة يدوياً فقد أضرّت بالأداء، لأن المُعنوِنين البشريين يميلون لاختيار فقرات قريبة من الإجابة الصحيحة، فيتلقى النموذج إشارات تدريبية مربكة.
الاسترجاع على نطاق واسع: الفهرسة المسبقة باستخدام FAISS
بنية المُرمِّز الثنائي تتميز بخاصية جوهرية: مُرمِّز الفقرة ومُرمِّز السؤال مستقلان تماماً. هذا يعني أنك تستطيع ترميز 21 مليون فقرة من ويكيبيديا مرة واحدة وتخزين متجهاتها. عند وصول سؤال جديد لا تحتاج إلا لترميز السؤال وحده — واحدة عبر BERT صغير.
لكن البحث في 21 مليون متجه بـ 768 بُعداً بالطريقة المباشرة بطيء جداً. هنا يظهر دور FAISS (مكتبة بحث التشابه من فيسبوك). يبني FAISS فهرساً هرمياً يدعم : بدلاً من مقارنة السؤال بكل المتجهات يقسّم الفضاء إلى عناقيد ويبحث فقط في العناقيد القريبة من متجه السؤال.
عند تسير العملية كالتالي: (1) رمِّز السؤال إلى متجه بـ 768 بُعداً، (2) استعلم FAISS لاسترجاع أقرب k فقرة، (3) مرِّر تلك الفقرات إلى نموذج قارئ يستخرج نطاق الإجابة. خطوة الاسترجاع كلها تستغرق أجزاءً من الثانية.
هذا النموذج القائم على الفهرسة المسبقة هو ما جعل DPR العمود الفقري لأنظمة الاسترجاع في بيئات الإنتاج. تدفع تكلفة الترميز مرة واحدة ثم تخدم ملايين الاستعلامات على الفهرس نفسه. ولتحديث الفهرس لا تحتاج إلا لإعادة ترميز الفقرات التي تغيّرت.
داخل الفضاء المتجهي: حيث تلتقي الأسئلة بالفقرات
قوة DPR تظهر فيما يحدث داخل المشترك. قبل التدريب تكون متجهات [CLS] للأسئلة والفقرات متبعثرة عشوائياً — سؤال عن البنسلين قد يقع بعيداً عن فقرة تتحدث عن فلمنج. بعد التدريب تكون التبايُنية قد أعادت تشكيل هذا الفضاء بحيث يتجمّع كل سؤال بالقرب من الفقرات التي تحمل إجابته.
هذا يختلف جذرياً عمّا يفعله Sentence-BERT. يبني Sentence-BERT فضاءً متماثلاً تتقارب فيه الجمل المتشابهة. أما DPR فيبني فضاءً غير متماثل يتقارب فيه كل سؤال مع إجابته وليس مع أسئلة تشبهه. فالسؤال «مَن اكتشف البنسلين؟» بعيد عن «مَن اخترع الهاتف؟» في فضاء DPR رغم تشابههما في الصياغة — لأن فقرات إجاباتهما تقع في مناطق مختلفة تماماً.
اختيار الضرب النقطي كمقياس للتشابه قرار مدروس. على خلاف الذي يُهمل طول المتجه، يسمح الضرب النقطي لمتجهات بأطوال مختلفة بالتعبير عن مستويات ثقة مختلفة. المُرمِّز الذي يُنتج متجهاً أطول يكون كأنه «يرفع صوته» — فيُسترجَع أكثر. هذا يمنح النموذج درجة حرية إضافية للتعبير عن قوة ارتباط الفقرة بالموضوع المطلوب.
تحليل المكوّنات: لماذا اختيار العيّنات السلبية هو كل شيء
كشف تحليل المكوّنات في الورقة عن تسلسل مفاجئ في تأثير أنواع العيّنات السلبية. باستخدام العيّنات العشوائية فقط بلغت الدقة نحو 54% ضمن أعلى 20 نتيجة على مجموعة Natural Questions. بإضافة العيّنات السلبية من داخل الدفعة قفزت إلى نحو 68%. وبإضافة عيّنة صعبة واحدة من BM25 لكل سؤال وصلت إلى نحو 78%.
لماذا تُحدث عيّنة صعبة واحدة كل هذا الفرق؟ لأنها تُجبر النموذج على حل مسألة التمييز الصعبة. العيّنات العشوائية خاطئة بشكل واضح — فقرة عن الطبخ لن تُربك نموذجاً يبحث عن إجابة في الفيزياء. لكن عيّنات BM25 تتشارك كلمات سطحية مع السؤال، فيُضطر النموذج للنظر أعمق من الكلمات إلى المعنى الحقيقي. الأمر يشبه الاستعداد لامتحان بأسئلة خادعة: تتعلم منها أكثر بكثير مما تتعلم من الأسئلة السهلة.
المثير للاهتمام أن العيّنات السلبية المُعنوَنة يدوياً أضرّت بالأداء فعلاً. يفترض المؤلفون أن السبب هو قربها الشديد من الإجابات الصحيحة — فقد تكون إجابات بديلة صحيحة أو شبه صحيحة، فتُربك إشارة التدريب بدلاً من أن توضّحها.
الفكرة نفسها في الكود
مبسَّط لإظهار الفكرة — ليس التنفيذ الحقيقي.
import numpy as np
def encode_question(question_text, bert_q):
"""رمِّز السؤال ← متجه 768 بُعداً عبر [CLS] من BERT-السؤال."""
tokens = tokenize("[CLS] " + question_text + " [SEP]")
hidden = bert_q(tokens) # (طول_التسلسل, 768)
return hidden[0] # متجه [CLS] ← (768,)
def encode_passage(passage_text, bert_p):
"""رمِّز الفقرة ← متجه 768 بُعداً عبر [CLS] من BERT-الفقرة."""
tokens = tokenize("[CLS] " + passage_text + " [SEP]")
hidden = bert_p(tokens)
return hidden[0] # متجه [CLS] ← (768,)
def similarity(q_vec, p_vec):
"""الضرب النقطي — مقياس المسافة الوحيد الذي يحتاجه DPR."""
return q_vec @ p_vec # عدد قياسي
def nll_loss(q_vec, pos_vec, neg_vecs):
"""خسارة السالب اللوغاريتمي: قرِّب الإيجابيات وأبعِد السلبيات."""
pos_score = similarity(q_vec, pos_vec)
all_scores = [pos_score] + [similarity(q_vec, n) for n in neg_vecs]
log_sum_exp = np.log(sum(np.exp(s) for s in all_scores))
return log_sum_exp - pos_score # صغِّر هذه القيمة
def retrieve_top_k(question, faiss_index, bert_q, k=20):
"""عند الاستدلال: رمِّز السؤال، ابحث في FAISS، أعِد الفقرات."""
q_vec = encode_question(question, bert_q)
scores, indices = faiss_index.search(q_vec.reshape(1, -1), k)
return indices[0], scores[0] # أعلى k من معرّفات الفقرات ودرجاتها
# هذا هو مسترجِع DPR بالكامل. نموذجا BERT وضرب نقطي وFAISS.
# القارئ (مستخرج الإجابة) نموذج منفصل يعمل فوقه.لماذا كان DPR مؤثراً
2019
Sentence-BERT
شبكات BERT المتوازية لقياس تشابه الجمل. أنتجت تضمينات متماثلة فعّالة لكنها لم تكن مصمَّمة لمهمة الاسترجاع غير المتماثل بين السؤال والفقرة.
2020
DPR — الاسترجاع الكثيف للفقرات
أثبت أن الاسترجاع الكثيف يتفوق على BM25 ببنية بسيطة ثنائية المُرمِّز. عيّنات سلبية من داخل الدفعة + عيّنة صعبة من BM25 = دقة %78.4 ضمن أعلى 20.
2020
RAG — التوليد المعزّز بالاسترجاع
استخدم DPR كركيزة للاسترجاع داخل نموذج توليدي. بدلاً من استخراج مقطع الإجابة من النص، يولّد RAG إجابات حرة الصياغة بالاعتماد على الفقرات المسترجعة.
2020
ColBERT — التفاعل المتأخر
احتفظ بفكرة الترميز المستقل من DPR لكنه أبقى على تضمين كل رمز بدلاً من ضغطها جميعاً في متجه [CLS] واحد. التفاعل المتأخر يتيح مطابقة أدق بتكلفة إضافية معقولة.
2021
FiD — الدمج في فاكّ الترميز
استرجع 100 فقرة باستخدام DPR ورمّز كلاً منها على حدة ثم دمجها في فاكّ الترميز. أظهر أن زيادة عدد الفقرات تعني إجابات أفضل، مما يؤكد قوة الاستدعاء لدى DPR.
2022
Contriever — الاسترجاع الكثيف بلا إشراف
طوّر فكرة DPR بتدريب مسبق غير مُشرَف عليه عبر التعلُّم التبايُني على بيانات غير مُعنوَنة. لا حاجة لأزواج سؤال-فقرة في التدريب المسبق، بل فقط عند الضبط الدقيق.
الأثر الأعمق لـ DPR هو التحوّل الجذري الذي أثبته: لست بحاجة إلى سمات مصمَّمة يدوياً ولا سلاسل معالجة معقدة لتتفوق على أنظمة التي عمرها عقود. يكفي نموذجا لغة مُدرَّبان مسبقاً وضرب نقطي واختيار ذكي للعيّنات السلبية. كل نظام استرجاع حديث — من خطوط RAG إلى البحث المؤسسي إلى طبقة الاسترجاع في المساعدات الذكية — يرث هذا التصميم.
المرجعKarpukhin, Oguz, Min, Lewis, Wu, Edunov, Chen, Yih. Dense Passage Retrieval for Open-Domain Question Answering. EMNLP, 2020.
مصطلحات هذه الورقة
- الاسترجاع الكثيفDense Retrieval
- المُرمِّز الثنائيDual Encoder
- استرجاع الفقراتPassage Retrieval
- BM25BM25
- فايس (FAISS)FAISS
- سلبيات داخل الدُّفعةIn-Batch Negatives
- السلبيات الصعبةHard Negatives
- الاسترجاع المتناثرSparse Retrieval
- الجار الأقرب التقريبيApproximate Nearest Neighbor
- الإجابة المفتوحة عن الأسئلةOpen-Domain Question Answering