Fine-tuning LLM: подготовка датасета — форматы, дедупликация и чеклист

Как подготовить датасет для fine-tuning LLM: форматы, дедупликация и чеклист

Направления AI-разработки

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1414
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1284
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    980
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1240
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    696
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    982

Как подготовить датасет для fine-tuning LLM: форматы, дедупликация и чеклист

Допустим, вы решили дообучить LLaMA 3 под генерацию SQL. Собрали 50 000 примеров, но модель выдаёт ерунду. В чём дело? Скорее всего, в датасете: дубли, неверный формат, утечка промпта. Мы в TrueTech готовим датасеты много лет и знаем: без системного подхода 80% данных — мусор. Согласно документации Hugging Face Datasets, качество датасета — главный фактор успеха fine-tuning. «Мусор на входе — мусор на выходе» работает вдвойне для LLM: плохо структурированные или нерелевантные примеры не просто не помогают — они активно деградируют модель. Гарантируем чистоту данных — каждая запись проходит валидацию на дубли, PII и утечку промпта.

Проблемы, которые мы решаем

Типичные ошибки при подготовке датасета: неверный выбор формата, несбалансированность классов, дубли (exact и near-duplicate), утечка промпта в ответ, присутствие PII (имена, email, телефоны). Неравномерное распределение длины ответов приводит к смещению модели. Мы видим это на каждом втором проекте. Наши инженеры используют автоматические валидаторы и стратифицированное разбиение, чтобы исключить эти проблемы. Например, избыточный вес длинных ответов может исказить распределение вероятностей модели.

Как мы это делаем: стек и кейс из нашей практики

Для нашего клиента из финтеха мы подготовили датасет для дообучения LLaMA 3 под генерацию SQL-запросов. Использовали формат ChatML с системным промптом, добавили 15 000 примеров с различной сложностью (от SELECT до JOIN и подзапросов). Каждый пример проверяли семантической дедупликацией с порогом 0.93 — убрали 12% near-дублей. Экономия бюджета клиента составила 30% (около $4 500).

Форматы датасетов для fine-tuning

Instruction following (Alpaca формат):

{"instruction": "Переведи на английский", "input": "Привет мир", "output": "Hello world"} {"instruction": "Напиши SQL запрос", "input": "Выбери всех пользователей старше 30", "output": "SELECT * FROM users WHERE age > 30;"} 

Chat format (ShareGPT/ChatML):

{ "conversations": [ {"from": "system", "value": "Ты помощник по SQL"}, {"from": "human", "value": "Как выбрать уникальные значения?"}, {"from": "gpt", "value": "Используй SELECT DISTINCT: `SELECT DISTINCT column FROM table;`"} ] } 

Сравнение форматов датасетов

Формат Применение Пример использования
Alpaca Instruction-following Перевод, суммаризация
ChatML Многопользовательские диалоги Чат-боты, ассистенты
Completion Генерация текста без инструкций Код, статьи

Как правильно структурировать датасет для fine-tuning?

Каждый пример должен содержать чёткую инструкцию, контекст (если нужен) и идеальный ответ. Длина output — от 10 до 2000 токенов. Ответ не должен содержать фрагментов инструкции или устаревших данных. Мы используем класс FineTuningExample с валидацией полей:

Код класса FineTuningExample
class FineTuningExample: instruction: str # Чёткая задача без двусмысленности input: str # Конкретный контекст/данные (опционально) output: str # Идеальный ответ модели def validate(self) -> list[str]: issues = [] if len(self.output) < 10: issues.append("Output too short") if len(self.output) > 2000: issues.append("Output may be too long for this task") if self.output in ["I don't know", "N/A", ""]: issues.append("Uninformative output") if self.instruction.lower()[:20] in self.output.lower(): issues.append("Output contains instruction text") return issues 

Требования к объёму датасета

Задача Минимум примеров Оптимум
Tone/style transfer 500–1000 2000–5000
Domain adaptation 1000–3000 5000–15000
Task-specific (Q&A) 500–2000 3000–10000
Code generation 2000–5000 10000–50000
Multi-turn dialogue 1000–3000 5000–20000

Почему важна дедупликация?

Дубли (exact и near-duplicate) искажают распределение данных, заставляя модель «заучивать» одни и те же паттерны. Это снижает обобщающую способность и увеличивает риск переобучения. Мы применяем два уровня дедупликации:

Код дедупликации
def deduplicate_exact(examples: list) -> list: seen = set() unique = [] for ex in examples: h = hashlib.md5(f"{ex.instruction}{ex.input}".encode()).hexdigest() if h not in seen: seen.add(h) unique.append(ex) return unique def deduplicate_semantic(examples: list, threshold: float = 0.95) -> list: model = SentenceTransformer('all-MiniLM-L6-v2') texts = [f"{e.instruction} {e.input}" for e in examples] embeddings = model.encode(texts, batch_size=512, show_progress_bar=True) keep = [True] * len(examples) for i in range(len(examples)): if not keep[i]: continue for j in range(i+1, len(examples)): sim = cosine_similarity([embeddings[i]], [embeddings[j]])[0][0] if sim > threshold: keep[j] = False return [ex for ex, k in zip(examples, keep) if k] 

Разделение на train/eval

Стратифицированное разбиение по длине output — обязательное требование. Группируем примеры на короткие (<200 токенов), средние (200–500) и длинные (>500). Внутри каждой группы — случайное разделение 90/10. Eval set не должен пересекаться с train ни по exact, ни по semantic.

Финальный чеклист перед обучением

  • [ ] Нет дублей (exact и near-duplicate)
  • [ ] Нет PII в датасете (имена, email, телефоны)
  • [ ] Output не содержит ссылок на даты/версии
  • [ ] Равномерное распределение по типам задач
  • [ ] Eval set не пересекается с train
  • [ ] Токенизированные примеры не превышают max_length модели

Что входит в работу (deliverables)

  • Анализ исходных данных и выявление проблем
  • Структурирование в выбранный формат (Alpaca/ChatML)
  • Валидация каждого примера (PII, утечка, длина)
  • Дедупликация exact и semantic
  • Подготовка train/eval сплита с сохранением распределения
  • Документация по датасету (статистика, описание полей)
  • Поддержка на этапе обучения модели

Процесс работы

  1. Аналитика — изучаем задачу и исходные данные.
  2. Проектирование — выбираем формат и схему валидации.
  3. Реализация — пишем скрипты для структурирования и очистки.
  4. Тестирование — проверяем качество на пилотном датасете.
  5. Деплой — передаём готовый датасет с документацией.

Сроки и стоимость

Сроки: от 3 до 14 рабочих дней в зависимости от объёма и сложности. Стоимость рассчитывается индивидуально — оценим ваш проект за 2 дня. Свяжитесь с нами, чтобы получить консультацию по вашему датасету. Закажите подготовку датасета уже сегодня. Опыт наших инженеров — 5+ лет в дообучении LLM, мы гарантируем чистоту и сбалансированность данных.