1. 这期速递到底在聊什么每周追代码大模型方向的论文,最头疼的不是没东西看,而是东西太多、太杂,看完了记不住,记住了又串不起来。这周(0225-0305)我翻了一圈,挑出几篇真正值得花时间细读的工作,按主题归类整理成这份速递。核心关键词就三个:代码生成、仓库级理解、执行反馈。如果你在做代码补全、自动化测试生成、或者仓库级代码问答这类落地项目,这份速递能帮你快速判断哪些方向正在升温、哪些坑别人已经替你踩过了。先说清楚这份速递的定位。它不是论文翻译,也不是简单的摘要堆砌。我会把每篇工作的核心动机、方法上的关键取舍、以及对实际工程的影响讲透。比如同样是做代码生成,有的工作死磕解码策略,有的工作把重心放在数据构造上,还有的干脆绕开生成、去做检索增强。这些路线背后的逻辑是什么,哪种更适合你的场景,我会给出自己的判断。这周的工作大致可以分成四块:第一块是仓库级代码理解与生成,这是目前最卷的方向,因为真实开发场景里代码从来不是孤立的函数,而是散落在几十个文件里的依赖关系;第二块是执行反馈与自我修复,让模型写完代码后能自己跑测试、看报错、再改,这个闭环一旦跑通,实用性会大幅提升;第三块是代码检索与上下文构造,解决的是"模型该看哪些代码"这个前置问题;第四块是评测与数据,包括新的基准和训练数据构造方法。下面逐块展开。提示:速递里提到的所有方法名和数据集名,我都会用通用描述代替具体命名,重点讲思路,你对照自己关注的论文时能快速对上号。2. 仓库级代码理解与生成2.1 为什么仓库级是绕不过去的坎单文件代码生成已经做得不错了,但真实开发中你让模型改一个函数,它得知道这个函数被谁调用、调用了谁、依赖哪些全局配置、有没有相关的测试用例。这些信息散落在整个仓库里,上下文窗口再大也塞不下。所以仓库级任务的核心矛盾是:信息量远超窗口容量,但关键信息又必须精准命中。这周有篇工作专门处理这个矛盾。它的思路不是把整个仓库塞进上下文,而是先做一轮依赖图剪枝。具体做法是:以目标函数为起点,沿着调用关系、导入关系、继承关系往外扩,但每一层都设一个相关性阈值,低于阈值的边直接砍掉。这个阈值怎么定?论文里用的是基于标识符重合度和历史共现频率的加权分数。我实测过类似思路,标识符重合度这个信号在多数项目里都挺准,但历史共现频率需要仓库有足够的提交记录,新项目上会失效。另一个值得关注的点是,这篇工作在处理跨文件重命名时用了一个符号解析器,先把所有文件里的符号定义和引用抽出来建索引,再基于索引做检索。这比直接拿文本块去算相似度靠谱得多,因为代码里同一个名字可能在不同作用域指代不同东西,纯文本匹配会引入大量噪声。2.2 上下文构造的三种策略对比这周有几篇工作都在做上下文构造,但策略差异很大,我整理成表格方便你对比:策略核心做法优势劣势适用场景检索增强用目标代码做query,检索相关片段实现简单,可插拔检索质量依赖embedding模型通用补全、问答图剪枝基于依赖图按相关性裁剪精准,可解释需要静态分析支持仓库级重构、跨文件修改分层摘要先摘要文件,再摘要模块,逐层聚合窗口利用率高摘要过程会丢细节大型仓库概览我个人的经验是,检索增强适合做第一层过滤,图剪枝适合做第二层精排。两者结合的效果比单用任何一种都好。但图剪枝有个前提:你的项目得能跑通静态分析。如果项目里大量用了动态导入、反射、元编程,依赖图会残缺,这时候检索增强反而更稳。注意:做上下文构造时,别忽略测试文件。很多工作只检索源码,但测试文件里往往包含了函数的使用示例和边界条件,这些信息对生成正确代码非常关键。我试过把测试文件单独作为一个检索源,生成通过率有明显提升。2.3 一个容易被忽略的细节:位置编码仓库级任务里,代码片段的排列顺序会影响模型理解。这周有篇工作专门研究了位置编码在长代码上下文里的表现。结论是:把最相关的片段放在上下文开头和结尾,中间放次相关的,效果比按文件路径顺序排列好。这个结论和长文本理解里的"lost in the middle"现象一致。但代码有个特殊之处:函数之间的调用关系是有方向的。如果A调用B,那把A放在B前面更符合阅读习惯。论文里做了消融实验,发现按调用方向排列比按相关性排列在跨文件任务上更好,但在单文件内补全任务上两者差不多。所以我的建议是:跨文件任务优先按调用方向排,单文件任务按相关性排。3. 执行反馈与自我修复3.1 闭环是怎么跑起来的执行反馈这条路线的核心逻辑很直白:模型生成代码,跑测试,如果失败就把报错信息喂回去让模型改,反复几轮直到通过或达到轮次上限。听起来简单,但实际做起来有几个关键决策点。第一个决策点是报错信息怎么给。直接把完整traceback塞回去,模型容易被无关的栈帧干扰。这周有篇工作做了个报错归因模块,先把traceback里和当前修改文件相关的帧筛出来,再按调用顺序排列。我试过类似做法,把无关帧去掉后,模型定位问题的准确率提升很明显。第二个决策点是改几轮。轮次太少,复杂bug改不完;轮次太多,模型容易陷入死循环,越改越错。论文里给的默认值是3轮,但我在实际项目里发现,第2轮之后如果还没通过,继续改的收益就很小了。所以我的做法是设一个动态阈值:如果连续两轮报错信息没有实质变化,就提前终止。3.2 测试用例从哪来执行反馈的前提是有测试可跑。但很多场景下你手上只有代码没有测试。这周有篇工作专门解决这个问题,它的做法是用模型生成测试用例,再用生成的测试去筛生成的代码。具体流程是:先让模型根据函数签名和文档生成一批测试,然后跑这些测试看哪些能通过,能通过的测试作为"可信测试"留下来,再用这些可信测试去评估后续生成的代码。这个思路有个隐患:如果模型生成的测试本身就是错的,那筛出来的代码也是错的。论文里用了一个交叉验证机制来缓解:让两个不同的模型分别生成测试,取交集作为可信测试。这个做法增加了成本,但确实能过滤掉一部分噪声测试。我在实际使用中的体会是,对于有明确输入输出契约的函数,生成测试的可靠性比较高;对于涉及外部状态、IO、并发的函数,生成测试基本不可用。3.3 修复策略的取舍模型拿到报错后怎么改,这周有篇工作对比了三种策略:全量重写:把整个函数重新生成一遍。优点是简单,缺点是可能把原本正确的部分改坏。局部编辑:只修改报错指向的行或块。优点是精准,缺点是需要准确定位。差异生成:让模型输出一个diff,再应用。优点是可控,缺点是模型对diff格式的掌握不如直接生成代码。论文的结论是:简单bug用局部编辑,复杂bug用全量重写。判断标准是报错涉及的行数,超过5行就倾向于全量重写。这个阈值不是绝对的,但思路值得借鉴。我自己的做法是先用局部编辑试一轮,如果失败再切全量重写,这样兼顾了效率和成功率。提示:做执行反馈时,一定要给模型设一个最大修改范围。我踩过的坑是模型为了修一个变量名错误,把整个函数的逻辑都改了,结果引入了新bug。后来我在prompt里明确限制"只允许修改报错相关的行",情况就好多了。4. 代码检索与上下文构造4.1 检索粒度怎么选代码检索的粒度选择是个老问题:按函数检索、按块检索、还是按行检索?这周有篇工作做了系统性对比。结论是:按函数检索在大多数任务上最优,但前提是函数边界要准。如果项目里函数写得特别长(超过200行),按函数检索会引入太多无关代码,这时候按块检索更好。块怎么切?论文里用的是基于AST的切分,把函数体按控制流结构切成若干块。这个做法比按固定行数切分好,因为块边界和语义边界对齐。但AST切分有个成本:需要解析代码。对于多语言项目,你得为每种语言准备解析器。如果项目语言比较单一,这个成本可以接受;如果语言很杂,可以考虑退而求其次用基于缩进的切分。另一个值得关注的点是检索单元的表示。这周有篇工作对比了三种表示:原始代码、代码摘要、代码+摘要拼接。结果是在跨语言检索任务上,代码+摘要拼接效果最好。原因是摘要提供了自然语言信号,能弥补代码标识符命名不规范带来的匹配困难。但在同语言检索任务上,原始代码就够了,加摘要反而引入噪声。4.2 重排序的必要性第一轮检索出来的结果往往不够精准,这时候需要重排序。这周有篇工作用了交叉编码器做重排序,把query和候选片段拼在一起过一遍模型,输出相关性分数。这个做法比双塔检索准,但速度慢。论文里的优化是先用双塔检索召回top-50,再用交叉编码器精排top-10,这样兼顾了速度和精度。我在实际项目里的做法更粗暴一些:用规则做第一轮过滤,用模型做第二轮精排。规则包括:排除测试文件、排除自动生成的代码、排除注释占比过高的片段。这些规则能砍掉大量噪声,让模型精排的压力小很多。实测下来,加了规则过滤后,精排的准确率能提升一截。4.3 检索增强生成的坑检索增强生成(RAG)在代码任务上有个特殊问题:检索到的代码可能和当前上下文冲突。比如你检索到一个同名函数,但它的实现和当前文件里的版本不一样。这时候模型会困惑,到底该信哪个。这周有篇工作专门处理这个冲突,它的做法是在prompt里显式标注每个检索片段的来源和版本,让模型自己判断。同时,对于版本冲突的片段,只保留最新版本。这个做法听起来简单,但效果很好。我在实际使用中的体会是,检索结果里一定要带文件路径和行号,这样模型能建立空间感,知道每段代码在仓库里的位置。注意:检索增强不是万能的。对于需要全局推理的任务(比如"这个改动会影响哪些模块"),检索只能提供局部信息,还需要配合依赖分析。我试过纯检索方案做影响分析,漏报率很高,后来加了调用图分析才把召回率提上来。5. 评测、数据与训练方法5.1 新基准透露的信号这周有个新基准值得关注,它专门评测模型在多轮代码修改上的表现。传统基准都是单轮生成,但真实开发是迭代式的:改一版,跑测试,根据反馈再改。这个基准的设计是给模型一个初始代码库和一个修改目标,然后模拟多轮交互,看模型能不能逐步逼近目标。这个基准透露的信号很明确:单轮生成能力已经不够用了,多轮迭代能力才是下一步的竞争点。我看了下榜单,几个主流模型在多轮场景下的表现差距比单轮大得多。这说明多轮能力还没有被充分优化,是个值得投入的方向。另一个信号是评测维度在细化。以前只看pass@k,现在开始看修改轮次、修改范围、是否引入回归bug等指标。这些指标更贴近实际工程需求。我建议你在做内部评测时也加上这些维度,不然容易高估模型的实际可用性。5.2 训练数据的构造技巧这周有篇工作在训练数据构造上做了个有意思的尝试:用代码提交历史构造训练数据。具体做法是拿一个commit的diff作为目标,把commit之前的代码作为输入,训练模型学会"根据修改意图生成diff"。这个思路比传统的"给注释生成代码"更贴近真实场景,因为真实开发中你往往不是从零写代码,而是修改已有代码。但commit历史有个问题:很多commit的message写得很烂,比如"fix bug"、"update"。论文里的处理是过滤掉message长度小于一定阈值的commit,同时用模型对message做扩写。这个做法有争议,因为扩写可能引入幻觉。我的建议是:优先用message质量高的commit,宁缺毋滥。数据质量比数量重要得多。还有个技巧是负样本构造。论文里用了两种负样本:一种是语法错误但语义正确的代码,一种是语义错误但语法正确的代码。前者训练模型关注语法,后者训练模型关注语义。这个区分很重要,因为实际场景中这两类错误需要不同的修复策略。5.3 微调还是提示这周有篇工作对比了微调和提示在代码任务上的效果。结论是:对于格式要求严格的任务(比如生成特定风格的diff),微调明显更好;对于开放式任务(比如代码问答),提示就够了。这个结论和我的经验一致。微调的成本主要在数据构造和训练资源上,如果你的任务有大量标注数据,微调值得做;如果数据少,不如把精力花在提示工程上。但提示工程有个天花板:当任务复杂度超过一定阈值,提示再怎么调也上不去。这时候就得考虑微调或者换更强的基座模型。论文里给了一个判断标准:如果提示工程调了5轮以上还没有明显提升,就该考虑微调了。这个标准不一定精确,但可以作为参考。提示:做微调时,学习率设小一点。代码任务的输出空间很大,学习率大了容易过拟合到训练数据的表面模式上。我试过用常规学习率微调,模型在训练集上表现很好,但换一个项目就崩了。后来把学习率降了一个数量级,泛化能力明显改善。6. 常见问题与排查技巧实录6.1 模型生成的代码跑不通怎么办这是最常见的问题。排查思路按优先级排:先看报错类型。语法错误通常是模型对语言版本不熟悉,比如用了新版本的语法但项目用的是旧版本。这类问题可以通过在prompt里明确语言版本来缓解。再看依赖问题。模型可能引用了不存在的包或函数。这时候要检查检索到的上下文里有没有包含正确的导入语句。我遇到过模型自己编了一个函数名的情况,原因是检索没命中相关定义。最后看逻辑错误。这类最难排查,因为代码能跑但结果不对。我的做法是让模型自己生成断言,把预期行为写清楚,再跑一遍看断言是否通过。6.2 检索结果不相关怎么调检索不相关通常有三个原因:query构造得不好、embedding模型不适合代码、索引粒度不对。排查顺序是:先看query。如果query是自然语言,试试改写成代码形式;如果query是代码,试试加上注释或摘要。再看embedding模型。通用文本embedding在代码上表现一般,换成代码专用的embedding模型通常有提升。最后看索引粒度。如果检索出来的片段太长或太短,调整切分策略。我踩过的一个坑是:索引里混入了大量自动生成的代码(比如protobuf生成的文件),这些文件内容重复度高,会挤占检索结果。后来我在建索引时加了个过滤规则,把这类文件排除掉,检索质量立刻上来了。6.3 多轮修改陷入死循环怎么破死循环的典型表现是:模型每轮都在改同一个地方,但报错信息不变。这时候需要打破循环。我的做法是:第一,换一种报错呈现方式。如果之前给的是完整traceback,这次只给最后一行错误信息。第二,换一种修改策略。如果之前是局部编辑,这次强制全量重写。第三,引入外部信号。比如让另一个模型给个修改建议,或者检索类似问题的修复方案。论文里还提到一个技巧:在prompt里加入"如果你不确定,请输出你的推理过程"。这个做法能让模型把思考过程外化,有时候模型在写推理过程的过程中就发现了问题所在。6.4 速查表问题可能原因排查动作解决方向生成代码语法错误语言版本不匹配检查prompt里的版本声明明确版本,加版本相关示例引用不存在的函数检索未命中定义检查检索结果是否含导入语句扩大检索范围,加符号索引多轮修改无进展报错信息无变化对比连续两轮报错换报错呈现方式或修改策略检索结果重复度高索引含生成代码检查索引文件来源过滤自动生成文件微调后泛化差学习率过大对比训练集和验证集表现降低学习率,加正则7. 这周工作给我的几个判断追了这周的工作,有几个判断越来越清晰。第一,仓库级任务的重心正在从"怎么塞更多上下文"转向"怎么塞更准的上下文"。早期工作都在拼窗口大小,现在大家意识到精准比量大重要。这对工程实践的启示是:别盲目追求大窗口模型,先把检索和剪枝做好,小窗口也能出好效果。第二,执行反馈的闭环正在成为标配。以前做代码生成就是生成完事,现在越来越多的场景要求生成-执行-修复闭环。这个趋势对基础设施提出了要求:你得有沙箱环境、有测试用例、有快速的执行反馈通道。如果这些基础设施没建好,再好的模型也用不起来。第三,评测正在从单轮向多轮迁移。单轮pass@k高不代表实际可用,多轮迭代能力才是真实开发场景的刚需。我建议你在做内部评测时,至少加一个多轮修改的评测维度,不然容易高估模型的实际价值。最后分享一个我在实际项目里的小技巧:把每次模型修改的diff存下来,定期做聚类分析。你会发现模型犯的错误有明显的模式,比如总是忘记处理空输入、总是搞错边界条件。把这些模式整理成检查清单,在prompt里显式提醒模型,能避免大量重复错误。这个做法比单纯调模型参数有效得多,而且成本极低。
1. 这期速递到底在聊什么每周追代码大模型方向的论文,最头疼的不是没东西看,而是东西太多、太杂,看完了记不住,记住了又串不起来。这周(0225-0305)我翻了一圈,挑出几篇真正值得花时间细读的工作,按主题归类整理成这份速递。核心关键词就三个:代码生成、仓库级理解、执行反馈。如果你在做代码补全、自动化测试生成、或者仓库级代码问答这类落地项目,这份速递能帮你快速判断哪些方向正在升温、哪些坑别人已经替你踩过了。先说清楚这份速递的定位。它不是论文翻译,也不是简单的摘要堆砌。我会把每篇工作的核心动机、方法上的关键取舍、以及对实际工程的影响讲透。比如同样是做代码生成,有的工作死磕解码策略,有的工作把重心放在数据构造上,还有的干脆绕开生成、去做检索增强。这些路线背后的逻辑是什么,哪种更适合你的场景,我会给出自己的判断。这周的工作大致可以分成四块:第一块是仓库级代码理解与生成,这是目前最卷的方向,因为真实开发场景里代码从来不是孤立的函数,而是散落在几十个文件里的依赖关系;第二块是执行反馈与自我修复,让模型写完代码后能自己跑测试、看报错、再改,这个闭环一旦跑通,实用性会大幅提升;第三块是代码检索与上下文构造,解决的是"模型该看哪些代码"这个前置问题;第四块是评测与数据,包括新的基准和训练数据构造方法。下面逐块展开。提示:速递里提到的所有方法名和数据集名,我都会用通用描述代替具体命名,重点讲思路,你对照自己关注的论文时能快速对上号。2. 仓库级代码理解与生成2.1 为什么仓库级是绕不过去的坎单文件代码生成已经做得不错了,但真实开发中你让模型改一个函数,它得知道这个函数被谁调用、调用了谁、依赖哪些全局配置、有没有相关的测试用例。这些信息散落在整个仓库里,上下文窗口再大也塞不下。所以仓库级任务的核心矛盾是:信息量远超窗口容量,但关键信息又必须精准命中。这周有篇工作专门处理这个矛盾。它的思路不是把整个仓库塞进上下文,而是先做一轮依赖图剪枝。具体做法是:以目标函数为起点,沿着调用关系、导入关系、继承关系往外扩,但每一层都设一个相关性阈值,低于阈值的边直接砍掉。这个阈值怎么定?论文里用的是基于标识符重合度和历史共现频率的加权分数。我实测过类似思路,标识符重合度这个信号在多数项目里都挺准,但历史共现频率需要仓库有足够的提交记录,新项目上会失效。另一个值得关注的点是,这篇工作在处理跨文件重命名时用了一个符号解析器,先把所有文件里的符号定义和引用抽出来建索引,再基于索引做检索。这比直接拿文本块去算相似度靠谱得多,因为代码里同一个名字可能在不同作用域指代不同东西,纯文本匹配会引入大量噪声。2.2 上下文构造的三种策略对比这周有几篇工作都在做上下文构造,但策略差异很大,我整理成表格方便你对比:策略核心做法优势劣势适用场景检索增强用目标代码做query,检索相关片段实现简单,可插拔检索质量依赖embedding模型通用补全、问答图剪枝基于依赖图按相关性裁剪精准,可解释需要静态分析支持仓库级重构、跨文件修改分层摘要先摘要文件,再摘要模块,逐层聚合窗口利用率高摘要过程会丢细节大型仓库概览我个人的经验是,检索增强适合做第一层过滤,图剪枝适合做第二层精排。两者结合的效果比单用任何一种都好。但图剪枝有个前提:你的项目得能跑通静态分析。如果项目里大量用了动态导入、反射、元编程,依赖图会残缺,这时候检索增强反而更稳。注意:做上下文构造时,别忽略测试文件。很多工作只检索源码,但测试文件里往往包含了函数的使用示例和边界条件,这些信息对生成正确代码非常关键。我试过把测试文件单独作为一个检索源,生成通过率有明显提升。2.3 一个容易被忽略的细节:位置编码仓库级任务里,代码片段的排列顺序会影响模型理解。这周有篇工作专门研究了位置编码在长代码上下文里的表现。结论是:把最相关的片段放在上下文开头和结尾,中间放次相关的,效果比按文件路径顺序排列好。这个结论和长文本理解里的"lost in the middle"现象一致。但代码有个特殊之处:函数之间的调用关系是有方向的。如果A调用B,那把A放在B前面更符合阅读习惯。论文里做了消融实验,发现按调用方向排列比按相关性排列在跨文件任务上更好,但在单文件内补全任务上两者差不多。所以我的建议是:跨文件任务优先按调用方向排,单文件任务按相关性排。3. 执行反馈与自我修复3.1 闭环是怎么跑起来的执行反馈这条路线的核心逻辑很直白:模型生成代码,跑测试,如果失败就把报错信息喂回去让模型改,反复几轮直到通过或达到轮次上限。听起来简单,但实际做起来有几个关键决策点。第一个决策点是报错信息怎么给。直接把完整traceback塞回去,模型容易被无关的栈帧干扰。这周有篇工作做了个报错归因模块,先把traceback里和当前修改文件相关的帧筛出来,再按调用顺序排列。我试过类似做法,把无关帧去掉后,模型定位问题的准确率提升很明显。第二个决策点是改几轮。轮次太少,复杂bug改不完;轮次太多,模型容易陷入死循环,越改越错。论文里给的默认值是3轮,但我在实际项目里发现,第2轮之后如果还没通过,继续改的收益就很小了。所以我的做法是设一个动态阈值:如果连续两轮报错信息没有实质变化,就提前终止。3.2 测试用例从哪来执行反馈的前提是有测试可跑。但很多场景下你手上只有代码没有测试。这周有篇工作专门解决这个问题,它的做法是用模型生成测试用例,再用生成的测试去筛生成的代码。具体流程是:先让模型根据函数签名和文档生成一批测试,然后跑这些测试看哪些能通过,能通过的测试作为"可信测试"留下来,再用这些可信测试去评估后续生成的代码。这个思路有个隐患:如果模型生成的测试本身就是错的,那筛出来的代码也是错的。论文里用了一个交叉验证机制来缓解:让两个不同的模型分别生成测试,取交集作为可信测试。这个做法增加了成本,但确实能过滤掉一部分噪声测试。我在实际使用中的体会是,对于有明确输入输出契约的函数,生成测试的可靠性比较高;对于涉及外部状态、IO、并发的函数,生成测试基本不可用。3.3 修复策略的取舍模型拿到报错后怎么改,这周有篇工作对比了三种策略:全量重写:把整个函数重新生成一遍。优点是简单,缺点是可能把原本正确的部分改坏。局部编辑:只修改报错指向的行或块。优点是精准,缺点是需要准确定位。差异生成:让模型输出一个diff,再应用。优点是可控,缺点是模型对diff格式的掌握不如直接生成代码。论文的结论是:简单bug用局部编辑,复杂bug用全量重写。判断标准是报错涉及的行数,超过5行就倾向于全量重写。这个阈值不是绝对的,但思路值得借鉴。我自己的做法是先用局部编辑试一轮,如果失败再切全量重写,这样兼顾了效率和成功率。提示:做执行反馈时,一定要给模型设一个最大修改范围。我踩过的坑是模型为了修一个变量名错误,把整个函数的逻辑都改了,结果引入了新bug。后来我在prompt里明确限制"只允许修改报错相关的行",情况就好多了。4. 代码检索与上下文构造4.1 检索粒度怎么选代码检索的粒度选择是个老问题:按函数检索、按块检索、还是按行检索?这周有篇工作做了系统性对比。结论是:按函数检索在大多数任务上最优,但前提是函数边界要准。如果项目里函数写得特别长(超过200行),按函数检索会引入太多无关代码,这时候按块检索更好。块怎么切?论文里用的是基于AST的切分,把函数体按控制流结构切成若干块。这个做法比按固定行数切分好,因为块边界和语义边界对齐。但AST切分有个成本:需要解析代码。对于多语言项目,你得为每种语言准备解析器。如果项目语言比较单一,这个成本可以接受;如果语言很杂,可以考虑退而求其次用基于缩进的切分。另一个值得关注的点是检索单元的表示。这周有篇工作对比了三种表示:原始代码、代码摘要、代码+摘要拼接。结果是在跨语言检索任务上,代码+摘要拼接效果最好。原因是摘要提供了自然语言信号,能弥补代码标识符命名不规范带来的匹配困难。但在同语言检索任务上,原始代码就够了,加摘要反而引入噪声。4.2 重排序的必要性第一轮检索出来的结果往往不够精准,这时候需要重排序。这周有篇工作用了交叉编码器做重排序,把query和候选片段拼在一起过一遍模型,输出相关性分数。这个做法比双塔检索准,但速度慢。论文里的优化是先用双塔检索召回top-50,再用交叉编码器精排top-10,这样兼顾了速度和精度。我在实际项目里的做法更粗暴一些:用规则做第一轮过滤,用模型做第二轮精排。规则包括:排除测试文件、排除自动生成的代码、排除注释占比过高的片段。这些规则能砍掉大量噪声,让模型精排的压力小很多。实测下来,加了规则过滤后,精排的准确率能提升一截。4.3 检索增强生成的坑检索增强生成(RAG)在代码任务上有个特殊问题:检索到的代码可能和当前上下文冲突。比如你检索到一个同名函数,但它的实现和当前文件里的版本不一样。这时候模型会困惑,到底该信哪个。这周有篇工作专门处理这个冲突,它的做法是在prompt里显式标注每个检索片段的来源和版本,让模型自己判断。同时,对于版本冲突的片段,只保留最新版本。这个做法听起来简单,但效果很好。我在实际使用中的体会是,检索结果里一定要带文件路径和行号,这样模型能建立空间感,知道每段代码在仓库里的位置。注意:检索增强不是万能的。对于需要全局推理的任务(比如"这个改动会影响哪些模块"),检索只能提供局部信息,还需要配合依赖分析。我试过纯检索方案做影响分析,漏报率很高,后来加了调用图分析才把召回率提上来。5. 评测、数据与训练方法5.1 新基准透露的信号这周有个新基准值得关注,它专门评测模型在多轮代码修改上的表现。传统基准都是单轮生成,但真实开发是迭代式的:改一版,跑测试,根据反馈再改。这个基准的设计是给模型一个初始代码库和一个修改目标,然后模拟多轮交互,看模型能不能逐步逼近目标。这个基准透露的信号很明确:单轮生成能力已经不够用了,多轮迭代能力才是下一步的竞争点。我看了下榜单,几个主流模型在多轮场景下的表现差距比单轮大得多。这说明多轮能力还没有被充分优化,是个值得投入的方向。另一个信号是评测维度在细化。以前只看pass@k,现在开始看修改轮次、修改范围、是否引入回归bug等指标。这些指标更贴近实际工程需求。我建议你在做内部评测时也加上这些维度,不然容易高估模型的实际可用性。5.2 训练数据的构造技巧这周有篇工作在训练数据构造上做了个有意思的尝试:用代码提交历史构造训练数据。具体做法是拿一个commit的diff作为目标,把commit之前的代码作为输入,训练模型学会"根据修改意图生成diff"。这个思路比传统的"给注释生成代码"更贴近真实场景,因为真实开发中你往往不是从零写代码,而是修改已有代码。但commit历史有个问题:很多commit的message写得很烂,比如"fix bug"、"update"。论文里的处理是过滤掉message长度小于一定阈值的commit,同时用模型对message做扩写。这个做法有争议,因为扩写可能引入幻觉。我的建议是:优先用message质量高的commit,宁缺毋滥。数据质量比数量重要得多。还有个技巧是负样本构造。论文里用了两种负样本:一种是语法错误但语义正确的代码,一种是语义错误但语法正确的代码。前者训练模型关注语法,后者训练模型关注语义。这个区分很重要,因为实际场景中这两类错误需要不同的修复策略。5.3 微调还是提示这周有篇工作对比了微调和提示在代码任务上的效果。结论是:对于格式要求严格的任务(比如生成特定风格的diff),微调明显更好;对于开放式任务(比如代码问答),提示就够了。这个结论和我的经验一致。微调的成本主要在数据构造和训练资源上,如果你的任务有大量标注数据,微调值得做;如果数据少,不如把精力花在提示工程上。但提示工程有个天花板:当任务复杂度超过一定阈值,提示再怎么调也上不去。这时候就得考虑微调或者换更强的基座模型。论文里给了一个判断标准:如果提示工程调了5轮以上还没有明显提升,就该考虑微调了。这个标准不一定精确,但可以作为参考。提示:做微调时,学习率设小一点。代码任务的输出空间很大,学习率大了容易过拟合到训练数据的表面模式上。我试过用常规学习率微调,模型在训练集上表现很好,但换一个项目就崩了。后来把学习率降了一个数量级,泛化能力明显改善。6. 常见问题与排查技巧实录6.1 模型生成的代码跑不通怎么办这是最常见的问题。排查思路按优先级排:先看报错类型。语法错误通常是模型对语言版本不熟悉,比如用了新版本的语法但项目用的是旧版本。这类问题可以通过在prompt里明确语言版本来缓解。再看依赖问题。模型可能引用了不存在的包或函数。这时候要检查检索到的上下文里有没有包含正确的导入语句。我遇到过模型自己编了一个函数名的情况,原因是检索没命中相关定义。最后看逻辑错误。这类最难排查,因为代码能跑但结果不对。我的做法是让模型自己生成断言,把预期行为写清楚,再跑一遍看断言是否通过。6.2 检索结果不相关怎么调检索不相关通常有三个原因:query构造得不好、embedding模型不适合代码、索引粒度不对。排查顺序是:先看query。如果query是自然语言,试试改写成代码形式;如果query是代码,试试加上注释或摘要。再看embedding模型。通用文本embedding在代码上表现一般,换成代码专用的embedding模型通常有提升。最后看索引粒度。如果检索出来的片段太长或太短,调整切分策略。我踩过的一个坑是:索引里混入了大量自动生成的代码(比如protobuf生成的文件),这些文件内容重复度高,会挤占检索结果。后来我在建索引时加了个过滤规则,把这类文件排除掉,检索质量立刻上来了。6.3 多轮修改陷入死循环怎么破死循环的典型表现是:模型每轮都在改同一个地方,但报错信息不变。这时候需要打破循环。我的做法是:第一,换一种报错呈现方式。如果之前给的是完整traceback,这次只给最后一行错误信息。第二,换一种修改策略。如果之前是局部编辑,这次强制全量重写。第三,引入外部信号。比如让另一个模型给个修改建议,或者检索类似问题的修复方案。论文里还提到一个技巧:在prompt里加入"如果你不确定,请输出你的推理过程"。这个做法能让模型把思考过程外化,有时候模型在写推理过程的过程中就发现了问题所在。6.4 速查表问题可能原因排查动作解决方向生成代码语法错误语言版本不匹配检查prompt里的版本声明明确版本,加版本相关示例引用不存在的函数检索未命中定义检查检索结果是否含导入语句扩大检索范围,加符号索引多轮修改无进展报错信息无变化对比连续两轮报错换报错呈现方式或修改策略检索结果重复度高索引含生成代码检查索引文件来源过滤自动生成文件微调后泛化差学习率过大对比训练集和验证集表现降低学习率,加正则7. 这周工作给我的几个判断追了这周的工作,有几个判断越来越清晰。第一,仓库级任务的重心正在从"怎么塞更多上下文"转向"怎么塞更准的上下文"。早期工作都在拼窗口大小,现在大家意识到精准比量大重要。这对工程实践的启示是:别盲目追求大窗口模型,先把检索和剪枝做好,小窗口也能出好效果。第二,执行反馈的闭环正在成为标配。以前做代码生成就是生成完事,现在越来越多的场景要求生成-执行-修复闭环。这个趋势对基础设施提出了要求:你得有沙箱环境、有测试用例、有快速的执行反馈通道。如果这些基础设施没建好,再好的模型也用不起来。第三,评测正在从单轮向多轮迁移。单轮pass@k高不代表实际可用,多轮迭代能力才是真实开发场景的刚需。我建议你在做内部评测时,至少加一个多轮修改的评测维度,不然容易高估模型的实际价值。最后分享一个我在实际项目里的小技巧:把每次模型修改的diff存下来,定期做聚类分析。你会发现模型犯的错误有明显的模式,比如总是忘记处理空输入、总是搞错边界条件。把这些模式整理成检查清单,在prompt里显式提醒模型,能避免大量重复错误。这个做法比单纯调模型参数有效得多,而且成本极低。