코딩 에이전트 벤치마크를 Kaggle으로 포팅하며 발견한 첫 버그는 내 것이었다
요약
작성자는 코딩 에이전트 오픈 벤치마크인 cli-bench를 Kaggle으로 포팅하는 과정에서, 모델의 실패 원인이 자신(검증기 설계)에게 있음을 발견했습니다. 특히 XSS 패치 작업에서 검증기의 프로브와 테스트가 상충되는 모순을 지적하며, 최신 LLM들이 너무 쉽게 벤치마크를 통과하는 현상을 분석했습니다.
핵심 포인트
- 코딩 에이전트의 오픈 벤치마크(cli-bench)를 Kaggle으로 포팅함.
- XSS 패치 작업에서 검증기 자체의 프로브와 테스트 간 모순을 발견함.
- 최신 LLM들은 단 한 번의 시도로 복잡한 코딩 작업을 너무 쉽게 통과하는 경향이 있음.
- 에이전트 루프 없이 직접 작성된 코드가 에이전트보다 더 높은 성능을 보임.
본 제출물은 Kaggle Benchmarking Challenge에 대한 것입니다.
내가 벤치마크한 것들
저는 터미널에서 작동하는 코딩 에이전트를 위한 오픈 벤치마크인 cli-bench를 유지하고 있습니다. 각 작업은 버그 수정, 기능 추가, 또는 속도 개선을 해야 하는 작은 리포지토리와, 통과 또는 실패를 결정하는 검증기(verifier script)로 구성됩니다. 다른 모델에 의해 점수가 매겨지는 것은 없습니다. 테스트가 통과하거나 추가 확인 사항이 유지되어야만 실행이 성공합니다.
이번 챌린지를 위해 저는 여섯 개의 cli-bench 작업을 Kaggle Benchmarks로 포팅했습니다:
| Kaggle task | 모델이 해야 할 일 | 검증기가 확인하는 것 |
|---|---|---|
cb-debug-wrong-answer | 작은 통계 라이브러리의 버그 찾기 | 제출된 pytest 스위트가 통과함 |
| ... |
sec/patch-xss는 올바른 수정으로 통과할 수 없었다. 두 개의 배포된 테스트(shipped tests)는 렌더링된 페이지에 alert와 onerror라는 단어가 전혀 나타나지 않음을 주장한다. 검증기(verifier) 자체의 프로브(probe)는 alert를 포함한 이스케이프된 페이로드 텍스트가 여전히 페이지에 있어야 한다고 요구한다. 주석을 html.escape로 이스케이프하는 것이 교과서적인 해결책이며, 이는 <script>alert(...)가 여전히 'alert'라는 단어를 포함하고 있기 때문에 테스트를 통과하지 못한다. 텍스트를 삭제하면 테스트는 통과하지만 프로브는 실패한다. Codex 실행에서 세 번의 시도 중 두 번은 html.escape를 사용했고 테스트에 실패했으며, 나머지 한 번은 텍스트를 제거하여 프로브에 실패했다. 나는 이 실패들을 모델의 잘못으로 기록했었다.
data/log-analysis는 하나의 규칙을 설명하고 다른 것을 채점했다. 질문지(question sheet)는 error_rate를
| task | Opus 5.5 | Gemini 3.1 Pro | GPT-5.6 Luna | Qwen3 Coder 480B | gpt-oss-120b | Gemini 3.7 Flash |
|---|---|---|---|---|---|---|
| cb-debug-wrong-answer | pass | pass | pass | pass | pass | pass |
| ... | ||||||
| 1. 단 한 번의 시도로 이 여섯 가지 작업에 충분했다. 36개 중 35개의 실행이 통과했다. 파일들이 눈앞에 있고 아무것도 실행할 방법이 없었음에도 불구하고, 모든 모델은 통계 버그를 수정하고, 정확히 세 개의 죽은 함수(dead functions)를 제거했으며, 원자적으로 롤백되고 100개 스레드에서 살아남는 토큰 버킷을 작성했고, 주석 게시판을 올바르게 탈출했다. 이 작업들은 단 한 번의 시도로 최첨단 모델들을 구분하기에는 너무 쉽다. 이것이 결과로 나타났다: cli-bench에서 측정했던 난이도는 이 작업들에서 나온 것이 아니었다. |
2. 동일한 모델은 에이전트 루프(agent loop) 없이 더 잘 작동했다. GPT-5.6 Luna는 단 한 번의 시도로 여섯 가지 모두를 통과했다. Codex 에이전트로서는 hot-loop에서 3번 중 1번만 통과했으며, gridded 데이터셋에서 최악의 경우 속도 향상은 1.2배였다. 단 한 번의 시도로 작성한 공간 그리드(spatial grid)는 동일한 검증기(verifier)를 사용하여 내 기계에서 측정했을 때, 균일점(uniform points)에서는 42.5배, gridded에서는 26.5배, 클러스터링된 점(clustered)에서는 14.6배 더 빠르게 작동했다. 주의할 점은 분명하다: 세 번 중 한 번의 실행, 세 번 중 하나의 데이터셋 시드, 그리고 서로 다른 기계들이다. 하지만 이것은 내가 예상했던 것과는 정반대다. 셸(shell)을 가지고 있는 것이 에이전트가 빠른 솔루션을 찾는 데 도움이 되지 않았고, 오히려 측정하고 느린 것을 패치하는 쪽으로 끌어당겼을 수도 있다.
3. 모든 모델은 hot-loop에서 같은 아이디어를 추구했고, 유닛 테스트(unit tests)로는 보이지 않는 실패만이 존재했다. 여섯 가지 모두 점들을 그리드에 넣었다. 클러스터링된 점들이 passing한 모든 모델에게 최악의 경우였으며 (내 기계에서 14.6배~41배), gridded가 아니었다. Qwen3 Coder의 그리드는 배포된 아홉 개의 유닛 테스트를 모두 통과했지만 여전히 과소 계산했다: 무작위 케이스 하나에서 123쌍이 있어야 할 곳에 84쌍을 발견했다. 오직 naive 버전과의 무작위 비교만이 이를 잡아냈다. 만약 내 검증기가 배포된 테스트에서 멈췄다면, 그 버그는 통과로 점수화되었을 것이다.
4. 제가 겪은 첫 번째 실패 사례 중 대부분은 다시 한번 제 테스트 환경(harness) 때문이었습니다. 최초의 Kaggle 실행 배치에서는 총 9건의 실패가 있었습니다. 그중 7건은 저로 인한 것이었습니다:
- Kaggle의 태스크 런타임에는 pytest가 설치되어 있지 않았습니다. 제가 대체 테스트 러너를 사용했는데, 이 러너는 pytest fixture(
tmp_path,monkeypatch)를 지원하지 않아 여섯 개의 모든 모델이 XSS 태스크에서 "실패"했습니다. 하지만 그들 모두 출력값을 올바르게 탈출(escape) 처리했었습니다. - 제 응답 파서(reply parser)는
FILE: solve.py를 예상했지만, gpt-oss-120b가 제출한**FILE: solve.py**를 거부했습니다. 저는 이 모델의 스크립트를 수동으로 동일 로그에 적용해 보았고 모든 답변이 정확했습니다.
저는 두 가지 문제를 모두 수정하고 해당 태스크들의 새 버전을 푸시했으며, 모든 모델을 다시 실행했습니다. 표에는 재실행 결과가 나와 있습니다. 나머지 두 건의 첫 번째 실패 사례는 실제 문제였습니다. 하나는 위에서 언급한 핫-루프(hot-loop) 버그입니다. 다른 하나에서는 Qwen3 Coder의 로그 스크립트가 존재하지 않는 메서드 이름으로 statistics.quantiles를 호출하여 충돌했습니다. 재실행 시에는 다른 스크립트를 작성했고 통과했습니다. 이는 기본 온도(default temperature)에서의 단일 실행이므로, 어떤 단일 통과 또는 실패도 판결이 아닌 샘플로 간주해야 합니다.
5. 수정된 XSS 태스크는 교과서적인 해결책으로 통과 가능합니다. 여섯 개의 모든 모델이 HTML 이스케이핑을 사용했으며, 모두 수정된 테스트와 프로브를 통과했습니다. cli-bench 0.9.1에서는 동일한 접근 방식이 실패했습니다. 이는 문제가 모델 자체가 아니라 테스트에 있었음을 확인시켜 주었습니다.
저를 놀라게 한 점은 다음과 같습니다: 이 벤치마크의 두 버전 모두에서, 저 쪽의 버그(두 개의 태스크 명세서, 하나의 테스트 러너, 하나의 파서)가 모델들이 일으킨 실패보다 더 많은 실패를 유발했다는 것입니다.
다음으로 측정하고 싶은 것들:
- 더 어려운 cli-bench 태스크: flaky-test와 CI 태스크, 그리고 모델이 검증기(verifier)를 속이는지 확인하는 네 개의 "houdini" 프로브.
- 모델당 세 번 이상의 실행 횟수, 그래야 Qwen의 단일 충돌 같은 현상이 분산(variance)으로 보이게 할 수 있습니다.
- 모델에게 테스트를 실행할 도구를 제공하는 버전, 이를 통해 한 번 재시도하는 것이 도움이 되는지 아니면 (핫-루프처럼) 해로운지를 확인할 수 있을 것입니다.
제가 얻은 교훈은 이렇습니다. 알려진 정답과 비교하여 한 번도 실행된 적 없는 벤치마크는 아직 진정한 벤치마크가 아니라는 것입니다. 현재 포팅된 모든 작업에는 참조 솔루션(reference solution), 빈 응답(empty reply), 그리고 테스트 재작성 응답(test-rewriting reply)이 포함되어 있습니다. 어떤 작업은 첫 번째 항목이 통과하고 나머지 두 항목이 실패할 때만 유효하며, 이는 모델이 실제로 실행되는 환경에서 성립해야 하며 단순히 제 노트북에서만 성립해서는 안 됩니다.
나의 벤치마크
Kaggle 벤치마크: https://www.kaggle.com/benchmarks/aks1321/cli-bench-one-shot
여섯 가지 공개 작업(각 페이지에는 게시된 노트북에 전체 작업 코드가 포함되어 있습니다):
- https://www.kaggle.com/benchmarks/tasks/aks1321/cb-debug-wrong-answer
- https://www.kaggle.com/benchmarks/tasks/aks1321/cb-refactor-deadcode
- https://www.kaggle.com/benchmarks/tasks/aks1321/cb-feature-rate-limiter
- https://www.kaggle.com/benchmarks/tasks/aks1321/cb-perf-hot-loop
- https://www.kaggle.com/benchmarks/tasks/aks1321/cb-data-log-analysis
- https://www.kaggle.com/benchmarks/tasks/aks1321/cb-sec-patch-xss
cli-bench는 Apache-2.0 라이선스입니다: https://github.com/arjunkshah12345-hash/cli-bench
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기