别再让 AI 瞎编代码了:Cody 如何用你的整个代码库来阻止 Copilot 式的幻觉
你有没有遇到过这样的情况:让 Copilot 帮你写一个支付接口,它生成了一堆看着像模像样、其实完全不存在的函数?这不是你的错——因为 Copilot 只看到了你当前打开的几个文件,它根本不知道你的项目里已经有一套现成的工具库。结果就是,它“发明”了一个你早就写好的接口,还编了四个根本不存在的辅助函数。
这就是 Sourcegraph Cody 想要解决的问题。它不会像 Copilot 那样靠猜,而是先索引你整个代码仓库,然后用这个索引作为上下文来回答任何 AI 问题。我花了两个星期,在真实的企业级 TypeScript 项目(260 万行代码、约 1.1 万个文件)上测试 Cody,想看看“感知代码库”到底能不能让 AI 的代码更靠谱。
Cody 的“代码图谱”是怎么工作的?
Cody 不是简单搜索你的代码。它建立了一个搜索索引,这个索引能理解代码之间的逻辑关系——哪个函数调用了哪个、哪些接口在哪里被实现、哪些类型在模块间传递。当你提问或触发补全时,Cody 会查询这个索引,找到最相关的代码片段,然后把这些真实代码作为上下文丢给大模型。
初次索引需要时间。我测试的那个巨型仓库,第一次运行时索引跑了大约 14 分钟,处理了约 1.1 万个 TypeScript 文件。之后如果文件有改动,增量更新不到 30 秒就能完成。索引占了约 450 MB 磁盘空间,对于一个这么大的仓库来说,这个体积很合理,甚至比仓库本身还小。
实际效果就是:Cody 的回答会引用你项目里实际存在的代码。当我问“这个仓库的认证是怎么实现的”,Cody 顺着中间件链追溯了五个文件,找到了 JWT 验证模块,还解释了基于角色的权限控制模式——每个关键点都标注了具体的函数名和行号。同样的问题问 Copilot,它只给出一个通用的 JWT 流程,方向大致对,但完全忽略了你自己写的那个策略引擎(它夹在中间件和路由处理器之间)。答案“听起来对”和“真的对”之间的差距,就在这里。
Cody 的上下文检索不限于符号,它还会索引代码模式和结构关系。比如我问“有哪些地方还在用旧的
legacyFetch包装器?我想迁移”,Cody 返回了 23 个文件里的 47 处位置。如果我用grep legacyFetch来搜,只找到了 31 处,因为它漏掉了函数被导入时用了别名或者通过重导出模块调用的场景。符号感知的搜索能抓到纯文本搜索抓不到的模式。
企业级功能:多仓库搜索和本地部署
Cody 的企业版增加了两个对大型组织特别有用的功能:多仓库搜索和本地部署。
多仓库搜索允许你索引多个仓库,然后跨仓库查询。在微服务架构里,一个功能可能横跨三四个服务,Cody 可以追踪请求从 API 网关到认证服务、再到业务逻辑服务、再到数据库层的完整路径——即使这些服务分别放在不同的仓库里。我用四个相互关联的仓库做了测试,问“用户更新订阅等级时,端到端会发生什么?”,Cody 给出了一个横跨所有四个代码库的连贯追踪。没有多仓库功能,我得在四个编辑器窗口里问四次同样的问题,然后手动拼凑答案。
本地部署通过 Sourcegraph Enterprise 实现,整个栈——代码图谱索引器、Cody AI 网关、IDE 集成——都运行在公司自己的基础设施里。大模型调用可以路由到自建模型或者通过客户控制的 API 密钥走云服务商,安全团队可以完全控制代码和提问的去向。这对国防承包商、金融机构、医疗保健公司来说是硬性要求,而 Cody 是少数原生支持这一点、不需要第三方代理的 AI 编码工具之一。
// Cody 正确识别出这是我们仓库的标准认证模式,
// 它沿着中间件栈一路追踪到了策略引擎。
// src/shared/auth/middleware.ts
export async function authMiddleware(req: Request, res: Response, next: NextFunction) {
// 从请求头中提取 Bearer token
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: '缺少 Token' });
// 验证 JWT 并拿到用户声明
const claims = await verifyToken(token);
// 根据用户角色、请求路径和方法,评估策略引擎
const policyResult = await evaluatePolicy(claims.role, req.path, req.method);
if (!policyResult.allowed) {
return res.status(403).json({ error: policyResult.reason });
}
req.user = claims;
next();
}
IDE 集成与日常使用
Cody 通过插件集成到 VS Code、JetBrains 和 Neovim。VS Code 插件最成熟——它支持上下文感知的自动补全、聊天面板、以及解释、修复、生成代码的内联命令。与通用 AI 插件的关键区别是:每次交互都会显示一个“上下文”指示器,告诉你 Cody 正在引用哪些文件,你可以手动扩大或缩小这个上下文。
自动补全的速度比 Copilot 慢——我的测试中每次建议大约 400 到 700 毫秒,而 Copilot 是 150 到 300 毫秒——但因为建议是基于真实代码库的,所以更准确。经过两周每天使用,Cody 补全的接受率约为 68%,而 Copilot 在同一代码库上约为 55%。这 13 个百分点的差距,反映的是 Copilot 经常生成看起来合理但实际引用了项目中不存在的函数或类型。
聊天面板支持用 @ 提到文件、符号和仓库,这样你可以很方便地把问题限定到代码库的某一部分。我经常用 @file 和 @symbol 来缩小 Cody 的上下文范围,回答更精准;如果问整体架构问题,就不加这些限定,让 Cody 使用整个代码库的上下文。
Cody 的短板
Cody 生成代码的速度不如 Copilot。它生成的代码更可能正确,但延迟差异明显,这对追求补全速度的场景很重要。如果你只是写模板代码或者填充重复模式,Copilot 更快的补全更合适。Cody 的优势在于调试和理解代码,而不是原始生成速度。
索引依赖是一把双刃剑。如果你的代码库很小(不到 5000 个文件),索引的开销是多余的,上下文的好处也微乎其微。Copilot 只靠打开文件和相邻文件的上下文在这个规模下已经够用。Cody 的价值在文件数超过 1 万时才开始显现,随着代码库越大越重要。低于这个阈值,设置成本不值得那一点点准确率提升。
价格也是个因素。Cody 个人计划免费,包含代码库索引和 IDE 集成。专业计划每月 9 美元,提供无限自动补全和更高速率限制。企业版包括多仓库搜索、本地部署和管理控制,按座位年付。对个人开发者来说,免费版真的能用。对团队来说,如果代码库足够大、能从代码库感知中受益,企业版的功能就值得付费。
当你切换分支且分支间差异较大时,Cody 的代码图谱索引会从头重建。在我测试的巨型仓库中,从主分支切到一个修改了 40 个文件的特性分支,触发了 5 分钟的增量重新索引。这不算致命,但如果你经常在差异很大的分支间切换,需要知道索引会滞后——重新索引期间的补全准确率会下降。
Cody 命令与自定义配方
除了标准的聊天和自动补全,Cody 还包含一个命令系统,这个功能被低估了。命令是预先配置好的提示,针对特定上下文运行——比如解释选中的代码、为当前文件生成单元测试、在打开的模块里找代码坏味道、或者为某个包的公共 API 生成文档。这些想法不新鲜,但 Cody 的实现因为有了代码图谱,效果比通用实现更好。
“生成单元测试”命令,当它作用于一个依赖其他三个内部模块的函数时,生成的测试文件给这三个依赖都导入了正确的模拟对象。同样的函数我用 Copilot 的等效命令测试,结果生成了一个调用真实实现的测试,因为 Copilot 看不到依赖链。Cody 生成的测试并不完美——它漏了两个边界情况——但模拟对象的搭建是对的,而这恰好是手动写最花时间的部分。我只花了 4 分钟检查和添加边界情况,而不是花 15 分钟从头写模拟对象。
自定义配方让你定义自己的命令,并指定需要的上下文。我的团队设置了一个配方:每次拉取请求(PR)前扫描破坏性 API 变更——它对比当前分支和主分支导出的类型和函数,标记新增、删除和签名变更。该配方在一个 500 个文件差异的 PR 上运行约 30 秒,已经抓住了两次无意中修改了接口、可能破坏下游消费者的情况。这就是代码库感知的 AI 能做到、通用助手做不到的事情——因为他们缺乏对“什么变了”以及“谁依赖它”的结构理解。
// 一个自定义 Cody 配方,用于检测破坏性 API 变更。
// 因为 Cody 的代码图谱知道依赖链,它可以标记那些影响下游消费者的变更,
// 而不仅仅是文本差异。
// 配方名称: breaking-change-detector
// 触发条件: 在 PR 对比主分支时
// 上下文: 完整仓库索引
// 提示词:
// "比较当前分支和主分支的导出 API 表面。
// 对每个变更:
// 1. 分类为:新增、删除、签名变更、行为变更
// 2. 如果是删除或签名变更,列出所有受到影响的内部调用者
// 3. 如果影响到了公共 API 导出,标记为严重(HIGH)
// 4. 为破坏性变更提供迁移路径建议"
最初发布于 pickuma.com。
