我们CoDistAI正在努力构建一种能够理解源代码和相关文档的人工智能。因为我们自己就是开发人员,所以在编写代码的同时,我们也面临着编写文档和保持文档更新的痛苦(增加了交付和截止日期的压力!)。在我们需要的时候找到他们也是一个很大的问题。我们知道,我们并不是唯一一个遭受这种痛苦的人。
但是,要建立这样一个系统,我们需要数据。而且很多。我们需要挖掘大量跨越不同语言的代码,你猜怎么着,当涉及到代码作为数据时,数据源并不多。我们能找到的几个主要来源主要是Github的CodeSearchNet Challenges数据集,Google BIG-Query的Github活动数据集,Py150,以及很少有其他类似的数据集。
挖掘不同的语言代码文件并从中收集重要信息并非易事。我们不想创建新的解析器,所以像ANTLR或lex-yacc这样伟大的解析器生成器框架不是我们的选择。我们需要的是一个良好的高级库,它在某种通用代码解析器之上公开一个简单的PythonAPI。
因此,最终的选择归结为两个选择。芭比尔鱼和保姆。现在,Babelfish是这个街区上的新手,它有一些很好的特性,但UAST(通用AST)并不是我们真正喜欢的东西。API也不是那么简单。所以照看树是一个自然而然的选择(另外,Babelfish也不再被维护了)。
我们对其简洁的设计、速度、语言覆盖率以及对树木保姆的最小依赖性印象深刻。但是,我们仍然在努力解决它通过Python绑定提供的低级接口。因此,我们开始编写一些代码,在其之上创建一些更高级别的抽象。
Tree-Hugger是一个建立在Tree-Sitter之上的轻量级、可扩展、高级、通用的代码解析器。
轻量级:Tree-Hugger的目标是成为一个简单易用的框架。它为开发人员提供了足够的工具来快速开始挖掘代码数据,同时还要处理大量的样板文件。它还旨在通过向它们提供一些命令行实用程序来简化工作。为此,它本身的重量仍然非常轻。我们的依赖性也相当低。
可扩展:抱树人的目标是通过设计实现可扩展。它主要通过两种方式实现这一目标。其一是拥有外部查询源。我们从一个YML文件中读取查询(s表达式)(示例可以在这里找到),这意味着我们不需要在代码中编写它们,我们可以非常容易地对它们进行迭代。第二件事是有一个模块化的结构,已经为您提供了一些通用的样板代码。也就是说,你可以专注于实际的事情。编写对您很重要的代码的重要部分。
高级:树保持器隐藏了运行查询或在最后一页上行走的小细节,也隐藏了在CLEAN、Pythonic API下从查询结果中检索一些代码的棘手部分,这样您就可以自由地专注于手头的问题。
Universal:我们实际上利用了令人惊叹的保姆,所以默认情况下我们(几乎)是语言不可知论者:)。
假设您希望将代码视为数据,并尝试在其上安装机器学习模型(如果您想了解更多信息,可以在此处查看我们以前的一篇文章)。
手头的任务是挖掘大量代码(不同的语言,如Python、PHP、C、C++、JS、C#、Java等)。并生成一个数据集,其中每个样本如下所示-(f,d),其中f代表函数体,d代表相关注释(如果您愿意,可以使用Docstring)。
现在您开始处理此问题,您会发现您遇到了一个问题。您需要一些东西,让您可以阅读所有不同的语言文件,并获得您感兴趣的数据。此外,您检索的数据应该是您可以方便使用的形式。像tree-sitter这样的框架和库在这里很有用。
您需要将查询编写为s-expression,并且它们嵌入到代码中。使您自己的代码很难阅读,也很难调试。
虽然这些文件都是通用的,但当您重新获得s表达式时,每个文件的内部表示形式都不同。因此,您需要编写、管理和跟踪相似的查询,但对于所有这些不同的语言编写的查询略有不同。
一旦开始获取数据,您将需要进行一些后处理,以使其在建模方案中可用。
所有这些都需要大量的时间,而且没有微不足道的解决方案。