跨越 46 个代码仓库构建统一的知识图谱

我是 Ryan,airCloset 的 CTO。

我花了三个月的时间构建了 code-graph。这是一个统一了跨多个服务的 46 个代码仓库的单一知识图谱。

许多人认为只需将所有代码交给 AI 并提出问题即可。但这种做法会因为两个原因而失败:

  • 上下文窗口:你无法将来自 46 个仓库、长达数年的代码全部放入一个提示词(prompt)中。
  • 幻觉:AI 在尝试推断关系时会犯错,从而遗漏连接。

为了解决这个问题,我使用了静态分析来构建“事实来源”(source of truth)。

挑战:跨越边界

大型代码库非常混乱。一个 API 可能会被五个不同的仓库调用。一个数据库表可能会被三个不同的服务使用。

如果你只看一个仓库,就会错失全局视图。这是很危险的。如果你修改了代码却没看到真实的“爆炸半径”(blast radius),就会破坏整个系统。

我的方法是使用 tree-sitter 将代码解析为语法树。但仅靠 tree-sitter 无法跨越仓库边界。

我构建了“边界节点”(boundary nodes)来解决这个问题。

工作原理如下:

  • 我们使用 tree-sitter 提取仓库内部的关系。
  • 我们使用 TypeScript Compiler API 来解析类型和变量。
  • 我们使用 Gemini 来处理工具无法处理的动态情况。

我们不是让 AI 去猜测,而是给它事实。我们告诉它:“这个 API 也被 Repo X 调用。”这可以防止幻觉。

难点:框架丛林

真正的战斗在于提取这些边界。每个框架定义边界的方式都不同。

一个团队使用 NestJS 装饰器(decorators)。另一个使用 Express 路由(routes)。还有一个使用原生 jQuery。每种方式都会在代码中创建不同的结构。

为了实现这一点,我们必须为以下内容构建自定义解析器:

  • NestJS 和 TypeORM
  • Express 和 Fastify
  • AngularJS 和 Redux
  • 各种路径别名(path-alias)方案

我们必须追求 99% 的准确率。如果我们的连接率只有 90%,AI 就会遗漏 10% 的连接。在生产系统中,那 10% 正是 Bug 隐藏的地方。

我们现在每天进行一次检查。如果连接率下降超过 5%,我们就会收到警报。这可以捕捉到由于新的代码模式导致解析器失效的情况。

当前的局限性

图谱并不完美。

  • 搜索困难。你通常需要知道一个函数名称才能开始搜索。
  • 节点爆炸。沿着路径追踪可能会引入数千个微小且无用的辅助函数。
  • 维护成本高。每当我们的技术栈中引入一个新的框架,我们就必须编写一个新的解析器。

这是第一部分。在第二部分中,我将讨论我为填补这些空白而构建的服务-产品图(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