بناء مخطط معرفي واحد عبر 46 مستودعاً
أنا رايان، المدير التقني (CTO) في airCloset.
قضيت ثلاثة أشهر في بناء code-graph. وهو عبارة عن مخطط معرفي واحد يوحد 46 مستودعاً عبر خدمات متعددة.
يعتقد الكثيرون أنه يمكنك ببساطة تسليم كل الكود الخاص بك إلى ذكاء اصطناعي وطرح الأسئلة. هذا يفشل لسببين:
- نوافذ السياق (Context windows): لا يمكنك وضع سنوات من الكود من 46 مستودعاً في مطالبة (prompt) واحدة.
- الهلوسة (Hallucination): يرتكب الذكاء الاصطناعي أخطاءً عندما يحاول استنتاج العلاقات، حيث يفقد الروابط بينها.
ولحل هذه المشكلة، استخدمت التحليل الساكن (static analysis) لبناء مصدر موثوق للحقيقة (source of truth).
التحدي: تجاوز الحدود
قاعدة الكود الكبيرة تكون فوضوية. قد يتم استدعاء واجهة برمجة تطبيقات (API) واحدة من قبل خمسة مستودعات مختلفة. وقد يتم استخدام جدول قاعدة بيانات واحد من قبل ثلاث خدمات مختلفة.
إذا نظرت إلى مستودع واحد فقط، فستفقد الصورة الكاملة. وهذا أمر خطير؛ فإذا قمت بتغيير الكود ولم تدرك نطاق التأثير الحقيقي (blast radius)، فستتسبب في تعطل النظام.
يعتمد نهجي على استخدام tree-sitter لتحليل الكود إلى أشجار بناء جملة (syntax trees). لكن tree-sitter وحده لا يمكنه الرؤية عبر حدود المستودعات.
لقد قمت ببناء عقد حدودية (boundary nodes) لحل هذه المشكلة.
كيف يعمل الأمر:
- نستخرج العلاقات داخل المستودع باستخدام tree-sitter.
- نستخدم TypeScript Compiler API لفك رموز الأنواع والمتغيرات.
- نستخدم Gemini للتعامل مع الحالات الديناميكية التي تغفل عنها الأدوات.
بدلاً من مطالبة الذكاء الاصطناعي بالتخمين، نحن نعطيه حقائق. نخبره: "يتم استدعاء هذه الـ API أيضاً من المستودع X". هذا يمنع الهلوسة.
الجزء الصعب: غابة أطر العمل (The Framework Zoo)
كانت المعركة الحقيقية هي استخراج هذه الحدود. فكل إطار عمل يكتب الحدود بطريقة مختلفة.
يستخدم أحد الفرق NestJS decorators، ويستخدم فريق آخر Express routes، بينما يستخدم فريق ثالث jQuery الخام. كل منها ينشئ بنية مختلفة في الكود.
لجعل هذا يعمل، كان علينا بناء محللات مخصصة (custom parsers) لكل من:
- NestJS و TypeORM
- Express و Fastify
- AngularJS و Redux
- مخططات أسماء المسارات المستعارة (path-alias schemes) المختلفة
كان علينا استهداف دقة تصل إلى 99%. فإذا كانت نسبة الربط لدينا 90% فقط، فإن الذكاء الاصطناعي سيفقد 10% من الروابط. وفي أنظمة الإنتاج، هذا الـ 10% هو المكان الذي تختبئ فيه الأخطاء (bugs).
نقوم الآن بإجراء فحص يومي. إذا انخفضت نسبة الربط لدينا بأكثر من 5%، نتلقى تنبيهاً. هذا يساعدنا في اكتشاف الحالات التي تؤدي فيها أنماط الكود الجديدة إلى تعطيل المحللات الخاصة بنا.
القيود الحالية
المخطط ليس مثالياً.
- البحث صعب؛ فغالباً ما تحتاج إلى معرفة اسم الدالة لتبدأ بحثك.
- انفجار العقد (Node explosion)؛ فبمجرد تتبع مسار ما، قد يتم سحب آلاف الدوال المساعدة الصغيرة وغير المفيدة.
- الصيانة؛ ففي كل مرة يدخل فيها إطار عمل جديد إلى مجموعتنا التقنية (stack)، يجب علينا كتابة محلل جديد.
هذا هو الجزء الأول. في الجزء الثاني، سأناقش طبقة مخطط الخدمة-المنتج (service-product-graph - SPG) التي بنيتها لسد هذه الثغرات.
مجتمع تعليمي اختياري: https://t.me/GyaanSetuAi
