如何在自己的代码库上评估 Sourcegraph

代码检索做得更好,并不自动意味着任务完成得更好。下面这套方法可以帮你分别衡量检索质量、agent 表现和成本,而不会把三者混为一谈。
Sourcegraph 能让 coding agent 在你的代码库上表现更好吗?这取决于你说的“更好”指什么:是完成更多任务,是更快找到正确的代码,是降低成本,还是让困难的工作更可靠。公开榜单回答不了这个问题。
答案与其说取决于代码库多大,不如说取决于相关工作在代码库里怎么分布。如果 agent 需要的代码就在某个显眼的目录里,那么即使面对一个超大的单体仓库(monorepo),它也能低成本地找到。反过来,在规模小得多的代码库里,如果搞清一个行为要横跨多个服务、多个仓库、多个归属边界和历史变更去追,它照样会卡住。检索的难度,既取决于代码库,也取决于任务本身。
我们在评估 Sourcegraph MCP server 时就直接看到了这种区别。在 288 个任务里,两组配置都能访问同一版本(revision)上的同一份代码,结果结构化检索把文件级 F1(一种衡量检索命中准确度的指标)从 0.091 提升到 0.240,召回率从 0.120 提升到 0.272,但总体任务完成奖励几乎没变。成本方面,当基线 agent 大范围搜索时,结构化检索能省钱;当它能快速定位到工作范围时,成本反而上升。
这些结果并不矛盾。检索质量、任务完成和成本,衡量的是系统里不同的部分。只测其中一项,可能得出技术上正确、却导向错误推广决策的结论。
真正该问的不是结构化代码检索在平均意义上是否更优,而是它对你团队里工程师和 agent 难以定位的那些工作是否有帮助。下面介绍一套方法,用你自己的仓库、任务、模型和成本结构来做这项对比。
同一次评测,三种不同结果
同样是 288 个任务,最终得出三种截然不同的结论,而且全程信息对等:两组实验都能访问相同的代码、相同的版本。
Sourcegraph 确实改善了检索效果,文件级 F1 从 0.091 提升到 0.240,召回率从 0.120 提升到 0.272。但任务完成的总体奖励几乎没有变化。成本则走向第三个方向,而且因任务而异:当基线 agent 大范围搜索时,结构化检索能省下 15% 到 51% 的成本;可当基线只用七次以内的搜索就定位到目标时,结构化检索反而平均多花 0.15 美元。
我们衡量任务完成情况,用的是确定性的、针对具体任务的校验器,而不是让模型自己判断。我们同时报告连续奖励和二元通过率,因为这两者回答的是不同问题:一个反映 agent 离目标有多近,另一个反映它是否达到了任务的验收门槛。
任务完成率持平这个结果很容易被误读。后来做的一次清点发现,语料里大约 74% 的任务单靠 grep 就能解决。38% 的提示直接点明了路径、符号或目录,只有大约四分之一的任务既给出了行为描述,又要求答案散落在代码库各处。所以大多数任务本身就没给更好的检索留出多少发挥空间。
这样的任务组合,会稀释任何检索系统的整体效果。建议你搭建自己的评测集时,先把那些已经告诉 agent 去哪找的任务剔掉,再把容易定位的任务和真正需要探索发现的任务分开统计。
检索难度比代码库规模更关键
动手测量之前,先按定位难度给你关心的任务分个类。
容易定位的任务,要么直接点名路径、符号或目录,要么搜几次就能找到答案。难以定位的任务,描述的是某种行为,而它的实现跨越多个服务、多个仓库、生成代码、归属边界甚至 git 历史。
如何在你的代码库上评估 Sourcegraph
我们定义的检索难度权重是在查看结果之前确定的:仓库跨度与目录分散度所占权重,高于代码总行数。一个四千万行的单体仓库(monorepo),如果相关代码都集中在一个目录里,它的检索难度其实和一个很小的仓库相当。反过来,一个两百万行的代码资产,如果答案散落在四个服务里,反而会成为更难的检索问题。
有两种分散情形尤其值得纳入试点。第一种是依赖历史的工作:比如某一行代码是哪次改动删掉的——这类问题无法仅凭当前代码树回答,还要跨任意分支或仓库追溯。git log -S 可以搜索这段历史,但每次只能针对一个仓库。第二种是生成、第三方引入或其他团队负责的代码:答案确实存在,但提出任务的人事先并不知道该去哪里找。这两类问题在事故响应和合规调查中很常见,在基准语料库中却很少见,我们的语料库也不例外。
你不需要依赖什么分类法来识别这些任务。你的基线智能体(agent)追踪记录本身就能提供更强的信号。在接入 Sourcegraph 之前,先测量智能体做了多少搜索:重复查询、大范围读取文件、过长的轨迹、大量的上下文消耗——这些都比仓库大小或工作流类别更能反映检索难度。
成本与这种实际观测到的搜索负担关系最紧密。在 113 组配对任务中,Sourcegraph 的成本优势与基线的搜索广度之间的相关系数为 (r = -0.57):基线智能体搜索得越多,结构化检索就越有可能降低成本。
从 113 组测量任务中选取了七个示例,目的是展示成本结果在哪些地方发生方向性变化,并不代表完整分布。
在我们的测试运行中,收益明显的任务往往同时跨过四个阈值:基线组中大约 20 次或更多搜索、15 次或更多文件读取、30 轮或更多对话轮次,以及 75,000 个或更多 payload token。这些是来自单一语料库的参考点,并非通用分界线。在判断检索在哪些场景可能真正见效之前,请先在你自己的基线上测量同样的指标。
跨过这些阈值后聚集起来的工作包括:事件响应、合规调查、迁移以及跨仓库追踪。在这些场景中,代理一开始面对的是某种症状或行为,而不是一个已知位置。
domain-160 说明了为什么实际观察到的搜索负担比任务标签更重要。我们把它归类为困难任务,因为指令是行为性的,答案又分散各处,但基线只用了两次搜索就定位到了它。因此,结构化检索反而成本更高。更有用的预测指标不是我们分配的任务类别,而是基线代理实际需要执行多少搜索。
你的评估需要九项控制措施
对于任务完成度而言,实际问题通常是:Sourcegraph 是否在减少搜索、时间或成本的同时,至少表现同样好。在运行之前先明确这个目标,让检索指标来支撑改进的论证,并应用以下九项控制措施。
- 选择真实任务。 从已合并的拉取请求、故障事件、迁移、合规调查和跨服务变更中挖掘任务。从私有仓库历史中挖掘任务,能大幅降低模型已经见过该任务或其解决方案的风险,但真实变更并不自动等于有效的评估任务。OpenAI 对 SWE-Bench Pro 的审计估计,约 30% 的任务存在问题,最常见的原因是提示词与测试不一致、测试强制要求某种未说明的实现方式,或者不完整的解决方案也能通过。检查每个提示词是否说明了验证器会检查什么、测试是否接受功能上有效的替代方案,以及参考变更是否不是唯一能通过的方案。2. 剔除简单任务。 拒绝那些点名答案所在文件、目录或符号的提示词。在我们的语料库中,随着提示词透露的答案信息增多,成本胜率单调下降,因此这个过滤器会实质性改变评估所能衡量的内容。3. 固定代码。 两组必须访问相同的仓库和相同的修订版本。我们审计时发现,基线缺少仓库的任务显示出 +0.091 的奖励差值,而在完全对齐的情况下为 −0.007。前者衡量的是有没有代码,而不是能不能找到代码。4. 保持智能体不变。 两组使用相同的模型、验证器、预算、运行时和任务文本。保持任务指令逐字节完全一致。任何 Sourcegraph 特有的前言或工具描述都属于处理的一部分,应当记录并随结果一起发布。5. 比较访问方式。 将基线本地搜索与 Sourcegraph 辅助检索进行比较。对于替代测试,应移除本地源码访问,而不是要求智能体优先使用 Sourcegraph,因为智能体在压力下可能回退,从而把实验变成对指令遵循能力的测试。这种隔离条件是为了归因,不一定是你在生产环境中会使用的配置。6. 每个任务至少重复三次。 在比较两组之前,先对每个任务内的多次运行取平均值。
单次试验设计会把差异夸大到 40% 到 60%,而且任务内的方差通常超过要估计的效应本身。
-
测量整个系统。 记录完成情况、检索、实际耗时、总 token 数、总成本、搜索调用次数,以及进入上下文的代码量。在实验之前先界定 token 记账的边界,并对两组采用完全相同的口径。对于实现类任务,如果智能体没有产出所要求的代码变更,就给它记零分,这样“什么都不做”就不会和“尝试了但失败”拿到一样的分数。
-
先分段,再汇总。 把容易定位的任务和分散、搜索量大的任务分开报告。混在一起算出来的数字,既回答不了部署问题,也说明不了实际情况。
-
审计实际的工具使用情况。 配置并不能证明工具真的可用或被采用了。要用观察到的工具调用来验证连通性,把零调用试验记为采用失败或配置失败,并将它们与检索能力分析区分开来。
如果提示词直接暴露了答案藏在哪儿,检索就没什么发挥空间了。在这批语料里,指令透露的信息越少、答案越分散,成本胜率就越高。
如何解读结果
| 结果 | 可能说明什么 | 下一步怎么做 |
|---|---|---|
| 完成度更高、成本更低 | 有力证据表明 Sourcegraph 同时提升了能力和效率 | 扩大评估范围,优先推进部署 |
| 完成度相当,成本或延迟更低 | Sourcegraph 带来了效率优势,同时没有降低任务质量 | 先部署到节省最多的流程 |
| 完成度更高,但成本增加 | Sourcegraph 能完成基线做不到的工作,但这份额外能力有代价 | 判断该流程的完成度提升是否值得额外成本 |
| 检索更好、完成度相当、成本更高 | Agent 找到了更多相关代码,但这一改进没有高效地传导到最终结果 | 检查调用接口、结果整形和任务分布 |
| 收益集中在分散或搜索密集型任务 | 总体数据掩盖了特定流程的优势 | 把 Sourcegraph 瞄准这些任务,而不是要求全面取胜 |
| 没有收益,且基线搜索活动很少 | 所选任务可能不需要索引检索 | 加入带行为提示、跨仓库范围或重要历史的任务 |
| 基线缺少必要仓库时出现大幅收益 | 实验衡量的是信息获取,而不是检索质量 | 先恢复仓库和版本的一致性,再解读结果 |
| 成本更低但完成度更差 | Agent 做的工作更少,不一定是效率更高 | 把完成度当作硬约束,并调查失败模式 |
| 大量零工具调用试验 | 工具可能不可用、描述不清,或未被 Agent 采用 | 先诊断连通性和采用情况,再评估检索能力 |
关键结论
在自有代码库上评估 Sourcegraph,要回答的是「值不值得部署」这个问题,而不是产出一张排行榜分数。有用的结论应该聚焦、范围窄,并且可以被检验:在同一批任务上,仓库和版本一致,使用的智能体也固定不变,Sourcegraph 达到相同或更好的完成度,同时消耗更少的搜索调用、更短的耗时或更少的 token。
其余指标都只是诊断信息。检索效果提升了,改动最终却没有落到代码差异里,这说明问题出在工具调用入口或结果整理上;只有基线缺少仓库时才出现的完成度优势,说明差异来自代码访问权限;成本降低了但完成度变差,说明智能体干脆停止了工作。这些都不是实验失败,恰恰说明实验在正常发挥作用,但每种情况指向的下一步动作各不相同。把它们合并成一个差值,反而会丢失信号。
报告结果时,同时说明实验条件
要公布足够的信息,让别人能够复现或推翻你的结论:
- 任务集包含哪些任务、如何筛选出来,以及有多少任务因泄露答案位置、过于简单或提示与验证器判断不一致而被剔除
- 两组实验的仓库和版本是否一致;如果并不完全一致,还要给出在这种条件下测到的差值,作为合理性检查
- 两组都使用的模型、验证器、预算、运行时,以及逐字节完全一致的任务文本,包括任何 Sourcegraph 专用的前置提示或工具说明
- 每个任务跑了几次,差值是在任务内部计算后再平均,还是跨任务直接平均
- 完成度、检索效果、耗时、token、成本、搜索调用次数和上下文规模,并说明 token 的统计边界
- 每次试验实际观察到的工具调用次数,以及有多少次试验完全没有发生工具调用
缺少这些条件的结果,与其说是错误的,不如说是无法解读的:读者判断不了 Sourcegraph 到底有没有帮助,基线是不是被削弱了,或者智能体究竟有没有调用过这个工具。
从比想象中更小的规模起步
准备二十到三十个有一定难度的任务,配上行为提示词(behavioral prompt),覆盖真实的代码仓库范围,每个任务至少跑三次,固定在同一个代码版本(pinned revision)上。这样做得到的信息,比一千个简单任务各跑一次要多得多。如果这轮小规模测试显示,在完成度相当的情况下,分散型任务有收益,那就扩大规模、进一步细分。如果没看到收益,基线检索活动也很少,那说明语料本身在告诉你:它从来就不需要索引检索。这时候先补上真正需要检索的那些任务,再对产品下任何结论。
你的第一次实验,从开始到结束
上面清单里的内容并不依赖某个特定的评测框架。如果你已经有能对任务跑 agent、并给结果打分的系统,那大部分机制你就齐了。缺的通常是这几点:各组之间干净的隔离、重复试验,以及核查检索工具到底有没有真被提供、真被用上。
我们用 CodeProbe 做这套评测。它从仓库历史里挖掘任务,搭出对照的几组,跑重复试验,再报告逐任务的配对差值(paired per-task delta)。CodeProbe 还在 alpha 阶段,目前正在内部和合作方那边测试,所以会有不兼容的改动。把实验内部的差异当作有用的产出;绝对分数还没跨实验校准。
想在合作方测试期用自己的仓库评测 Sourcegraph,可以发邮件给我:stephanie.jarmak@sourcegraph.com。
整个运行流程长这样:
codeprobe assess /path/to/repo
codeprobe mine /path/to/repo --org-scale --count 40 \
--consensus-backends ast,grep --no-llm
codeprobe experiment init /path/to/repo --name sourcegraph-eval
codeprobe experiment add-config <exp> \
--label local-baseline --agent <agent> --model <model>
codeprobe experiment add-config <exp> \
--label sourcegraph --agent <agent> --model <model> \
--mcp-config '<sourcegraph-config>' \
--mcp-mode strict --hide-local-source scaffold
codeprobe run <exp> --dry-run
codeprobe run <exp> --repeats 3 --parallel 5
codeprobe interpret <exp> --format html
这个实验只问一个问题:从你自己已合并的 pull request 中挖掘出 40 个任务,让同一个 agent 和模型去完成——当它通过 Sourcegraph 而不是本地搜索来访问代码时,是完成的工作更多,还是成本更低?Sourcegraph 配置中的两个 flag 用来隔离访问方式。
--mcp-mode strict 会保留已配置的检索工具和写权限,同时屏蔽本地读取、grep、glob 和 shell 命令。这是个实验条件,不是推荐的生产配置。在生产环境中,agent 可以把 Sourcegraph 和本地工具一起用。这里的隔离之所以有用,是因为它能明确归因;但严格模式也会移除与检索无关的 shell 能力——所以它衡量的是完整的隔离工具面,而不只是检索后端本身。
--hide-local-source scaffold 会把源文件替换成原始路径上的零字节占位符,然后在验证前把 agent 的编辑叠加到真实代码上。agent 无法查看本地实现,但验证器仍然在真实仓库上评估。如果所需产物是文本而非代码改动,改用 hide。
先运行 --dry-run,查看预估成本。40 个任务、两个实验组、三次重复,一共产生 240 次 agent 运行。--max-cost-usd 限制整个实验的总花费,--parallel 控制并发。这个规模的试点足以暴露集成失败、识别不同配置之间的方向性差异,但还不足以支撑稳定的效应估计。
有两个检查从第一轮起就该放进 CI。交叉验证门槛会在独立推导的基准真值不一致时失败。interpret 中的有效性门槛会在分析样本中仍有未解决的基础设施故障时拒绝报告结果。这一点很重要,因为仓库历史提供的是真实工作,而不是自动有效的评估任务:为某个 pull request 写的测试可能编码了那个特定实现,而不是定义完整的可接受解集。
一次有用的试点,并不需要证明 Sourcegraph 能改善每一项任务。它需要识别出索引检索会改变结果的工作:涉及大范围搜索、所有权分散、跨仓库依赖,或重要历史的任务。
先从 40 个有代表性的任务入手,用来验证集成是否跑通,并找出明显差异。在把测得的效果当作稳定结论之前,至少扩展到 80 个配对任务;如果主要看检索质量,就做到接近 100 个——在我们的功效分析里,这是最难精确估计的效果。然后按基线搜索的广度给结果分段,优先部署在完成率保持稳定、而搜索耗时或成本下降的地方。
把本文里的数字当成针对你自己代码库的假设,而不是基准分数。如果你的结果和我们的方向相反,那恰恰值得深挖,我们也乐意听你分享。