Itinai.com it company office background blured chaos 50 v 41eae118 fe3f 43d0 8564 55d2ed4291fc 0

Как быстро собрать данные для SFT с Open‑SWE‑Traces: парсинг траекторий и метрики

Itinai.com it company office background blured chaos 50 v 41eae118 fe3f 43d0 8564 55d2ed4291fc 0

Зачем нужен DataFrame и как его собрать правильно

Вы уже пробежали первые два шага: собрали сырые данные и привели их к удобному виду. Теперь настало время собрать анализирующий DataFrame, который будет служить основой для всех дальнейших метрик и визуализаций. Если вы когда‑нибудь пытались «построить таблицу из кода», то знаете, насколько легко запутаться в именах колонок и типах данных. Давайте разберём все подводные камни и выстроим процесс так, чтобы потом не пришлось гадать, где же исчезли нужные строки.

Шаг 1 — Подготовка функций‑помощников

Прежде чем бросаться в цикл, убедитесь, что у вас есть небольшие, тестируемые функции. Ниже перечислены основные:

  • normalize_trajectory – чистит и стандартизирует список сообщений.
  • role_counts – считает, сколько раз встречаются роли system, user, assistant и tool.
  • parse_patch – извлекает из патча количество файлов, добавленных/удалённых строк и прочее.
  • normalize_metadata – превращает произвольный словарь метаданных в предсказуемый набор полей.
  • extract_tool_names – собирает все упомянутые инструменты из траекторий.

Все эти функции можно посмотреть в репозитории your‑org/analysis‑utils. Тесты к ним уже включены в CI, так что просто запустите pytest и убедитесь, что всё зелёное.

Шаг 2 — Функция, собирающая строку таблицы

Главный «механизм» – функция process_example. Она принимает один пример (запись из вашего набора) и возвращает словарь, готовый для превращения в строку DataFrame. Обратите внимание на несколько нюансов:

  • Все строки приводятся к нижнему регистру (language.lower()), иначе «Python» и «python» окажутся разными категориями.
  • Для полей, где потенциально может быть None, задаём «запасные» значения (например, "unknown").
  • Токенизация текста производится функцией count_tokens, которая должна соответствовать токенайзеру вашей модели (GPT‑2, LLaMA и пр.). Это важно для корректного сравнения «размеров» диалогов.
  • Новый булевый столбец is_resolved создаётся позже, а сейчас просто запоминаем оригинальное значение resolved.

Проверяйте типы возвращаемого словаря с помощью assert isinstance(..., dict) – это спасёт от тихих ошибок, когда одна запись случайно превратится в список.

Шаг 3 — Генерация списка записей

Теперь, когда process_example готова, собираем итоговый список:

records = [process_example(ex) for ex in raw_rows]

Важно, чтобы raw_rows был уже «очищен» от пустых элементов. Если в процессе появится None, добавьте фильтрацию:

records = [process_example(ex) for ex in raw_rows if ex is not None]

Шаг 4 — Создание DataFrame

Самый простой способ – воспользоваться pandas:

df = pd.DataFrame(records)

После создания добавляем удобные флаги:

  • is_resolved(df["resolved"] == 1) (логическое значение, удобно для фильтров).
  • known_labeldf["resolved"].isin([0, 1]) (отсекаем «неизвестные» метки).

Шаг 5 — Контроль качества получившейся таблицы

Покажите размер таблицы и базовую статистику. Это помогает сразу увидеть, нет ли «потерянных» колонок:

print(f"DataFrame: {df.shape[0]} rows x {df.shape[1]} cols")
print("\nNumeric summary:")
print(df[["n_messages", "n_assistant", "n_tool",
         "patch_files", "patch_churn", "traj_tokens"]].describe().round(1))

Если какие‑то столбцы покажут NaN вместо чисел, проверьте функции‑парсеры – часто причина кроется в отсутствии ожидаемых полей в исходных данных.

Шаг 6 — Сохранение результата

Для дальнейшего анализа удобно хранить таблицу в нескольких форматах:

  • df.to_parquet("analysis_dataset.parquet") – быстрый бинарный формат.
  • df.to_csv("analysis_dataset.csv", index=False) – читаемый людьми.

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

Типичные подводные камни и как их избежать

  • Разные типы токенизации. Если в разных проектах вы используете разные токенайзеры, сравнивать traj_tokens будет бессмысленно.
  • Пропущенные роли. Иногда в траектории нет assistant – в этом случае rc.get("assistant", 0) гарантирует ноль, а не ошибку KeyError.
  • Большие патчи. При работе с огромными diff‑файлами подсчёт add и del может стать bottleneck. Рассмотрите возможность предварительной агрегации на уровне файлов.
  • Неоднородные метаданные. Если у некоторых записей отсутствует поле category, используйте meta.get("category", "unspecified").

Что дальше?

Получив готовый DataFrame, вы можете:

  • Построить корреляцию между patch_churn и числом сообщений.
  • Разделить данные на обучающую/тестовую выборки по is_resolved.
  • Визуализировать распределения ролей с помощью seaborn или plotly.

Главное – держать процесс «чистым» и «модульным». Тогда любые изменения в парсинге или новых полях впишутся без боли, а ваша аналитика будет работать, как часы.

Запустите свой ИИ проект бесплатно

ИИ-агенты искусственный интеллект онлайн для бизнеса

Лучший ИИ онлайн