介绍如何在自己的代码库上科学评估 Sourcegraph 的检索质量、Agent 性能和成本效益,避免混淆不同指标。
更好的代码检索并不一定意味着更好的任务完成。这是如何在不混淆检索、智能体性能和成本的情况下衡量它们的方法。
Sourcegraph 能让编码智能体在你的代码库上表现更好吗?这取决于"更好"对你的团队意味着什么:完成更多任务、更快地找到正确的代码、降低成本,或让困难的工作更可靠。公开基准测试无法直接回答这个问题。
答案更多取决于相关工作如何分布在代码库中,而不是代码库的规模。当智能体需要的代码位于一个明显的目录中时,它可以廉价地导航非常大的单体仓库。但当理解一个行为需要追踪多个服务、存储库、所有权边界和历史变更时,即使在更小的环境中它也会遇到困难。检索难度是代码库和任务的共同属性。
在评估 Sourcegraph MCP 服务器时,我们直接看到了这种区别。在 288 个任务中,当两个方案都能在相同的修订版本处访问相同的代码时,结构化检索将文件级 F1 从 0.091 提高到 0.240,召回率从 0.120 提高到 0.272。总体任务完成奖励基本没有变化。当基线智能体进行广泛搜索时成本有所改善,但当它能够快速定位工作时成本恶化。
这些结果并不矛盾。检索质量、任务完成和成本衡量的是系统的不同部分。仅测量其中一个可能产生技术上正确的结果,但仍然导致错误的推出决策。
实际问题不是结构化代码检索在平均情况下是否胜出。而是它是否能帮助你的工程师和智能体难以定位的工作。下面是用你自己的存储库、任务、模型和成本结构运行该比较的方法。
同样的 288 个任务在完全信息对等的条件下产生了三个不同的结果:两个方案都能在相同的修订版本处访问相同的代码。
Sourcegraph 改进了检索,将文件级 F1 从 0.091 提高到 0.240,召回率从 0.120 提高到 0.272。总体任务完成奖励基本没有变化。成本朝第三个方向发展,取决于具体任务。当基线智能体进行广泛搜索时,结构化检索可节省 15% 到 51% 的成本,但当基线在七次或更少搜索中定位工作时,平均多花 $0.15。
我们使用确定性、特定任务的验证器而不是模型判断来测量完成情况。我们同时报告连续奖励和二进制通过率,因为它们回答不同的问题:智能体的完成程度以及是否满足任务的接受阈值。
平坦的完成结果容易被误读。随后的普查发现,大约 74% 的语料库仅用 grep 就能解决。38% 的提示直接命名了路径、符号或目录,而只有大约四分之一将行为指令与分散在代码库中的答案结合在一起。因此,大多数任务都没有给更好的检索留下影响完成情况的余地。
该任务组合将稀释任何检索系统的总体效果。在构建你自己的评估集时,首先删除已经告诉智能体在哪里查看的任务,然后将易于定位的工作与需要真正发现的任务分开报告。
在测量任何东西之前,按定位难度对你关心的工作进行分类。
易于定位的任务命名路径、符号或目录,或在几次搜索后得出答案。难以定位的任务描述的是一个行为,其实现跨越服务、存储库、生成的代码、所有权边界或 git 历史。
我们的检索难度加权(在我们查看结果之前定义),对存储库跨度和目录分散的加权比总代码行数更高。当相关代码位于一个目录中时,一个 4000 万行的单体仓库表现得像一个小存储库。当答案分散在四个服务中时,一个 200 万行的资产变成了更难的检索问题。
两种形式的分散特别重要,应该包含在试点中。第一种是依赖历史的工作:诸如哪个变更删除了一行这样的问题,跨越任何分支或存储库,无法仅从当前树中回答。git log -S 可以搜索该历史,但一次只能搜索一个存储库。第二种是由另一个团队生成、提供或拥有的代码,其中答案存在但定义任务的人还不知道在哪里查看。这两者在事件响应和合规调查中很常见,但在基准语料库(包括我们的)中并不常见。
你不必依赖分类法来识别这些任务。你的基线智能体追踪已经提供了更强的信号。在添加 Sourcegraph 之前,测量智能体执行的搜索量:重复查询、广泛文件读取、长轨迹和高上下文消耗是比存储库规模或工作流类别更好的检索难度指标。
成本与观察到的搜索负担关联最强。在 113 个配对任务中,Sourcegraph 的成本优势与基线搜索广度之间的相关性为 (r = -0.57):基线智能体搜索越多,结构化检索越有可能降低成本。
来自 113 个测量任务对中的七个示例,选择是为了说明成本结果改变方向的地方,而不是代表完整的分布。
在我们的运行中,受益的任务倾向于同时跨越四个阈值:基线智能体中大约 20 次或更多搜索、15 次或更多文件读取、30 次或更多轮次,以及 75,000 个或更多有效载荷令牌。这些是来自一个语料库的参考点,不是通用截止值。在决定检索可能在哪里得到回报之前,针对你自己的基线测量相同的量。
聚集在这些阈值之上的工作包括事件响应、合规调查、迁移和跨存储库追踪。在每种情况下,智能体都从症状或行为开始,而不是已知的位置。
domain-160 表明为什么观察到的搜索负担比任务标签更重要。我们将其分类为困难,因为指令是行为性的,答案是分散的,但基线仅用两次搜索就定位了它。因此,结构化检索成本更高。更有用的预测器不是我们分配的类别,而是基线智能体实际必须进行多少搜索。
对于任务完成,实际问题通常是 Sourcegraph 是否在减少搜索、时间或成本的同时至少表现得一样好。在运行之前说明该目标,让检索指标支撑改进的论点,并应用以下九个控制。
选择真实工作。挖掘已合并的拉取请求、事件、迁移、合规调查和跨服务变更。从私有存储库历史中挖掘的任务大大降低了模型已经看到任务或其解决方案的风险,但实际变更不会自动成为有效的评估任务。OpenAI 对 SWE-Bench Pro 的审计估计其大约 30% 的任务被破坏了,最常见的原因是提示和测试不一致、测试强制执行未声明的实现,或不完整的解决方案可以通过。检查每个提示是否说明了验证器强制执行的内容,测试是否接受功能上有效的替代方案,以及参考变更是否是唯一可以通过的解决方案。
删除琐碎任务。拒绝命名答案文件、目录或符号的提示。在我们的语料库中,随着提示揭示更多关于答案的信息,成本胜率单调下降,因此该过滤器从本质上改变了评估能衡量的内容。
固定代码。两个方案必须在相同的修订版本处访问相同的存储库。当我们审计这一点时,基线缺少存储库的任务显示 +0.091 的奖励差异,而在完全对等下为 −0.007。前者测量的是拥有代码而不是找到代码。
保持智能体不变。在两个方案中使用相同的模型、验证器、预算、运行时和任务文本。保持任务指令字节级相同。任何 Sourcegraph 特定的前言或工具描述都是处理的一部分,应该与结果一起记录和发布。
比较访问方法。将本地搜索基准与 Sourcegraph 辅助检索进行比较。为了进行替换测试,应该移除本地源码访问权限,而不是要求智能体优先选择 Sourcegraph,因为智能体在压力下可能会回退,将实验变成指令遵循能力的测试。这个隔离条件是为了因果归因,不一定是生产环境中你会使用的配置。
每个任务至少重复三次。在比较两组配置前,先对每个任务内的多次运行求平均值。单次试验设计会高估效果 40% 到 60%,而任务内的方差通常会超过被估计的效果大小。
测量整个系统。记录完成情况、检索、墙钟时间、总 Token 数、总成本、搜索调用次数和进入上下文的代码量。在实验前定义 Token 计量边界,并向两组配置等同地应用。对于实现任务,当智能体不产生任何必要 diff 时赋予零分,这样什么都不做不能得分与尝试任务但失败相同。
分段后再聚合。将容易定位的任务与分散的、搜索密集的任务分别报告。将它们混在一起会产生一个既不能有效回答部署问题的数字。
审计实际工具使用。配置不能证明工具可用或被采用。用观察到的工具调用验证连通性,将零调用试验报告为采用失败或配置失败,并将其与检索能力分析分开。
揭示答案位置的提示词给检索帮助的空间不大。在这个语料库中,随着指令透露信息越少、答案变得越分散,成本胜率上升。
上述检查清单不需要特定的框架。如果你已经有一个系统可以针对任务运行智能体并为结果评分,你就有了大部分机制。缺少的部分通常是两组配置之间的清晰隔离、重复试验,以及检查检索工具是否实际可用和被使用的审计。
我们用 CodeProbe 运行这个评估。它从仓库历史中挖掘任务,构建比较组、运行重复试验,并报告成对的每任务增量。CodeProbe 仍然处于 alpha 阶段,目前正在内部和与合作伙伴测试中,所以要预期破坏性变化。把实验内的差异当作有用的输出;绝对分数尚未跨实验校准。
要在合作伙伴测试期间在你自己的仓库上评估 Sourcegraph,请通过 stephanie.jarmak@sourcegraph.com 联系我。
运行的步骤:
# 1. 这个仓库能否产生有效任务?
codeprobe assess /path/to/repo
# 2. 从已合并的 pull request 中构建 40 个任务。基准真值来自两个
# 独立后端;--no-llm 使挖掘保持在你的边界内。
codeprobe mine /path/to/repo --org-scale --count 40 \
--consensus-backends ast,grep --no-llm
# 3. 定义比较及其两组配置。
codeprobe experiment init /path/to/repo --name sourcegraph-eval
codeprobe experiment add-config <exp> \
--label local-baseline --agent <agent> --model <model> # 组 1:本地搜索
codeprobe experiment add-config <exp> \
--label sourcegraph --agent <agent> --model <model> \
--mcp-config '<sourcegraph-config>' \
--mcp-mode strict --hide-local-source scaffold # 组 2:仅检索
# 4. 运行前先评估成本,然后运行。
codeprobe run <exp> --dry-run # 预计成本,不启动智能体
codeprobe run <exp> --repeats 3 --parallel 5 # 240 次运行:40 个任务 x 2 组 x 3 次重复
# 5. 成对的每任务增量,加上下文中描述的有效性检查。
codeprobe interpret <exp> --format html
这个实验问一个问题:在从你自己已合并的 pull request 中挖掘出的 40 个任务中,当同一个智能体和模型通过 Sourcegraph 而不是本地搜索到达代码时,是否完成更多工作,或以更低成本完成?Sourcegraph 配置上的两个标记隔离访问方法。--mcp-mode strict 保留配置的检索工具和写入访问权限,同时阻止本地读取、grep、glob 和 shell 命令。这是一个实验条件,不是推荐的生产配置。在生产环境中,智能体可以将 Sourcegraph 与本地工具一起使用。隔离在这里很有用,因为它使归因成为可能,但严格模式也移除了与检索无关的 shell 能力。因此其结果测量的是完整的隔离工具表面,而不仅仅是检索后端。--hide-local-source scaffold 用零字节占位符在其原始路径替换源文件,然后在验证前将智能体的编辑覆盖到真实代码上。智能体无法检查本地实现,但验证器仍然评估真实仓库。当所需的输出是文本工件而不是代码更改时使用 hide。
先运行 --dry-run 并检查预计成本。40 个任务跨越两组配置和三次重复会产生 240 次智能体运行。--max-cost-usd 限制总活动支出,而 --parallel 控制并发。这个大小的试点对于暴露集成故障和识别配置之间的方向性差异很有用,但不足以支持稳定的效果估计。
从第一次运行开始,有两个检查应该在 CI 中。当独立的基准真值推导不一致时,交叉验证检查失败。interpret 中的有效性检查在分析群体中存在未解决的基础设施故障时拒绝报告结果。这很重要,因为仓库历史提供现实的工作,而不是自动有效的评估任务:为特定 pull request 编写的测试可能对该实现进行编码,而不是定义完整可接受解决方案集。
来自公共仓库的结果不会自动转移到私有企业代码,这就是为什么这个评估应该在你自己的仓库上进行。一个小试点可以暴露集成故障和方向性差异,但不能建立稳定的效果。在我们的分析中,大约 80 对任务是统计下限,而 200 对为部署声称提供了更有说服力的基础。
检索评分也不能替代任务验证。智能体可以找到每个相关文件但仍然产生错误答案,或不使用检索就到达正确答案。调用接口也很重要:智能体访问检索的方式可以像检索结果本身一样改变成本。最重要的要测试的工作是以代码历史为基础的跨仓库工作,因为那是索引检索与本地搜索差异最大的地方,也是我们自己的语料库覆盖最少的地方。
一个有用的试点不需要显示 Sourcegraph 改进每个任务。它需要识别索引检索改变结果的工作:涉及广泛搜索、分散的代码所有权、跨仓库依赖或重要历史的任务。
从 40 个代表性任务开始,以验证集成并表面明显差异。在将测量的效果视为稳定之前扩展到至少 80 对任务,在检索质量是主要评估指标时接近 100,因为那是我们统计分析中最难精确估计的效果。按基准搜索广度对结果进行分段,并首先部署到搜索、时间或成本下降而完成保持稳定的地方。
把这篇文章中的数字当作关于你的代码库的假设,而不是基准分数。如果你的结果指向与我们相反的方向,那就是值得调查的结果,我们很乐意听到。
解锁你的组织。更快地交付。
使用 Sourcegraph,企业的代码理解平台。