仓库地图
Aider 使用整个 Git 仓库的简明地图,其中包含:
- 最重要的类和函数
- 它们的类型和调用签名
这有助于 aider 理解正在编辑的代码,以及代码与代码库其他部分的关系。仓库地图还能帮助 aider 编写新代码时,尊重并利用代码库中其他地方已有的库、模块和抽象概念。
使用代码库地图提供上下文
Aider 在每次处理用户变更请求时,会向大型语言模型(LLM)发送一份代码库地图。这份地图包含代码库中所有文件的列表,以及每个文件中定义的关键符号。它通过包含每个定义的关键代码行,展示这些符号是如何被定义的。
以下是 aider 代码库地图的一部分,展示了 base_coder.py 和 commands.py 文件的内容:
aider/coders/base_coder.py:
⋮...
│class Coder:
│ abs_fnames = None
⋮...
│ @classmethod
│ def create(
│ self,
│ main_model,
│ edit_format,
│ io,
│ skip_model_availabily_check=False,
│ **kwargs,
⋮...
│ def abs_root_path(self, path):
⋮...
│ def run(self, with_message=None):
⋮...
aider/commands.py:
⋮...
│class Commands:
│ voice = None
│
⋮...
│ def get_commands(self):
⋮...
│ def get_command_completions(self, cmd_name, partial):
⋮...
│ def run(self, inp):
⋮...
这种代码库地图提供了以下关键优势:
- LLM 可以看到代码库中所有位置的类、方法和函数签名。仅这一点就可能为它提供足够的上下文来解决许多任务。例如,它可能仅基于地图中显示的细节就能理解如何使用模块导出的 API。
- 如果需要查看更多代码,LLM 可以利用地图确定需要查看哪些文件。LLM 可以请求查看这些特定文件,aider 会将这些文件添加到聊天上下文中。
优化代码库地图
对于大型代码库而言,即便是完整的代码库地图也可能超出大型语言模型(LLM)的上下文窗口限制。Aider 通过仅发送最相关的部分代码库地图来解决这个问题。具体实现方式是:将整个代码库地图视为图结构进行分析,其中每个源文件作为节点,文件间的依赖关系构成边,然后运用图排序算法进行计算。Aider 通过选择代码库中最重要且能适配当前令牌预算的部分来优化地图呈现。这种优化会动态识别并映射与当前聊天状态最相关的代码部分。
令牌预算受 --map-tokens
参数影响(默认值为 1k 令牌)。Aider 会根据聊天状态动态调整代码库地图的大小,通常会将地图规模控制在该设定值范围内。但在某些情况下(特别是当聊天中尚未添加任何文件且 Aider 需要尽可能理解整个代码库时),地图规模会显著扩大。
上文展示的示例地图并未包含那些文件中的每个类、方法和函数,仅保留了最重要的标识符——即代码其他部分最常引用的关键元素。这些正是 LLM 需要了解的核心上下文信息,用以理解整个代码库的结构。
延伸阅读
关于 Aider 代码库地图的构建原理及更多技术细节,请参阅 Aider 博客上的专题文章。