660. Konwinski Prize | konwinski-prize
我想向 Kaggle 团队和竞赛组织者表达我诚挚的感谢,他们创造了这样一个高度引人入胜且智力挑战性的赛事。我也非常感谢 @huikang 通过 Starter Notebook - Select-Patch-Verify 和 LB 计算器 做出的宝贵贡献。他们的工作为我的方法提供了坚实的基础,并显著增强了整体竞赛体验。
本次竞赛提出了一个独特而复杂的挑战:平衡模型准确性与生成补丁的有效性,就像在能见度有限的情况下走钢丝。随着模型性能的提高,生成看似正确但根本存在缺陷的补丁的风险也随之增加。
基于 @huikang 的 Starter Notebook - Select-Patch-Verify 的基础工作,我在最终提交中探索了两种不同的策略,每种策略都有其自身的优势和权衡:
| 策略 | 私有排行榜分数 (Private LB) | 公共排行榜分数 (Public LB) |
|---|---|---|
| Select-Patch-Verify-Test (获胜提交) | 0.016571 (4 正确,2 错误,114 跳过) |
-0.000097 (1 正确,1 错误,69 跳过) |
| Select-Patch-Verify-Choose | -0.008429 (2 正确,3 错误,115 跳过) |
-0.000094 (2 正确,2 错误,67 跳过) |
Select-Patch-Verify-Test (获胜提交):
Select-Patch-Verify-Choose:
通过利用 tree-sitter 进行函数和类级别的代码分析,我能够为模型检索更丰富的上下文信息。这提高了模型对特定感兴趣行周围代码的理解。
以下是为第 4778 行检索到的代码上下文示例:
[file name]: astroid/nodes/node_classes.py
[terms searched]:
line(4778)
string_to_search(formatted = format(value.value, format_spec.value))
string_to_search(if value is not None:)
[file relevant content begin]
Match #1, lines 4708 to 4791:
4708|class JoinedStr(NodeNG):
4709| """Represents a list of string expressions to be joined.
4710|
4711| >>> import astroid
4712| >>> node = astroid.extract_node('f"Format {type_}"')
4713| >>> node
4714|
4715| """
...|
4719| def __init__(
4720| self,
4721| lineno: int | None = None,
4722| col_offset: int | None = None,
4723| parent: NodeNG | None = None,
4724| *,
4725| end_lineno: int | None = None,
4726| end_col_offset: int | None = None,
4727| ) -> None:
...|
4773| @classmethod
4774| def _infer_from_values(
4775| cls, nodes: list[NodeNG], context: InferenceContext | None = None, **kwargs: Any
4776| ) -> Generator[InferenceResult, None, InferenceErrorInfo | None]:
4777| if len(nodes) == 1:
4778| yield from nodes[0]._infer(context, **kwargs)
4779| return
4780| uninferable_already_generated = False
4781| for prefix in nodes[0]._infer(context, **kwargs):
4782| for suffix in cls._infer_from_values(nodes[1:], context, **kwargs):
4783| result = ""
4784| for node in (prefix, suffix):
4785| if isinstance(node, Const):
4786| result += str(node.value)
4787| continue
4788| result += MISSING_VALUE
4789| if MISSING_VALUE in result:
4790| if not uninferable_already_generated:
4791| uninferable_already_generated = True
[file relevant content end]
我使模型能够根据问题陈述生成包含两个测试函数的 pytest 脚本:
test_before_patch: 在问题修复前应通过,修复后应失败。test_after_patch: 在修复前应失败,修复后应通过。以下是生成的测试脚本示例:
import pytest
from astroid.nodes.node_classes import FormattedValue, Const
def test_before_patch():
# 测试在没有补丁的情况下,尝试格式化 None 值会引发 TypeError
value_node = Const(None)
format_spec_node = Const('.1f')
formatted_value = FormattedValue(value=value_node, format_spec=format_spec_node)
try:
list(formatted_value.infer())
except TypeError:
# 如果引发 TypeError,测试通过(补丁前)
pass
else:
# 如果未引发 TypeError,测试失败(补丁后)
pytest.fail("Expected TypeError was not raised")
def test_after_patch():
# 测试在有补丁的情况下,格式化 None 值返回 None 且无错误
value_node = Const(None)
format_spec_node = Const('.1f')
formatted_value = FormattedValue(value=value_node, format_spec=format_spec_node)
inferred = list(formatted_value.infer())
# 补丁后,结果应为单个值为 None 的 Const
assert len(inferred) == 1
assert inferred[0].value is None
本次竞赛标志着我获得第一枚 Kaggle 金牌 —— 这是一个激励我巨大的重要里程碑。然而,仍有几个领域需要改进。时间限制限制了对有前景想法的探索,优化期间的重大代码重构导致改进在两种策略中的应用不一致。许多变化缺乏彻底的消融研究,我认识到这是未来工作流程中需要改进的关键领域。
展望未来,我致力于完善这些方法,将获得的见解应用于未来的挑战,并采用更系统、更严格的开发流程,以最大限度地提高性能和创新。