46 റെപ്പോസിറ്ററികൾക്കായി ഒരു നോളജ് ഗ്രാഫ് നിർമ്മിക്കുന്നു

ഞാൻ റയാൻ, airCloset-ലെ CTO ആണ്.

code-graph നിർമ്മിക്കാൻ ഞാൻ മൂന്ന് മാസങ്ങൾ ചെലവഴിച്ചു. ഇത് ഒന്നിലധികം സർവീസുകളിലായി വ്യാപിച്ചുകിടക്കുന്ന 46 റെപ്പോസിറ്ററികളെ ഏകോപിപ്പിക്കുന്ന ഒരു സിംഗിൾ നോളജ് ഗ്രാഫ് ആണ്.

നിങ്ങളുടെ എല്ലാ കോഡും ഒരു AI-ക്ക് നൽകി ചോദ്യങ്ങൾ ചോദിക്കാം എന്ന് പലരും കരുതുന്നു. ഇത് രണ്ട് കാരണങ്ങളാൽ പരാജയപ്പെടുന്നു:

  • കോൺടെക്സ്റ്റ് വിൻഡോകൾ (Context windows): 46 റെപ്പോസിറ്ററികളിലെ വർഷങ്ങളായുള്ള കോഡ് ഒരു പ്രോംപ്റ്റിൽ ഉൾക്കൊള്ളിക്കാൻ കഴിയില്ല.
  • ഹാലൂസിനേഷൻ (Hallucination): ബന്ധങ്ങൾ കണ്ടെത്താൻ ശ്രമിക്കുമ്പോൾ AI തെറ്റുകൾ വരുത്തുന്നു. അത് കണക്ഷനുകൾ വിട്ടുപോകുന്നു.

ഇത് പരിഹരിക്കുന്നതിനായി, ഒരു 'സോഴ്സ് ഓഫ് ട്രൂത്ത്' (source of truth) നിർമ്മിക്കാൻ ഞാൻ സ്റ്റാറ്റിക് അനാലിസിസ് (static analysis) ഉപയോഗിച്ചു.

വെല്ലുവിളി: അതിരുകൾ മറികടക്കുക

ഒരു വലിയ കോഡ്ബേസ് സങ്കീർണ്ണമാണ്. ഒരു API അഞ്ച് വ്യത്യസ്ത റെപ്പോസിറ്ററികൾ ഉപയോഗിച്ച് വിളിച്ചേക്കാം. ഒരു ഡാറ്റാബേസ് ടേബിൾ മൂന്ന് വ്യത്യസ്ത സർവീസുകൾ ഉപയോഗിച്ചേക്കാം.

നിങ്ങൾ ഒരു റെപ്പോസിറ്ററി മാത്രം നോക്കുകയാണെങ്കിൽ, പൂർണ്ണമായ ചിത്രം നിങ്ങൾക്ക് ലഭിക്കില്ല. ഇത് അപകടകരമാണ്. കോഡിൽ മാറ്റം വരുത്തുമ്പോൾ അതിന്റെ യഥാർത്ഥ ആഘാതം (blast radius) കാണുന്നില്ലെങ്കിൽ, സിസ്റ്റം തകരാറിലാകും.

എന്റെ സമീപനത്തിൽ കോഡിനെ സിന്റാക്സ് ട്രീകളായി (syntax trees) മാറ്റാൻ tree-sitter ഉപയോഗിക്കുന്നു. എന്നാൽ tree-sitter കൊണ്ട് മാത്രം റെപ്പോസിറ്ററികൾക്കിടയിലുള്ള അതിരുകൾ കാണാൻ കഴിയില്ല.

ഇത് പരിഹരിക്കാൻ ഞാൻ ബൗണ്ടറി നോഡുകൾ (boundary nodes) നിർമ്മിച്ചു.

ഇത് എങ്ങനെ പ്രവർത്തിക്കുന്നു:

  • tree-sitter ഉപയോഗിച്ച് ഒരു റെപ്പോസിറ്ററിനുള്ളിലെ ബന്ധങ്ങൾ ഞങ്ങൾ വേർതിരിച്ചെടുക്കുന്നു.
  • ടൈപ്പുകളും വേരിയബിളുകളും പരിഹരിക്കാൻ ഞങ്ങൾ TypeScript Compiler API ഉപയോഗിക്കുന്നു.
  • ടൂളുകൾക്ക് വിട്ടുപോകുന്ന ഡൈനാമിക് കേസുകൾ കൈകാര്യം ചെയ്യാൻ ഞങ്ങൾ Gemini ഉപയോഗിക്കുന്നു.

AI-യോട് ഊഹിക്കാൻ ആവശ്യപ്പെടുന്നതിന് പകരം, ഞങ്ങൾ അതിന് വസ്തുതകൾ നൽകുന്നു. "ഈ API Repo X-ൽ നിന്നും വിളിക്കപ്പെടുന്നു" എന്ന് ഞങ്ങൾ അതിനോട് പറയുന്നു. ഇത് ഹാലൂസിനേഷനുകൾ ഒഴിവാക്കുന്നു.

പ്രയാസകരമായ ഭാഗം: ഫ്രെയിംവർക്ക് സൂ (Framework Zoo)

ഈ അതിരുകൾ വേർതിരിച്ചെടുക്കുക എന്നതായിരുന്നു യഥാർത്ഥ പോരാട്ടം. ഓരോ ഫ്രെയിംവർക്കും അതിരുകൾ എഴുതുന്ന രീതി വ്യത്യസ്തമാണ്.

ഒരു ടീം NestJS ഡെക്കറേറ്ററുകൾ ഉപയോഗിക്കുന്നു. മറ്റൊരാൾ Express റൂട്ടുകൾ ഉപയോഗിക്കുന്നു. വേറൊരാൾ പച്ചയായ jQuery ഉപയോഗിക്കുന്നു. ഓരോന്നും കോഡിൽ വ്യത്യസ്തമായ ഘടന സൃഷ്ടിക്കുന്നു.

ഇത് പ്രവർത്തിപ്പിക്കാൻ, താഴെ പറയുന്നവയ്ക്കായി ഞങ്ങൾക്ക് കസ്റ്റം പാഴ്സറുകൾ നിർമ്മിക്കേണ്ടി വന്നു:

  • NestJS and TypeORM
  • Express and Fastify
  • AngularJS and Redux
  • Various path-alias schemes

ഞങ്ങൾക്ക് 99% കൃത്യത ലക്ഷ്യമിടേണ്ടി വന്നു. കണക്ഷൻ നിരക്ക് 90% മാത്രമാണെങ്കിൽ, AI 10% കണക്ഷനുകൾ വിട്ടുപോകുന്നു. ഒരു പ്രൊഡക്ഷൻ സിസ്റ്റത്തിൽ, ആ 10% ആണ് ബഗുകൾ ഒളിച്ചിരിക്കുന്ന ഇടം.

ഞങ്ങൾ ഇപ്പോൾ ദിവസേനയുള്ള പരിശോധന നടത്തുന്നു. കണക്ഷൻ നിരക്ക് 5%-ൽ കൂടുതൽ കുറഞ്ഞാൽ ഞങ്ങൾക്ക് ഒരു അലേർട്ട് ലഭിക്കും. പുതിയ കോഡ് പാറ്റേണുകൾ ഞങ്ങളുടെ പാഴ്സറുകളെ തകരാറിലാക്കുന്നത് ഇത് കണ്ടെത്തുന്നു.

നിലവിലെ പരിമിതികൾ

ഗ്രാഫ് പൂർണ്ണമല്ല.

  • സെർച്ച് പ്രയാസകരമാണ്. തിരച്ചിൽ തുടങ്ങാൻ പലപ്പോഴും ഒരു ഫംഗ്ഷൻ പേര് അറിയേണ്ടതുണ്ട്.
  • നോഡ് എക്സ്പ്ലോഷൻ (Node explosion). ഒരു പാത്ത് പിന്തുടരുന്നത് ആയിരക്കണക്കിന് ചെറിയ, ഉപയോഗശൂന്യമായ ഹെൽപ്പർ ഫംഗ്ഷനുകളിലേക്ക് എത്തിച്ചേച്ചേക്കാം.
  • മെയിന്റനൻസ്. ഞങ്ങളുടെ സ്റ്റാക്കിൽ ഓരോ തവണ പുതിയൊരു ഫ്രെയിംവർക്ക് വരുമ്പോഴും, ഞങ്ങൾക്ക് പുതിയൊരു പാഴ്സർ എഴുതേണ്ടി വരുന്നു.

ഇത് ഭാഗം 1 ആണ്. ഈ വിടവുകൾ പരിഹരിക്കാൻ ഞാൻ നിർമ്മിച്ച service-product-graph (SPG) ലെയറിനെക്കുറിച്ച് ഭാഗം 2-ൽ ഞാൻ ചർച്ച ചെയ്യും.

സ്രോതസ്സ്: https://dev.to/ryantsuji/building-one-knowledge-graph-across-46-repositories-with-static-analysis-part-1-egm

ഓപ്ഷണൽ ലേണിംഗ് കമ്മ്യൂണിറ്റി: https://t.me/GyaanSetuAi