English translation is not available yet. Showing Russian content.
Как вы делаете data quality для синтетических датасетов?
Краткий тезис
Качество синтетических датасетов критически важно для обучения и оценки RAG-систем и AI-агентов. Основные методы контроля качества включают LLM-as-judge для автоматической оценки примеров, self-consistency для проверки стабильности генерации, проверку на противоречия внутри датасета, human validation выборочной выборки и holdout для исключения пересечения с продакшен-данными. Комбинация этих подходов позволяет отсеять шум, повысить достоверность и избежать катастрофического забывания.
1. Термин: Синтетический датасет
Синтетический датасет — это набор данных, сгенерированный искусственно (обычно с помощью LLM), а не собранный из реальных пользовательских запросов. Он используется, когда реальных данных мало, они дороги в разметке или содержат чувствительную информацию.
Зачем нужен контроль качества
- LLM может генерировать галлюцинации (фактически неверные ответы).
- Модель может повторять одни и те же паттерны, снижая разнообразие (diversity).
- Синтетические данные могут быть несбалансированными (например, слишком много лёгких вопросов).
- Если синтетика похожа на продакшен-данные, оценка на ней будет смещённой (overly optimistic).
Основные риски
- Шум (noise): нерелевантные или некорректные пары вопрос-ответ.
- Противоречия (contradictions): один и тот же факт описан по-разному.
- Утечка (leakage): синтетические примеры совпадают с тестовыми данными.
2. LLM-as-judge (Оценка с помощью LLM)
LLM-as-judge — это подход, при котором отдельная LLM (обычно более мощная, например GPT-4 или Claude) оценивает качество каждого сгенерированного примера по заданным критериям.
Процесс
- Для каждой пары (вопрос, ответ, контекст) отправляем запрос к judge-модели.
- Judge ставит оценку по шкале, например от 1 до 10, по критериям:
- Полезность (helpfulness): отвечает ли ответ на вопрос?
- Фактологическая точность (factual accuracy): соответствует ли ответ контексту?
- Читаемость (readability): понятен ли язык?
- Отбрасываем примеры с оценкой ниже порога (например, < 7).
Пример промпта для judge
Оцените качество следующего примера для RAG-датасета по шкале 1-10.
Критерии: ответ должен быть полезным, точным и соответствовать контексту.
Вопрос: {question}
Контекст: {context}
Ответ: {answer}
Оценка (только число):
Преимущества
- Автоматизация, масштабируемость.
- Можно адаптировать под домен.
Недостатки
- Judge-модель может быть предвзятой (bias).
- Дорого (call|вызовы API).
Рекомендации
- Использовать несколько judge-моделей и усреднять оценку.
- Калибровать порог на небольшой выборке, проверенной человеком.
3. Self-consistency (Самосогласованность)
Self-consistency — метод, при котором на один и тот же вопрос генерируется несколько ответов (например, 3–5) с разной температурой или разными seed. Затем оценивается согласованность (agreement) между ответами.
Метрики согласованности
- ROUGE-L или BLEU между парами ответов.
- BERTScore (семантическая близость).
- Процент совпадения ключевых фактов (если ответы структурированы).
Правило отбора
- Если согласованность низкая (например, средний BERTScore < 0.85), пример считается ненадёжным и отбрасывается.
- Если ответы сильно различаются, это может указывать на неоднозначность вопроса или нестабильность генерации.
Пример кода
from sentence_transformers import SentenceTransformer, util
model = SentenceTransformer('all-MiniLM-L6-v2')
def self_consistency_score(answers):
embeddings = model.encode(answers)
similarities = []
for i in range(len(answers)):
for j in range(i+1, len(answers)):
sim = util.cos_sim(embeddings[i], embeddings[j]).item()
similarities.append(sim)
return sum(similarities) / len(similarities)
answers = ["Ответ A", "Ответ B", "Ответ C"]
score = self_consistency_score(answers)
if score < 0.8:
print("Пример нестабилен, отбрасываем")
4. Проверка на противоречия (Contradiction Detection)
Внутри датасета не должно быть примеров, где один и тот же факт описан по-разному. Например, вопрос "Какова столица Франции?" в одном примере имеет ответ "Париж", а в другом — "Лион".
Методы
- Семантическая кластеризация: группируем вопросы по эмбеддингам, внутри кластера проверяем ответы на противоречия.
- LLM-based проверка: для каждой пары (вопрос1, ответ1) и (вопрос2, ответ2) с высокой семантической близостью вопросов judge-модель определяет, противоречат ли ответы друг другу.
- Правила на основе NER: если в ответах разные сущности на одно и то же место, это подозрительно.
Пример:
from sklearn.cluster import DBSCAN
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
questions = ["Столица Франции?", "Какой город является столицей Франции?"]
embeddings = model.encode(questions)
clustering = DBSCAN(eps=0.5, min_samples=2).fit(embeddings)
# Если вопросы в одном кластере, проверяем ответы на противоречия
Порог если доля противоречивых пар в кластере > 5%, кластер перегенерируется или удаляется.
5. Human validation (Валидация человеком)
Полная ручная проверка всех синтетических примеров невозможна из-за стоимости. Поэтому используется выборочная проверка (sampling).
Процесс
- Случайно отбираем 5–10% датасета.
- Аннотаторы (или команда) оценивают каждый пример по шкале:
- Accept (принять) — пример корректен.
- Reject (отклонить) — пример содержит ошибку.
- Fix (исправить) — пример можно доработать.
- Считаем метрики:
- Acceptance rate (доля принятых).
- Inter-annotator agreement (согласие между аннотаторами, Cohen's Kappa).
- Если acceptance rate < 80%, пересматриваем процесс генерации или увеличиваем выборку.
Совет Использовать платформы вроде Label Studio или Prodigy для разметки.
6. Holdout и семантическое пересечение (Semantic Similarity Check)
Holdout — это отложенный набор реальных данных (production), который не используется при генерации синтетики. Необходимо убедиться, что синтетические примеры не пересекаются с holdout, иначе оценка на holdout будет завышена.
Метод
- Берём все синтетические вопросы и все вопросы из holdout.
- Вычисляем семантическую близость (cosine similarity эмбеддингов) между каждой парой.
- Если для какого-то синтетического вопроса находится holdout-вопрос с similarity > 0.9, такой синтетический пример удаляем (или переформулируем).
Инструменты
- Sentence Transformers для эмбеддингов.
- FAISS или Annoy для быстрого поиска ближайших соседей.
Пример:
import faiss
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
synth_questions = [...] # список синтетических вопросов
holdout_questions = [...] # список продакшен-вопросов
synth_emb = model.encode(synth_questions)
holdout_emb = model.encode(holdout_questions)
index = faiss.IndexFlatIP(holdout_emb.shape[1])
index.add(holdout_emb)
D, I = index.search(synth_emb, k=1) # ближайший сосед
max_sim = D.max()
if max_sim > 0.9:
print("Есть пересечение, нужно удалить или переформулировать")
7. Дополнительные методы контроля качества
7.1 Проверка формата (Format Validation)
- Убедиться, что ответы соответствуют ожидаемой структуре (JSON, Markdown, таблица).
- Использовать pydantic или JSON Schema для валидации.
7.2 Фактологическая точность (Factual Accuracy)
- Если контекст известен (например, из базы знаний), можно проверить, что ответ не противоречит контексту.
- Использовать NLI-модели (Natural Language Inference) для проверки entailment/contradiction.
7.3 Разнообразие (Diversity)
- Измерить внутрикластерное расстояние между вопросами. Если все вопросы слишком похожи, датасет нерепрезентативен.
- Использовать intra-list similarity (средняя попарная косинусная близость). Порог: < 0.6.
7.4 Баланс классов (Class Balance)
- Для задач классификации или генерации с метками проверить распределение меток. Если какой-то класс составляет < 5%, добавить примеров.
8. Инструменты и пайплайн (пример на Python)
Ниже — пример пайплайна контроля качества синтетического датасета.
import pandas as pd
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
class SyntheticDataQuality:
def __init__(self, judge_model_name='gpt-4', threshold_judge=7, threshold_consistency=0.8):
self.judge_model = judge_model_name # для LLM-as-judge
self.threshold_judge = threshold_judge
self.threshold_consistency = threshold_consistency
self.embedder = SentenceTransformer('all-MiniLM-L6-v2')
def llm_judge(self, question, context, answer):
# вызов LLM (упрощённо)
score = 8 # заглушка
return score
def self_consistency(self, question, n=3):
# генерация n ответов (заглушка)
answers = [f"answer_{i}" for i in range(n)]
emb = self.embedder.encode(answers)
sim_matrix = cosine_similarity(emb)
avg_sim = (sim_matrix.sum() - n) / (n * (n-1))
return avg_sim
def check_contradictions(self, df, eps=0.5):
# кластеризация вопросов
emb = self.embedder.encode(df['question'].tolist())
from sklearn.cluster import DBSCAN
clusters = DBSCAN(eps=eps, min_samples=2).fit_predict(emb)
df['cluster'] = clusters
contradictions = []
for cluster_id in set(clusters):
if cluster_id == -1:
continue
cluster_df = df[df['cluster'] == cluster_id]
if len(cluster_df) < 2:
continue
# здесь можно вызвать LLM для проверки противоречий
return contradictions
def run_pipeline(self, df_synthetic, holdout_questions=None):
# 1. LLM-as-judge
scores = []
for _, row in df_synthetic.iterrows():
score = self.llm_judge(row['question'], row['context'], row['answer'])
scores.append(score)
df_synthetic['judge_score'] = scores
df_synthetic = df_synthetic[df_synthetic['judge_score'] >= self.threshold_judge]
# 2. Self-consistency
consistency_scores = []
for q in df_synthetic['question']:
cs = self.self_consistency(q)
consistency_scores.append(cs)
df_synthetic['consistency'] = consistency_scores
df_synthetic = df_synthetic[df_synthetic['consistency'] >= self.threshold_consistency]
# 3. Проверка на противоречия (упрощённо)
contradictions = self.check_contradictions(df_synthetic)
# удаляем проблемные строки
# 4. Holdout check
if holdout_questions is not None:
holdout_emb = self.embedder.encode(holdout_questions)
synth_emb = self.embedder.encode(df_synthetic['question'].tolist())
sim = cosine_similarity(synth_emb, holdout_emb)
max_sim = sim.max(axis=1)
df_synthetic = df_synthetic[max_sim < 0.9]
# 5. Human validation (выборка)
sample = df_synthetic.sample(frac=0.05)
# отправить на ручную проверку
return df_synthetic
9. Метрики качества датасета
После фильтрации полезно посчитать итоговые метрики:
| Метрика | Описание | Целевое значение |
|---|---|---|
| Acceptance rate | Доля примеров, прошедших все автоматические проверки | > 80% |
| Human acceptance rate | Доля принятых человеком в выборке | > 90% |
| Average judge score | Средняя оценка LLM-as-judge | > 7.5 |
| Consistency score | Средняя самосогласованность | > 0.85 |
| Contradiction rate | Доля противоречивых пар в кластерах | < 2% |
| Max similarity to holdout | Максимальная семантическая близость к продакшену | < 0.85 |
Пет-проект для закрепления
Задача Разработать пайплайн контроля качества для синтетического датасета вопросов-ответов по документации библиотеки LangChain.
Инструменты
- Python, pandas, sentence-transformers, faiss.
- LLM API (OpenAI или локальная модель через Ollama).
- Streamlit для визуализации результатов.
Шаги:
- Сгенерировать 500 синтетических примеров с помощью GPT-4 (вопрос, контекст, ответ).
- Реализовать модуль LLM-as-judge (использовать GPT-4-mini для оценки).
- Реализовать self-consistency (3 генерации на вопрос, BERTScore).
- Реализовать проверку на противоречия (кластеризация + LLM).
- Взять 50 реальных вопросов из чата поддержки LangChain как holdout, проверить пересечение.
- Отобрать 10% для ручной проверки (можно самому).
- Посчитать итоговые метрики и построить дашборд в Streamlit.
Ожидаемый результат Пайплайн, который принимает сырой CSV с синтетическими данными и возвращает отфильтрованный датасет с отчётом о качестве (доля отбракованных примеров, средние оценки, список проблемных кластеров).
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 533 | Как генерировать синтетические данные для обучения RAG? |
| 535 | Как оценивать качество работы AI-агента? |
| 536 | Как тестировать agentic RAG-систему? |
| 537 | Как деплоить agentic RAG-систему? |
| 538 | Как мониторить agentic RAG-систему? |
| 5 | Как оценивать качество retrieval'а в RAG? |
Навигация
- Предыдущий: 533
- Следующий: 535
- Индекс: 00. Индекс разборов