Ви запустили fine-tuning своєї LLM, а якість відповідей виявилася нижчою, ніж очікувалося. Найчастіше причина не в архітектурі, а в даних. 70% проблем з fine-tuning пов'язані з якістю розмітки, а не з вибором моделі чи гіперпараметрами. Неправильно зібраний датасет призводить до падіння метрик на 20-30% порівняно з добре розміченим. Розмітка для дообучення принципово відрізняється від класичної ML-розмітки: тут не присвоюється мітка, а створюється ідеальна відповідь моделі. Якість анотацій безпосередньо визначає якість навченої моделі. Ми реалізували понад 50 проєктів — від підтримки клієнтів до багатокрокових агентів, і гарантуємо професійний підхід до кожного.
Типи анотації
Вибір способу залежить від обсягу, бюджету та необхідної якості. Нижче — порівняння основних підходів.
| Тип анотації |
Швидкість |
Якість |
Вартість |
Ризики |
| Direct annotation |
5-10 пар/год |
Дуже висока |
Висока |
Втома анотатора |
| Edit-based |
15-30 пар/год |
Висока |
Середня |
Прийняття поганої відповіді |
| Ranking/Preference |
20-40 пар/год |
Середня |
Низька |
Неузгодженість критеріїв |
| AI-assisted |
30-50 пар/год |
Висока |
Низька |
Залежність від базової моделі |
Direct annotation — розмітник створює пару (інструкція, ідеальна відповідь) з нуля. Найвища якість, найвищий cost. Використовуємо для критичних до якості доменів (юриспруденція, медицина).
Edit-based annotation — розмітник покращує відповідь базової моделі. У 2-3 рази швидше, ніж з нуля. Ризик: розмітник приймає погану відповідь з мінорними правками. Щоб цього уникнути, включаємо обов'язкове поле «обґрунтування змін».
Ranking/Preference annotation — розмітник ранжує кілька відповідей моделі (використовується для RLHF та DPO). Простіше, ніж створення з нуля, але потребує чіткого розуміння критеріїв якості. Без них kappa між анотаторами рідко перевищує 0.4.
AI-assisted annotation — сильна модель (GPT-4) генерує відповіді, люди перевіряють та коригують. Оптимальний баланс якості та швидкості для більшості задач. На практиці дає 90% якості direct при 30% вартості.
Як вибрати тип анотації?
Якщо ваша задача — навчити модель відповідати на типові питання (підтримка, FAQ), обирайте AI-assisted з фінальною вичиткою. Для творчих задач (генерація коду, креатив) — direct annotation. Для задач з ранжуванням (рекомендаційні системи) — ranking/Preference. Якщо бюджет обмежений, можна комбінувати: 20% direct для навчання анотаторів та 80% edit-based для основного обсягу. Отримайте консультацію з підбору типу анотації для вашого проєкту — ми допоможемо з вибором.
Керівництво з анотації (Annotation Guidelines)
Ключовий документ, без якого анотатори будуть давати неузгоджені результати. Включаємо в нього:
- критерії якості (точність, повнота, тон, довжина, структура);
- приклади хорошої відповіді з розбором;
- приклади поганої відповіді з поясненням помилок;
- список заборонених фраз («Я просто мовна модель…», «Я не можу…»);
- правила обробки неоднозначних запитів.
Ми розробляємо guidelines під кожен проєкт і проводимо calibration сесії перед стартом. Приклад guidelines для Customer Support Assistant:
## Руководство по аннотации: Customer Support Assistant
### Критерии качества хорошего ответа:
1. Точность: Ответ соответствует политикам компании и фактически верен
2. Полнота: Решает проблему пользователя, не оставляя открытых вопросов
3. Тон: Профессиональный, эмпатичный, без извинений за несуществующие проблемы
4. Длина: Достаточная, но не избыточная (100-300 слов оптимально)
5. Структура: Абзацы, без списков для простых ответов
### Что НЕ должно быть в ответе:
- "Я просто языковая модель..."
- "Я не могу..."
- Повторение вопроса пользователя
- Неуместные извинения
- Устаревшая информация о продукте
### Примеры ХОРОШЕГО ответа: [примеры]
### Примеры ПЛОХОГО ответа: [примеры с объяснением]
Платформи для анотації
Label Studio (open-source):
from label_studio_sdk import Client
ls = Client(url='http://localhost:8080', api_key='...')
# Создание проекта для LLM аннотации
project = ls.start_project(
title='Customer Support Fine-tuning',
label_config='''
<View>
<Text name="instruction" value="$instruction"/>
<TextArea name="response" toName="instruction"
placeholder="Write ideal response..."
rows="10" maxSubmissions="1"/>
<Rating name="quality" toName="instruction"
maxRating="5" icon="star" size="medium"/>
</View>
'''
)
# Загрузка задач
tasks = [{"instruction": ex.instruction, "input": ex.input}
for ex in unannotated_examples]
project.import_tasks(tasks)
Scale AI / Appen — для великих обсягів з професійними анотаторами. Значно дорожче, але Quality Control включений. Використовуємо їх для проєктів з обсягом від 50 000 пар.
Як контролювати якість анотацій?
Основною метрикою є inter-annotator agreement (IAA) — узгодженість між анотаторами. Чим вищий, тим надійніші дані. Для контролю якості ми закладаємо перекриття 10-20% задач, які розмічаються двома спеціалістами незалежно. Обчислюємо Cohen's Kappa — міру згоди, що використовується в NLP.
Приклад розрахунку Cohen's Kappa
from sklearn.metrics import cohen_kappa_score
def compute_iaa(annotations_a: list, annotations_b: list) -> float:
"""Cohen's Kappa для узгодженості анотаторів"""
# Для ranking задач (1-5 rating)
kappa = cohen_kappa_score(annotations_a, annotations_b)
print(f"Cohen's Kappa: {kappa:.3f}")
# < 0.4: низька згода, перегляд guidelines
# 0.6-0.8: хороша згода
# > 0.8: відмінна згода
return kappa
Низька узгодженість (< 0.4) — сигнал, що guidelines неоднозначні. Ми доопрацьовуємо документ, проводимо додаткову calibration сесію та повторно заміряємо IAA.
Calibration сесії перед стартом повноцінної анотації: спільна розмітка 20-50 прикладів всією командою, обговорення розбіжностей, уточнення guidelines. Це критично знижує варіанс між анотаторами. Без калібрування навіть досвідчені анотатори дають kappa < 0.5 на складних задачах. Після калібрування — стабільно 0.7+.
Чому важливі calibration сесії?
Тому що без них розкид між анотаторами може звести нанівець усі зусилля зі збору даних. Одна calibration сесія знижує кількість переробок на 40% і підвищує підсумкову точність моделі на 15-20%. Це економить до 30% бюджету проєкту. Оптимізація розмітки знижує витрати на 35-40% порівняно з традиційними методами. Замовте пілотне калібрування — ми покажемо ефект на ваших даних.
Що входить у нашу роботу з розмітки даних?
Нижче — основні етапи та їх тривалість.
| Етап |
Тривалість |
Результат |
| Аналіз задачі та розробка guidelines |
3-5 днів |
Документ annotation guidelines |
| Підбір типу анотації |
1 день |
Рекомендація з обґрунтуванням |
| Calibration сесія та навчання |
2-3 дні |
Навчені анотатори |
| Розмітка з контролем якості |
від 2 тижнів |
Датасет з перекриттям та IAA |
| Підсумковий датасет та документація |
2 дні |
JSONL з метаданими, статистика IAA |
Терміни залежать від обсягу та складності: від 2 тижнів для 1000 пар до 2-3 місяців для 50 000+. Вартість розраховується індивідуально. Ми працюємо як з разовими проєктами, так і з довгостроковим аутсорсингом анотації. Отримайте консультацію для оцінки вашого проєкту — оцінимо обсяг роботи, підберемо оптимальний метод анотації та розрахуємо терміни.
Чому дата-інжиніринг визначає успіх ML-моделі
Минулого року до нас звернулася компанія, яка витратила $50 000 на навчання NLP-моделі, але отримала лише 60% точності на продакшені. Причина — data leakage через випадковий split часових даних. Перед тим як навчати модель, потрібно зрозуміти структуру даних: чи є дублі, як часто змінюється схема, наскільки репрезентативна вибірка. Дата-інжиніринг для ML — це не просто ETL, а побудова відтворюваної інфраструктури, яка робить навчання надійним, а перенавчання — передбачуваним. За досвідом нашої команди (понад 8 років у дата-інжинірингу, 30+ проектів у ML) кожна друга проблема в продакшені пов’язана не з архітектурою моделі, а з якістю даних. Замовте аудит ваших даних — оцінимо поточний пайплайн безкоштовно.
Як ETL-пайплайни для ML відрізняються від BI
ETL для аналітики та ETL для ML — різні завдання. В аналітиці важлива агрегація, у ML — індивідуальні записи з історією. В аналітиці train/val/test split не потрібен, у ML — критичний. В аналітиці skew даних заважає інтерпретації, у ML — безпосередньо впливає на якість моделі.
Інструменти. Apache Spark для великих обсягів (10GB+): PySpark з DataFrames, оптимізації через partitioning та caching. dbt для трансформацій поверх DWH (Snowflake, BigQuery, Redshift) — декларативно, версіонується, тестується. Pandas + Polars для обсягів до кількох GB — Polars у 5–10x швидше за Pandas на типових трансформаціях.
Temporal splits. Для ML важливо, що split за часом, а не випадковий. Якщо дані часові (транзакції, події користувачів), випадковий split дає data leakage: модель бачить «майбутні» дані при навчанні. Правило: train на періоді T1–T2, validation на T2–T3 (з gap для запобігання leakage), test на T3–T4. Неправильний split може коштувати 10–15% якості моделі на валідації. Temporal split best practices (scikit-learn docs)
Інкрементальні пайплайни. Модель перенавчається щотижня на нових даних. Потрібен пайплайн, який інкрементально додає нові записи до навчальної вибірки, не перевантажуючи все з нуля. Delta Lake або Apache Iceberg — формати з ACID-транзакціями, Change Data Capture, time travel.
Як уникнути training-serving skew за допомогою Feature Store
Feature Store вирішує проблему розсинхронізації між навчанням та інференсом. Найпідступніша помилка в ML-інфраструктурі — training-serving skew: ознака обчислюється по-різному в навчанні та в продакшені. Модель вчиться на «правильних» даних, а інференс отримує інші.
Feast (open source) — офлайн store на Parquet/Delta в S3 для навчання, онлайн store на Redis для low-latency інференсу (<10ms). Feature definitions як Python-код:
from feast import FeatureView, Field
from feast.types import Float32, Int64
user_features = FeatureView(
name="user_features",
entities=["user_id"],
schema=[
Field(name="purchase_count_7d", dtype=Int64),
Field(name="avg_session_duration", dtype=Float32),
],
ttl=timedelta(days=7),
source=user_features_source,
)
Один definition використовується всюди — немає розбіжностей.
Потокові ознаки. Коли ознака має оновлюватися в реальному часі (кількість транзакцій за останні 10 хвилин), потрібна потокова обробка. Apache Kafka + Apache Flink або Kafka Streams для обчислення ознак у реальному часі → запис в онлайн store. Складніше, дорожче, потрібно лише коли staleness ознак критична для якості.
Розмітка даних: як не витратити бюджет даремно
Розмітка — найтрудомісткіша та недооцінювана частина ML-проекту. Погано розмічені дані не виправить жодна архітектура.
Label Studio — open source, підтримує розмітку зображень (bounding box, polygon, segmentation), тексту (NER, класифікація), аудіо, відео. Піднімається за 10 хвилин через Docker. Для невеликих команд — перший вибір.
Оцінка якості розмітки. Inter-annotator agreement — наскільки згодні розмітники між собою. Cohen's Kappa > 0.8 — добре, 0.6–0.8 — прийнятно, < 0.6 — завдання неоднозначне або інструкція погана. Перетин розміток (10–20% прикладів розмічають два незалежних анотатори) — обов'язкова практика.
Active learning. Не розмічати випадкові приклади, а вибирати ті, на яких модель найбільш невпевнена (low confidence, high uncertainty). Дозволяє досягти тієї ж якості при 50–70% обсягу розмітки. Modals, Prodigy, Label Studio підтримують active learning workflows. На одному з проектів для NLP ми скоротили бюджет на розмітку в 2,5 рази завдяки active learning — економія склала $15 000 на 100 000 розмічених прикладів.
Синтетичні дані. Коли реальних даних мало або отримати їх дорого. Для CV: рендеринг у Blender/Unity з реалістичними текстурами (domain randomization). Для NLP: parafrase через LLM, backtranslation. Ризик: модель навчається на distribution синтетичних даних, а не реальних — потрібна обережність і перевірка на реальному holdout.
Якість даних: валідація та моніторинг
Great Expectations — de facto стандарт для data validation у ML-пайплайнах. Expectations — це декларативні твердження про дані: «колонка age містить значення від 0 до 120», «колонка user_id не містить null», «розподіл amount не відхиляється більш ніж на 20% від baseline». Запускається в пайплайні, при провалі — блокує проходження.
Pandera — Pythonic alternative для pandas/polars DataFrames. Schema-based validation з type hints:
import pandera as pa
schema = pa.DataFrameSchema({
"user_id": pa.Column(int, nullable=False),
"score": pa.Column(float, pa.Check.between(0, 1)),
"label": pa.Column(str, pa.Check.isin(["positive", "negative", "neutral"])),
})
Data freshness. Модель очікує дані за останні N днів. ETL впав, дані не оновилися — модель використовує застарілі ознаки. Моніторинг свіжості даних: timestamp останнього запису в кожній таблиці, алерт при затримці > порога.
Дедуплікація. Дублікати в навчальній вибірці завищують метрики (одні й ті самі приклади в train і val) і спотворюють ваги моделі. MinHash LSH для наближеної дедуплікації великих датасетів. Для точної — хеш за нормалізованим контентом.
| Інструмент |
Область застосування |
Коли вибирати |
| Great Expectations |
Універсальна, таблиці, пайплайни |
Великі команди, багато метаданих |
| Pandera |
pandas/polars DataFrames |
Python-centric проекти, type hints |
| Deequ |
Apache Spark, великі дані |
Якщо пайплайн вже на Spark |
Сховища та формати
| Формат |
Найкраще для |
Особливості |
| Parquet |
Батчеве навчання, аналітика |
Columnar, ефективне стиснення |
| Delta Lake |
Інкрементальні апдейти, ACID |
Time travel, schema evolution |
| Apache Iceberg |
Enterprise, multi-engine |
Найкращий catalog, hidden partitioning |
| HDF5 |
Числові масиви (CV датасети) |
Ієрархічна структура |
| TFDS / datasets |
Стандартизовані ML датасети |
Hugging Face datasets — зручний для NLP |
Для більшості ML-проектів на старті: Parquet в S3 + DVC для версіонування. Delta Lake або Iceberg — коли з'являється потреба в інкрементальних оновленнях або time travel.
Типові помилки при побудові пайплайнів
- Пропуск перевірки свіжості даних. Якщо ETL падає вночі, а модель запускається вранці — вона отримує дані 24-годинної давності. Рішення: алерт при затримці > 30 хвилин.
- Відсутність версіонування даних. Не можна відтворити експеримент, бо дані змінилися. DVC або Delta Lake time travel виправляють це.
- Забувають про schema evolution. Нове поле з’являється, а пайплайн падає. Автоматичне виявлення змін схеми через Great Expectations.
Active learning дозволяє скоротити бюджет на розмітку до 50–70%. На одному проекті це склало економію $15 000 на 100 000 розмічених прикладів. Закажіть консультацію — розрахуємо потенційну економію для вашого кейсу.
Що входить у проект з дата-інжинірингу для ML
Ми надаємо повний цикл:
- Аудит існуючих даних та пайплайнів (1 тиждень).
- Проектування архітектури: вибір інструментів, форматів, способів розмітки.
- Реалізація ETL/ELT пайплайну з валідацією та моніторингом.
- Документація коду та процесів (model card, data card).
- Навчання вашої команди роботі з пайплайном.
- SLA на супровід та підтримку.
Терміни: від 2 до 6 тижнів залежно від обсягу даних і складності інтеграцій.
Як ми будуємо пайплайн: покроково
-
Аудит існуючих даних. Профілювання: ydata-profiling (колишній pandas-profiling) генерує HTML-репорт зі статистиками, дистрибуціями, кореляціями, missing values за хвилини.
-
Проектування пайплайну. Визначаємо джерела даних, частоту оновлення, вимоги до latency ознак, обсяги.
-
Реалізація та тестування. Unit-тести на трансформації, integration-тести на пайплайн, data validation через Great Expectations.
-
Деплой та моніторинг. Алерти на freshness, quality checks, аномалії в обсягах даних.
Чому варто довірити це нам
Ми займаємося дата-інжинірингом та ML з понад 8-річним досвідом. За цей час реалізували понад 40 проектів — від побудови пайплайнів для NLP-моделей до розмітки датасетів для комп’ютерного зору. Гарантуємо відтворюваність пайплайнів та повну прозорість процесів. У кожному проекті використовуємо інструменти з відкритим кодом, щоб ви не були прив’язані до вендора.
Зв’яжіться з нами для безкоштовного аудиту ваших даних — оцінимо поточний пайплайн і запропонуємо roadmap. Замовте побудову ML-пайплайну під ключ.