TL;DR
Зацикливание (repetition problem) — ситуация, когда LLM начинает генерировать повторяющийся контент и не может остановиться, продолжая до лимита токенов. Исследователи из Shenzhen Sunline выявили три паттерна: (1) повторение похожих правил ("если А, то Б... если А, то Б..."), (2) повторение одного и того же имени метода в анализе кода, (3) повторение закрывающих конструкций в синтаксисе диаграмм.
Проблема возникает из-за эффекта самоусиления: когда модель сгенерировала паттерн один раз, вероятность его повторения растёт. Greedy decoding (стандартная стратегия выбора токенов) усугубляет ситуацию — модель идёт по одному пути, а не исследует альтернативы, поэтому не может выбраться из петли. В реальных задачах это увеличивало время обработки на 43-471% (с 28 минут до 40-160 минут).
Исследователи протестировали три решения: Beam Search (multi-path декодирование) решает все три типа зацикливания, но недоступен в ChatGPT/Claude через UI. presence_penalty — параметр API OpenAI, который штрафует повторяющиеся токены — эффективен для первого типа зацикливания и доступен читателю. DPO fine-tuning решает все типы, но требует GPU и обучения модели.
Схема проблемы и решений
ПРОБЛЕМА: Зацикливание
├─ Паттерн 1: Повторение правил
├─ Паттерн 2: Повторение названий
└─ Паттерн 3: Повторение синтаксиса
РЕШЕНИЯ:
├─ Beam Search + early_stopping=True (API вроде vLLM)
│ └─ Работает: для всех 3 паттернов
│ └─ Доступность: только специализированные API
│
├─ presence_penalty (OpenAI API)
│ └─ Работает: только для паттерна 1
│ └─ Доступность: OpenAI API, ChatGPT API
│
└─ DPO fine-tuning
└─ Работает: для всех 3 паттернов
└─ Доступность: требует GPU, код, обучение
Пример применения
Ограничения метода: presence_penalty работает только для паттерна 1 (повторение похожих структур), не подходит для паттернов 2-3 (повторение одного слова, синтаксических элементов).
Задача: Генерируешь правила валидации для формы заявки на кредит через OpenAI API. Модель начинает зацикливаться, выдавая десятки похожих условий "если возраст < 18, отклонить... если возраст < 21, отклонить... если возраст < 25, отклонить...".
API запрос (Python с библиотекой openai):
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "user", "content": "Сгенерируй список правил валидации для формы заявки на кредит. Включи проверки возраста, дохода, кредитной истории."}
],
presence_penalty=1.2, # Штрафует повторение уже упомянутых концепций
temperature=0.7
)
Результат: Модель выдаст разнообразные правила по разным аспектам (возраст, доход, история, документы), не зацикливаясь на одном типе проверок. Каждое правило касается нового аспекта, а не вариаций одной темы.
Почему это работает
Слабость LLM: Greedy decoding (стандартная стратегия) выбирает самый вероятный токен на каждом шаге. Когда модель сгенерировала паттерн один раз, этот паттерн появляется в контексте. Модель учится копировать из недавней истории — вероятность повторения растёт с каждым повтором. Это эффект самоусиления: чем больше повторений, тем выше вероятность следующего. Greedy decoding идёт по одному пути, поэтому не может выбраться из петли.
Сильная сторона LLM: Модель хорошо оценивает контекст и распределяет вероятности между токенами. Если ввести штраф за повторение уже упомянутых токенов, модель пересчитает вероятности — теперь новые концепции станут предпочтительнее повторов.
Механика presence_penalty: Параметр снижает вероятность токенов, которые уже появились в сгенерированном тексте. Значение 1.2 — умеренный штраф, который не ломает связность, но делает повторы менее привлекательными. Модель "видит" что концепт "возраст" уже использован → ищет другие аспекты (доход, история). Это разрывает цикл самоусиления на уровне декодирования.
Рычаги управления:
- Сила штрафа (0.0 - 2.0): увеличь до 1.5-2.0 для агрессивной борьбы с повторами, уменьши до 0.5-0.8 если модель теряет связность
- temperature: при temperature=0 (детерминистика) зацикливание сильнее — модель всегда выбирает топ-1. Подними до 0.7-1.0 для разнообразия
- Комбинируй с frequency_penalty (штрафует частоту повторения токена): presence_penalty = "упоминал ли вообще?", frequency_penalty = "сколько раз упоминал?"
Ограничение: Работает только для паттерна 1 (повторение похожих структур). Если модель зацикливается на одном слове (паттерн 2) или на синтаксической конструкции (паттерн 3) — presence_penalty не спасёт, нужен Beam Search или fine-tuning.
Шаблон API запроса (OpenAI)
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "user", "content": "{твоя_задача_генерации}"}
],
presence_penalty=1.2, # Штраф за повторение концепций
frequency_penalty=0.3, # Опционально: штраф за частоту
temperature=0.7, # Добавляет разнообразие
max_tokens=1000 # Ограничение на случай зацикливания
)
print(response.choices[0].message.content)
Подстановка:
- {твоя_задача_генерации} — задача где модель может зациклиться на похожих структурах (списки правил, перечисления, классификации)
Диапазоны:
- presence_penalty: 0.0 (нет штрафа) → 2.0 (максимум). Старт с 1.0-1.2, увеличивай если зацикливается
- frequency_penalty: 0.0 → 2.0. Комбинируй с presence для усиления
- temperature: 0.7-1.0 для креативных задач, 0.3-0.5 для точных
Ограничения
⚠️ Только паттерн 1:
presence_penaltyэффективен только для зацикливания на похожих структурах (правила, условия, перечисления). Не работает для паттернов 2 (повторение одного слова) и 3 (повторение синтаксиса).
⚠️ Только OpenAI API: Claude API не имеет параметра
presence_penalty. Доступны толькоtemperatureиtop_p.
⚠️ Требуется API доступ: Решение не работает в UI ChatGPT/Claude. Нужно делать запросы через API (Python, curl, Postman).
⚠️ Балансировка связности: Слишком высокий
presence_penalty(>1.5) может сломать логическую связность — модель будет избегать нужных повторений терминов.
⚠️ Не универсальное решение: Beam Search (недоступен в OpenAI/Claude) решает все типы зацикливания.
presence_penalty— частичное решение для одного паттерна.
Как исследовали
Исследователи из Shenzhen Sunline столкнулись с проблемой в production: система batch-обработки финансовых транзакций зависала. Вместо 28 минут обработка занимала 40-160 минут в 75-80% запусков.
Анализ логов показал: модель зацикливается на генерации повторяющегося контента, продолжая до лимита max_tokens. Выявили три паттерна:
1. Генерация бизнес-правил — корректные правила, затем петля похожих условий
2. Анализ вызовов методов — корректные связи, затем повтор одного имени
3. PlantUML диаграммы — валидный код, затем повтор закрывающих конструкций
Теоретический анализ через Markov-модели показал: в greedy decoding вероятность повторения растёт с каждым повтором (self-reinforcement). Модель не может выбраться без внешнего вмешательства.
Эксперименты:
- Beam Search с параметром early_stopping=True — 0% зацикливаний на всех паттернах
- Beam Search с early_stopping=False — 60% зацикливаний (ключевая находка!)
- presence_penalty=1.2 — эффективен для паттерна 1, не работает для 2-3
- DPO fine-tuning (4×A100, 15-18 GPU-часов) — решает все паттерны на уровне модели
Ключевой инсайт: параметр early_stopping=True в Beam Search — не опция, а критическое требование. Без него Beam Search не решает проблему.
Ресурсы
Статья: "Solving LLM Repetition Problem in Production: A Comprehensive Study of Multiple Solutions"
Авторы: Weiwei Wang, Weijie Zou, Jiyong Min · Shenzhen Sunline Tech Co., Ltd
Связанные работы: - "Learning to break the Loop: Analyzing and Mitigating Repetitions for Neural Text Generation" — базовая работа про repetition problem - vLLM framework documentation — параметры Beam Search - LlamaFactory — фреймворк для DPO fine-tuning
OpenAI API документация: Параметры presence_penalty и frequency_penalty для контроля повторений
