البحث المدمَج متعدد الأنماط: اختيار المسترجِع الصحيح لكل استعلام
> استعلام مثل "أين يُعرَّف parseConfig" يحتاج إلى بحث مختلف عن "كيف تعمل المصادقة". يصنِّف Maguyva النية، ويُرجِّح أربعة أنماط استرجاع تبعًا لذلك، ثم يدمج النتائج عبر Reciprocal Rank Fusion الموزون.
ملاحظة عن التصميم التاريخي: تصف هذه المقالة من أبريل 2026 تصميم التوجيه آنذاك، لا السلوك الافتراضي الحالي. يعالج تصحيح سبتمبر أدناه ادعاءً متعلقًا بالقياس فقط. للاطلاع على التوجيه الحالي والإعدادات المسبقة والتحكم الصريح في أنماط البحث، راجع آلية العمل.
استعلام البحث ليس شيئًا واحدًا.
“أين يُعرَّف parseConfig” يريد رمزًا دقيقًا — موقعًا واحدًا محدَّدًا، بسرعة. “كيف تعمل المصادقة” يريد المعنى — مجموعة أجزاء الكود ذات الصلة التي تشرح مفهومًا. “ما الذي ينكسر إذا غيّرت هذه الدالة” يريد الرسم البياني للتبعيات. “ابحث عن السلسلة ECONNREFUSED” يريد مطابقة حرفية، لا شيء ذكيًا.
grep ممتاز للمطابقات الحرفية ومفيد لبعض عمليات البحث عن المراجع، لكنه ليس رسمًا بيانيًا للتبعيات ولا يفهم المعنى. تُغطِّي التضمينات الجانب الدلالي، لكنها الأداة الخطأ للسلاسل الدقيقة وتحليل التأثير. تختار معظم أدوات بحث الكود محركًا واحدًا وتُلزم كل استعلام بذلك الاختيار. Maguyva لا يختار. إنه يستنتج نوع السؤال الذي طرحته، ثم يمزج أربعة مسترجِعات بالنسبة التي يستحقها ذلك السؤال.
أربعة أنماط
تحت الغطاء، توجد أربع طرق مستقلة لإيجاد الكود:
- الدلالي (semantic) — بحث متجهي عبر تضمينات Voyage الثنائية (binary)؛ يجد الكود بالمعنى.
- النصي (text) — مطابقة المقاطع الثلاثية (trigram)؛ يجد السلاسل الحرفية، وسلاسل الأخطاء، والمعرِّفات الدقيقة.
- البنيوي (structural) — استعلامات AST؛ يجد التعريفات، والتوقيعات، وبُنى اللغة.
- الرسم البياني (graph) — رسم بياني للتبعيات؛ يجد الدوال المُستدعِية، والدوال المُستدعاة، ونطاق التأثير.
كل واحد قوي في فئة مختلفة من الأسئلة. الحيلة هي تحديد مقدار الثقة التي تُمنَح لكل واحد بالنسبة إلى الاستعلام الذي أمامك.
تصنيف النية
قبل تشغيل أي استرجاع، يُصنِّف مُصنِّف خفيف الوزن الاستعلام إلى واحدة من ست نوايا، بدرجة ثقة. إنه قليل التكلفة عمدًا — أساليب استدلال مرتَّبة، وتفوز أول مطابقة — لأنه يعمل على المسار الساخن ولا يضيف سوى ميلي ثانية أو اثنتين:
- يبدأ بـ
def،class،func،import… → find_definition (ثقة 0.95) - “who calls” (من يستدعي)، “usages of” (استخدامات لـ)، “references to” (مراجع إلى) → find_references (0.90)
- “impact” (التأثير)، “blast radius” (نطاق التأثير)، “what depends on” (ما الذي يعتمد على) → impact_analysis (0.90)
"string"مقتبَس أو رمز خطأ مثلtraceback→ exact_match (0.85–0.90)- معرِّف
CamelCaseأوsnake_case→ find_definition (0.60–0.80) - “how” (كيف)، “why” (لماذا)، “explain” (اشرح)، “architecture” (البنية المعمارية) → understand_code (0.75)
- لا شيء يطابق → understand_code، ثقة منخفضة (0.40)
تحمل كل نية مجموعة أوزان عبر الأنماط الأربعة. هذه هي الأرقام الحقيقية:
| النية | الدلالي | النصي | البنيوي (AST) | الرسم البياني |
|---|---|---|---|---|
| find_definition | 0.2 | 0.1 | 0.6 | 0.1 |
| find_references | 0.1 | 0.2 | 0.2 | 0.5 |
| understand_code | 0.5 | 0.2 | 0.2 | 0.1 |
| find_similar | 0.4 | 0.3 | 0.2 | 0.1 |
| impact_analysis | 0.1 | 0.1 | 0.1 | 0.7 |
| exact_match | 0.0 | 0.9 | 0.1 | 0.0 |
إذًا “أين يُعرَّف parseConfig” يعتمد بشدة على AST (0.6). “كيف تعمل المصادقة” يعتمد على المتجهات الدلالية (0.5). “ما الذي يعتمد على هذا” هو تقريبًا كله رسم بياني (0.7). “ابحث عن ECONNREFUSED” هو تقريبًا كله مطابقة المقاطع الثلاثية (0.9)، مع إيقاف نموذج التضمين تمامًا — لأن التشابه الدلالي هو بالضبط الأداة الخطأ لسلسلة حرفية دقيقة.
المسار السريع، والمسار المدمَج
عندما يكون المصنِّف واثقًا — درجة ≥ 0.85 — ويكون الاستعلام عاديًا، يتخطى Maguyva الدمج تمامًا ويوجِّه مباشرة إلى النمط المهيمِن الواحد. “أين يُعرَّف X” لا يحتاج إلى أربعة مسترجِعات؛ إنه يحتاج إلى فهرس AST، الآن. يُبلَّغ عن هذا المسار المباشر باسم fusion_strategy: "direct".
يمر كل ما هو غامض عبر الدمج. تعمل الأنماط الأربعة (أو الثلاثة، في الإعداد الافتراضي) بالتوازي، ويُعيد كل واحد قائمته المُرتَّبة الخاصة، وندمجها معًا.
دمج الرتب التبادلي الموزون (Weighted Reciprocal Rank Fusion)
دمج مسترجِعات متغايرة أصعب مما يبدو: تشابه جيب تمام بقيمة 0.82، ودرجة مطابقة مقاطع ثلاثية بقيمة 137، ومركزية رسم بياني بقيمة 0.004 ليست على المقياس نفسه، لذا لا يمكنك ببساطة جمعها. يتفادى دمج الرتب التبادلي (RRF) المشكلة بتجاهل الدرجات الخام والاحتفاظ فقط بـالرتبة التي منحها كل محرك. مساهمة نتيجة من نمط واحد هي:
contribution = weight × 1 / (k + rank + 1)
حيث rank هي موضعها في قائمة ذلك النمط وk ثابت تنعيم. تُجمَع المساهمات عبر الأنماط لأي نتيجة وجدها أكثر من محرك — يطفو الاتفاق بين المسترجِعات طبيعيًا إلى القمة. نستخدم k = 40 في الإعداد الافتراضي و60 في thorough (quick يعمل دلاليًا فقط، لذا لا يتدخل الدمج هناك أبدًا). استقر عمل RRF الأصلي على k = 60 للاسترجاع العام؛ نحن نفترض قيمة افتراضية تمنح الرتب الأولى أفضلية أكبر قليلًا، مما يمنح الاتفاق الأعلى رتبة بين الأنماط وزنًا أكبر قليلًا — ولا نوصي بضبطها يدويًا.
فوق ذلك، تحمل النتائج تعزيزًا لأهمية الرسم البياني. يجب أن تتفوق عقدة محورية — دالة تعتمد عليها قاعدة الكود بأكملها — على عقدة طرفية قليلة الاستخدام حتى عند التساوي في الأهمية النصية، لذا نضرب كل مساهمة في:
boost = min(1 + 0.3 × ln(1 + centrality), 1.5)
تأتي المركزية من مقاييس PageRank/الدرجة المحسوبة مسبقًا لخط الأنابيب، ويُقيَّد التعزيز عند 1.5× كي لا تستطيع دالة شائعة أن تدفن تمامًا دالة غامضة أكثر صلة. أخيرًا، نُخفِّض رتبة النتائج من مسارات مكتبات الأطراف الخارجية (vendor)، والبناء (build)، والأرشيف، ونزيل التكرار مع الاحتفاظ بأفضل جزء لكل ملف.
ما لا يزال غير كامل
مصنّف النوايا مجموعة من التعبيرات النمطية، وليس نموذجًا مدرّبًا. يعالج أنماط الاستعلام الشائعة بقواعد استدلالية، ويعود الاستعلام الملتبس إلى understand_code ومزيج يميل إلى البحث الدلالي. وصفت نسخة سابقة من هذه المقالة انخفاض معدل الاستعلامات بلا نتائج من نحو 15% إلى أقل من 5% بأنه تحقق بالفعل. لكن مقترح ديسمبر 2025 كان يسرد في الواقع خط أساس تقديريًا وهدفًا؛ ولم تُقدّم مجموعة استعلامات أو سجل قياس يدعمان ذلك. نسحب الادعاء بتحقيق هذا التحسن؛ راجع أدلة المصدر والتصحيح. لم نستبدل المصنّف بنموذج مدرّب لأن النسخة قليلة التكلفة سريعة وكافية لدورها المقصود في التوجيه، ولأن مصنّفًا مخطئًا وواثقًا أسوأ من رجوع صريح إلى الخيار الافتراضي. الأوزان نفسها افتراضات أولية اختيرت يدويًا، وليست متعلَّمة من بيانات نقرات لا نجمعها.
اطرح سؤالك ودع النظام يختار الأداة
لا ينبغي أن يحتاج الوكيل إلى معرفة ما إذا كان يلجأ إلى grep أو التضمينات أو رسم الاستدعاء البياني — بل ينبغي أن يطرح سؤاله بعبارات بسيطة ويحصل على الإجابة الصحيحة. الدمج متعدد الأنماط هو ما يتيح لـfind_symbol، والبحث الدلالي، وتحليل التبعيات أن تتاح عبر واجهة استعلام واحدة: يقرأ النظام شكل السؤال ويُجمِّع بصمت المسترجِع الصحيح له. النموذج الذي يُقيِّم التضمينات مهم، لكن معرفة متى لا تُستخدَم مهمة أيضًا. اختيار الأداة الصحيحة لكل استعلام نوع خاص به من الجودة، وهو نوع نُفضِّل تولّيه بأنفسنا بدلًا من تحميله على المُستدعِي.
// you bring the question. it brings the tools.
قراءات ذات صلة
المزيد من سجل بناء Maguyva
لماذا رقّينا بحث الكود إلى voyage-4-large_
انتقلنا بتضميناتنا للكود إلى voyage-4-large — الذي يتصدر حاليًا لوحة صدارة RTEB العامة لاسترجاع الكود. النسخة الصادقة: المقايضة التي نقبلها، وما نُفهرِسه فعليًا، ولماذا ندفع مقابل تضمينات متميزة.
مراقبة الوكلاء (Observability): الخطافات (Hooks) وAlloy وGrafana_
ربطنا Claude Code وCodex بمكدس Grafana واحد باستخدام OpenTelemetry وAlloy، ثم استخدمنا التتبعات (traces) والسجلات لإيجاد مشكلات سلوك الوكلاء وإصلاحها من مصدرها.
تعدين الحلقة: كيف تتحول التغييرات إلى ذاكرة مؤسسية_
تتحول إيداعات Git إلى مدخلات سجل تغييرات منظَّمة وسجلات قرارات معمارية، ثم تُغذّي وكلاء الذكاء الاصطناعي كذاكرة مؤسسية قابلة للاستعلام.