评估 AI Coding Agent 从代码库中检索到的上下文是否相关、完整、不产生幻觉。
RAG Eval 回答的是:
给定一个关于代码库的查询,Agent 能否找到正确的上下文,并基于这些上下文给出准确的回答或执行正确的操作?
Agent 再聪明,如果读错了文件、漏看了关键上下文,后续动作也会错。
通用文档 RAG 和代码库 RAG 很不一样:
| 维度 | 通用文档 RAG | 代码库 RAG |
|---|---|---|
| 结构 | 连续文本 | 文件、类、函数、调用关系 |
| 粒度 | 段落 | 函数、类、行、提交 |
| 关系 | 主题相关 | 调用、继承、import、依赖 |
| 版本 | 较少变化 | 分支、commit、PR 差异 |
| 验证 | 人工判断为主 | 可结合编译器、测试 |
因此代码库 RAG 评测不能只靠语义相似度,还要考虑:
- AST 结构
- Import/call 图
- 类型信息
- Git 历史
- 测试覆盖
核心问题:系统是否找到了正确的上下文?
| 指标 | 说明 | 适用场景 |
|---|---|---|
| Recall@K | 正确答案是否在前 K 个结果中 | 检索是否漏掉关键文件 |
| Precision@K | 前 K 个结果中有多少是相关的 | 检索是否引入噪音 |
| MRR | 第一个正确答案的平均倒数排名 | 关注最相关结果的位置 |
| NDCG | 考虑排序和相关度加权的综合指标 | 结果排序质量 |
| Hit Rate | 是否至少命中一个正确答案 | 简单通过性指标 |
| 指标 | 说明 |
|---|---|
| Definition Recall | 函数/类的定义是否被检索到 |
| Call Graph Recall | 调用链上的相关文件是否被检索到 |
| Import Closure Recall | import 依赖的文件是否被检索到 |
| Cross-file Recall | 跨文件关联是否被正确捕捉 |
核心问题:Agent 基于检索内容生成的回答/动作是否准确?
| 指标 | 说明 |
|---|---|
| Faithfulness | 生成内容是否忠实于检索到的上下文 |
| Answer Relevance | 回答是否针对查询 |
| Hallucination Rate | 是否引用了不存在的信息 |
| Completeness | 是否覆盖了查询所需的所有关键信息 |
| 指标 | 说明 |
|---|---|
| Retrieval Latency | 检索耗时 |
| Context Size | 喂给模型的上下文 token 数 |
| Compression Ratio | 原始检索结果 vs 最终喂入上下文的比例 |
每个评测样本包含:
id: rag-001
query: "用户登录失败时,错误信息是在哪里渲染的?"
codebase: ./fixtures/web-app-v1/
golden_context:
files:
- src/components/LoginForm.tsx
- src/utils/errorMessages.ts
snippets:
- file: src/components/LoginForm.tsx
lines: [45, 62]
reason: "登录失败时调用 showError 的逻辑"
- file: src/utils/errorMessages.ts
lines: [1, 15]
reason: "错误信息映射表"
golden_answer: |
登录失败的错误信息在 LoginForm.tsx 第 52 行通过 showError(errorMessages[error.code])
渲染,具体文案定义在 src/utils/errorMessages.ts。获取检索结果和生成结果。
对比检索结果和 golden_context。
对比生成结果和 golden_answer,并检查是否忠实于检索内容。
如果生成错误,判断是检索问题还是生成问题:
- 检索到了正确上下文但生成错了 → 生成问题
- 没检索到正确上下文 → 检索问题
- 检索到了但没喂给模型 → 上下文压缩问题
| 类型 | 查询示例 | 难点 |
|---|---|---|
| 定位定义 | "X 函数在哪里定义?" | 同名函数、跨文件 |
| 追踪调用 | "哪些文件调用了 X?" | 间接调用、反射 |
| 理解依赖 | "修改 X 会影响哪些模块?" | 传递依赖、动态依赖 |
| 版本差异 | "这个 bug 是哪次提交引入的?" | 需要 git 历史 |
| 实现查询 | "这个接口是怎么实现的?" | 需要结合文档和代码 |
| 模式 | 表现 | 根因 |
|---|---|---|
| 漏检关键文件 | 检索结果没包含答案 | 分块策略、嵌入模型、查询扩展 |
| 检索到无关文件 | 噪音太多 | 相似度阈值、过滤策略 |
| 跨文件断裂 | 只找到定义没找到调用 | 缺少 call graph |
| 版本混淆 | 检索到旧分支代码 | 未按分支/版本索引 |
| 幻觉引用 | 生成中引用了不存在的文件 | 生成模型编造 |
见 datasets/examples/ 中的 rag-eval-example.jsonl。