repoCodeGen🤖
repoCodeGen
>>> Code Generation at Repository-Level 💻
Repository-Level Prompt Generation for Large Language Models of Code
RLPG
核心理念是,用代码库中其他部分替换默认上下文的一部分。选取什么代码以及从哪里选取是由提示提案管理的
- 提示源:从何处获取提示提案的上下文代码
- 有十种不同的提示源(父类、导入、兄弟类、相似名称、子类、导入父类、导入兄弟类、导入类似名称、导入子类)
- 提示上下文类型:决定从提示源获取何种代码
- 有七种不同的提示上下文类型(所有行、类型标识符、字段声明、字符串字面量、方法名称、方法名和主体)
Prompt Proposal Classifier (PPC)
PPC 的目标是预测出能够成功生成目标代码片段的最佳提示提案(prompt proposal)
- 训练过程:如果某个提示提案能够成功生成目标代码片段,则对应的向量位置为1,否则为 0,通过二元交叉熵损失优化模型参数、
- 模型变体:
- RLPG-H:使用预训练模型的表示来预测最有可能成功的提示提案。
- RLPG-R:使用多头注意力机制来评估洞窗口与提示提案上下文的相似性,从而选择最佳提示。
Prompt Composer
作用是组合 最佳提示提案 和 codex 默认上下文 (空白位置之前的代码)
- 上下文分配:
- 上下文组合
- 截断策略
RepoCoder – Repository-Level Code Completion Through Iterative Retrieval and Generation
RepoCoder 框架
一个针对仓库级代码完成任务的新型迭代检索生成框架
原始 RAG
- 使用检索模型 R,使用未完成的代码 X 作为检索查询,从代码片段 C 中提取最相关的信息 **$C = R (C, X)$**,再利用语言模型 M 补全代码 $Y = M (C, X)$
优化后的 RepoCoder
- 检索查询不只是未完成的代码 X,还包括**上一次迭代生成的预测代码 $Y^{i-1}$**,即$Y^i =M (C, X, Y^{i-1})$
代码检索
- 滑动窗口,每次提取 $S_w$ 行代码,每次滑动固定行数 $S_s$ (滑动大小)
- 初始检索过程使用未完成代码最后几行作为查询
- 后续迭代都引入上一次迭代生成的代码 $Y^{i-1}$ 作为查询,原代码片段提取 $(S_w-S_s)$ 行,从$Y^{i-1}$ 中提取 $S_s$ 行
代码生成
- 仓库中检索最相关的代码 $C_{ret}$,并于待补充的代码 $X$ 进行拼接
- 有一个提示模板,将 $C_{ret}$ 和 $X$ 无缝拼接
- 检索到的代码按照相似度排序,用于提示的代码片段有最大数量 $K$
基准构建
一种新的 RepoEval 基准,使用从 Github 获取的最新高质量仓库,评估涵盖代码完成度的三个层次:
- 行
- API 调用
- 函数体完成
深入分析
这些分析不仅帮助理解了RepoCoder的工作原理,也为未来的研究方向提供了指导
代码质量
- 包含与目标补全相似的代码语句或展示目标API调用示例的代码片段通常最有用
检索代码位置
- “相似导入”、“相似名称”或“当前目录”位置的文件提取代码效果良好
Guiding Language Models of Code with Global Context using Monitors
LMs 常出现的错误:
如果需要引用在训练过程中未见过的类型或API,会出现错误
缺乏对上下文的理解,无法正确处理跨文件或跨模块的代码依赖
symbol not found
没有相关信息,LMs 会出现臆想和幻觉complile-time-errors
编译时错误,例如使用错误数量的参数时“实际和形式参数列表长度不符”runtime errors
运行时错误,例如违反 API 协议
语言服务器协议 LSP
LSP 旨在提供特定于语言的智能,并通过支持进程间通信的协议与开发工具进行通信,这样单个 LSP 可以在多个开发工具中使用
LSP 相当于在中间层做一个抽象,让语言的「静态分析服务」和「编辑器 / IDE」分离开来
本文就是专注通过 LSP 以语言无关的方式提供的类型导向代码完成分析
监视引导解码
- 集成开发环境 IDEs 主要是在开发的不完整代码上应用静态分析,使用增量解析和语义分析算法对部分代码进行解析
- 部分抽象语法树:带有特殊节点(表示代码不完整部分)的不完整抽象语法树
- 监视器(Monitor):LMs 和静态分析之间的接口,观察 LM 生成的代码并在预定义的触发点查询静态分析。
- 触发条件
- 状态更新函数
- 掩码生成函数
- 静态分析
- 解码过程:一般解码过程是根据 LM 生成的 logits 概率分布进行 token 采样,如果 monitor 处于非等待状态,静态分析生成的掩码会调整 logits 从而影响采样
- 掩码生成:识别与当前静态分析建议一致的 token。当一个 token 被采样,监视器会更新状态和建议
总体性研究
- MGD 中的监控器可以围绕 LSP 的特定语言实例化,不需要更改静态分析接口,支持新语言很容易
- MGD 会在特定情况下触发,这里就需要判定触发静态分析的情况,如下情况可以予以考虑:
- 变量和符号
- 跟踪局部和全局变量的定义和使用
- 识别变量的作用域和生命周期
- 函数和方法
- 分析函数签名,包括参数列表和返回类型(文中就提到了基于堆栈的监视器,指导生成正确数量的参数)
- 检查函数调用的正确性和参数匹配
- 类和对象
- 分析类的结构,包括属性、方法和继承关系
- 检查对象的实例化
- 模块和导入
- 追踪导入的模块和符号
- 分析模块依赖关系
- 变量和符号
RepoFusion-Training Code Models to Understand Your Repository
Fusion-in-Decoder
- 将周围上下文附加到仓库上下文,分别编码并组合以生成目标空缺的预测
Repository Contexts
该部分和第一篇论文 Repository-Level Prompt Generation for Large Language Models of Code 思想大致相同
- 提示提案上下文 (PPC)
- 提示提案上下文是通过提取来自特定类别的相关源文件的特定类型的上下文创建
- 它是由一个提示提案函数生成的
- 提示上下文类型的示例包括目标孔后面的行、方法名称和主体、标识符、字符串文字等
- 包括 prior PPC 和 post PPC
- 提示源
- 提示源的示例包括当前文件、导入到当前文件的文件、与当前文件同名的文件等
RepoFusion
核心理念是训练一个代码模型,使其能够识别仓库中的上下文,帮助目标空缺的代码生成
- 从提示提案 (PPC) 生成 仓库上下文 (PC),然后某种顺序拼接
- 有四种策略 T-Rank、T-Rand、NT-Rank、NT-Prior-Last
REPOEXEC-Evaluate Code Generation with a Repository-Level Executable Benchmark
关于LMs 代码生成能力的评估
作者提出了一个评估代码生成模型能力的方法,主要侧重于生成可执行和功能正确的代码的能力,这也是评估方法的两个难点,也是推动开发更强大可靠的代码生成模型的灵感来源。
可执行的代码,即能够在实际环境中运行的代码,评估可执行性需要评估代码生成模型是否能识别和映射代码中的依赖项,并且确保依赖项被正确整合到生成的代码中。
正确性,就是代码按照预期功能正确执行。这需要高覆盖率的测试用例来测试代码的正确性,检查其是否通过测试用例,衡量其是否可以完成各种预定任务。
这虽然是评估生成代码模型能力的方法需要考虑的因素,其实也给代码生成模型的后续优化提供了思路。