改一改函数名,14 种模型读同一份代码最多少烧三分之二的 token
- 你给函数起的名字,决定 AI 改它的时候是翻 19 个文件还是翻 459 个。Modem 用 1680 次对照跑出了这笔账
- 根子在这里:AI 找代码靠的是纯文本搜索,没有编译器给依赖图,也没有语言服务器解析符号。Claude Code 团队早期试过向量库,后来扔了
- 把名字换成一搜就中的,14 种模型和工具组合读同一份代码全部少烧 token:省得最多的那个从平均 7 万降到 2.4 万,中位数省三成,而且自信满满答错的情况归零
- 省下的检索预算会直接变成判断力:同样给八轮预算查 bug,弱模型在巨石文件里只查出 3/8,代码拆开重命名之后是 8/8。那些失败的审查大多没给出错误答案,预算全烧在了翻文件上,没走到下结论那一步
AI 到底是怎么找代码的?(底层机制)
你让 AI 编码的时候,要它改个函数名,它第一件事是在你的仓库里搜。
这个「搜」没有任何高深的地方:把整个仓库的文字过一遍,看哪些行里出现了你要的那串字符,跟你在编辑器里按 Ctrl+F 是同一回事。这个动作在命令行里叫 grep,几十年前就有了;AI 用的是它的加速版 ripgrep(命令写作 rg)。
它不会去问编译器要一张依赖关系图,也没有语言服务器帮它把符号解析明白。它认的只有字面。搜一次、读命中处前后那一段、不够就换个词再搜。
这不是某个工具偷懒。Claude Code 团队早期试过向量库那一套,后来扔掉了,因为纯文本搜索效果更好。学术界做的 SWE-agent 也落在同一个地方:给模型的就是专门做的关键词搜索工具,没有更花哨的东西。
路径也是搜索词。你问 session broker(会话中介)是怎么工作的,AI 会拿 session-broker、sessionBroker、session_broker 三种拼法去扫文件名,一个叫 session-broker/ 的目录,在它读到第一行代码之前就已经是一次命中。
它就在这个圈里转:搜一次、读命中处附近那一段、不够就换个词再搜,够了才开始改。
所以这条链上有一个输入完全握在写代码的人手里:你代码里的词和文件上的名字,能不能当好搜索词。
这笔账是 Modem 算出来的。这家公司 2025 年初创业时就决定全用 AI 写代码,一年下来 36 万行 TypeScript 应用代码加 32 万行测试代码,99.9% 由模型生成;下面的经验和 1680 次对照实验,都出自这一年。
名字起得泛,代价有多大?
那「能不能当好搜索词」到底差多少?他们拿三个函数做了对比。
这三个函数功能完全一样,都是创建一个调用外部服务的 API 客户端,区别只在名字:
export function create(apiKey: string) { ... }
export function createClient(apiKey: string) { ... }
export function createStripeClient(apiKey: string) { ... }
在 Modem 那个约 2900 个 TypeScript 文件的仓库里各搜一遍:
所以问题不在搜得快不快。grep 交回来的是匹配的行,不是答案。一行 const client = create(config) 并不能告诉 AI 这是不是你要的那个客户端,还是那几百个同样叫 create 的东西之一。
要弄清楚,它得打开文件读命中处周围那一段,经常还要往外扩,或者再打开别的段落。一个文件几十到上千行,一行按十个 token 算(token 是 AI 读写文字的计量单位,一次对话能装多少、要花多少钱都按它算,大致一个英文单词一个多),排除掉一个错误候选就是几百到几千 token。挨个排除十几个,几万 token 已经没了,而你交代的活还一个字没动。
那 1585 个命中散在几百样不相干的东西里:测试用的假数据、往数据库里插记录、注册后台任务。而 createStripeClient 的 43 个命中,就是定义、调用点和测试,全都在讲同一个客户端。