CODEXGRAPH:突破代码与AI的壁垒,开启智能编程新时代
- CODEXGRAPH论文阅读
- 1. 概述
- 2. 相关研究
- 代码库级别的任务
- 检索增强代码生成(RACG)
- 3. CODEXGRAPH系统设计
- 代码图数据库的构建
- 与图数据库的交互
- 4. 实验设计与结果
- CrossCodeEval
- SWE-bench
- EvoCodeBench
- 5. 深入分析
- 查询策略的优化
- 翻译LLM代理的作用
- 高级LLM的增强作用
- 6. 实验指标
- 1. Exact Match (EM)
- 2. Edit Similarity (ES)
- 3. Identifier Exact Match (ID-EM)
- 4. Identifier F1 (ID-F1)
- 5. Pass@1
- 6. Recall@1
- 7. 实际应用场景
- 8. 讨论与未来工作
- 使用示例
- 1.代码聊天:
- 2. 代码调试:
- 3. 代码添加注释:
- 4. 代码生成:
- 5. 代码添加单元测试:
CODEXGRAPH论文阅读
CODEXGRAPH通过结合LLM和图数据库接口,解决了现有RACG方法在处理复杂代码库任务时的灵活性和通用性不足的问题。实验结果表明,CODEXGRAPH在多个学术基准测试和实际应用场景中表现出色,展示了其广泛的适用性和实际价值。
1. 概述
论文首先介绍了大型语言模型(LLMs)在代码生成和理解任务中的重要性,但也指出当前LLMs在处理整个代码库时面临的挑战。这些挑战包括难以处理长上下文输入以及在复杂代码结构中进行推理的能力不足。现有的解决方案,如基于相似性的检索方法和手动工具/API,虽然在特定任务中有效,但在应对复杂的代码库任务时表现出色的效果有限。
为了解决这些问题,作者提出了CODEXGRAPH,一个将LLM与图数据库接口相结合的系统。该系统通过利用代码库的结构化特性,帮助LLM更好地理解和操作大规模代码库,从而提高代码检索和导航的精度和效率。
2. 相关研究
论文的相关研究部分分为两个主要部分:代码库级别的任务和检索增强代码生成(RACG)。
代码库级别的任务
研究回顾了近年来关于代码库级别任务的工作,这些任务需要模型理解跨文件的代码结构和执行复杂推理。例如,DevBench和SketchEval等基准测试要求模型基于自然语言描述生成完整的代码库,或者在参考代码库的基础上进行代码补全和生成。
检索增强代码生成(RACG)
RACG系统旨在通过从外部知识库检索相关内容来增强代码生成的上下文理解。当前的RACG方法主要分为基于相似性的检索、手动设计的工具或API,以及两者结合的方法。虽然这些方法在特定场景下有效,但它们通常依赖于任务特定的设计,缺乏通用性和灵活性。
3. CODEXGRAPH系统设计
论文详细描述了CODEXGRAPH系统的构建和工作流程,分为以下几个关键部分:
代码图数据库的构建
系统通过静态分析将输入的代码库索引为图数据库,其中节点代表代码符号(如模块、类、方法、函数等),边代表这些符号之间的关系(如继承、包含、使用等)。这一过程中,使用了浅层索引和深度索引两阶段策略,以确保准确捕捉代码库的结构信息。
与图数据库的交互
CODEXGRAPH利用图查询语言(如Cypher)构建复杂的查询条件,使得LLM可以在图数据库中高效地导航和检索代码结构信息。系统还采用“写然后翻译”的策略,由主LLM代理生成自然语言查询,再由翻译LLM代理将其转换为可执行的图查询,以减少主LLM代理的推理负担。
4. 实验设计与结果
论文通过三个基准测试(CrossCodeEval、SWE-bench、EvoCodeBench)评估了CODEXGRAPH的性能,并与其他RACG方法(如BM25和AUTOCODEROVER)进行对比:
CrossCodeEval
该基准测试主要评估代码补全任务。CODEXGRAPH在代码匹配和标识符匹配等多个指标上表现良好,尤其在配备更高级的LLM(如GPT-4o)时表现最佳。
SWE-bench
此基准测试评估模型解决GitHub问题的能力。CODEXGRAPH与AUTOCODEROVER在这一任务上表现接近,但展示了更好的通用性。
EvoCodeBench
此基准测试用于评估代码生成任务。CODEXGRAPH在多个指标上优于其他RACG方法,展示了其在处理复杂代码生成任务中的优势。
此外,论文指出了CODEXGRAPH的代价,即由于使用了更复杂的查询过程,系统的令牌消耗相对较高。
5. 深入分析
论文还对CODEXGRAPH的性能进行了更深入的分析,包括:
查询策略的优化
实验显示,在不同的基准测试中,选择生成单个查询或多个查询的策略会对性能产生影响。例如,在推理难度较低的任务中,多查询策略更有效,而在推理难度较高的任务中,单查询策略更为合适。
翻译LLM代理的作用
当取消翻译LLM代理的协助时,主LLM代理必须独立分析编码问题并直接制定用于代码检索的图查询。这增加了主LLM代理上的推理负载,导致图查询的语法准确性下降。实验结果强调了删除LLM翻译代理对CrossCodeEval Lite (Python)基准中所有选定的LLM的CODEXGRAPH性能产生的显著负面影响。即使使用GPT-Χo作为骨干模型,性能指标也会出现显著下降(例如,EM指标从27.90%下降到8.30%),这凸显了翻译LLM代理在减轻主要LLM代理的推理负担方面的关键作用。
高级LLM的增强作用
实验表明,随着LLM能力的提升,CODEXGRAPH的性能也显著提高,说明了更高级的LLM能够更好地利用代码图数据库提供的灵活接口。如果底层LLM缺乏足够的推理和编码能力,那么CODEXGRAPH中的LLM代理可能很难制定适当的图查询。这可能导致检索预期代码失败,进而阻碍进一步的推理。
6. 实验指标
1. Exact Match (EM)
- 定义: Exact Match (EM) 指标衡量模型生成的代码与参考代码在字符级别上是否完全一致。
- 计算方式: 对于每一个测试示例,如果模型生成的代码和参考答案完全相同,EM记为1,否则记为0。最后,将所有测试示例的EM值取平均,得到总体的EM分数。
- 优点: EM是一个严格的指标,只有当生成的代码完全正确时,才会给予正反馈。
- 缺点: 由于EM要求完全匹配,即使代码在功能上等价但细节不同,EM也会记为0。
2. Edit Similarity (ES)
-
定义: Edit Similarity (ES) 是一种衡量模型生成代码与参考代码之间相似度的指标,通常基于编辑距离(edit distance)来计算。
-
计算方式: ES通常通过归一化的编辑距离来计算。具体而言,它计算的是1减去编辑距离与最大可能的编辑距离的比值,公式如下:
-
优点: ES可以更宽松地评估模型的输出,即使代码不完全匹配,也能根据相似度给予一定的正反馈。
-
缺点: ES可能会对代码的功能性错误不够敏感。
3. Identifier Exact Match (ID-EM)
- 定义: Identifier Exact Match (ID-EM) 是一个指标,用于衡量模型生成的代码中的标识符是否与参考代码中的标识符完全一致。
- 计算方式: 对于每一个测试示例,如果模型生成的代码中的所有标识符都与参考代码中的标识符完全一致,ID-EM记为1,否则记为0。最后,所有测试示例的ID-EM值取平均,得到总体的ID-EM分数。
- 优点: ID-EM指标专注于标识符的准确性,这在评估模型是否正确理解和生成关键代码元素时非常重要。
- 缺点: ID-EM可能会忽略生成代码与参考代码在功能上等价但标识符命名不同的情况。
标识符是否与参考代码中的标识符完全一致,指的是模型生成的代码中的变量名、函数名、类名等标识符必须与参考代码中的对应标识符在拼写和格式上完全相同。
#参考代码:
def calculate_area(radius):pi = 3.14159area = pi * radius * radiusreturn area#代码结构不同,但标识符完全一致
def calculate_area(radius):pi = 3.14return pi * radius * radius#代码结构和顺序不同,但标识符完全一致
def calculate_area(radius):area = radius * radius * 3.14159return area#标识符部分不一致
def compute_area(r):pi = 3.14return pi * r * r
4. Identifier F1 (ID-F1)
- 定义: Identifier F1 (ID-F1) 是基于精确率(Precision)和召回率(Recall)计算的F1得分,专门用于衡量生成代码中标识符的匹配情况。
- 计算方式:
- 精确率 (Precision): 指生成代码中正确的标识符占生成标识符总数的比例。
- 召回率 (Recall): 指生成代码中正确的标识符占参考代码标识符总数的比例。
- F1得分 (F1 Score): F1得分是精确率和召回率的调和平均数
- ID-F1通过比较生成代码和参考代码中的标识符,计算出它们的精确率和召回率,然后得出F1得分。
- 优点: ID-F1能够综合考虑标识符的准确性和覆盖度。
- 缺点: ID-F1对标识符的部分匹配敏感度较低。
5. Pass@1
- 定义: Pass@1 指标衡量的是模型在生成一段代码后,是否能够在一次尝试中就通过所有的测试用例或达到特定的标准。
- 计算方式:
- 对于每一个测试示例,模型生成一段代码并进行测试。如果该代码通过了所有测试用例,Pass@1 得分记为1,否则记为0。
- 最终,Pass@1 分数是所有测试示例的平均得分,即:
- 例如,如果100个测试示例中有85个在第一次生成的代码中通过了测试,那么 Pass@1 得分为 0.85。
- 优点: Pass@1 直接衡量了模型生成代码的实用性。
- 缺点: 由于Pass@1只记录一次成功的情况,指标具有较高的严格性。
- Pass@1 指标的应用场景
代码生成任务: 在生成函数或类时,Pass@1 衡量生成的代码是否在第一次尝试中通过所有单元测试。
自动化修复: 在自动代码修复任务中,Pass@1 衡量模型生成的修复代码是否在一次应用后就解决了所有问题。
软件工程中的应用: 在真实的软件开发环境中,Pass@1 可用于评估自动化代码工具的有效性,即该工具生成的代码能否立即在生产环境中运行。
6. Recall@1
- 定义: Recall@1 衡量的是在模型生成或检索的多个候选答案中,正确答案是否出现在排名第一的位置。
- 计算方式:
- 对于每一个测试示例,模型生成一个排名列表(或输出多个候选代码),并检查正确答案是否出现在第一个位置(即排名第一的候选项)。
- 如果正确答案在第一个位置上,Recall@1 得分记为1,否则记为0。
- 最终,Recall@1 分数是所有测试示例的平均得分,即:
- 例如,如果在100个测试示例中有70个示例的正确答案出现在第一个位置上,那么 Recall@1 得分为 0.7。
- 优点: Recall@1 直接评估了模型在第一次输出中是否找到了正确答案。
- 缺点: Recall@1 强调输出结果的排名顺序,要求模型将正确答案排在最前面。
- Recall@1 指标的应用场景
代码生成和补全: 在代码生成任务中,Recall@1 用于评估模型生成的代码片段是否在第一位置上就达到了预期的功能。
信息检索: 在检索任务中,Recall@1 衡量模型从候选项列表中检索到正确答案的能力,特别是检索到的第一个候选项的准确性。
自动化推荐: 在代码推荐系统中,Recall@1 评估系统推荐的第一个代码片段是否满足用户的需求。
7. 实际应用场景
为了展示CODEXGRAPH的实际应用价值,作者开发了五个基于ModelScope-Agent框架的代码代理,包括:
- Code Chat: 允许用户查询代码存储库,从而深入了解代码结构和函数使用情况。
- Code Debugger: 通过应用迭代推理和信息检索来诊断和解决错误,并提出有针对性的修复建议。
- Code Unittestor: 自动生成详细的单元测试代码。
- Code Generator: 自动生成代码片段。
- Code Commentor: 自动为代码添加注释。
8. 讨论与未来工作
论文的讨论部分提到CODEXGRAPH目前仅在Python代码库中进行评估,未来的工作计划包括将其扩展到更多的编程语言(如Java和C++),并提高代码图数据库的构建效率和模式的完整性。此外,作者计划探索与现有的高级代理技术更紧密的集成,以进一步优化CODEXGRAPH的工作流程。
使用示例
1.代码聊天:
代码聊天允许用户查询代码存储库,从而深入了解代码结构和函数使用情况。此功能对于理解复杂的代码库、识别依赖关系以及探索特定类、方法和函数的使用情况特别有用。
下面是一个代码聊天的例子。用户的问题是:“总结一下这个CodexGraphAgentChat类,它有哪些方法,以及它们是用来做什么的。收集到必要的信息后,Code Chat会针对用户的问题构建全面的回复。此回复包括类的摘要CodexGraphAgentChat、其方法列表以及每种方法的说明。
2. 代码调试:
代码调试器通过应用迭代推理和信息检索来诊断和解决错误,并提出有针对性的修复建议。它利用 Cypher 查询来分析代码存储库,找出问题的原因,并推荐精确的修改。
下面是一个Code Debugger的例子。用户的输入是一个实际的问题,其结果与预期的行为不符。Code Debugger首先分析问题,然后使用 Cypher 查询检索相关信息并推断出 bug 的原因。最后,它对 bug 进行了解释并建议修改的位置。确定代码库中错误的精确位置并提供问题的详细解释以及错误的根本原因。
3. 代码添加注释:
代码注释器分析代码以提供详细注释,增强代码的可读性和可维护性。它利用代码图数据库来了解代码的结构和行为,确保注释准确且信息丰富。
4. 代码生成:
用户已请求一个函数来检索 的输入和输出令牌的数量CypherAgent。然而,挑战在于识别其中的相应字段,CypherAgent因为用户输入中未提供此信息。
首先,Code Generator会思考如何找到相关字段,然后通过 Cypher 查询,发现对应的字段为input_token_num和output_token_num,从而生成正确的代码。
5. 代码添加单元测试:
下面是一个Code Unittestor的例子,用户的输入是:“为 生成测试用例TaskManager”。Code Unittestor会先检索 中的所有方法和继承关系TaskManager,然后生成详细的测试用例代码。
Code Unittestor将为该类生成详细的单元测试代码TaskManager,涵盖其方法和继承关系。