中文翻译暂不可用,显示俄语原文。

Fine-tune LoRA для стиля

ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Fine-tune LoRA для стиля

1. Цель задачи

Научиться применять параметро-эффективное дообучение (LoRA) для изменения стиля ответов языковой модели. Необходимо собрать 500 диалогов в стиле "вежливый помощник", выполнить LoRA-дообучение на небольшой открытой модели (например, GPT-2 или Qwen2.5-0.5B) и добиться улучшения качества ответов по сравнению с исходной (baseline) моделью не менее чем на 10% по выбранной метрике.

Ключевой результат LoRA-адаптер, который при тестировании на 100 вежливых запросах получает более высокий рейтинг (win rate) относительно baseline в ≥55% случаев (baseline = 50%, +10% = 55%).

2. Исходные данные

Что нужноОткуда взять
Базовые знания Python, PyTorchКурс ML-инженерии / практика
Доступ к GPU (Google Colab / локально с CUDA)Среда выполнения
LLM для синтеза датасета (необязательно)OpenAI API, Together AI, или любая открытая модель
Модель для fine-tune (например, Qwen/Qwen2.5-0.5B или openai-community/gpt2)Hugging Face Model Hub
~5 ГБ свободного места на дискеЛокальный / облачный хранение

Если нет реального датасета — симулируем:

  1. Загрузить шаблон диалогов (примеры "грубый" vs "вежливый" ответ).
  2. Использовать любую LLM (через API или локально) для генерации 500 пар (запрос, вежливый ответ).
  3. Вручную проверить и отфильтровать 10% датасета – удалить токсичные или бессмысленные примеры.

3. Технологический стек

КомпонентИнструментыНазначение
Фреймворк дообученияtransformers, peft, trlLoRA, обучение, PPO/SFT
ДатасетыdatasetsЗагрузка, обработка, разделение
Оптимизация памятиbitsandbytes, accelerateQLoRA (4-bit), распределение
Базовый языкPython 3.10+Скрипты обучения и оценки
Визуализацияmatplotlib, wandb (опционально)Логи loss, метрик
Оценкаscikit-learn, ручная аннотацияМетрики качества стиля
ВерсионированиеGit + DVC (опционально)Трекинг данных и весов

4. Этапы выполнения

Этап 1: Подготовка датасета (2–3 часа)

Действия

  1. Создать шаблон диалогов Пример структуры:
    Instruction: {user_message}
    Response: {assistant_answer}
    
  2. Собрать 500 диалогов в стиле "вежливый помощник":
    • 200 примеров взять из открытых датасетов (например, databricks/databricks-dolly-15k, отфильтровать по ключевым словам "please", "thank you", "could you").
    • 300 примеров сгенерировать синтетически с помощью другой LLM (например, через API GPT-4-mini с промптом: "Напиши вежливый ответ ассистента на пользовательский запрос: …").
  3. Разделить на train/val/test (400/50/50). Использовать datasets.Dataset.train_test_split.
  4. Проверить качество прочитать 20 случайных диалогов, удалить с неадекватным содержанием.

Ожидаемый результат этапа Файл data/train.jsonl, data/val.jsonl, data/test.jsonl с колонками instruction и response.

Этап 2: Настройка LoRA конфигурации (1 час)

Действия

  1. Выбрать базовую модель Рекомендуется Qwen/Qwen2.5-0.5B-Instruct (инструктивная версия) или openai-community/gpt2 (но потребуется дополнительная настройка токенизатора).
  2. Загрузить модель в 4-bit (QLoRA) для экономии памяти:
    from transformers import AutoModelForCausalLM, BitsAndBytesConfig
    bnb_config = BitsAndBytesConfig(load_in_4bit=True,
                                     bnb_4bit_use_double_quant=True,
                                     bnb_4bit_quant_type="nf4",
                                     bnb_4bit_compute_dtype=torch.bfloat16)
    model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-0.5B-Instruct",
                                                   quantization_config=bnb_config,
                                                   device_map="auto")
    
  3. Создать LoRA config (PEFT):
    from peft import LoraConfig, get_peft_model
    lora_config = LoraConfig(
        r=8,
        lora_alpha=32,
        target_modules=["q_proj", "v_proj"],  # или все линейные слои
        lora_dropout=0.1,
        bias="none",
        task_type="CAUSAL_LM"
    )
    model = get_peft_model(model, lora_config)
    
  4. Проверить количество обучаемых параметров model.print_trainable_parameters() должно быть <1% от общего.

Ожидаемый результат этапа Модель с PEFT-адаптером готова, конфиг сохранён в lora_config.yml.

Этап 3: Обучение (2–3 часа на GPU Tesla T4)

Действия

  1. Подготовить коллатор данных (data collator):
    from transformers import DataCollatorForSeq2Seq
    tokenizer.pad_token = tokenizer.eos_token
    data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer,
                                            model=model,
                                            padding="longest",
                                            max_length=512)
    
  2. Настроить Trainer (SFTTrainer из trl проще):
    from trl import SFTTrainer
    trainer = SFTTrainer(
        model=model,
        train_dataset=train_dataset,
        eval_dataset=eval_dataset,
        args=transformers.TrainingArguments(
            output_dir="./lora-polish-assistant",
            per_device_train_batch_size=4,
            per_device_eval_batch_size=2,
            gradient_accumulation_steps=4,
            num_train_epochs=3,
            learning_rate=2e-4,
            logging_steps=10,
            evaluation_strategy="steps",
            eval_steps=50,
            save_strategy="steps",
            save_steps=50,
            load_best_model_at_end=True,
            report_to="none"
        ),
        data_collator=data_collator,
        formatting_func=lambda ex: ex["instruction"] + " " + ex["response"]
    )
    
  3. Запустить обучение Мониторить loss (целевой train loss < 0.5, eval loss < 0.6).
  4. Сохранить адаптер trainer.model.save_pretrained("lora-polish-adapter").

Ожидаемый результат этапа Папка lora-polish-adapter/ с весами LoRA (файл adapter_model.bin, конфиг).

Этап 4: Оценка и сравнение с baseline (1–2 часа)

Действия

  1. Собрать baseline-ответы — прогнать тестовый набор через исходную модель (без LoRA) с тем же токенизатором.
  2. Собрать LoRA-ответы — применить адаптер:
    from peft import PeftModel
    base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-0.5B-Instruct",
                                                       load_in_4bit=True)
    lora_model = PeftModel.from_pretrained(base_model, "lora-polish-adapter")
    
  3. Провести pairwise-оценку
    • Для 50 случайных тестовых запросов показывать два ответа (baseline и LoRA) трём асессорам (или одному, если solo).
    • Асессоры выбирают, какой ответ вежливее и релевантнее.
    • Посчитать win rate LoRA vs baseline. Если win rate >= 55% – задача выполнена.
  4. Дополнительно вычислить автоматические метрики (perplexity, ROUGE-L) – они не должны сильно ухудшиться.

Ожидаемый результат этапа Таблица с результатами (win rate, количество побед/поражений/ничьи), визуализация распределения.

Этап 5: Документация и фиксация результатов (1 час)

Действия

  1. Создать README проекта с описанием:
    • цель, датасет, модель, конфиг LoRA, гиперпараметры
    • метрики и выводы
  2. Загрузить адаптер на Hugging Face Hub (опционально) или в Git LFS.
  3. Сохранить лог обучения (console output / wandb) в папку logs/.

Ожидаемый результат этапа README.md, готовый к публикации, все артефакты закоммичены.

5. Критерии приемки (Definition of Done)

  • Датасет из 500 диалогов собран, размечен, разделён на train/val/test и помещён в data/.
  • LoRA-адаптер обучен (финальный loss < 0.5 на train) и сохранён.
  • Baseline и LoRA модели корректно загружаются и выдают ответы на тестовых запросах.
  • Проведена pairwise-оценка на 50 запросах (минимум одним асессором) с получением win rate.
  • Win rate LoRA >= 55% (целевое улучшение +10% относительно baseline).
  • Код обучения и оценки воспроизводим (один скрипт run.sh или notebook).
  • README с описанием эксперимента, метриками и инструкцией по запуску.

6. Ожидаемый результат

Основной артефакт папка lora-polish-adapter/ с файлами:

  • adapter_config.json — конфигурация LoRA
  • adapter_model.bin — веса адаптера (~10-20 МБ)
  • training_args.bin — аргументы обучения

Сопутствующие результаты

  • results/win_rate.csv — таблица результатов оценки
  • data/ — датасет и его разбивка
  • logs/training.log — полный лог обучения
  • baseline_predictions.jsonl и lora_predictions.jsonl — ответы на тесте

Опционально модель опубликована на Hugging Face Hub в формате username/polish-lora-assistant.

7. Возможные сложности и их решение

СложностьРешение
Не хватает памяти GPU (OOM)Использовать QLoRA (4-bit), градиентный аккумуляция, batch size = 1, уменьшить max_length до 256
Датасет слишком мал (500 диалогов)Применить data augmentation (вариации тех же запросов), увеличить число эпох (до 5-6) с ранней остановкой
Модель не учится (loss не снижается)Проверить формат данных (добавить EOS токен), уменьшить learning rate до 1e-4, проверить target_modules
Субъективность оценки вежливостиИспользовать чёткие критерии: наличие "please", благодарности, избегание повелительного наклонения; привлечь 2-3 дополнительных асессора
LoRA адаптер портит другие качестваВо время оценки сравнивать не только вежливость, но и релевантность ответа (если LoRA резко хуже по смыслу – увеличить weight decay)

8. Бюджет времени (оценка)

ЭтапВремя (часы)
Этап 1: Подготовка датасета2–3
Этап 2: Настройка LoRA1–1.5
Этап 3: Обучение2–3 (ожидание на GPU)
Этап 4: Оценка1–2
Этап 5: Документация0.5–1
Итого6.5–10.5

Примечание для первого раза Большую часть времени занимает подготовка датасета и ручная оценка. На этапе обучения можно использовать уже готовые датасеты (например, фильтрация Dolly), чтобы сократить Этап 1 до 1 часа.

9. Связанные вопросы из базы знаний

ВопросТема
101Как работает LoRA и чем отличается от full fine-tune?
112Выбор ранга LoRA (r) и alpha
134Практика с Hugging Face PEFT
201Синтетическая генерация датасетов с LLM
221RAG: оценка качества ответов (сходство с эталоном)
312Обучение SFT с TRL
415Human evaluation: как проводить pairwise сравнение
501Метрики для генерации текста (perplexity, ROUGE)
603Управление памятью в PyTorch / CUDA Out of Memory
789Baseline и сравнение моделей в NLP

10. Чек-лист самопроверки

  • Я собрал 500 диалогов, проверил, что они соответствуют стилю "вежливый помощник".
  • Я настроил LoRA с r=8, target_modules подходящими для моей модели.
  • Я обучил модель минимум 3 эпохи, убедился, что loss снижается.
  • Я получил ответы от baseline и LoRA на 50 тестовых запросах.
  • Я провёл pairwise-оценку (сам или с коллегами) и убедился, что win rate ≥55%.
  • Я сохранил все файлы (адаптер, логи, результаты) и написал README.