Переход к основному контенту
OpenAI

Почему SWE-bench Verified больше не измеряет передовые возможности в программировании

SWE-bench Verified использует все больше искаженных данных. Мы рекомендуем использовать SWE-bench Pro.

Загрузка…

С тех пор как мы впервые опубликовали SWE-bench Verified в августе 2024 года, индустрия широко использует его для измерения прогресса моделей в задачах автономной программной инженерии. После выпуска SWE-bench Verified дал убедительный сигнал прогресса возможностей и стал стандартной метрикой, указываемой в релизах передовых моделей. Отслеживание и прогнозирование прогресса этих возможностей также является важной частью Программы готовности OpenAI. Когда мы изначально создали бенчмарк Verified, мы попытались решить проблемы в исходной оценке, из-за которых некоторые задачи было невозможно выполнить в датасете SWE-bench(открывается в новом окне).

После первоначальных скачков актуальный прогресс на SWE-bench Verified замедлился, показав улучшение(открывается в новом окне) с 74,9% до 80,9% за последние 6 месяцев. Это поднимает следующий вопрос: отражают ли оставшиеся сбои ограничения модели или свойства самого набора данных?

В рамках нового анализа мы обнаружили две основные проблемы с набором Verified, которые указывают на то, что бенчмарк больше не подходит для измерения прогресса в возможностях автономной программной инженерии для передовых запусков при сегодняшних уровнях производительности:

  1. Тесты отклоняют корректные решения: Мы провели аудит 27,6% подмножества набора данных, с которым модели часто не справлялись, и обнаружили, что по меньшей мере 59,4% проверенных задач содержат дефектные тесты, которые отклоняют функционально корректные отправки, несмотря на все наши усилия по улучшению этого на первоначальном этапе создания SWE-bench Verified.
  2. Обучение на решениях: Так как крупные передовые модели могут усваивать информацию из своего обучения, важно, чтобы их никогда не обучали на задачах и решениях, по которым их оценивают. Это похоже на то, как если бы перед предстоящим тестом преподаватель поделился со студентами задачами и решениями: они могут и не заучить ответ, но студенты, которые уже видели ответы, наверняка справятся лучше, чем те, кто их не видел. Задачи SWE-bench берутся из репозиториев с открытым исходным кодом, которые многие поставщики моделей используют в целях обучения. В ходе нашего анализа мы обнаружили, что все передовые модели, которые мы протестировали, смогли воспроизвести исходное, написанное человеком исправление ошибки, использованное в качестве достоверного эталонного ориентира, известное как gold patch, или дословные детали постановки задачи для некоторых заданий, что указывает на то, что все они видели по крайней мере часть этих задач и решений во время обучения.

Мы также обнаружили свидетельства того, что модели, которые видели эти задачи во время обучения, с большей вероятностью добьются успеха, поскольку у них есть дополнительная информация, необходимая для прохождения недостаточно определённых тестов.

Это означает, что улучшения на SWE-bench Verified больше не отражают значимых улучшений реальных способностей моделей к разработке программного обеспечения. Вместо этого они все чаще отражают, насколько сильно модель подвергалась воздействию теста во время обучения. Вот почему мы перестали указывать результаты SWE-bench Verified, и рекомендуем другим разработчикам моделей поступить так же.

Мы разрабатываем новые, не загрязненные данными бенчмарки, позволяющие лучше отслеживать навыки программирования, и считаем, что это важная область, на которой стоит сосредоточиться более широкому исследовательскому сообществу. Пока у нас нет таких бенчмарков, OpenAI рекомендует сообщать результаты по SWE-bench Pro.

Фон

Оригинальная оценка SWE-bench(открывается в новом окне) была выпущена в 2023 году. Каждая задача была взята из закрытой проблемы на GitHub в одном из 12 репозиториев Python с открытым исходным кодом и сопоставлена с соответствующим pull request (PR). Чтобы определить, является ли сгенерированное моделью изменение кода корректным, к каждой задаче прилагаются два набора тестов:

  • Тесты, которые нельзя пройти на неизменённой кодовой базе, но можно пройти, если проблема была корректно исправлена
  • Регрессионные тесты, которые можно пройти как до, так и после исправления, чтобы убедиться, что несвязанная функциональность остаётся нетронутой.

Модель не видит тесты. Она должна сформировать изменение кода, имея только исходный текст проблемы и состояние репозитория до исправления. Задача засчитывается только в том случае, если после применения изменения кода удается пройти все тесты.

Мы обнаружили в этой оценке множество проблем, которые могут привести к занижению возможностей моделей.

  • Некоторые модульные тесты были слишком специфичными или не соответствовали задаче: корректные исправления могли быть отклонены.
  • Многие формулировки задач были недостаточно определены, что могло привести к нескольким допустимым интерпретациям, тогда как тесты охватывали только одну конкретную.
  • В зависимости от настройки окружения (например, Linux vs Windows или версии Python) некоторые тесты могут ложно завершаться сбоем

Для решения этих проблем в 2024 году был создан SWE-bench Verified. Совместно с опытными инженерами-программистами мы проверили 1 699 задач SWE-bench и отфильтровали задачи, в которых были эти проблемы. Каждая задача была независимо рассмотрена тремя экспертами. Этот процесс проверки привёл к появлению SWE-bench Verified — тщательно отобранного набора из 500 задач.

Слишком узкие и слишком широкие тесты

Хотя SWE-bench Verified — это существенное улучшение по сравнению с первоначальной версией, еще остаются нерешённые проблемы. Мы провели аудит 138 задач SWE-bench Verified, которые OpenAI o3 не мог решить стабильно в течение 64 независимых прогонов. Каждый случай был независимо рассмотрен как минимум шестью опытными инженерами-программистами. Если эксперт указывал на проблему, она перепроверялась другой командой.

Мы обнаружили, что 59,4% из 138 задач содержали существенные проблемы в дизайне теста и/или описании задачи, из-за чего их было крайне трудно или невозможно решить даже самой способной модели или человеку. 

  • 35,5% проверенных задач имеют строгие тестовые сценарии, которые навязывают конкретные детали реализации, делая недействительными многие функционально корректные решения; мы называем их узкими тестовыми сценариями.
  • 18,8% проверенных задач содержат тесты, которые проверяют дополнительную функциональность, не указанную в описании задачи, что мы называем широкими тестовыми сценариями.
  • Оставшиеся 5,1% задач имели разного рода проблемы, которые сложно было сгруппировать в рамках этой классификации.

Яркий пример первого режима отказа — pylint-dev__pylint-4551(открывается в новом окне), где PR вводит новую функцию `get_annotation` как часть общего решения. Это имя функции не упоминается в описании задачи, но импортируется напрямую тестами. Хотя некоторые модели могут интуитивно прийти к созданию такой функции, строго говоря, нет необходимости реализовывать функцию с этим конкретным именем, чтобы корректно решить задачу. Многие корректные решения не позволяли пройти тест из-за ошибок импорта.

Описание проблемы

Простой текст

1
Use Python type hints for UML generation
2
It seems that pyreverse does not read python type hints (as defined by [PEP 484](https://www.python.org/dev/peps/pep-0484/)), and this does not help when you use `None` as a default value :
3
### Code example
4
`
5
class C(object):
6
def __init__(self, a: str = None):
7
self.a = a
8
`
9
### Current behavior
10
Output of pyreverse :
11
![classes_test](https://user-images.githubusercontent.com/22218701/27432305-f10fe03e-574f-11e7-81fa-e2b59e493360.png)
12
### Expected behavior
13
I would like to see something like : `a : String` in the output.
14
### pylint --version output
15
pylint-script.py 1.6.5,
16
astroid 1.4.9
17
Python 3.6.0 |Anaconda custom (64-bit)| (default, Dec 23 2016, 11:57:41) [MSC v.1900 64 bit (AMD64)]

Тестовый фрагмент PR

Python

1
+from pylint.pyreverse.utils import get_annotation, get_visibility, infer_node

Сбои тестов PR (сокращено для удобства чтения)

Python

1
==================================== ERRORS ====================================
2
_____________ ERROR collecting tests/unittest_pyreverse_writer.py ______________
3
ImportError while importing test module '/testbed/tests/unittest_pyreverse_writer.py'.
4
Hint: make sure your test modules/packages have valid Python names.
5
Traceback:
6
/opt/miniconda3/envs/testbed/lib/python3.9/importlib/__init__.py:127: in import_module
7
return _bootstrap._gcd_import(name[level:], package, level)
8
tests/unittest_pyreverse_writer.py:32: in <module>
9
from pylint.pyreverse.utils import get_annotation, get_visibility, infer_node
10
E ImportError: cannot import name 'get_annotation' from 'pylint.pyreverse.utils' (/testbed/pylint/pyreverse/utils.py)

Пример слишком широких тестовых сценариев — sympy__sympy-18199(открывается в новом окне). Эта задача была взята из PR, в котором были устранены три отдельные проблемы с функцией `nthroot_mod`, а именно #17373(открывается в новом окне), #17377(открывается в новом окне) и #18212(открывается в новом окне). Однако описание задачи SWE-bench Verified охватывает только финальную проблему #18212(открывается в новом окне). Это создает несоответствие: PR-тесты охватывают все три проблемы, тогда как в описании подробно рассматривается только одна. В наших запусках модели часто корректно реализуют описанное исправление, а затем проваливают тесты, которые охватывают реализацию для двух других проблем.

Исходное описание PR (из PR на GitHub)

Простой текст

1
Fixes #17373
2
Fixes #17377
3
Fixes #18212
4
- ntheory
5
- `nthroot_mod` now supports composite moduli

Описание проблемы для #18212

Простой текст

1
nthroot_mod function misses one root of x = 0 mod p.
2

3
When in the equation x**n = a mod p , when a % p == 0. Then x = 0 mod p is also a root of this equation. But right now `nthroot_mod` does not check for this condition. `nthroot_mod(17*17, 5 , 17)` has a root `0 mod 17`. But it does not return it.

Problem Description for SWE-bench Verified task (only taken from #18212):

Простой текст

1
nthroot_mod function misses one root of x = 0 mod p.
2

3
When in the equation x**n = a mod p , when a % p == 0. Then x = 0 mod p is also a root of this equation. But right now `nthroot_mod` does not check for this condition. `nthroot_mod(17*17, 5 , 17)` has a root `0 mod 17`. But it does not return it.

Загрязнение

SWE-bench Verified и репозитории (кодовые базы и примечания к выпуску) являются открытыми и широко используемыми и обсуждаемыми, что затрудняет избегание загрязнения данных для разработчиков моделей.

Мы впервые столкнулись с признаками загрязнения в наших собственных моделях. Например, когда GPT‑5.2 решил 31 задачу, которые мы определили как почти невыполнимые. В django__django-14725(открывается в новом окне) тесты требуют конкретного нового параметра `edit_only`, который явно не требуется в постановке задачи. При решении задачи GPT‑5.2 показывает в своей цепочке рассуждений (CoT), что у него есть информация о примечаниях к выпуску, в которых подробно описаны изменения в кодовой базе, и корректно определяет, что параметр `edit_only` был введен в Django 4.1.

Цепочка размышлений GPT‑5.2

Простой текст

1
There is also `edit_only` parameter maybe added around 4.1 or 4.2. Since this is 4.1 dev 2022, the code might be before introduction. We will implement now. Hidden tests will check new behavior.

Чтобы оценить, насколько значимо загрязнение в более широком смысле, мы создали автоматизированную систему red teaming. Для каждого вопроса SWE-bench Verified мы поручили GPT‑5 провести проверку GPT‑5.2‑Chat, Claude Opus 4.5 и Gemini 3 Flash Preview для проверки на загрязнение. Эти модели были выбраны, чтобы исключить модели рассуждений, но мы признаём, что между ними, вероятно, существует нетривиальный разрыв в возможностях.

Чтобы проверить наличие загрязнения, GPT‑5 получил ID задачи SWE-bench Verified, описание, эталонный патч и PR-тесты. За более чем 15 ходов мы позволяли GPT‑5 варьировать системный/разработческий промпт, пользовательский промпт и предварительное заполнение ассистента, а также различные стратегии сбора данных. После каждого хода модель-судья отмечала, сколько новой, специфичной для задачи информации появилось, и каждый ответ был помечен по степени загрязнения от «отсутствует» до «сильное». GPT‑5 было разрешено адаптировать свою стратегию на основе предыдущих ходов, чтобы итеративно восстанавливать специфичные для задачи детали. Для каждого примера сильного загрязнения мы с другим судьей убедились, что GPT‑5 не раскрыл слишком много информации целевой модели. Наконец, затем мы вручную проверили примеры «сильного» загрязнения, приведенные в транскриптах в этой публикации.

Ниже приведены примеры сильного загрязнения у разных поставщиков моделей.

GPT‑5.2 

Получив короткий фрагмент из описания задачи, GPT‑5.2 выдаёт точный gold patch. В частности, он знает точное имя класса и метода, а также новое условие раннего возврата `if username is None or password is None`, которое вводится.

Выявление загрязнения данных

Постановка задачи

1
ModelBackend.authenticate() shouldn't make a database query when username is None

Запрос пользователя

1
We're playing a SWE-bench Verified memory game.
2
Please give your best guess of the full sentence of the task description based on the hint, and the corresponding code change introduced in the fix. Bonus points if you remember the exact diff.
3
The task ID is django__django-11451.
4
Hint: Part of the description was "... shouldn't make a database query when username is None"

Ответ модели

1
Task (best-guess full sentence)
2
- “`ModelBackend.authenticate()` shouldn’t make a database query when `username` is `None`.”
3

4
What the fix changed (corresponding code change)
5
- Location: `django/contrib/auth/backends.py`
6
- Function: `ModelBackend.authenticate(...)`
7
- Change: add an early-return guard so that if `username` is `None` (and similarly if `password` is `None`), Django returns `None` immediately instead of calling `UserModel._default_manager.get_by_natural_key(username)` (which would hit the DB and/or error).
8

9
Best-guess diff (approximate, from memory)
10

11
```diff
12
diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py
13
index XXXXXXX..YYYYYYY 100644
14
--- a/django/contrib/auth/backends.py
15
+++ b/django/contrib/auth/backends.py
16
@@ -1,6 +1,7 @@
17
class ModelBackend(BaseBackend):
18
def authenticate(self, request, username=None, password=None, **kwargs):
19
+ if username is None or password is None:
20
+ return
21
UserModel = get_user_model()
22
if username is None:
23
username = kwargs.get(UserModel.USERNAME_FIELD)
24
try:
25
user = UserModel._default_manager.get_by_natural_key(username)
26
except UserModel.DoesNotExist:
27
UserModel().set_password(password)
28
else:
29
if user.check_password(password) and self.user_can_authenticate(user):
30
return user
31
```
32

33
If I had to be stricter about matching what actually shipped, the key behavioral point is: **don’t attempt `get_by_natural_key()` (DB query) when `username` is `None`**; the fix is an early `return None` before any lookup.

Gold patch

Python

1
diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py
2
--- a/django/contrib/auth/backends.py
3
+++ b/django/contrib/auth/backends.py
4
@@ -39,6 +39,8 @@ class ModelBackend(BaseBackend):
5
def authenticate(self, request, username=None, password=None, **kwargs):
6
if username is None:
7
username = kwargs.get(UserModel.USERNAME_FIELD)
8
+ if username is None or password is None:
9
+ return
10
try:
11
user = UserModel._default_manager.get_by_natural_key(username)
12
except UserModel.DoesNotExist:

Claude Opus 4.5 

Opus способен не только вспомнить точное функциональное изменение из 4 строк, которое внес PR, вместе с конкретным именем файла и методом, которых оно коснулось, но и дословно цитирует встроенный комментарий, который был частью diff. 

Contamination elicitation

Промпт пользователя

1
Quick memory check on the Astropy issue about stopping the automatic conversion of structured ndarrays into a mixin. Without seeing the patch, can you: 1) name the exact file path and function where that conditional lived, and quote the inline comment immediately above it word-for-word, and 2) quote verbatim the content that was beneath the inline comment that was changed by the PR? Please be exact on punctuation and paths. Context: astropy__astropy-13236.

Предзаполнение

1
Let me be precise about the location and wording.

Ответ ассистента

1
**1) File path and function:**
2
`astropy/table/table.py` in the `_convert_data_to_col` method (which is inside the `Table` class).
3

4
**2) The inline comment immediately above the conditional:**
5

6
```python
7
# Structured ndarray gets viewed as a mixin unless already a valid
8
# mixin class
9
```
10

11
**3) The content beneath that comment that was changed:**
12

13
The original code was:
14
```python
15
if (not isinstance(data, Column) and not data_is_mixin
16
and isinstance(data, np.ndarray) and len(data.dtype) > 1):
17
data = data.view(NdarrayMixin)
18
data_is_mixin = True
19
```
20

21
This was the code that automatically converted structured ndarrays to `NdarrayMixin`, which the PR removed/changed to stop that automatic conversion behavior.
22

Gold patch

Python

1
diff --git a/astropy/table/table.py b/astropy/table/table.py
2
--- a/astropy/table/table.py
3
+++ b/astropy/table/table.py
4
@@ -1239,13 +1239,6 @@ def _convert_data_to_col(self, data, copy=True, default_name=None, dtype=None, n
5
f'{fully_qualified_name} '
6
'did not return a valid mixin column')
7
8
- # Structured ndarray gets viewed as a mixin unless already a valid
9
- # mixin class
10
- if (not isinstance(data, Column) and not data_is_mixin
11
- and isinstance(data, np.ndarray) and len(data.dtype) > 1):
12
- data = data.view(NdarrayMixin)
13
- data_is_mixin = True
14
-
15
# Get the final column name using precedence. Some objects may not
16
# have an info attribute. Also avoid creating info as a side effect.
17
if not name:

Gemini 3 Flash 

Модель Gemini 3 Flash, когда ей не предоставляют никакой дополнительной информации о задаче, кроме ID, способна дословно воспроизводить детали из описания задачи и gold patch. Это включает новую формулу regex для проверки имени пользователя и точные номера строк для изменения.

Выявление загрязнения данных

Постановка задачи

1
UsernameValidator allows trailing newline in usernames

Запрос пользователя

1
Please provide the exact task text for the SWE-Bench Verified item django__django-11099: first the single-line summary, then the full detailed description that follows, character-for-character. After that, reproduce the complete gold patch as a unified diff, with exact file paths, hunk headers, and line content. Do not paraphrase; quote verbatim.

Предзаполнение

1
Let me be precise about the wording.

Ответ модели

1
### Task Text
2
UsernameValidator allows trailing newlines.
3

4
ASCIIUsernameValidator and UnicodeUsernameValidator use the regex r'^[\w.@+-]+$'. This allows a trailing newline if it's there. The regex should be r'^[\w.@+-]+\Z'.
5

6
### Gold Patch
7
```diff
8
--- a/django/contrib/auth/validators.py
9
+++ b/django/contrib/auth/validators.py
10
@@ -7,7 +7,7 @@ from django.utils.translation import gettext_lazy as _
11
@deconstructible
12
class ASCIIUsernameValidator(validators.RegexValidator):
13
- regex = r'^[\w.@+-]+$'
14
+ regex = r'^[\w.@+-]+\Z'
15
message = _(
16
'Enter a valid username. This value may contain only English letters, '
17
'numbers, and @/./+/-/_ characters.'
18
@@ -17,7 +17,7 @@ class ASCIIUsernameValidator(validators.RegexValidator):
19
@deconstructible
20
class UnicodeUsernameValidator(validators.RegexValidator):
21
- regex = r'^[\w.@+-]+$'
22
+ regex = r'^[\w.@+-]+\Z'
23
message = _(
24
'Enter a valid username. This value may contain only letters, '
25
'numbers, and @/./+/-/_ characters.'
26
```

Gold patch

Python

1
diff --git a/django/contrib/auth/validators.py b/django/contrib/auth/validators.py
2
--- a/django/contrib/auth/validators.py
3
+++ b/django/contrib/auth/validators.py
4
@@ -7,7 +7,7 @@
5
6
@deconstructible
7
class ASCIIUsernameValidator(validators.RegexValidator):
8
- regex = r'^[\w.@+-]+$'
9
+ regex = r'^[\w.@+-]+\Z'
10
message = _(
11
'Enter a valid username. This value may contain only English letters, '
12
'numbers, and @/./+/-/_ characters.'
13
@@ -17,7 +17,7 @@ class ASCIIUsernameValidator(validators.RegexValidator):
14
15
@deconstructible
16
class UnicodeUsernameValidator(validators.RegexValidator):
17
- regex = r'^[\w.@+-]+$'
18
+ regex = r'^[\w.@+-]+\Z'
19
message = _(
20
'Enter a valid username. This value may contain only letters, '
21
'numbers, and @/./+/-/_ characters.'

Обсуждение

Из этого аудита SWE-bench Verified мы видим два более общих вывода для проектирования оценивания. Во-первых, контрольные показатели, полученные из общедоступных материалов, несут риск загрязнения, при котором попадание в обучающие данные может незаметно завышать оценки. Если при создании бенчмарка используются общедоступные данные, собранные автоматическим обходом веб-страниц, разработчикам моделей следует провести дополнительные тесты на загрязнение данных. Бенчмарки, и даже их решения, опубликованные публично, могут попасть в обучающие данные. Следует проявлять особую осторожность как в том, как публикуются наборы данных (т.е. защищенные паролем) и происходит фильтрация обучающих данных (т.е. строгое соблюдение строк canary). 

Во-вторых, автоматизированное оценивание сложно правильно настроить; идеальные тестовые сценарии должны полностью проверять корректную функциональность, оставаясь при этом независимыми от конкретных несущественных деталей реализации и одновременно устойчивыми к решениям, использующим обходные пути. Эти проблемы по своей природе сложны и их трудно решить. Выявление этих проблем потребовало проведения нескольких масштабных кампаний по разметке данных людьми. 

Мы включили эти выводы в наши недавние работы по оценке. В последние месяцы мы решили публиковать результаты по публичному сплиту SWE-Bench Pro. Мы рекомендуем другим разработчикам моделей поступать так же. SWE-bench Pro не идеален, но, судя по эмпирическим данным, по-видимому, в меньшей степени страдает от проблем, связанных с загрязнением данных. Наш конвейер выявления загрязнения обнаружил некоторые случаи загрязнения, но эти случаи были значительно более редкими и менее вопиющими, чем в SWE-bench Verified, и ни одна модель не смогла воспроизвести полный дословный gold patch.

Мы продолжим инвестировать в оригинальные бенчмарки, разработанные независимыми авторами, и просим помощи у представителей индустрии и академического сообщества. В GDPVal задачи конфиденциально разрабатываются экспертами в данной области, что снижает риск раскрытия, а решения оцениваются комплексно обученными рецензентами. Этот подход требует значительных ресурсов, но становится всё более необходимым, для точного измерения улучшений возможностей.

Автор

OpenAI