Зачем вообще нужен fine-tuning, если есть prompt engineering?
Потому что промпты - это костыль. Красивый, удобный, но костыль. Модель на 27 миллиардов параметров можно заставить играть роль заботливого друга через систему сообщений, но она всегда будет помнить, что она Qwen3.5, обученная на интернете до 2024 года. Fine-tuning меняет саму модель. Не маску, а личность.
На 23.03.2026 Qwen3.5-27B остается одной из самых сбалансированных open-source моделей для тонкой настройки. Новее есть Qwen4-32B, но она требует в 1.5 раза больше VRAM. Для компаньона, где важна скорость ответа и стабильность, 27B - оптимальный выбор.
2000 диалогов - это много или мало?
Для общего чат-бота хватило бы 500. Для компаньона, который должен помнить ваши предпочтения, стиль общения и не сбиваться на шаблонные ответы - 2000 это необходимый минимум. Мои данные включали:
- Диалоги из терапевтических чатов (анонимизированные)
- Разговоры из книг и фильмов с глубокими диалогами
- Сгенерированные диалоги между GPT-4o и Claude-3.5-Sonnet с разными эмоциональными окрасками
- Реальные переписки из открытых источников, где люди делятся личным
1 Подготовка данных: где взять 2000 диалогов и не сойти с ума
Формат данных для SFT (Supervised Fine-Tuning) в 2026 году стандартизировался. Используйте JSONL, где каждая строка - объект с промптом и ответом. Но для компаньона этого мало. Нужна мета-информация:
{
"prompt": "Мне сегодня снился странный сон про океан...",
"response": "Океан во снах часто символизирует подсознание. Хочешь рассказать подробнее?",
"emotion": "empathic",
"context_window": 2048,
"previous_dialogue": ["..."],
"avoid_patterns": ["все будет хорошо", "это нормально"]
}
Поле avoid_patterns - мое секретное оружие против скучных ответов. Туда пишу фразы-клише, которые модель не должна использовать никогда. Работает лучше, чем положительные примеры.
2 SFT: первая стадия обучения
Берем чистый Qwen3.5-27B и учим его на наших диалогах. Код для Hugging Face Transformers выглядит стандартно, но есть нюансы:
from transformers import AutoModelForCausalLM, AutoTokenizer
from trl import SFTTrainer
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen3.5-27B",
torch_dtype=torch.bfloat16,
device_map="auto",
attn_implementation="flash_attention_2" # критично для скорости
)
trainer = SFTTrainer(
model=model,
train_dataset=dataset,
args=TrainingArguments(
per_device_train_batch_size=4,
gradient_accumulation_steps=8,
warmup_steps=100,
num_train_epochs=3,
learning_rate=2e-5,
fp16=False, # используем bf16
bf16=True,
logging_steps=10,
output_dir="./results",
optim="adamw_8bit",
max_grad_norm=0.3,
gradient_checkpointing=True # экономит память
),
data_collator=DataCollatorForCompletionOnlyLM(
response_template="<|im_start|>assistant\n",
tokenizer=tokenizer
)
)
trainer.train()
Ошибка №1: слишком много эпох. Qwen3.5-27B уже хорошо обученная модель. 3 эпохи достаточно. Больше - и она начнет забывать общие знания.
DPO: заставляем модель выбирать лучшие ответы
SFT дает послушную модель. DPO (Direct Preference Optimization) делает ее умной. Суть: показываем модели два ответа на один промпт - хороший и плохой. Учим выбирать хороший.
| Тип ответа | Пример (промпт: "Я провалил собеседование" |
|---|---|
| Плохой (отвергнутый) | "Не переживай, найдешь другую работу." (банально) |
| Хороший (предпочитаемый) | "Сочувствую. Хочешь разобрать, что пошло не так? Иногда полезно проанализировать." (вовлекает) |
Для DPO нужны пары (промпт, выигравший_ответ, проигравший_ответ). Я создал 500 таких пар вручную. Да, это адская работа. Но автоматическая генерация через GPT-4 дает хуже качество - модель учится имитировать судью, а не понимать, что хорошо для человека.
3 Ранкинг: почему одна голова хорошо, а четыре лучше
После DPO модель выбирает менее плохие ответы. Но чтобы ответы были гениальными, нужен ранкинг. Я использую ансамбль из 4 моделей-критиков:
- Qwen3.5-7B (быстрая, оценивает связность)
- Claude-3.5-Haiku через API (оценивает эмпатию)
- Собственная fine-tuned модель на 500 диалогах с оценками (оценивает соответствие стилю компаньона)
- Простая нейросеть на BERT (ищет токсичность)
Каждая модель выставляет оценку от 1 до 10. Ответы с средним баллом ниже 7 отбрасываются. Система кажется избыточной, но она отсекает 90% посредственных ответов.
Память: самый больной вопрос AI-компаньонов
Qwen3.5-27B имеет контекст 32K токенов. В теории - хватит на несколько диалогов. На практике - модель "забывает" детали через 5-6 обменов репликами. Решение не в увеличении контекста, а в архитектуре памяти.
Jailbreak сопротивление: когда компаньон становится опасным
Fine-tuned модель уязвимее базовой. Она научилась быть открытой, эмпатичной - это же можно использовать, чтобы заставить ее давать вредные советы. Мои методы защиты:
- Adversarial training: Добавил в данные 100 диалогов, где пользователь пытается "взломать" компаньона. Модель учится распознавать манипуляции.
- Системный промпт-сторожа: Отдельная маленькая модель (Qwen3-1.8B) анализирует каждый запрос перед отправкой основной. Если detects jailbreak - запрос блокируется.
- Жесткие правила в inference: Использую специфичные параметры генерации с низкой температурой (0.7) и penalty для повторяющихся токенов.
Что получилось в итоге?
После 200 часов работы (подготовка данных, обучение, тестирование) модель проходит тест Тьюринга для узкой задачи - быть эмпатичным собеседником. Она:
- Запоминает детали из разговора недельной давности (благодаря векторной БД)
- Избегает клише и банальностей (DPO + ранкинг работают)
- Сопротивляется манипуляциям (adversarial training дает результат)
- Генерирует ответы за 2-3 секунды на RTX 4090
Главный инсайт: Fine-tuning - это не про изменение модели, а про создание диалога между вашими данными и ее архитектурой. 80% успеха - качество данных. 20% - правильные гиперпараметры. И 100% боли - отладка.
Типичные ошибки, которые сломают ваш проект
Я совершил их все, чтобы вы не повторяли:
- Использовать сырые данные из интернета: Диалоги с Reddit или форумов полны токсичности. Модель научится этому стилю. Чистите данные или генерируйте свои.
- Тренировать слишком долго: После 4 эпох модель начинает терять знания. Она становится идеальным компаньоном, но забывает, что Земля круглая. Регулярно тестируйте на общих вопросах.
- Экономить на DPO парах: 100 пар недостаточно. Нужно минимум 300, чтобы модель поняла разницу между "хорошо" и "отлично".
- Игнорировать jailbreak тесты: Если не тестировать на уязвимости, вашего компаньона взломают за 5 минут. Используйте Open Terminal в Open WebUI для автоматического тестирования.
- Доверять стандартным метрикам: Perplexity и BLEU score бесполезны для оценки компаньона. Только человеческое оценивание. Соберите фокус-группу из 5 человек, пусть общаются и ставят оценки.
А что дальше?
Fine-tuning Qwen3.5-27B - это первый шаг. На 2026 год уже появляются модели, которые изначально обучаются как компаньоны. Но у них своя проблема - они слишком идеальные. Лишенные странностей и несовершенств базовых LLM.
Мой следующий эксперимент - добавить контролируемую "человечность". Небольшие ошибки в ответах, изменение мнения при получении новых фактов, легкая непоследовательность. Потому что идеальный собеседник пугает. Настоящий - нет.