660. Konwinski Prize | konwinski-prize
首先,我要向我的队友(@kazukishida, @nozomiyamamoto)、组织者 Andy、Kaggle 运营团队以及所有参与本次竞赛的朋友表示衷心的感谢。
我们团队三人是多年的老友,未来也将继续参加许多竞赛。
Konwinski 奖赛与原始 SWE-bench 的主要区别
我们最好的 Public LB 得分是 LB = +0.056243(4 个正确,0 个错误),排名第 4!
为了达到这个分数——并最大化我们在 Private LB 上的获胜机会——我们实施了以下策略。
简而言之,数据集构成如下:
训练数据:非常少(仅 6 个实例)
外部数据:约 6,400 个实例,但与 LB 的分布略有不同
Public LB:71 个干净实例
Private LB:更加干净,有 150-200 个实例
所以我们的策略是:忽略 CV,关注 Public LB,相信方法论。
虽然竞赛的指标无疑是不稳定的,但我们希望它不仅仅是运气。
此外,在"LLM Prompt Recovery"竞赛中(该竞赛有 0 训练数据),Public 和 Private LB 之间的分布差异很小。
首先,我们的目标是增加正确答案的数量。我们基于 @huikang 分享的优秀的 Public Notebook Version 94 进行构建,该版本实现了 7 个正确答案。非常感谢你——你无疑是本次竞赛的 MVP!
我们使用了 DeepSeek-R1 · deepseek-r1-distill-qwen-32b-awq。有趣的是,非 AWQ 量化模型表现不佳。我们尝试了各种其他模型,但都不令人满意。我们对最近发布的 QwQ-32B 抱有很高期望,但无论是 AWQ 量化版还是非量化版表现都不好。如果有团队成功使用了这个模型,我们很乐意听取经验。
对于阅读、打补丁和验证步骤,我们将 temperature 参数设置为 0.6/0.6/0.0。对于最后一步,基于我在 LLM 20 Questions 中的经验,我们设置了较低的 temperature。
基于 Public Notebook 中的提示,我们设计了一个改进版本,包含以下增强功能。我们的目标是通过允许模型在缺乏信心时输出"None"(除了"Yes"和"No"之外)来减少错误答案的数量。然而,由于差异不显著,我们决定不在最终提交中包含它。我们在此分享以供参考。
verifying_prompt: str = """
This is the problem statement.
{problem_statement}
These are the files that are thought to be relevant, which may not be complete.
{file_content_string}
This is the proposed patch to fix the problem.
{patch_string}
Evaluate whether the patch works
- The patch fully fixes the problem described in the problem statement.
- The patch does not cause side effects and make any other tests fail.
End your response with exactly one of the following:
- <label>Yes</label>, this fixes the problem.
- <label>No</label>, this does not fix the problem.
- <label>None</label>, I am unsure whether the patch fixes the problem.
Reminder
- Only evaluate, do not provide suggestions on how to fix.
- If you cannot confidently determine whether the patch fully fixes the problem, return exactly `<label>None</label>`.
- When you don't know how to do it, please honestly output `<label>None</label>`, which will be more pleasing than just randomly outputting it.
- Remember to write exactly either of <label>Yes</label> or <label>No</label> or <label>None</label> in the last line
""".strip()
我们在选择最终候选文本时应用了一些改进。
len 超过 1000 的生成补丁。通过选择 总编辑距离最小 的文本,我们确保选择了最具代表性和平均化的文本,有效地过滤掉了异常值。
在竞赛早期,一个最初导致 LB=-1 的提交通过使用编辑距离选择改进为有效的 LB 分数,这表明这种方法可能是有效的。
=== Edit Distance Selection Check ===
Candidate Texts:
1: I like cats.
2: I love cats.
3: I love animals.
4: Animals are great.
5: Dogs are wonderful so much.
Selected (Most Average) Text: I love cats.
作为一个基本前提,获得至少一个正确答案至关重要,其次是 correct - incorrect 的值。在确保正确答案后,积极跳过对于减少错误答案至关重要。因此,我们努力完善跳过机制。
LB=-1 的可能性令人担忧,但由于 Private 数据集的实例数量大约是 Public 数据集的 2.5 倍,我们认为 LB=-1 的可能性很低。
我们的目标是赢得金牌。
在竞赛结束前一个月,我们注意到金牌范围内的许多团队都有 correct=1, incorrect=0。预计这个分数在 Private LB 中也是一个热门的甜蜜点。在竞赛结束前三天,只有 63 个团队实现了 Public LB 分数,其中正确答案超过错误答案(即 correct=1, incorrect=0 或更高)。
因此,为了最大化超过这个分数的概率,我们模拟了获胜概率。
如果确定了正确、错误和提取实例的数量,可以使用超几何分布计算超过 correct=1, incorrect=0 的概率。
例如,让我们模拟当正确和错误答案总数为 10 时,基于不同挑战次数(抽取尝试,非跳过尝试)的获胜概率。
与相邻的偶数抽取相比,奇数往往显示出更好的获胜概率。这是因为偶数抽取包括偶数结果(例如 correct=2, incorrect=2),在这种情况下被视为失败分数。为了解决这个问题,我们实施了一种策略,确保挑战次数更频繁地以奇数结束。详见第 3.5 节。
最初,我们假设 correct < incorrect 的场景,计划设置 challenges=3。这种方法的次要好处是它提供了显著的时间缓冲。
P.S. 如果目标是实现 correct=1, incorrect=0,它可以简化为 "秘书问题"。然而,我们选择克服这个挑战。
然而,3 月 2 日左右发生了一个事件。Public Notebook 的 Version 113 取得了当时相当于第 5 名的分数(correct=3, incorrect=0)。
大多数时候,这个 Notebook 的结果是 LB=-1,但在极少数情况下,它取得了如此高的分数。尽管如此,一些参与者复制并提交了这个高分 Notebook,我们预计其中一些人会实现 correct=3, incorrect=0。
因此,我们将元目标转移到了这个分数。结果,我们将 challenges 改为 5。
实现 correct=5, incorrect=0 或 correct=4, incorrect=1 非常有可能获得金牌,甚至 correct=3, incorrect=2 可能就足够了。
上述假设分数使我们能够与竞赛结束前三天内特别常见分数范围内的团队有利地竞争:
考虑到正确答案少于错误答案的情况,我们决定不使用 challenges ≥ 7。
为了支持这一决定,我们使用了以下模拟,考虑到从 Public LB 到 Private LB 的实例增加,将正确和错误答案的总数设置为 15。
间隔时间限制:LLM 推理特别耗时。我们分别为阅读、打补丁和验证设置了 7 分钟、15 分钟和 19 分钟的间隔限制。如果超过这些限制,跳过该问题是一个强有力的选项。
全局时间限制:我们为 Public LB 设置了 8 小时的全局时间限制,为 Private LB 设置了 23 小时。允许 1 小时余量的原因是本次竞赛中跳过的惩罚很小。
顺便说一下,我可能在 AIMO1 中因为超时失去了一个最终提交😂。
根据 SWE-bench 论文,问题长度与难度相关。此外,本次竞赛中跳过的惩罚极小。
因此,我们最初跳过了长度在 1200-3800 个字符之外的问题。这种方法提供了额外的时间灵活性。
通过仅关注此范围内的长度,我们达到了 (5,8),对应于 LB=-0.042335(当时排名第 18)。
进一步分析显示,超过 3400 个字符的问题从未产生正确答案。
较短的问题(低于 1200 个字符)也只产生了一个正确答案。
我们认为较短的问题表现较差,因为它们缺乏足够的信息或包含嘈杂的问题。
然而,由于 Private LB 应该是经过策划的,我们的判断可能是不正确的。
对于最终提交,进一步的调整(包括参数调整)导致跳过 1802-3400 个字符之外的问题。这实现了 LB=+0.056243(correct=4, incorrect=0),使我们排名第 4。
通过跳过文件内容数量超过 500 的实例,我们的分数从 (5, 8) 变为 (5, 4),改进为 LB=+0.013997(当时排名第 7)。
我们进一步探索了文件内容计数的阈值:
因此,我们将最终提交的文件内容阈值设置为 388。
通过绘制问题陈述长度(x 轴)与文件内容计数(y 轴),我们根据提交结果估计了数据集分布。鉴于只有六个训练实例,在 71 个 Public LB 实例上进行微调似乎是合理的,尽管存在过拟合的风险。
为了更好地说明我们的方法,我们根据多个提交结果模拟了正确、错误和跳过实例的分布。
由于我们只有基于范围的数据,我们从均匀分布中采样。散点图是一个概念可视化,可能包含错误。
下图显示了模拟结果:
如果经过一定数量的回合(limit_turn)仍未达到目标挑战计数,则方法会更新参数。
def update_to_plan_B(self):
if self.challenge_count % 2 == 1:
self.cfg.max_challenge_num = self.challenge_count # End with this challenge count
else:
self.cfg.max_challenge_num = self.challenge_count + 1 # End with the next challenge count
if self.challenge_count == 0:
self.cfg.max_file_contents_num = self.calc_bottom_20(self.file_contents_num_list)
limit_turn=100 允许在需要时额外尝试一个问题。在大多数情况下,5 次挑战在 100 回合内完成,防止了应急计划触发。
正如许多人可能感受到的那样,本次竞赛的实施难度极高。因此,我们仔细设计了我们的开发策略。
得益于以下战略改进,我们只遇到了 一个严重 bug:一个实例中我们超过了每个预测的间隔限制。(即使这也通过实施 第 3.2 节 中描述的时间管理策略迅速解决了。)
我们大致分配了以下角色:
当然,职责有一些重叠,但这种结构使我们能够高效工作。
我们很自豪能够展示出色的团队合作,因为我们是分享了许多经验的老朋友。
我们积极进行 代码审查。@isakatsuyoshi 和 @kazukishida 相互审查彼此的拉取请求以确保代码质量。
本次竞赛的 提交限制 极其严格,使得任何 bug 都可能成为灾难性的。为了减轻这种风险,我们编写了彻底的 测试代码。
总之,我们编写了广泛的测试代码,实施了异常处理和时间管理策略,并深入了解了 LLM 的局限性。我们的最终目标是 最大化赢得金牌的机会。
我们热切期待三个月后的结果。
致敬所有 Kagglers!🚀✨