Impact-driven Context Filtering:用真实 completion likelihood 训练代码上下文过滤器
CodeFilter 怎样筛上下文:系统先用 ground-truth completion 的 likelihood change,把检索 chunk 标为正、负或中性。代码模型在线输出“是否检索”和“该 chunk 是否保留”的控制 token,只留下有用的跨文件上下文,prompt 也随之缩短。
本文目录 · 16 节
1. 问题与 baseline
repo-level completion 只看当前文件经常缺少 API 定义、相邻模块用法和项目约定,因此常见做法是把当前代码作为 query,从其他文件取 top-10 chunks,拼进 prompt。baseline 有三类:No Retrieve 只用 in-file context;Full Retrieve 总是加入 top-10;RepoFormer 先判断要不要检索,但一旦检索仍把候选整体交给 generator。它们都把“检索相似”近似成“对这次 completion 有帮助”。
作者在 RepoEval-API 上逐 chunk 检查后发现,top-10 中只有约 15% 是 positive,5.6% 会降低正确 completion 的 likelihood,影响 19.81% instances,其余大多 neutral;大约一半 instance 连一个 positive chunk 都没有。StarCoderBase-3B 的 Full Retrieve EM 为 47.27%,删掉 negative 后为 49.96%,只留 positive 为 49.47%。因此问题不只是 token 浪费,而是负上下文会把生成分布推向错误代码。
2. 如何定义“影响”
目标 completion: Y = (y1, ..., yT)
in-file context: C_in
候选跨文件 chunk: c_i
L(Y | C) = sum_{t=1..T} log P(y_t | y_<t, C; G)
S(c_i | C_in, Y) =
[L(Y | C_in, c_i) - L(Y | C_in)] / L(Y | C_in)
polarity(c_i) =
Positive, if S > T_p (论文设 T_p = +10%)
Negative, if S < T_n (论文设 T_n = -5%)
Neutral, otherwise
分数直接问:“加入这个 chunk 后,模型给已知正确答案的 log-likelihood 提高还是降低?”它比 Jaccard 或 embedding similarity 更靠近最终生成目标。线上当然没有 ground truth,所以该式只用于离线标注;部署时由 fine-tuned CodeFilter 预测控制 token,这也是方法最重要的训练/推理边界。
3. 两组控制 token
<EC>/<MC>:Enough Context 与 More Context。先判断当前文件是否已经足够,也在每次接受 positive chunk 后重新判断是否还要继续。<pos>/<neg>/<neu>:预测刚查看的候选对 completion 的极性。只有 positive chunk 留在最终 prompt。
训练数据使用 FIM verbalization。一个极性学习样本会呈现打乱顺序的候选及其标签;另一个生成样本只呈现 positive chunks,随后是 <EC><MIDDLE>[Target]。若没有 positive,直接生成 <EC>,教模型不要为检索而检索。目标函数同时训练代码和 signal token:
L = -log P_G(Y | C_in, C_cc)
+ lambda * [-log P_G(T | C_in, C_cc)]
lambda = 2.0
计算 loss 时 mask 掉作为条件的 in-file/cross-file 内容,
只监督 signal tokens 与 target tokens。
4. 完整在线数据流
- 将左上下文、右上下文组织为
<PREFIX>...<SUFFIX>...;模型先在<EC>/<MC>上做一次小决策。 - 若
<EC>,直接加入<MIDDLE>并生成代码,不调用 retriever。 - 若
<MC>,用当前文件前 10 行作 query,将其他文件按 10 行窗口、5 行 stride 切块,以 Jaccard 排序取 top-10。 - 候选按序送给 CodeFilter。模型为当前 chunk 生成 polarity token;
<neu>/<neg>立即丢弃,<pos>才追加到可见 completion context。 - 接受 positive 后再次在
<EC>/<MC>间选择。上下文已足够就提前停止,否则看下一个候选。 - 最终只把 in-file + accepted positive chunks 交给 generator。CodeFilter 自己也可生成;论文另证实 3B 的过滤决策可以作为 plug-in policy 给 7B-16B、GPT-3.5、DeepSeek-R1 等更大模型。
5. 一个完整例子
假设当前文件要补 client.fetch_user(user_id) 的错误处理。top-10 中:chunk A 是项目里同一 client 的重试 wrapper,B 是另一个模块的 interval 数值计算,C 是该 API 返回 None 时抛 UserNotFound 的调用。Full Retrieve 会把 A/B/C 连同七个相似但无关片段都塞入 prompt;B 中同名变量和错误类型可能让模型走错分支。
CodeFilter 首先输出 <MC>。A 后输出 <pos> 并保留,但再次判断仍是 <MC>;B 输出 <neg>,不进入最终上下文;C 输出 <pos>,随后 <EC>,立即停止。最终 generator 只看到 A、C,既学到重试约定,也拿到正确异常语义。离线标签并不是靠作者主观判断:加入 A/C 会让 ground-truth log-likelihood 相对基线提高超过 10%,B 让它下降超过 5%。
6. 训练与评测设置
数据来自 Stack 中近 6,000 个 Python repositories。每个实例取 line、chunk 或 function body 为 target,top-10 Jaccard chunks 做 likelihood 标注;清洗后得到约 43K instances、400K labeled chunks,verbalize 后约 130K training instances,95/5 切分。模型为 StarCoderBase-3B/7B、CodeLlama-7B/13B,训练 2 epochs,初始 LR 2e-5、5% warmup、linear decay、batch 512、max length 4096,4x A100 80GB。推理用 vLLM 与 greedy decoding,in-file/cross-file budget 为 1024/3072 tokens;<MC>、<pos>、<neg> threshold 均设 0.3。
benchmark 是 RepoEval(14 个高质量 Python repos 的 line/API/function)与 CrossCodeLongEval(chunk/function),同时测 FIM 与 left-to-right。指标为 EM、Edit Similarity,RepoEval function 另用 unit-test pass rate。
7. 准确结果
| 模型/设置 | Full Retrieve | CodeFilter | 含义 |
|---|---|---|---|
| StarCoderBase-3B, FIM RepoEval-Line EM | 56.25 | 60.50 | 更短 context 反而更准 |
| StarCoderBase-3B, FIM RepoEval-API EM | 47.27 | 50.59 | 接近/超过 7B full retrieval |
| CodeLlama-13B, FIM RepoEval-API EM | 48.66 | 51.84 | 跨模型族一致收益 |
| StarCoderBase-7B, negative subset, LTR Line EM | 7.23 | 28.92 | 负 chunk 场景收益最明显 |
| StarCoderBase-7B, negative subset, FIM API EM | 10.63 | 22.83 | 过滤确实缓解误导 |
论文总体概括为平均 EM 相对 RAG baseline 提升约 3%,cross-file prompt tokens 减少近/超过 80%。Full Retrieve 在各 benchmark 都超过 1,500 cross-file tokens;CodeFilter 进一步比 RepoFormer 少得多。negative subset 来自 1,600 test instances,其中 API/Line 分别 285/166 个包含负 chunk;在该子集 Full Retrieve 有时甚至弱于 No Retrieve,支持“negative context 真的有害”而不只是相关性分数不漂亮。
8. 消融:阈值不是越严格越好
StarCoderBase-3B、FIM RepoEval-API 中,<MC> threshold 从 0 到 0.3 时 EM 保持 50.16%-50.59%;升到 1.0 等于禁用检索,EM 掉到 41.15%。两个 threshold 都为 0.3 时,cross-file context 为 355 tokens,不到原始的 30%。<MC> threshold 还决定要评估多少 chunk:signal-token overhead 从 threshold 0 的 10.85 tokens,降到 threshold 1 的 1 token。作者因此推荐 0.2-0.3 的质量/成本折中,而不是最大化过滤。
9. 方法贡献
CodeFilter 没有再训练一个 relevance ranker。它用 generator 对正确 completion 的因果式对照构造标签:同一 in-file context 下只加一个 chunk,观察目标 likelihood 的变化。标签除了“相关/不相关”,还会标出让模型更容易出错的 negative。随后,retrieval sufficiency 与 chunk polarity 被编码成模型可生成的 tokens,检索、过滤、停止由一个自回归过程统一控制;做决策的小模型也可以与更大的 generator 解耦。
10. 局限与适用边界
- ground-truth likelihood 只能离线计算,标签依赖所选 generator;换模型后同一 chunk 的 polarity 可能改变。
- 训练和主评测以 Python 为主,跨语言、monorepo build system、生成代码仓库需要重标与重测。
- Jaccard top-10 是主要 retriever;虽然附录验证 UniXcoder,更多 graph/symbol-aware retriever 仍会改变候选分布。
- 逐 chunk 生成 signal token 有额外 latency;prompt 节省和 quality gain 要与过滤器调用成本一起算。
- EM/ES 对语义等价代码较严格,unit test 只覆盖 RepoEval function,不能等同生产正确性或安全性。
11. 与合集其他论文的关系
Rethinking KV Cache Compression 说明压缩虽减少显存,却可能拉长输出;CodeFilter 说明检索虽增加信息,却可能拉低 likelihood。两篇都把端到端请求结果置于局部资源指标之上。PACE/CONCUR 从 agent 生命周期控制并发,CodeFilter 从 prompt 构造减少 prefill token,可在同一 code agent serving stack 组合。与一般 RAG router 相比,它优化的不是选哪个大模型,而是进入模型前哪些代码证据值得保留。
12. 为什么相似 chunk 会产生负影响
代码仓库里常见同名函数、旧版本接口、测试 mock 和不同子模块的局部约定。词法相似检索会把这些片段排得很高,但 generator 并不知道哪个定义处于当前 import path。一个旧 API 示例可能包含几乎相同的符号,却让模型选择错误参数顺序;一个测试 double 可能把真实异常吞掉。negative label 捕捉的是这种“看起来相关、实际把正确答案概率拉低”的情况,neutral 则只是没有提供新增信息。二者在资源上都可删,在错误风险上却应分开分析。
13. 标签构造中的三个关键选择
一次只加入一个候选
贡献分数比较 C_in 与 C_in+c_i,避免多个 chunk 同时出现后无法归因。代价是它没有直接建模互补关系:两个单独 neutral 的片段合在一起可能足以解释调用。训练 verbalization 通过逐步接受 positive 并重新判断 <EC> 部分弥补组合需求,但初始 polarity 标签仍是一阶近似。
用相对变化而不是原始 likelihood
不同 target 的长度和难度不同,原始 log-likelihood 不可直接横比。相对基线变化把问题变成该 chunk 对同一个 target 的增益;正负阈值又故意不对称,positive 需提升超过 10%,negative 下降超过 5% 就进入风险类。这个标准更重视避免有害信息,但阈值和标注模型一起决定数据分布。
控制 token 与代码 token 联合训练
若模型只学 polarity classification,它可能知道 chunk 好坏却不知道何时停止;若只学 <MC>/<EC>,则会复现 RepoFormer 的“要么全取、要么不取”。联合 loss 让判断与最终 completion 共享表示,lambda=2 又避免稀少 signal token 被长 target loss 淹没。部署时这些 token 是执行协议,必须从用户可见代码中剥离。
14. 如何公平核算效率
论文清楚报告 prompt token 缩短,但生产系统还要加上过滤阶段的 decode、逐 chunk KV 构建与 retriever latency。可采用两阶段 serving:小 CodeFilter 独立批处理所有候选,只把 positive chunk ID 返回大 generator;常用仓库片段的编码和检索结果可缓存。应同时测总 TTFT、generator prefill tokens、过滤 signal tokens、最终 EM/UT,而不能只把减少的 80% prompt 当作等比例 latency speedup。
15. 泛化时应先检查什么
迁移到 Java/C++ 时,需要保留 package/include、重载、类型与 build target 等结构,单纯 10 行窗口可能切断语义;迁移到 agentic editing 时,target 也从一段 completion 变成多文件 patch,单 chunk likelihood 标签要重新定义。若更换 generator,先抽样重算 polarity agreement;若 3B policy 与目标大模型对同一 chunk 经常意见相反,就不能直接复用 plug-in 结论。最稳妥的做法是保留线上 shadow evaluation,让 full-retrieve 与 filtered prompt 在不执行写操作时并行评分。
16. 前置背景、工程复现与结论边界
跨文件补全为什么先要检索
单文件补全可从光标左右的代码推断局部语法,但真实仓库中的类型、函数签名、错误约定和辅助工具常定义在其他文件。仅依赖预训练记忆会生成通用写法,无法知道当前仓库的私有接口。跨文件检索因此把光标附近代码作为查询,从仓库其他位置找相似片段,放到填空提示前。填空模式同时给前缀和后缀,模型生成中间;左到右模式只给前缀。CodeFilter 同时评测两种。
词法检索的优势是便宜、无需索引模型,问题是相似度衡量文本重叠,不衡量候选对具体正确补全的因果影响。仓库中测试、旧实现和不同模块会复用同名变量;一个相似片段甚至比无关片段更危险,因为模型会高置信模仿错误约定。论文先通过逐候选干预证明 negative context 存在,再训练线上控制器,这条证据链比直接比较新 ranker 更完整。
Likelihood 影响分数的符号与长度
目标序列 Y 有 T 个 token,L 是在给定上下文下逐 token 对数概率之和。对数概率通常为负;论文公式用加入候选前后的差再除基线值,阈值按其实现定义解释。复现不能只看公式符号自行反转标签,应在一个已知提高目标概率的候选上检查输出确实标 positive。目标长度固定时差值可比,同一候选对不同目标的相对归一化减少难度尺度差。
标注每个 chunk 时其他候选不出现,所以 S 衡量一阶边际影响。若两个片段只有合并才有帮助,它们可能都被标中性;若两个 positive 内容重复,依次加入后第二个新增价值可能很小。在线算法按序查看并在保留正片段后重新判断是否已足够,能处理部分冗余,却没有重新预测剩余候选在新上下文下的 polarity。它以有限控制 token 换取可执行复杂度。
正阈值百分之十高于负阈值绝对值百分之五,意味着保留需要更强证据,删除风险更敏感。Neutral 占大多数,既不明显提升也不明显伤害;删除它主要省 token。Negative 比例虽只有百分之五点六,却分布在近五分之一实例中,解释了为什么平均比例小仍能显著影响请求子集。
离线数据构造的完整流水线
- 从近六千 Python 仓库抽取可形成 line、API、function completion 的位置,保留光标前后代码和 ground truth。
- 排除当前文件,将其他文件按十行窗口、五行步长切块;用当前文件前十行等查询做 Jaccard 排序,取前十候选。
- 冻结用于标注的 generator,分别计算只有文件内上下文与额外加入单一候选时的目标对数似然,按阈值标正、负、中性。
- 构造 signal 学习样本:把候选及 polarity 控制 token verbalize;构造生成样本:只保留 positive,并在足够位置监督 EC,目标区监督真实代码。
- 清洗后约四万三千 completion、四十万 chunk 标签,展开约十三万训练样本,按九十五比五划分。
仓库级拆分必须避免同一项目的相似代码同时进入训练与测试,否则过滤器可能记住文件。论文主 benchmark 是独立的十四个高质量仓库。复现还要固定 tokenizer 与最大长度四千零九十六;候选拼接超过预算时的截断顺序会改变哪个 chunk真正可见。
联合目标和控制 token 如何进入一次 forward
训练 loss 第一项监督 target code,第二项监督 EC、MC 与 polarity token,权重二。条件中的文件内代码、候选正文被 mask,不计算语言建模损失,防止模型把容量花在复述输入。控制 token 要加入 tokenizer 词表并初始化 embedding;若只用普通字符串,可能被拆成多个 token,阈值概率和协议都失效。
推理先对 EC 与 MC 的概率做阈值决策。阈值零点三不等于必须 argmax 超过一半;模型可在多个普通 token 中分散概率,控制 token 达到零点三就触发。Polarity 同理。采用 greedy completion,但控制阶段可以读取指定 token 概率,而不是让模型自由生成任意文本。每接受一个 positive 后再次判断 EC,形成早停;negative 与 neutral 都不进入 generator 上下文。
若 CodeFilter 与最终 generator 是同一模型,保留上下文后可继续生成;若作为三十亿 policy 给更大模型,控制器只输出候选标识和停止点,再由大模型重新 prefill 过滤后的 prompt。后者多一次小模型成本,却可大幅减少昂贵大模型 token。跨模型有效的前提是小模型判断与大模型收益相关,论文实验提供经验支持,没有理论保证。
端到端手算一个 polarity 标签
假设正确补全包含四个 token,只有文件内上下文时逐 token 对数概率相加为某个基线值。候选甲给出同一 API 的正确异常处理,加入后四个正确 token 概率整体上升,相对变化越过正阈值,标 positive。候选乙来自旧版本,第二个参数顺序相反,模型在关键 token 上把概率分给旧参数,使总似然下降超过负阈值,标 negative。候选丙只是相同 import,概率几乎不变,标 neutral。
线上没有这四个正确 token,因此不能重算 S。模型先判断文件内上下文不足,依次看甲乙丙的正文。甲被接受,乙丢弃;接受甲后若输出 EC,丙甚至无需判断。最终大模型只见甲。若过滤器把乙错标 positive,负影响仍存在,所以 polarity 分类准确率与最终 EM 都要测;若把甲错删,系统退化为文件内补全,但通常比保留强误导片段安全。
实验主表的多维读法
RepoEval 分 line、API、function,CrossCodeLongEval 分 chunk、function;每格同时有精确匹配和编辑相似度,function 另可跑单测。三十亿 StarCoder 在填空 line 中 Full Retrieve 精确匹配五十六点二五,CodeFilter 六十点五;API 从四十七点二七到五十点五九。十三亿 CodeLlama 的 API 从四十八点六六到五十一点八四,说明收益跨架构。
平均提高约三个百分点看似不大,negative subset 更能隔离机制。七十亿 StarCoder 左到右 line 中 Full Retrieve 七点二三,过滤后二十八点九二;填空 API 从十点六三到二十二点八三。这里样本专门包含负 chunk,巨大差距证明过滤不只是节省 prompt。总体数据中许多请求无负片段,提升被中性/易样本稀释。
跨文件 token 从普遍一千五百以上降到约三百多,减少超过八成,但过滤阶段仍会查看候选正文。论文报告的是最终 generator context,不应直接称总读取量下降八成。生产延迟需把 retriever、policy prefill、signal decode、最终 generator prefill 和 completion 全部计入。
阈值消融与错误权衡
MC threshold 越高,越少请求检索;到一等价禁用检索,API 精确匹配降到四十一点一五。零到零点三区间保持约五十点一六到五十点五九,说明模型在低阈值内稳。信号 token 开销随阈值上升从约十点八五降到一个,因为更早判断足够。论文推荐零点二到零点三,是质量与控制成本折中。
Polarity threshold 高会删更多候选,context 更短,但 false negative 会丢 API 证据;低会保留 neutral/negative,接近 Full Retrieve。部署应分别画 EC/MC 与 polarity 的校准曲线,不要用同一阈值假定两类概率同样校准。还可按候选名次设成本:越靠后检索价值通常越低,判断开销却持续增加,早停应结合剩余预算。
实现、复现与最终结论
数据泄漏检查要在仓库层执行。相同项目的 fork、复制文件和生成代码可能跨 split,Jaccard 又会轻易找到近重复,导致控制器看似准确。应按仓库来源去重,报告训练与 benchmark 的项目重合;候选检索必须排除 target 所在文件,不能让 ground truth 同窗口进入。构造 function completion 时,右上下文应只包含真实光标后代码,不能额外泄漏函数体。
Likelihood 标注成本约等于每个实例为基线和十个候选多次跑 generator。可以把同一文件内前缀的 KV 或 hidden 复用,但加入候选会改变 prompt 排列,缓存必须保证位置编码一致。批处理应按长度分组,保存每个候选的原始分数、相对分数和标签,之后改变阈值无需重跑模型。标签生成模型要用 eval 模式和固定精度,避免 dropout 或量化差异让阈值附近样本随机翻转。
Polarity 数据的类别极不平衡:正约一成多、负更少、中性占多数。只看总准确率会让全预测中性的模型显得很好。应报告每类 precision/recall,特别是 negative recall 与 positive precision;负漏检会伤质量,正误删会损失跨文件收益。最终 EM 是联合结果,但分类指标能定位是检索充分性还是 polarity 出错。
EC/MC 监督如何产生也应明确。没有正候选时,文件内上下文被视为最终可用输入并监督 EC,教模型避免无意义检索;存在正候选时,初始通常需要更多上下文,逐个加入正证据后在足够位置输出 EC。若数据只在最后监督 EC,模型可能总看完十个才停,无法获得 token 节省。候选顺序打乱可减少死记 top rank,但线上仍按 retriever 顺序,训练应覆盖不同正片段位置。
插件模式还涉及分布差异。三十亿 policy 的 positive 是相对自身 completion likelihood 学得,大模型可能利用 policy 认为 neutral 的细节,或被它认为 negative 的代码纠正。论文跨七十亿到更大模型实验说明平均可迁移,部署仍应在目标 generator 上抽样做四种对照:无检索、全检索、policy 过滤、用目标自身离线 oracle 过滤。Policy 与 oracle 差距才是跨模型代价。
Retriever 变化会改变候选难度。Jaccard 候选常词面相近,UniXcoder 等语义检索可能带来词面不同但逻辑相关片段,旧过滤器未见过这种分布。不能只替换检索器后沿用阈值;应重新统计 positive/negative/neutral 比例与控制概率校准。更强 retriever 也不会消除过滤需要,因为高相关旧版本或测试 mock 仍可能有害。
对于 function-level 单测,执行环境必须隔离依赖、超时和副作用。Exact Match 偏严:两个语义等价实现文本不同算错;Edit Similarity 连错误代码也可能很高;unit test 更接近功能,却只覆盖有限路径。三者联合说明过滤是否改善语法、文本和行为,不能挑一个最有利指标。
延迟实验可把控制器部署成独立 worker pool。多个 completion 的候选判断可批处理,但每个请求在接受 positive 后需要重新 EC 决策,形成状态依赖。可一次为所有候选预测 polarity,再按顺序模拟停止以提高吞吐,但这与论文逐步条件不同,后面候选没有看到已接受上下文。若做这种近似,必须重新测质量,不应仍称相同算法。
隐私和安全方面,跨文件检索可能把仓库敏感片段送入外部大模型。过滤器减少最终 prompt,但它自己仍读取候选;若 policy 本地部署而 generator 远程,只把 positive 发送可降低暴露。Negative 片段不一定恶意,也可能含旧密钥、测试数据或许可证受限代码,检索层还需独立访问控制,不能把模型 polarity 当安全分类。
上线监控应保存匿名化的检索率、停止 rank、保留 token 数和生成接受反馈。若模型版本更新后 MC 比例突然升高,可能是控制 token embedding 或模板不兼容;若 positive 比例下降,可能索引过期;若 prompt 变短但 EM/测试失败上升,可能阈值过严。按仓库和语言分桶比全局平均更容易发现漂移。
一个容易忽略的复现变量是候选在 prompt 中的格式。文件路径、起止行、代码围栏和分隔 token 会影响模型判断,也会占用跨文件预算。路径本身可能提供模块语义;完全删除路径会让两个同名实现难以区分。应沿用论文 verbalization,并把格式 token 计入长度,不能只统计源码 token。
右上下文在填空任务中尤其重要。候选可能与左侧调用相似,却与右侧变量使用冲突;影响分数由完整文件内前后文计算,能够捕捉这种不一致。迁移到只支持左到右的模型时,过滤器少了右侧证据,polarity 会改变,所以论文分别训练/评测模式,不能直接把 FIM checkpoint 当 LTR policy。
控制信号权重二是经验设置。权重太低,长代码 loss 淹没几个 signal token,模型会补代码但不会可靠路由;太高,模型可能学会分类却损伤生成能力。消融可分别报告 signal 准确率与 completion EM,寻找二者折中。若采用独立 policy 而不让它生成代码,可重新设计纯分类目标,但那已不是论文的统一模型。
当文件内上下文已经包含完整 API 定义时,MC false positive 会造成额外检索和延迟,即使之后所有 chunk 都丢弃。EC/MC 的价值因此不只是 prompt 缩短,还减少 retriever 与十次 polarity 判断。统计应把“初始 EC 直接生成”“检索后无正片段”“检索后早停”分开,分别定位充分性模型与过滤模型。
Oracle 实验中删除所有 negative 后三十亿模型 API 精确匹配从四十七点二七到四十九点九六,只保留 positive 为四十九点四七。只留 positive 略低于删除 negative,说明部分 neutral 可能有微弱组合价值,或阈值把有用片段划为 neutral。CodeFilter 达五十点五九,可能还受联合训练改善生成能力影响,不能把全部差值简单归因于完美 polarity。
最终部署应保留可关闭的开关。仓库索引缺失、控制 token 概率异常或过滤器超时时,可回退文件内生成,而不是默认 Full Retrieve;论文负样本分析说明后者可能更危险。对于需要最高召回的低风险离线补全,也可保留更多 neutral,策略应随错误代价调整。
检索只负责扩大候选,生成前仍要按任务影响做准入。相似度高表示片段可能相关,likelihood 标签检验它对指定模型与正确补全是否有帮助,EC/MC 再判断当前证据是否已经足够。三层判断回答的是不同问题;少掉任何一层,系统都会退回总是检索、全量拼接或过早停止的旧行为。完整复现应保留这三个边界,不能把方法简化成普通的二分类 reranker。
复现固定四张 A100 八十吉字节、两轮训练、学习率二乘十的负五次方、预热百分之五、线性衰减、有效 batch 五百一十二;推理用 vLLM、greedy、文件内预算一千零二十四、跨文件三千零七十二。记录 label 分布、控制 token accuracy、检索率、平均查看候选数、保留正负中性数、最终 prompt token、TTFT、EM、编辑相似度与单测。
正确性测试应验证输入正文 loss 被 mask、特殊 token 单 token 化、EC 真正停止、negative 不进入最终 prompt、插件模式不把 signal token 传给大模型。更换 retriever 或语言后重新生成 likelihood 标签;更换 generator 先测 polarity agreement。代码库更新时索引和候选版本要与 completion 样本一致。
CodeFilter 的核心贡献是把“相似”换成“对正确补全概率的影响”,显式识别有害上下文,再让同一个代码模型学会是否检索、逐块极性和何时停止。它在主表提高准确率并显著缩短最终 prompt,在负上下文子集收益最大。边界是离线标签依赖 generator、一阶 chunk 影响忽略组合、主数据以 Python 为主,以及小 policy 本身有延迟。把这些条件纳入端到端核算后,它才是一套可复现的跨文件上下文控制方法。
最终判断应以功能测试和真实延迟为准:过滤器既要减少误导,也要保留完成当前仓库接口所需的最小证据;任何只追求最短上下文的实现都偏离了论文目标。
方法的成功标准始终是更可靠的补全,而不是过滤比例本身。上线验收也应围绕补全正确性、仓库测试和真实响应时间展开,不能把过滤掉多少 token 当成独立的成功指标。