35 KiB
35 KiB
Konwinski Prize 2025 前排方案对比学习
竞赛: Konwinski Prize 2025 - AI GitHub Issue Resolver
研究重点: 1st Place vs 5th Place 技术方案对比
更新日期: 2026-01-25
目录
竞赛概览
竞赛基本信息
| 项目 | 内容 |
|---|---|
| 竞赛名称 | Konwinski Prize 2025 |
| 主办方 | Andy Konwinski (Databricks 联合创始人) |
| 总奖金 | $1,225,000+ |
| 最高奖金 | $1,000,000 (90% 成功率,尚未触发) |
| Round 1 首奖 | $50,000 |
| 参与团队 | 616 个团队 |
| 竞赛时间 | 2024年12月 - 2025年7月 |
任务定义
目标: 构建 AI Agent,自动修复 GitHub 真实项目中的 bug
挑战:
- 测试集完全隐藏(提交后收集)
- 无数据泄露(contamination-free)
- 严格评分机制
- 仅允许使用开源模型
评分机制
# 评分公式(简化版)
score = num_correct - C * num_wrong
# 其中 C 是错误修复的惩罚系数(通常较大)
# skip 仅有轻微惩罚
关键洞察:
- 错误修复 → 重罚
- 跳过 → 轻罚
- 策略: 宁可跳过,不要出错
前排方案对比表
排名和成绩
| 排名 | 参与者 | 成功率 | 核心策略 | 关键技术 |
|---|---|---|---|---|
| 1st | Eduardo Rocha de Andrade | 7.5% | Prompt Engineering + F2P Testing | • Fail-to-Pass 测试 • 保守提交策略 • 精心设计的 prompt |
| 5th | Anonymous (Ambrosm?) | ~5% | Regex Traceback Analysis | • 正则提取 traceback • 精确定位错误 • 上下文优化 |
| 6th | quan16369 | 0.8% | Select-Patch-Verify-Choose | • 多次验证 • 指数大小惩罚 • 严格过滤 |
核心差异概览
| 维度 | 1st Place | 5th Place | 6th Place |
|---|---|---|---|
| 测试验证 | ✅ F2P 测试(关键) | ✅ F2P 测试 | ❌ 仅 LLM 验证 |
| 错误定位 | Prompt Engineering | Regex Traceback | LLM Select |
| 补丁选择 | 保守策略 | 保守策略 | 规则评分 |
| 提交策略 | 仅高置信度 | 仅高置信度 | 相对宽松 |
| 上下文使用 | 全面的 issue 分析 | 精准的 traceback | 全代码树 |
1st Place 方案深度解析
核心理念
"质量 > 数量,客观测试 > 主观判断"
架构设计
┌─────────────────────────────────────────────────────────┐
│ 1st Place 完整流程 │
└─────────────────────────────────────────────────────────┘
输入: GitHub Issue + 代码库
│
▼
┌──────────────────┐
│ 1. Issue 分析 │ • 提取关键信息
│ │ • 理解问题本质
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 2. F2P 测试生成 │ ⭐ 核心创新
│ │ • 测试必须在原代码失败
└────────┬─────────┘ • 测试必须在补丁后通过
│
▼
┌──────────────────┐
│ 3. 补丁生成 │ • 基于测试指导
│ │ • 多个候选方案
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 4. F2P 测试验证 │ • 客观验证
│ │ • 确保修复有效
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 5. 保守决策 │ • 仅高置信度提交
│ │ • 宁可跳过
└──────────────────┘
关键技术 1: F2P (Fail-to-Pass) 测试
定义: 生成在原始代码上失败、在修复后通过的测试用例
实现流程:
def generate_f2p_test(issue: str, code_context: str, model) -> str:
"""
生成 Fail-to-Pass 测试
Args:
issue: GitHub issue 描述
code_context: 相关代码上下文
model: LLM 模型
Returns:
test_code: F2P 测试代码
"""
prompt = f"""
你是一个测试工程师。根据以下 GitHub Issue,生成一个单元测试:
GitHub Issue:
{issue}
相关代码:
{code_context}
要求:
1. 测试必须在当前(有 bug 的)代码上 FAIL
2. 测试必须在修复 bug 后 PASS
3. 测试应该最小化,专注于特定 bug
4. 使用 pytest 框架
返回完整的测试代码。
"""
test_code = model.generate(prompt)
return test_code
def validate_f2p_test(
test_code: str,
original_code: str,
patched_code: str
) -> bool:
"""
验证 F2P 测试的有效性
Returns:
True 如果测试是有效的 F2P 测试
"""
# 1. 在原始代码上运行测试(应该 FAIL)
original_result = run_test(test_code, original_code)
if original_result.status != "FAIL":
return False # 测试在原代码上没有失败!
# 2. 在补丁后代码上运行测试(应该 PASS)
patched_result = run_test(test_code, patched_code)
if patched_result.status != "PASS":
return False # 测试在补丁后没有通过!
return True
F2P 测试的优势:
- 客观验证: 不依赖 LLM 主观判断
- Bug 复现: 确保 bug 真实存在
- 修复确认: 确保补丁真正修复了问题
- 回归预防: 防止补丁引入新问题
关键技术 2: 保守提交策略
def should_submit_patch(
patch: str,
f2p_test_result: dict,
confidence_metrics: dict
) -> bool:
"""
保守的提交决策
只有在所有条件都满足时才提交
"""
# 条件 1: F2P 测试必须通过
if not f2p_test_result['valid_f2p']:
return False
# 条件 2: 补丁必须成功应用
if not f2p_test_result['applied_successfully']:
return False
# 条件 3: 补丁大小必须合理
if len(patch) > 500: # 字符数限制
return False
# 条件 4: 修改的文件数量有限
if f2p_test_result['files_modified'] > 2:
return False
# 条件 5: 高置信度
if confidence_metrics['score'] < 0.9:
return False
# 所有条件满足 → 提交
return True
关键技术 3: Prompt Engineering
Issue 分析 Prompt:
ISSUE_ANALYSIS_PROMPT = """
你是一个资深的软件工程师和调试专家。
任务:分析以下 GitHub Issue,提取关键信息
GitHub Issue:
{issue}
请提供:
1. 问题类型(bug/feature/性能/安全等)
2. 错误消息(如果有)
3. Traceback 信息(如果有)
4. 复现步骤
5. 期望行为
6. 相关文件或模块
7. 可能的根本原因
以结构化的 JSON 格式返回。
"""
补丁生成 Prompt:
PATCH_GENERATION_PROMPT = """
你是一个代码修复专家。
任务:根据以下信息生成修复补丁
GitHub Issue:
{issue}
F2P 测试:
{f2p_test}
相关代码:
{code}
要求:
1. 生成最小化的补丁
2. 只修改必要的代码
3. 确保补丁能让 F2P 测试通过
4. 不要添加不必要的功能
5. 使用 git diff 格式
返回补丁代码。
"""
5th Place 方案深度解析
核心理念
"精确的错误定位 + 有效的上下文"
架构设计
┌─────────────────────────────────────────────────────────┐
│ 5th Place 完整流程 │
└─────────────────────────────────────────────────────────┘
输入: GitHub Issue + 代码库
│
▼
┌──────────────────┐
│ 1. Traceback │ ⭐ 核心创新
│ 提取 │ • 正则表达式匹配
└────────┬─────────┘ • 提取错误位置
│
▼
┌──────────────────┐
│ 2. 精确定位 │ • 文件级别
│ │ • 行级别
└────────┬─────────┘ • 函数级别
│
▼
┌──────────────────┐
│ 3. 上下文收集 │ • 仅相关代码
│ │ • 减少噪音
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 4. F2P 测试生成 │ • 基于定位结果
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 5. 目标化补丁 │ • 精准修复
│ │ • 最小化修改
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 6. 测试验证 │ • F2P 验证
└──────────────────┘
关键技术: Regex Traceback 分析
完整的 Traceback 提取器:
import re
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass
@dataclass
class TracebackInfo:
"""Traceback 信息结构"""
files: List[str]
lines: List[int]
functions: List[str]
error_types: List[str]
error_messages: List[str]
raw_traceback: str
class TracebackExtractor:
"""使用正则表达式提取 Traceback 信息"""
# Python Traceback 模式
PATTERNS = {
'traceback_header': r'Traceback \(most recent call last\):',
'frame': r' File "([^"]+)", line (\d+), in (\w+)',
'error': r'(\w*Error):\s*(.+)',
'assertion': r'AssertionError:\s*(.+)',
'exception_in': r'Exception in (\w+) (.+)',
}
def __init__(self):
# 编译正则表达式
self.compiled_patterns = {
name: re.compile(pattern)
for name, pattern in self.PATTERNS.items()
}
def extract(self, issue_text: str) -> Optional[TracebackInfo]:
"""
从 issue 文本中提取 traceback 信息
Args:
issue_text: GitHub issue 的完整文本
Returns:
TracebackInfo 对象,如果没有找到 traceback 则返回 None
"""
# 1. 检查是否有 traceback
if not self.compiled_patterns['traceback_header'].search(issue_text):
return None
# 2. 提取帧信息
frames = self.compiled_patterns['frame'].findall(issue_text)
files = [frame[0] for frame in frames]
lines = [int(frame[1]) for frame in frames]
functions = [frame[2] for frame in frames]
# 3. 提取错误信息
error_match = self.compiled_patterns['error'].search(issue_text)
if error_match:
error_types = [error_match.group(1)]
error_messages = [error_match.group(2)]
else:
# 尝试匹配 AssertionError
assertion_match = self.compiled_patterns['assertion'].search(issue_text)
if assertion_match:
error_types = ['AssertionError']
error_messages = [assertion_match.group(1)]
else:
error_types = []
error_messages = []
# 4. 提取原始 traceback 文本
traceback_match = re.search(
r'(Traceback \(most recent call last\):.*?)(?=\n\n|\Z)',
issue_text,
flags=re.DOTALL
)
raw_traceback = traceback_match.group(1) if traceback_match else ""
return TracebackInfo(
files=files,
lines=lines,
functions=functions,
error_types=error_types,
error_messages=error_messages,
raw_traceback=raw_traceback
)
def prioritize_files(
self,
traceback: TracebackInfo,
all_files: List[str]
) -> List[str]:
"""
根据 traceback 优先排序文件
Args:
traceback: 提取的 traceback 信息
all_files: 代码库中所有文件的列表
Returns:
优先排序后的文件列表
"""
prioritized = []
# 优先级 1: traceback 中直接提到的文件
for tb_file in traceback.files:
# 标准化路径
normalized = tb_file.replace('/', '.')
if normalized in all_files:
prioritized.append((normalized, 1.0))
# 尝试部分匹配
elif any(tb_file in f or f in tb_file for f in all_files):
match = next(f for f in all_files if tb_file in f or f in tb_file)
prioritized.append((match, 0.9))
# 优先级 2: 同目录下的文件
if traceback.files:
tb_dir = '/'.join(traceback.files[0].split('/')[:-1])
for f in all_files:
if f.startswith(tb_dir) and f not in [p[0] for p in prioritized]:
prioritized.append((f, 0.7))
# 优先级 3: 相关测试文件
for f in all_files:
if 'test' in f.lower() and f not in [p[0] for p in prioritized]:
prioritized.append((f, 0.5))
# 按优先级排序
prioritized.sort(key=lambda x: x[1], reverse=True)
return [p[0] for p in prioritized]
def get_context_lines(
self,
traceback: TracebackInfo,
file_content: str,
context_window: int = 10
) -> str:
"""
获取错误行周围的上下文
Args:
traceback: Traceback 信息
file_content: 文件内容
context_window: 上下文行数
Returns:
上下文代码字符串
"""
if not traceback.lines:
return file_content[:500] # 默认返回前 500 字符
lines = file_content.split('\n')
error_line = traceback.lines[0]
# 提取上下文
start = max(0, error_line - context_window)
end = min(len(lines), error_line + context_window + 1)
context_lines = lines[start:end]
# 添加行号
context_with_line_numbers = [
f"{i+1:4d}: {line}"
for i, line in enumerate(context_lines, start=start)
]
# 标记错误行
if error_line - start < len(context_with_line_numbers):
idx = error_line - start
context_with_line_numbers[idx] = f">>> {context_with_line_numbers[idx]}"
return '\n'.join(context_with_line_numbers)
使用示例:
# 初始化
extractor = TracebackExtractor()
# 从 issue 中提取 traceback
issue_text = """
When I run the model, I get this error:
Traceback (most recent call last):
File "train.py", line 42, in train_loop
loss = model(batch)
File "model.py", line 156, in __call__
outputs = self.layer(inputs)
TypeError: Layer.__call__() got an unexpected keyword argument 'training'
This happens when I use the new layer type.
"""
traceback = extractor.extract(issue_text)
if traceback:
print(f"Error Type: {traceback.error_types}")
print(f"Error Message: {traceback.error_messages}")
print(f"Files: {traceback.files}")
print(f"Lines: {traceback.lines}")
print(f"Functions: {traceback.functions}")
# 优先排序文件
all_files = ['model.py', 'train.py', 'utils.py', 'test_model.py']
prioritized = extractor.prioritize_files(traceback, all_files)
print(f"Prioritized files: {prioritized}")
# 获取上下文
model_code = read_file('model.py')
context = extractor.get_context_lines(traceback, model_code)
print(f"Context:\n{context}")
基于 Traceback 的补丁生成
def generate_traceback_aware_patch(
issue: str,
traceback: TracebackInfo,
code_context: str,
model
) -> str:
"""
基于 traceback 信息生成精准的补丁
Args:
issue: GitHub issue
traceback: 提取的 traceback 信息
code_context: 错误行周围的代码上下文
model: LLM 模型
Returns:
patch: 生成的补丁
"""
prompt = f"""
你是一个代码修复专家。
Bug 报告:
{issue}
错误位置信息:
- 文件: {traceback.files[0] if traceback.files else 'Unknown'}
- 行号: {traceback.lines[0] if traceback.lines else 'Unknown'}
- 函数: {traceback.functions[0] if traceback.functions else 'Unknown'}
- 错误类型: {traceback.error_types[0] if traceback.error_types else 'Unknown'}
- 错误消息: {traceback.error_messages[0] if traceback.error_messages else 'Unknown'}
错误行周围的代码:
{code_context}
任务:
1. 分析错误的根本原因
2. 生成最小的修复补丁
3. 只修改必要的代码
4. 使用 git diff 格式
返回补丁代码。
"""
patch = model.generate(prompt)
return patch
核心技术对比
对比维度分析
| 技术维度 | 1st Place | 5th Place | 优势分析 |
|---|---|---|---|
| 错误定位 | Prompt Engineering + 全面分析 | Regex Traceback 提取 | 5th 更精确,1st 更全面 |
| 测试验证 | F2P 测试 | F2P 测试 | 两者都使用(关键) |
| 上下文管理 | 全面 issue 分析 | 精准 traceback 定位 | 5th 更高效 |
| 补丁生成 | 多候选 + 精心 prompt | 目标化 + 精准定位 | 5th 更聚焦 |
| 提交策略 | 极度保守 | 保守 | 1st 更保守 |
| 适用场景 | 复杂、多文件问题 | 明确 traceback 错误 | 各有优势 |
F2P 测试 vs Traceback 分析
F2P 测试(1st Place 核心优势)
优势:
- ✅ 客观验证: 不依赖 LLM 主观判断
- ✅ Bug 复现: 确保问题真实存在
- ✅ 修复确认: 确保补丁有效
- ✅ 通用性强: 适用于所有类型的 bug
劣势:
- ❌ 生成困难: 需要高质量的 prompt
- ❌ 计算成本: 需要运行测试
- ❌ 测试质量: 可能生成不完整或错误的测试
最佳适用场景:
- 需要高置信度的场景
- 没有 traceback 的 bug 报告
- 功能性 bug(非错误消息)
Traceback 分析(5th Place 核心优势)
优势:
- ✅ 精确定位: 直接指向错误位置
- ✅ 高效: 减少不必要的上下文
- ✅ 明确信息: 错误类型和消息清晰
- ✅ 上下文优化: 只关注相关代码
劣势:
- ❌ 依赖 traceback: 不是所有 bug 都有
- ❌ 正则脆弱: 可能漏掉非标准格式
- ❌ 表面症状: 可能不是根本原因
最佳适用场景:
- 有明确 traceback 的错误
- 单文件或局部问题
- 需要快速定位的场景
组合策略(最优方案)
def combined_strategy(issue: str, codebase: dict) -> Optional[str]:
"""
组合 F2P 测试和 Traceback 分析
结合两者的优势
"""
# 1. 尝试提取 traceback
traceback = extract_traceback(issue)
# 2. 根据是否有 traceback 选择策略
if traceback:
# 使用 traceback 精确定位
relevant_files = traceback.prioritize_files(codebase.keys())
context = get_traceback_context(traceback, codebase)
else:
# 使用全面的 issue 分析
relevant_files = analyze_issue(issue, codebase)
context = get_full_context(issue, codebase)
# 3. 生成 F2P 测试(两种情况都需要)
f2p_test = generate_f2p_test(issue, context)
# 4. 生成补丁
patch = generate_patch(issue, f2p_test, context)
# 5. 验证
if validate_f2p_test(f2p_test, patch):
return patch
else:
return None
可复用代码模板
Template 1: 完整的 F2P 测试流程(1st Place 风格)
from typing import Optional, Dict, Any
import subprocess
import tempfile
import os
class F2PTestGenerator:
"""Fail-to-Pass 测试生成器"""
def __init__(self, model):
self.model = model
def generate(self, issue: str, code_context: str) -> str:
"""生成 F2P 测试"""
prompt = f"""
根据以下 GitHub Issue 生成一个单元测试:
Issue:
{issue}
相关代码:
{code_context}
要求:
1. 测试必须在当前(有 bug 的)代码上 FAIL
2. 测试必须在修复 bug 后 PASS
3. 使用 pytest 框架
4. 测试应该最小化且专注于特定 bug
返回完整的测试代码。
"""
return self.model.generate(prompt)
def validate(
self,
test_code: str,
original_code: str,
patched_code: str
) -> Dict[str, Any]:
"""验证 F2P 测试的有效性"""
results = {
'valid_f2p': False,
'original_result': None,
'patched_result': None,
'error': None
}
try:
# 1. 在原始代码上运行(应该 FAIL)
results['original_result'] = self._run_test(
test_code, original_code
)
if results['original_result']['status'] != 'FAIL':
results['error'] = "Test did not fail on original code"
return results
# 2. 在补丁后代码上运行(应该 PASS)
results['patched_result'] = self._run_test(
test_code, patched_code
)
if results['patched_result']['status'] != 'PASS':
results['error'] = "Test did not pass on patched code"
return results
# 3. 测试有效
results['valid_f2p'] = True
return results
except Exception as e:
results['error'] = str(e)
return results
def _run_test(self, test_code: str, code: str) -> Dict[str, Any]:
"""运行测试并返回结果"""
with tempfile.TemporaryDirectory() as tmpdir:
# 写入测试文件
test_file = os.path.join(tmpdir, 'test_fix.py')
with open(test_file, 'w') as f:
f.write(test_code)
f.write('\n\n')
f.write(code)
# 运行测试
result = subprocess.run(
['pytest', test_file, '-v'],
capture_output=True,
text=True,
timeout=10
)
return {
'status': 'PASS' if result.returncode == 0 else 'FAIL',
'stdout': result.stdout,
'stderr': result.stderr
}
# 使用示例
def solve_issue_with_f2p(
issue: str,
codebase: Dict[str, str],
model
) -> Optional[str]:
"""
使用 F2P 测试解决问题
"""
# 1. 生成测试
test_gen = F2PTestGenerator(model)
test_code = test_gen.generate(issue, codebase)
# 2. 生成补丁
patch = generate_patch(issue, test_code, codebase, model)
# 3. 验证
validation = test_gen.validate(
test_code,
codebase,
apply_patch(codebase, patch)
)
# 4. 返回结果
if validation['valid_f2p']:
return patch
else:
return None
Template 2: Traceback 分析器(5th Place 风格)
import re
from typing import Optional, List, Tuple
from dataclasses import dataclass
@dataclass
class TracebackInfo:
"""Traceback 信息"""
files: List[str]
lines: List[int]
functions: List[str]
error_type: Optional[str]
error_message: Optional[str]
full_traceback: str
class TracebackAnalyzer:
"""Traceback 分析器"""
def __init__(self):
self.patterns = {
'header': re.compile(r'Traceback \(most recent call last\):'),
'frame': re.compile(r' File "([^"]+)", line (\d+), in (\w+)'),
'error': re.compile(r'(\w*Error):\s*(.+)'),
}
def extract(self, text: str) -> Optional[TracebackInfo]:
"""从文本中提取 traceback"""
if not self.patterns['header'].search(text):
return None
# 提取帧
frames = self.patterns['frame'].findall(text)
# 提取错误
error_match = self.patterns['error'].search(text)
error_type = error_match.group(1) if error_match else None
error_message = error_match.group(2) if error_match else None
# 提取完整 traceback
tb_match = re.search(
r'(Traceback \(most recent call last\):.*?)(?=\n\n|\Z)',
text,
flags=re.DOTALL
)
full_traceback = tb_match.group(1) if tb_match else ""
return TracebackInfo(
files=[f[0] for f in frames],
lines=[int(f[1]) for f in frames],
functions=[f[2] for f in frames],
error_type=error_type,
error_message=error_message,
full_traceback=full_traceback
)
def get_error_location(self, traceback: TracebackInfo) -> Tuple[str, int]:
"""获取错误位置(文件,行号)"""
if traceback.files and traceback.lines:
return (traceback.files[0], traceback.lines[0])
return (None, None)
def get_context(
self,
traceback: TracebackInfo,
file_content: str,
window: int = 5
) -> str:
"""获取错误行周围的上下文"""
if not traceback.lines:
return file_content[:500]
lines = file_content.split('\n')
error_line = traceback.lines[0]
start = max(0, error_line - window)
end = min(len(lines), error_line + window + 1)
context = lines[start:end]
return '\n'.join(
f"{i+1:4d}: {line}"
for i, line in enumerate(context, start=start)
)
# 使用示例
def solve_issue_with_traceback(
issue: str,
codebase: Dict[str, str],
model
) -> Optional[str]:
"""
使用 Traceback 分析解决问题
"""
# 1. 提取 traceback
analyzer = TracebackAnalyzer()
traceback = analyzer.extract(issue)
if not traceback:
# 回退到其他方法
return solve_issue_without_traceback(issue, codebase, model)
# 2. 获取错误位置
file_path, line_no = analyzer.get_error_location(traceback)
# 3. 获取上下文
if file_path in codebase:
context = analyzer.get_context(
traceback,
codebase[file_path]
)
else:
return None
# 4. 生成补丁
prompt = f"""
修复以下错误:
Issue: {issue}
错误位置: {file_path}:{line_no}
错误类型: {traceback.error_type}
错误消息: {traceback.error_message}
上下文代码:
{context}
生成最小化的修复补丁(git diff 格式)。
"""
patch = model.generate(prompt)
# 5. 验证(仍然需要 F2P 测试)
# ...
return patch
Template 3: 组合策略(最优方案)
class HybridIssueSolver:
"""
组合 F2P 测试和 Traceback 分析的混合策略
结合 1st Place 和 5th Place 的优势
"""
def __init__(self, model):
self.model = model
self.traceback_analyzer = TracebackAnalyzer()
self.f2p_generator = F2PTestGenerator(model)
def solve(
self,
issue: str,
codebase: Dict[str, str]
) -> Optional[str]:
"""
主解决流程
"""
# 1. 尝试提取 traceback
traceback = self.traceback_analyzer.extract(issue)
# 2. 根据情况选择策略
if traceback:
return self._solve_with_traceback(issue, traceback, codebase)
else:
return self._solve_with_f2p(issue, codebase)
def _solve_with_traceback(
self,
issue: str,
traceback: TracebackInfo,
codebase: Dict[str, str]
) -> Optional[str]:
"""
使用 traceback 精准定位
"""
# 1. 获取错误位置
file_path, line_no = self.traceback_analyzer.get_error_location(traceback)
# 2. 获取精准上下文
if file_path and file_path in codebase:
context = self.traceback_analyzer.get_context(
traceback,
codebase[file_path]
)
else:
return None
# 3. 生成 F2P 测试(即使有 traceback 也要测试)
test_code = self.f2p_generator.generate(issue, context)
# 4. 生成补丁
patch = self._generate_traceback_aware_patch(
issue, traceback, context, test_code
)
# 5. 验证
validation = self.f2p_generator.validate(
test_code,
codebase[file_path],
apply_patch(codebase[file_path], patch)
)
return patch if validation['valid_f2p'] else None
def _solve_with_f2p(
self,
issue: str,
codebase: Dict[str, str]
) -> Optional[str]:
"""
使用纯 F2P 测试策略(1st Place 方法)
"""
# 1. 全面分析 issue
context = self._analyze_issue(issue, codebase)
# 2. 生成 F2P 测试
test_code = self.f2p_generator.generate(issue, context)
# 3. 生成补丁
patch = self._generate_patch(issue, test_code, context)
# 4. 验证
# ... (验证逻辑)
return patch
def _generate_traceback_aware_patch(
self,
issue: str,
traceback: TracebackInfo,
context: str,
test_code: str
) -> str:
"""生成基于 traceback 的精准补丁"""
prompt = f"""
修复以下错误:
Issue: {issue}
错误类型: {traceback.error_type}
错误消息: {traceback.error_message}
上下文:
{context}
F2P 测试:
{test_code}
生成最小化修复补丁(git diff 格式)。
"""
return self.model.generate(prompt)
def _generate_patch(
self,
issue: str,
test_code: str,
context: str
) -> str:
"""生成常规补丁"""
prompt = f"""
修复以下 bug:
Issue:
{issue}
测试用例:
{test_code}
代码上下文:
{context}
生成修复补丁(git diff 格式)。
"""
return self.model.generate(prompt)
关键经验教训
从排名差异中学到的
1. F2P 测试是成功的必要条件
证据:
- 1st Place: 使用 F2P → 7.5%
- 5th Place: 使用 F2P → ~5%
- 6th Place: 无 F2P → 0.8%
结论:
没有 F2P 测试,不可能获得好成绩
2. Traceback 分析提供显著优势
分析:
- 5th Place 的 traceback 分析使其在 6th Place 基础上提升了 ~4.2%
- 精准的上下文管理减少了 LLM 幻觉
- 更高效的 token 使用
建议:
有 traceback 一定要用,没有也要尝试提取
3. 保守策略是明智的
证据:
- 所有前排方案都采用保守提交策略
- 错误修复的惩罚远大于跳过
实践:
# 保守的阈值设置
CONFIDENCE_THRESHOLD = 0.9
MAX_PATCH_SIZE = 500
MAX_FILES_MODIFIED = 2
def should_submit(patch, validation_result):
return (
validation_result['valid_f2p'] and
len(patch) < MAX_PATCH_SIZE and
validation_result['confidence'] > CONFIDENCE_THRESHOLD
)
实施建议
优先级 1: 实现 F2P 测试
# 最小化的 F2P 实现
def minimal_f2p(issue, code, model):
# 1. 生成测试
test = generate_test(issue, code, model)
# 2. 验证测试
if not test_fails_on_original(test, code):
return None # 测试无效
# 3. 生成补丁
patch = generate_patch(issue, test, code, model)
# 4. 验证补丁
if not test_passes_on_patched(test, patch, code):
return None # 补丁无效
return patch
优先级 2: 添加 Traceback 分析
# 最小化的 Traceback 实现
def minimal_traceback_analysis(issue):
import re
# 提取文件和行号
pattern = r'File "([^"]+)", line (\d+)'
matches = re.findall(pattern, issue)
if matches:
return {
'file': matches[0][0],
'line': int(matches[0][1]),
'has_traceback': True
}
return {'has_traceback': False}
优先级 3: 采用保守策略
# 保守的提交决策
def conservative_submit(patch, validation):
# 多重检查
checks = [
validation['valid_f2p'],
len(patch) < 500,
validation['confidence'] > 0.9,
validation['files_modified'] <= 2
]
# 所有检查通过才提交
return all(checks)
技术栈建议
模型选择
| 任务 | 推荐模型 | 原因 |
|---|---|---|
| 补丁生成 | Qwen2.5-Coder-32B | 代码生成能力强 |
| 测试生成 | Qwen2.5-Coder-32B | 理解测试逻辑 |
| 验证 | Qwen2.5-Coder-32B | 一致性好 |
| Traceback 分析 | 规则(不需要模型) | 精确且快速 |
性能优化
# 并行处理
from concurrent.futures import ThreadPoolExecutor
def parallel_verify(patches, issue, model, num_workers=4):
"""并行验证多个补丁"""
with ThreadPoolExecutor(max_workers=num_workers) as executor:
futures = [
executor.submit(verify_patch, patch, issue, model)
for patch in patches
]
results = [f.result() for f in futures]
return results
常见陷阱
❌ 陷阱 1: 信任单次验证
# 错误:单次验证
if verify(patch) == "Yes":
submit(patch) # 可能是幻觉
# 正确:多次验证
verifications = [verify(patch) for _ in range(5)]
if sum(v == "Yes" for v in verifications) >= 4:
submit(patch)
❌ 陷阱 2: 忽略补丁大小
# 错误:不考虑大小
if is_valid_patch(patch):
submit(patch) # 可能提交巨大补丁
# 正确:考虑大小
if is_valid_patch(patch) and len(patch) < 500:
submit(patch)
❌ 陷阱 3: 没有测试就提交
# 错误:没有测试
if llm_says_good(patch):
submit(patch)
# 正确:必须有测试
if test_fails_on_original(test, code) and test_passes_on_patched(test, patch, code):
submit(patch)
总结
核心要点
- F2P 测试是关键: 所有前排方案都使用
- Traceback 分析提供优势: 5th Place 的核心创新
- 保守策略获胜: 质量远比数量重要
- 组合策略最优: 结合两种方法的效果最好
实施路线图
阶段 1: 基础
- 实现 F2P 测试生成和验证
- 实现保守提交策略
阶段 2: 优化
- 添加 Traceback 分析
- 实现多次验证
- 添加大小惩罚
阶段 3: 精进
- 优化 prompt
- 并行处理
- 性能优化
最终建议
"从 6th Place 的基础架构开始,添加 5th Place 的 traceback 分析,最终实现 1st Place 的 F2P 测试和保守策略"
文档版本: 1.0 最后更新: 2026-01-25 参考来源:
- Kaggle Konwinski Prize 竞赛页面
- 6th Place 开源代码: https://github.com/quan16369/Kaggle-Konwinski-Prize-6th-Place-Solution-
- 策略指南: https://github.com/raymyers/konwinski-prize-strategy-guide
- SWE-bench: https://www.swebench.com/