Таксономия дрейфа LLM: классификация изменений поведения языковых моделей | AiManual
AiManual Logo Ai / Manual.
19 Янв 2026 Гайд

Таксономия дрейфа LLM: как отличить контекстную вариацию от реального изменения поведения модели

Практическое руководство по диагностике дрейфа LLM. Учимся отличать контекстные вариации от системных изменений модели с помощью новой таксономии.

Когда модель сходит с ума: проблема, которую все игнорируют

Вы запускаете тот же промпт. На той же модели. С теми же параметрами. А ответ другой. Иногда чуть-чуть другой - синоним поменялся. Иногда кардинально - вместо "да" получаете "нет". Иногда модель просто начинает генерировать бред, которого раньше не было.

Это не баг. Это дрейф. И он убивает воспроизводимость экспериментов, ломает продакшен-системы и заставляет исследователей тратить недели на поиск несуществующих ошибок в коде.

Самый опасный дрейф - тот, который вы не замечаете. Модель медленно деградирует, качество падает на 2-3% в месяц, а вы списываете это на "статистическую погрешность" или "особенности датасета". Через полгода система работает вполсилы, но никто не понимает почему.

Почему существующие метрики не работают

BLEU, ROUGE, точность, F1-мера - все эти метрики измеряют что угодно, только не дрейф. Они сравнивают текст с эталоном, но не отвечают на главный вопрос: почему ответ изменился?

Может, это случайная вариация из-за температуры? Может, контекст переполнился и модель "забыла" инструкцию? Может, в новой версии модели действительно что-то сломали?

Без ответа на этот "почему" вы просто фиксируете факт изменения. Как врач, который говорит "у вас температура", но не проверяет, грипп это или солнечный удар.

💡
В статье "Interpretation Drift" мы уже касались этой проблемы, но там речь шла о временных изменениях. Сейчас нужна системная классификация - таксономия, которая разделит симптомы по причинам.

Таксономия дрейфа: четыре оси изменений

Новая таксономия (опубликована на Zenodo) предлагает смотреть на дрейф по четырем независимым осям. Не "есть дрейф/нет дрейфа", а "какой именно дрейф и насколько он опасен".

Тип дрейфа Что меняется Как обнаружить Опасность
Контекстная вариация Формулировка, стиль, синонимы Семантическое сходство > 0.9 Низкая
Поведенческий сдвиг Логика, решение, вывод Семантическое сходство < 0.7 Высокая
Систематический дрейф Качество по всем промптам Статистика по бенчмарку Критическая
Стохастическая нестабильность Непредсказуемые изменения Высокий std между запусками Средняя

1 Диагностика: что у вас на самом деле

Прежде чем паниковать, нужно понять тип дрейфа. Возьмите 50-100 промптов из вашего рабочего набора. Запустите их на "старой" версии системы (или на контрольной модели). Запустите на "новой". Не сравнивайте тексты - сравнивайте семантические ядра.

# Минимальный пример диагностики
from sentence_transformers import SentenceTransformer
import numpy as np

model = SentenceTransformer('all-MiniLM-L6-v2')

# Ответы от двух версий модели
answers_v1 = ["Да, это правильное решение.", "Нет, это ошибка.", ...]
answers_v2 = ["Да, это верное решение.", "Нет, это неверно.", ...]

# Эмбеддинги
embeddings_v1 = model.encode(answers_v1)
embeddings_v2 = model.encode(answers_v2)

# Косинусное сходство для каждой пары
similarities = []
for emb1, emb2 in zip(embeddings_v1, embeddings_v2):
    sim = np.dot(emb1, emb2) / (np.linalg.norm(emb1) * np.linalg.norm(emb2))
    similarities.append(sim)

# Анализ распределения
mean_sim = np.mean(similarities)
std_sim = np.std(similarities)

print(f"Среднее сходство: {mean_sim:.3f}")
print(f"Стандартное отклонение: {std_sim:.3f}")

if mean_sim > 0.9 and std_sim < 0.1:
    print("Вероятно, контекстная вариация")
elif mean_sim < 0.7:
    print("Вероятно, поведенческий сдвиг")
elif std_sim > 0.2:
    print("Вероятно, стохастическая нестабильность")

Это базовая диагностика. Она не идеальна, но отделяет реальные проблемы от статистического шума.

Не используйте BLEU/ROUGE! Они ломаются на синонимах и перефразированиях. Модель может дать идеально правильный ответ другими словами, а метрика покажет "низкое качество".

2 Глубокая проверка: ищем системные изменения

Если диагностика показала поведенческий сдвиг или системный дрейф - нужно копать глубже. Потому что разница может быть в:

  • Контекстном окне - модель "теряет" информацию в середине длинного контекста (помните Lost in the Middle?)
  • Температуре и seed - банальная случайность, которую забыли зафиксировать
  • Форматировании промпта - лишний пробел, другой шаблон
  • Реальном изменении весов - кто-то обновил модель и сломал логику

Создайте контрольные группы промптов:

  1. Короткие фактологические вопросы (проверка базовых знаний)
  2. Логические задачи с однозначным ответом
  3. Творческие задания с субъективной оценкой
  4. Промпты с длинным контекстом (10к+ токенов)

Запустите каждую группу отдельно. Если дрейф только в длинных контекстах - проблема в attention механизме. Если во всех группах - что-то сломано фундаментально.

Особый случай: дрейф в RAG-системах

В RAG дрейф может быть в трех местах одновременно: в модели, в эмбеддерах, в поиске. И самое мерзкое - они маскируют друг друга.

Модель начинает генерировать чуть более развернутые ответы → эмбеддер ищет другие фрагменты → качество падает на 15% → вы думаете, что сломался векторный поиск → начинаете его оптимизировать → на самом деле проблема была в температуре генерации.

Протокол проверки для RAG:

# Изолируем компоненты RAG

def test_retriever_only(query, documents):
    """Тестируем только поиск, без генерации"""
    # Фиксируем эмбеддинги запроса и документов
    # Сравниваем топ-N результатов между версиями
    return retrieval_similarity

def test_generator_only(context, query):
    """Тестируем только генерацию, с фиксированным контекстом"""
    # Даем модели одинаковый контекст
    # Сравниваем ответы
    return generation_similarity

def test_full_rag(query, documents):
    """Тестируем полный цикл"""
    # Полный RAG pipeline
    return answer_similarity

# Если падает только full_rag - проблема во взаимодействии
# Если падает generator_only - дрейф в LLM
# Если падает retriever_only - дрейф в эмбеддерах
💡
В RAG-чатботах для корпоративных знаний дрейф особенно опасен - модель может начать "галлюцинировать" факты из устаревших документов или неправильно интерпретировать политики компании.

Практические ловушки: где ошибаются даже опытные

Я видел команды, которые месяц искали "дрейф модели", а проблема была в кэше GPU. Или в том, что кто-то поменял версию CUDA. Или в том, что модель начали запускать на другом типе GPU (A100 vs H100 - разная числовая точность).

Чеклист перед тем, как диагностировать дрейф LLM:

  • Точная версия модели (хеш весов, не просто название)
  • Точная версия фреймворка (transformers, vLLM, etc)
  • Настройки квантования (если есть)
  • Тип GPU и драйверы
  • Параметры генерации (temperature, top_p, seed)
  • Шаблон чата (точно такой же формат)
  • Размер контекста и способ его заполнения

Пропустите один пункт - и будете искать несуществующий дрейф.

Самый частый источник "фантомного дрейфа" - разный seed. В продакшене seed часто не фиксируют (для разнообразия ответов). При тестировании используют seed=42. Модель с temperature=0.7 и разным seed дает разные ответы. Это не дрейф, это стохастичность.

Когда дрейф - это фича, а не баг

Иногда изменение поведения - это хорошо. Модель научилась лучше понимать контекст. Или стала менее токсичной. Или начала давать более развернутые объяснения.

Как отличить улучшение от деградации? Нужны человеческие оценщики и предметные метрики.

Пример: в финансовой аналитике (как у квантов) модель может начать добавлять disclaimer о рисках. По семантическому сходству ответы будут отличаться сильно. Но по качеству - улучшаться.

Решение: трехступенчатая оценка:

  1. Автоматическая проверка (семантическое сходство, точность)
  2. Предметная проверка (задача-специфичные метрики)
  3. Человеческая оценка (качество, полезность, безопасность)

Только если все три уровня покажут негативные изменения - это реальный дрейф, который нужно исправлять.

Инструменты и автоматизация

Вручную проверять дрейф на сотнях промптов - ад. Нужна автоматизация. Но готовых инструментов почти нет.

Базовый пайплайн мониторинга:

# Псевдокод системы мониторинга дрейфа
class DriftMonitor:
    def __init__(self, reference_model, test_model, prompts):
        self.reference = reference_model
        self.test = test_model
        self.prompts = prompts
        self.baseline = self._create_baseline()
    
    def _create_baseline(self):
        """Запускаем все промпты на референсной модели"""
        baseline_results = {}
        for prompt in self.prompts:
            answer = self.reference.generate(prompt)
            embedding = self._get_embedding(answer)
            baseline_results[prompt] = {
                'answer': answer,
                'embedding': embedding
            }
        return baseline_results
    
    def check_drift(self, threshold=0.8):
        """Проверяем дрейф относительно baseline"""
        drift_report = {
            'contextual_variation': [],
            'behavioral_shift': [],
            'systematic_drift': False
        }
        
        similarities = []
        for prompt in self.prompts:
            test_answer = self.test.generate(prompt)
            test_embedding = self._get_embedding(test_answer)
            
            baseline_embedding = self.baseline[prompt]['embedding']
            similarity = cosine_similarity(test_embedding, baseline_embedding)
            similarities.append(similarity)
            
            if similarity < threshold:
                # Анализируем тип расхождения
                if self._is_behavioral_shift(prompt, test_answer):
                    drift_report['behavioral_shift'].append(prompt)
                else:
                    drift_report['contextual_variation'].append(prompt)
        
        # Проверяем системный дрейф
        avg_similarity = np.mean(similarities)
        if avg_similarity < 0.7:
            drift_report['systematic_drift'] = True
        
        return drift_report

Такую систему нужно запускать регулярно: при каждом обновлении модели, изменении инфраструктуры, раз в неделю для мониторинга.

Что делать, если дрейф найден

Алгоритм действий:

  1. Не паниковать. 80% "дрейфов" оказываются контекстными вариациями или проблемами инфраструктуры.
  2. Изолировать проблему. Модель? Инфраструктура? Данные? Параметры?
  3. Воспроизвести на минимальном примере. Убрать все сложности, оставить один промпт.
  4. Сравнить с контрольной версией. Если есть старая версия модели/кода.
  5. Зафиксировать все параметры. Сделать снимок системы, который можно воспроизвести.
  6. Эскалировать правильно. Не "модель сломалась", а "на промптах типа X наблюдается поведенческий сдвиг с similarity 0.65, пример прилагаю".

Если дрейф системный и подтвержденный - нужно откатывать модель или исправлять промпты. Иногда помогает RLM-подход - заставить модель самой управлять контекстом. Иногда - переобучение на проблемных примерах.

💡
В статье "Модель на 99% в тестах, на 0% в продакшене" мы уже видели, как данные и время ломают ML-системы. Дрейф LLM - частный случай этой общей проблемы.

Прогноз: дрейф станет главной проблемой 2025

Сейчас все увлечены размером контекста, мультимодальностью, скоростью inference. Через год осознают: самая дорогая проблема - нестабильность.

Представьте: вы построили сложную агентскую систему на 10 моделях. Каждая обновляется раз в месяц. Каждая дрейфует по-своему. Система становится непредсказуемой. Отлаживать невозможно - ошибки плавающие.

Решение будет в:

  • Стандартизированных бенчмарках дрейфа (как GLUE для качества)
  • Версионировании не только моделей, но и их поведения
  • Автоматических систем мониторинга в реальном времени
  • Детерминированных режимах даже ценой креативности

Пока этого нет - используйте таксономию из этой статьи. Хотя бы понимайте, с каким типом дрейфа вы столкнулись. Это уже на 50% решает проблему.

И да, сохраняйте seed. Всегда.