ساخت یک گراف دانش واحد در میان ۴۶ مخزن

من رایان هستم، مدیر فنی (CTO) در airCloset.

من سه ماه را صرف ساخت code-graph کردم. این یک گراف دانش واحد است که ۴۶ مخزن را در چندین سرویس مختلف یکپارچه می‌کند.

بسیاری از مردم فکر می‌کنند که می‌توانید تمام کدهای خود را به یک هوش مصنوعی بدهید و سوال بپرسید. این کار به دو دلیل شکست می‌خورد:

  • پنجره‌های بافت (Context windows): شما نمی‌توانید سال‌ها کد از ۴۶ مخزن را در یک پرامپت بگنجانید.
  • توهم (Hallucination): هوش مصنوعی وقتی سعی می‌کند روابط را استنتاج کند، مرتکب اشتباه می‌شود. آن اتصالات را از دست می‌دهد.

برای حل این مشکل، از تحلیل استاتیک (static analysis) برای ساخت یک منبع حقیقت (source of truth) استفاده کردم.

چالش: عبور از مرزها

یک پایگاه کد (codebase) بزرگ، نامنظم است. ممکن است یک API توسط پنج مخزن مختلف فراخوانی شود. یک جدول پایگاه داده ممکن است توسط سه سرویس مختلف استفاده شود.

اگر فقط به یک مخزن نگاه کنید، تصویر کامل را از دست می‌دهید. این خطرناک است. اگر کد را تغییر دهید و شعاع اثرگذاری (blast radius) واقعی را نبینید، سیستم را از کار می‌اندازید.

رویکرد من از tree-sitter برای تجزیه کد به درخت‌های نحو (syntax trees) استفاده می‌کند. اما tree-sitter به تنهایی نمی‌تواند از مرزهای مخزن عبور کند.

من برای حل این مشکل، گره‌های مرزی (boundary nodes) ساختم.

نحوه عملکرد:

  • ما روابط درون یک مخزن را با استفاده از tree-sitter استخراج می‌کنیم.
  • ما از TypeScript Compiler API برای تعیین انواع (types) و متغیرها استفاده می‌کنیم.
  • ما از Gemini برای مدیریت موارد پویا (dynamic) که ابزارها از دست می‌دهند، استفاده می‌کنیم.

به جای اینکه از هوش مصنوعی بخواهیم حدس بزند، به آن واقعیت‌ها را می‌دهیم. ما به آن می‌گوییم: "این API از Repo X نیز فراخوانی می‌شود." این کار از توهم جلوگیری می‌کند.

بخش سخت: باغ‌وحش فریم‌ورک‌ها

نبرد واقعی، استخراج این مرزها بود. هر فریم‌ورک، مرزها را به شکل متفاوتی تعریف می‌کند.

یک تیم از دکوراتورهای NestJS استفاده می‌کند. تیم دیگر از مسیرهای (routes) Express استفاده می‌کند. تیم دیگری از jQuery خام استفاده می‌کند. هر کدام ساختار متفاوتی در کد ایجاد می‌کنند.

برای اینکه این کار عملی شود، مجبور شدیم پارسرهای سفارشی برای موارد زیر بسازیم:

  • NestJS و TypeORM
  • Express و Fastify
  • AngularJS و Redux
  • طرح‌های مختلف path-alias

ما باید دقت ۹۹ درصدی را هدف قرار می‌دادیم. اگر نرخ اتصال ما تنها ۹۰٪ باشد، هوش مصنوعی ۱۰٪ از اتصالات را از دست می‌دهد. در یک سیستم عملیاتی (production)، آن ۱۰٪ همان جایی است که باگ‌ها پنهان می‌شوند.

ما اکنون یک بررسی روزانه انجام می‌دهیم. اگر نرخ اتصال ما بیش از ۵٪ کاهش یابد، یک هشدار دریافت می‌کنیم. این کار باعث می‌شود زمانی که الگوهای کد جدید، پارسرهای ما را از کار می‌اندازند، متوجه شویم.

محدودیت‌های فعلی

این گراف بی‌نقص نیست.

  • جستجو دشوار است. اغلب برای شروع جستجو، نیاز دارید نام یک تابع را بدانید.
  • انفجار گره (Node explosion). دنبال کردن یک مسیر می‌تواند هزاران تابع کمکی کوچک و بی‌فایده را وارد زنجیره کند.
  • نگهداری. هر بار که فریم‌ورک جدیدی به پشته (stack) ما اضافه می‌شود، باید یک پارسر جدید بنویسیم.

این بخش اول است. در بخش دوم، درباره لایه service-product-graph (SPG) که برای رفع این شکاف‌ها ساخته‌ام، صحبت خواهم کرد.

Source: https://dev.to/ryantsuji/building-one-knowledge-graph-across-46-repositories-with-static-analysis-part-1-egm

Optional learning community: https://t.me/GyaanSetuAi