研究提案 已修订

依赖图感知的 Repo 级代码生成数据:让模型理解文件之间的调用关系再写代码

NL2Repo-Bench 暴露了当前模型在 repo 级代码生成上的惨淡表现(最佳 Pass@1 仅 19.39%)。本方案提出以仓库依赖图为骨架,构建'先理解架构再写代码'的中训练数据。

代码生成 仓库级 依赖图 知识图谱 中训练 长程任务 数据合成

触发动机

NL2Repo-Bench(arXiv:2512.12730)的数据让我震惊:最好的模型在仓库级代码生成任务上 Pass@1 只有 19.39% 。这不是”差一点”,而是”基本不行”。但更有趣的是失败模式分析——模型不是写不出语法正确的代码,而是不理解文件之间的调用关系:在 A 文件里写了一个函数签名,到 B 文件里调用时参数类型不匹配;或者创建了正确的模块结构但循环依赖。

美团的 R-HORIZON(HuggingFace 2025)也印证了这一点:代码任务的性能衰减比数学任务更陡峭,且主要原因是长程上下文中的”依赖关系遗忘”。

这让我想到:当前代码训练数据的根本问题是文件级碎片化——模型看到的是一个个独立文件,即使有上下文窗口看到多个文件,也缺少”这些文件之间关系是什么”的显式信号。如果中训练数据中包含大量”依赖图 + 对应代码”的配对,模型应该能在权重层面建立对代码架构的理解。

战略判断:为什么 Repo 级代码理解是代码能力的天花板

行业信号

  1. Repo 级是实际开发的主战场:真实的软件开发 95% 的时间在读/改已有代码,不是从零写文件。SWE-bench 的成功证明了”在已有 repo 中定位并修复 bug”是高价值能力,但”从需求描述生成整个 repo”是更高阶的能力。
  2. NL2Repo-Bench 的 19.39% 说明这不是微调能解决的:这个数字太低了,不是”提示工程”或”多采样”能弥补的差距。根本原因是模型在训练阶段没有足够的 repo 级结构理解数据。
  3. 知识图谱辅助代码生成(IEEE 2025)的初步尝试已经证明了”先理解依赖关系再写代码”的有效性。

核心假设

代码生成能力可以分解为三层:

  1. 语法层:写出语法正确的代码(已基本解决)
  2. 语义层:写出逻辑正确的代码(单文件基本解决,长文件仍有挑战)
  3. 架构层:写出结构正确的多文件代码(远未解决)

第三层的瓶颈是训练数据中缺少显式的”架构描述 + 对应代码”的配对。

方法论

核心思路:从 GitHub 仓库中提取”依赖图 → 代码”的配对数据

GitHub 高质量仓库
        │
        ├─ 1. 静态分析 → 提取依赖图
        │     (模块、类、函数之间的调用/继承/导入关系)
        │
        ├─ 2. 将依赖图转化为自然语言架构描述
        │
        ├─ 3. 将代码按依赖拓扑排序组织
        │     (先展示被依赖的模块,再展示调用方)
        │
        └─ 4. 打包为中训练语料:
              "架构描述 → 依赖图 → 代码(按拓扑序)"

Step 1:依赖图提取

对每个 GitHub 仓库,使用语言特定的静态分析工具:

语言工具提取内容
Pythonast + importlib模块导入、类继承、函数调用
TypeScriptts-morph类型依赖、模块导出/导入
JavaJavaParser包依赖、类继承/实现
Gogo/ast包导入、接口实现
Rustsyn + cargo metadatacrate 依赖、trait 实现

提取的依赖图包含:

nodes: [
  { name: "UserService", type: "class", file: "services/user.py" },
  { name: "UserRepository", type: "class", file: "repos/user.py" },
  { name: "EmailService", type: "class", file: "services/email.py" },
]
edges: [
  { from: "UserService", to: "UserRepository", type: "dependency" },
  { from: "UserService", to: "EmailService", type: "dependency" },
]

Step 2:架构叙事化

将依赖图转化为自然语言的架构描述:

## 用户管理模块架构

本模块采用经典的分层架构:Service 层处理业务逻辑,
Repository 层负责数据持久化。

UserService 是核心服务类,依赖两个组件:
1. UserRepository:提供用户的 CRUD 操作,底层使用 SQLAlchemy ORM
2. EmailService:负责发送注册确认邮件和密码重置邮件

依赖方向是单向的:Service → Repository/EmailService,
Repository 和 EmailService 之间没有直接依赖。
这种设计保证了关注点分离——修改邮件发送逻辑不会影响数据层。

接口契约:
- UserRepository.get_by_id(id: int) → Optional[User]
- UserRepository.create(data: UserCreateDTO) → User
- EmailService.send_verification(email: str, token: str) → bool

Step 3:代码拓扑排序

按依赖图的拓扑序组织代码——先展示被依赖的模块:

# 1. 数据模型(无依赖)
# File: models/user.py
class User:
    id: int
    email: str
    ...

# 2. Repository 层(依赖 models)
# File: repos/user.py
class UserRepository:
    def get_by_id(self, id: int) -> Optional[User]:
        ...

# 3. Email 服务(无内部依赖)
# File: services/email.py
class EmailService:
    def send_verification(self, email: str, token: str) -> bool:
        ...

# 4. 核心服务(依赖 Repository + EmailService)
# File: services/user.py
class UserService:
    def __init__(self, repo: UserRepository, email: EmailService):
        ...
    def register(self, data: UserCreateDTO) -> User:
        user = self.repo.create(data)
        self.email.send_verification(user.email, generate_token())
        return user

Step 4:打包为中训练语料

最终语料格式:

## 项目架构与实现:用户管理系统

### 架构概览
[自然语言架构描述——来自 Step 2]

### 依赖关系图
[文本化的依赖图——节点和边的描述]

### 实现代码
[按拓扑序排列的完整代码——来自 Step 3]

### 架构决策说明
为什么选择分层架构而非微服务?因为模块间的调用频率高、
数据共享需求强,分层更简单且性能更好。如果未来需要独立
扩展某个组件(比如邮件发送量暴增),再考虑拆分为独立服务。

增强数据:错误架构对比

类似前缀引导偏好的思路,构建”正确架构 vs. 错误架构”的对比:

### 错误架构示例:循环依赖
如果让 UserRepository 也依赖 UserService(比如在 Repository
中触发业务事件),就会形成循环依赖:
UserService → UserRepository → UserService

这会导致:
1. 模块无法独立测试
2. 初始化顺序问题
3. 违反单一职责原则

正确做法:引入事件机制,Repository 发布事件,Service 订阅处理。

规模估算

来源仓库数可用模块数Token 量
Python 高星仓库 (>1k stars)5,00050,0002 亿
TypeScript/JavaScript3,00030,0001.2 亿
Java2,00025,0001.5 亿
Go1,50015,0006000 万
Rust1,00010,0004000 万
总计12,500130,000~5.5 亿 token

落地路径

  1. Week 1-2:在 100 个 Python 仓库上构建依赖图提取 pipeline
  2. Week 3:构建架构叙事化 + 拓扑排序 pipeline
  3. Week 4:人工审查 100 条数据的质量
  4. Week 5-8:扩展到多语言 + 规模化
  5. Week 9-10:构建错误架构对比数据 + 消融实验

与已有方案的关系

与站内 CI/CD 失败诊断 proposal 互补:

  • CI/CD 失败诊断 = 模型学”repo 中哪里出了错”(调试能力)
  • 本方案 = 模型学”repo 应该长什么样”(架构能力)
  • 两者组合 = 完整的 repo 级代码理解能力