ExecRetrieval: Measuring the Functional-Correctness Gap in Code-Embedding Retrieval
Aaryan Kapoor, Md Abdullah Al Hafiz Khan
EMNLP 2026 (Main Conference)
cs.SE, cs.CL, cs.IR
2026-09-02
ExecRetrieval给939个Python代码任务各自植入经测试套件验证的单编辑错误近克隆。最强Gemini Embedding 2的exec@10达到1.00,exec@1仅0.331,rank-1错误几乎全是配对bug。
代码 embedding 检索是 coding agent 和 RAG 写代码的第一段:先召回候选,再交给重排、执行或模型去挑。现有基准按身份重合或话题相关打分。检索池里没有「跟正确答案只差一处编辑、但跑测试会挂」的对照物时,话题检索满分和功能检索满分是同一回事。
真正要命的情况是仓库、agent 缓存、提交历史里,经常同时躺着正确实现和几乎一样的错误变体。第一段检索如果分不清,后面再聪明也只能在错的候选上工作。
ExecRetrieval 造了一个功能可核对的检索基准。939 道 Python 任务,覆盖位运算、集合、日期时间、几何、字符串等十个算法域。每道题配一段自然语言查询、一份通过全部测试的标准实现、最多 4 个单编辑错误 distractor、7 到 10 条 assert。语料一共 4,694 段代码。标准实现必须全过,每个 distractor 必须至少挂一条。
错误不是让模型另写一套算法。锁定的六类机械变异对应经典变异测试算子:offbyone、wrongoperator、swaparguments、removeedgecasecheck、wrongcomparison、offbyoneboundary。禁止 wrongsemantics,因为早期用 Claude Sonnet 时,400 个 distractor 里 127 个(31.8%)其实是另一种正确实现。换成 GPT-5.4 high reasoning 后,首次尝试 4,112 个 distractor 里只有 3 个(0.07%)误通过测试。任务注册表由 Claude Sonnet 4.6 生成,实现由另一模型写,避免自己给自己出题。
五道闸依次过:schema、AST 语义、标准实现执行、distractor 执行、语料完整性。子进程隔离跑测试,5 秒超时。交叉检查确认没有函数名撞车,导致别人的代码碰巧过了这题的测试。数据集、执行缓存、23 份 embedding 矩阵都公开,列表价生成成本约 108.53 美元。
评测 23 种 dense 配置加 BM25,按各家官方文档的最佳调用方式,包括 task type、query/passage 前缀、dtype 和相似度。指标是 exec@k(top-k 里有没有一段能过测试)、executionprecision@k,以及按标准实现 ID 算的 nDCG。配 McNemar 配对检验和 5,000 次 query 级 bootstrap。
最强托管模型 Gemini Embedding 2 的 exec@1 只有 0.331(95% CI [0.299, 0.362]),exec@3 升到 0.823,exec@10 是 1.00。Gemini Embedding 001 的 exec@1 是 0.329,两者在 rank-1 上统计不可分。开源侧 Qwen3-Embedding-8B 是 0.214。OpenAI text-embedding-3-large 掉到 0.113。BM25 只有 0.058,exec@10 也才 0.422,低于最差 dense 模型 paraphrase-MiniLM 的 0.671。
| 系统 | exec@1 | exec@5 | exec@10 |
| Gemini Embedding 2 | 0.331 | 0.997 | 1.000 |
| Gemini Embedding 001 | 0.329 | 0.988 | 1.000 |
| Mistral Embed | 0.224 | 0.937 | 0.984 |
| Qwen3-8B | 0.214 | 0.979 | 0.997 |
| OpenAI 3-large | 0.113 | 0.939 | 0.985 |
| BM25 | 0.058 | 0.328 | 0.422 |
rank-1 错了,几乎总是配对的错误变体:四套头部系统里占 91.5% 到 99.4%。标准实现的 query-cosine 低于至少一个配对 distractor 的比例,Gemini 2 上 66.8%,Qwen3-8B 上 78.4%。六类变异的欺骗率挤在 39.3% 到 48.0%,总平均 44.3%,不是某一种 bug 特有。
密度消融把事情说死了。池里零个近克隆时,头部系统 exec@1 在 0.93 到 0.99。只留一个近克隆,最强系统从 0.993 掉到 0.678。编辑跨度从 1 个字符到 21 个以上,欺骗率几乎不变;把 2 到 4 个互不重叠的变异叠进同一函数,欺骗率相对单变异只差 1.7 个点。
日期时间是最难的域,24 套系统平均 exec@1 只有 0.091。939 题里 88 题没有任何系统能在 rank-1 做对,中位题只有 3/24 套系统做对。
给做代码 RAG 和 coding agent 的人一个测量学警告:现有 embedding 当召回器够用,当功能判别器不够。Gemini 2 能在 10 个候选里保证捞到能跑通的实现,但第一名经常是差一刀的错误代码。下游必须接执行、测试或重排,不能假设 cosine 第一名能跑。
这篇不声称线上语料有多频繁出现近克隆,只测量池里有近克隆时,第一段检索把多少判别负担甩给后面。克隆研究和提交历史说明这种共现说得通,频率仍未测。
只覆盖 Python,机械变异不是人类写的 bug,检索池是封闭的 4,694 段自造代码,exec@k 不能跟开放域代码搜索数字比。执行 runner 有进程隔离和超时,没有文件系统和网络沙箱。没有评 cross-encoder 或 LLM 重排,而那正是工程上最可能补 rank-1 的一步。939 题相对话题检索语料很小,绑定成本在逐条执行验证。托管 API 会漂,作者靠冻结 embedding 矩阵让打分可复现。
测试套件是生成的,可能比查询文本声明的定义域更严。正确性相对测试,不是相对形式化规约。Qwen3 家族内部 8B 对 4B 在 exec@1 上没有可检出的缩放,开源第一不能读成参数越大越好。