返回列表

Public 4th Place / Private 15th Place Solution - Konwinski Prize

660. Konwinski Prize | konwinski-prize

开始: 2024-12-12 结束: 2025-07-23 基础软件 AI大模型赛
Konwinski Prize 解决方案

Konwinski 奖赛 Public 第 4 名 / Private 第 15 名 解决方案

作者: ISAKA Tsuyoshi (@isakatsuyoshi)
团队成员: @kazukishida, @nozomiyamamoto
发布日期: 2025-03-18
竞赛: Konwinski Prize

首先,我要向我的队友(@kazukishida, @nozomiyamamoto)、组织者 Andy、Kaggle 运营团队以及所有参与本次竞赛的朋友表示衷心的感谢。
我们团队三人是多年的老友,未来也将继续参加许多竞赛。

Konwinski 奖赛与原始 SWE-bench 的主要区别

  • 完全新的数据,没有任何泄露
  • 错误答案的惩罚很高,需要有效的跳过机制
  • 不能使用 API,需要使用开源 LLM

我们最好的 Public LB 得分是 LB = +0.056243(4 个正确,0 个错误),排名第 4!
为了达到这个分数——并最大化我们在 Private LB 上的获胜机会——我们实施了以下策略。

1. 验证策略 (Validation Strategy)

简而言之,数据集构成如下:
训练数据:非常少(仅 6 个实例)
外部数据:约 6,400 个实例,但与 LB 的分布略有不同
Public LB:71 个干净实例
Private LB更加干净,有 150-200 个实例

所以我们的策略是:忽略 CV,关注 Public LB,相信方法论。

虽然竞赛的指标无疑是不稳定的,但我们希望它不仅仅是运气。
此外,在"LLM Prompt Recovery"竞赛中(该竞赛有 0 训练数据),Public 和 Private LB 之间的分布差异很小

2. 提高准确率 (Improving Accuracy)

首先,我们的目标是增加正确答案的数量。我们基于 @huikang 分享的优秀的 Public Notebook Version 94 进行构建,该版本实现了 7 个正确答案。非常感谢你——你无疑是本次竞赛的 MVP!

2.1. 模型 (Model)

我们使用了 DeepSeek-R1 · deepseek-r1-distill-qwen-32b-awq。有趣的是,非 AWQ 量化模型表现不佳。我们尝试了各种其他模型,但都不令人满意。我们对最近发布的 QwQ-32B 抱有很高期望,但无论是 AWQ 量化版还是非量化版表现都不好。如果有团队成功使用了这个模型,我们很乐意听取经验。

2.2. 模型参数 (Model Parameters)

对于阅读、打补丁和验证步骤,我们将 temperature 参数设置为 0.6/0.6/0.0。对于最后一步,基于我在 LLM 20 Questions 中的经验,我们设置了较低的 temperature。

2.3. 提示工程 (Prompt Engineering)

基于 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()

2.4. 候选文本选择:编辑距离选择 (Candidate Text Selection: Edit Distance Selection)

我们在选择最终候选文本时应用了一些改进。

  1. 首先,我们只选择至少有一个最终候选文本可用的情况。
  2. 接下来,我们过滤掉 len 超过 1000 的生成补丁。
  3. 最后,我们设计了一种称为 编辑距离选择 (Edit Distance Selection) 的算法。具体来说,对于每个候选文本,我们计算它与所有其他候选文本的编辑距离总和。

通过选择 总编辑距离最小 的文本,我们确保选择了最具代表性和平均化的文本,有效地过滤掉了异常值。

在竞赛早期,一个最初导致 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.

3. 跳过机制 (Skip Mechanism)

3.1. 评分函数的考量 (Consideration of the Scoring Function)

作为一个基本前提,获得至少一个正确答案至关重要,其次是 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 时,基于不同挑战次数(抽取尝试,非跳过尝试)的获胜概率。

Winning Probability Simulation

与相邻的偶数抽取相比,奇数往往显示出更好的获胜概率。这是因为偶数抽取包括偶数结果(例如 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=0correct=4, incorrect=1 非常有可能获得金牌,甚至 correct=3, incorrect=2 可能就足够了。

上述假设分数使我们能够与竞赛结束前三天内特别常见分数范围内的团队有利地竞争:

  • (5,0) 我们的假设分数
  • (4,1) 我们的假设分数
  • (3,0) 12 个团队排名第 6-15 位
  • (3,2) 我们的假设分数
  • (2,1) 18 个团队排名第 35-52 位
  • (1,0) 11 个团队排名第 53-63 位

考虑到正确答案少于错误答案的情况,我们决定不使用 challenges ≥ 7

为了支持这一决定,我们使用了以下模拟,考虑到从 Public LB 到 Private LB 的实例增加,将正确和错误答案的总数设置为 15。

Simulation Fig 2 Simulation Fig 3 Simulation Fig 4 Simulation Fig 5

3.2. 时间管理 (Time Management)

间隔时间限制:LLM 推理特别耗时。我们分别为阅读、打补丁和验证设置了 7 分钟、15 分钟和 19 分钟的间隔限制。如果超过这些限制,跳过该问题是一个强有力的选项。

全局时间限制:我们为 Public LB 设置了 8 小时的全局时间限制,为 Private LB 设置了 23 小时。允许 1 小时余量的原因是本次竞赛中跳过的惩罚很小。

顺便说一下,我可能在 AIMO1 中因为超时失去了一个最终提交😂。

3.3. 问题长度 (Problem Length)

根据 SWE-bench 论文,问题长度与难度相关。此外,本次竞赛中跳过的惩罚极小。

因此,我们最初跳过了长度在 1200-3800 个字符之外的问题。这种方法提供了额外的时间灵活性。

通过仅关注此范围内的长度,我们达到了 (5,8),对应于 LB=-0.042335(当时排名第 18)。

进一步分析显示,超过 3400 个字符的问题从未产生正确答案。
较短的问题(低于 1200 个字符)也只产生了一个正确答案。

我们认为较短的问题表现较差,因为它们缺乏足够的信息或包含嘈杂的问题。

然而,由于 Private LB 应该是经过策划的,我们的判断可能是不正确的。

对于最终提交,进一步的调整(包括参数调整)导致跳过 1802-3400 个字符之外的问题。这实现了 LB=+0.056243(correct=4, incorrect=0),使我们排名第 4。

3.4. 文件内容数量 (Number of File Contents)

通过跳过文件内容数量超过 500 的实例,我们的分数从 (5, 8) 变为 (5, 4),改进为 LB=+0.013997(当时排名第 7)。

我们进一步探索了文件内容计数的阈值:

  • 通过跳过文件内容超过 388 的实例,我们的分数变为 (4, 2),改进为 LB=+0.028077(当时排名第 6)。
  • 然而,当将限制放宽到 403 时,分数变为 (5, 4),意味着多了一个正确答案,但也多了两个错误答案。

因此,我们将最终提交的文件内容阈值设置为 388

通过绘制问题陈述长度(x 轴)与文件内容计数(y 轴),我们根据提交结果估计了数据集分布。鉴于只有六个训练实例,在 71 个 Public LB 实例上进行微调似乎是合理的,尽管存在过拟合的风险。

为了更好地说明我们的方法,我们根据多个提交结果模拟了正确、错误和跳过实例的分布。
由于我们只有基于范围的数据,我们从均匀分布中采样。散点图是一个概念可视化,可能包含错误。

下图显示了模拟结果:

  • 顶部: 全范围(x 轴 = 问题陈述长度,y 轴 = 文件内容计数)。
  • 底部: 限制 y 轴(文件内容计数 = 1–500)。
Scatter Plot Full Range Scatter Plot Limited Range

3.5. 应急计划 (Contingency Plan)

如果经过一定数量的回合(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 回合内完成,防止了应急计划触发。

4. 开发策略 (Development Strategy)

正如许多人可能感受到的那样,本次竞赛的实施难度极高。因此,我们仔细设计了我们的开发策略。
得益于以下战略改进,我们只遇到了 一个严重 bug:一个实例中我们超过了每个预测的间隔限制。(即使这也通过实施 第 3.2 节 中描述的时间管理策略迅速解决了。)

4.1. 团队角色分配 (Team Role Allocation)

我们大致分配了以下角色:

  • @isakatsuyoshi 专注于 Kaggle
  • @kazukishida 负责 开发
  • @nozomiyamamoto 负责 研究

当然,职责有一些重叠,但这种结构使我们能够高效工作。
我们很自豪能够展示出色的团队合作,因为我们是分享了许多经验的老朋友。

4.2. 使用 GitHub 进行开发 (Development Using GitHub)

我们积极进行 代码审查@isakatsuyoshi@kazukishida 相互审查彼此的拉取请求以确保代码质量。

  • @kazukishida 将一个优秀的公开 Notebook 转换为模块化、松耦合的脚本,使开发更易于管理。
  • @isakatsuyoshi 进行了大量试验实验,为本次竞赛的胜利铺平了道路。
  • @isakatsuyoshi 专注于激进创新时,@kazukishida 确保系统稳定性,使我们能够有效地开发。
  • 此外,@nozomiyamamoto 通过基于研究的构思、提示工程和代码验证提供了全面的支持。

4.3. 测试代码 (Test Code)

本次竞赛的 提交限制 极其严格,使得任何 bug 都可能成为灾难性的。为了减轻这种风险,我们编写了彻底的 测试代码

  • 我们开发了 12 个模块化脚本,包含 98 个测试用例,实现了 80% 的代码覆盖率
  • 我们的测试方法包括 并行测试、fixtures 和参数化 等优化。

总之,我们编写了广泛的测试代码,实施了异常处理和时间管理策略,并深入了解了 LLM 的局限性。我们的最终目标是 最大化赢得金牌的机会

我们热切期待三个月后的结果。
致敬所有 Kagglers!🚀✨

同比赛其他方案