TL;DR
CAPEL (Can LLMs Track Their Output Length) — метод, который вставляет счётчик длины прямо в процесс генерации текста. После каждого предложения модель видит feedback-строку типа <использовано_слов=87> и корректирует дальнейший вывод, чтобы попасть в заданный лимит.
Исследователи обнаружили парадокс: LLM умеют считать слова в чужом тексте, но теряют счёт в своём собственном. Чем длиннее генерация, тем хуже оценка. Для текста 50-150 токенов модели ошибаются в среднем на 30 токенов, для 250-350 — уже на 90. Когда просишь "напиши 300 слов", получаешь то 250, то 370. Причина: модель фокусируется на содержании, а не на подсчёте. Она не держит в "голове" точный счётчик — работает как человек, который пишет текст без редактора.
CAPEL решает это внешним инструментом: прерывает генерацию на границах предложений, вставляет точную цифру (токены/слова/предложения), продолжает. Модель видит "уже 87 слов из 150" → понимает что осталось 63 → подстраивает темп и объём. Метод работает training-free (без дообучения) и улучшается после простого SFT на примерах с feedback.
Схема метода
Training-free (один запрос, но с прерываниями):
ШАГ 1: Промпт с инструкцией + целевая длина
↓
ШАГ 2: Генерация до конца предложения
↓
ШАГ 3: Вставка feedback: <использовано_слов=N>
↓
ШАГ 4: Продолжение генерации → повтор шагов 2-3
↓
РЕЗУЛЬТАТ: Текст точной длины
Примечание: В обычном чате прерывания делаешь вручную. Через API можно автоматизировать.
Пример применения
Задача: Написать описание квартиры для Авито — ровно 150 слов (лимит для премиум-размещения без обрезки).
Промпт:
Напиши описание двухкомнатной квартиры в Москве (Сокол, 5 минут от метро,
56 кв.м., 8 этаж, кирпичный дом, евроремонт, цена 18 млн рублей).
ТРЕБОВАНИЕ: Ровно 150 слов.
Во время генерации я буду давать тебе feedback о текущей длине в формате
<использовано_слов=N>. Используй эту информацию, чтобы попасть точно в цель.
Начинай:
(После каждого 2-3 предложений останавливаешь генерацию, считаешь слова вручную
или через сервис, вставляешь: <использовано_слов=47>, продолжаешь)
Результат:
Модель будет генерировать описание порциями. После каждого feedback она скорректирует темп: если слов мало — развернёт детали (ремонт, планировка, инфраструктура), если близко к лимиту — свернёт к итогу. Финальный текст попадёт в диапазон 145-155 слов вместо обычных "то 120, то 180".
Почему это работает
LLM не умеют держать счётчик в голове во время генерации. Attention-механизм фокусируется на смысле следующего токена, а не на подсчёте предыдущих. Чем длиннее текст, тем сильнее накапливается ошибка оценки — как у человека, который пишет без редактора и примерно чувствует "ещё пару абзацев".
Зато LLM отлично следуют явным инструкциям и обрабатывают структурированный input. Счётчик <использовано_слов=87> — это чёткий сигнал, который модель интерпретирует как "прогресс выполнения задачи". Она видит разрыв между текущим (87) и целевым (150) значением → регулирует подробность и объём следующей части.
Feedback вставляется на границах предложений — это сохраняет естественный flow текста. Модель не ломает мысль посередине, а получает update в "безопасной точке".
Рычаги управления:
- Частота feedback: Вставляй после каждого предложения (максимальная точность) или каждые 2-3 (быстрее, но менее точно). Для коротких текстов (до 100 слов) хватит 2-3 вставок.
- Тип длины: Замени
<использовано_слов=N>на<использовано_токенов=N>или<использовано_предложений=N>под свою задачу. - Толеранс: В промпте можно указать "±5 слов допустимо" — модель будет мягче завершать.
Шаблон промпта
Задача: {опиши задачу}.
ТРЕБОВАНИЕ: Ровно {число} {слов/токенов/предложений}.
Во время генерации я буду давать тебе feedback о текущей длине в формате
<использовано_{слов/токенов/предложений}=N>. Используй эту информацию,
чтобы точно попасть в целевую длину.
Начинай:
Что подставлять:
- {опиши задачу} — конкретная задача с контекстом
- {число} — целевая длина (100, 250, 15...)
- {слов/токенов/предложений} — выбери единицу измерения
После каждого 1-3 предложений:
1. Останови генерацию
2. Посчитай длину (вручную, через сервис подсчёта слов, или попроси другой чат LLM: "Сколько слов в этом тексте: [вставь текст]")
3. Вставь: <использовано_слов=N>
4. Продолжи генерацию
🚀 Быстрый старт — вставь в чат:
Вот шаблон CAPEL для точного контроля длины. Адаптируй под мою задачу: [твоя задача].
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM спросит целевую длину, единицу измерения (слова/токены/предложения), детали задачи — потому что метод требует точной формулировки требований. Она возьмёт паттерн из шаблона и адаптирует под твою задачу.
Ограничения
⚠️ Ручные прерывания в чате: Без API нужно вручную останавливать генерацию, считать слова, вставлять feedback. Это 3-5 итераций для текста 150-300 слов — занимает 2-3 минуты.
⚠️ Конфликт с качеством на открытых вопросах: На задачах где важен точный ответ фиксированной длины (например, "объясни квантовую физику ровно в 100 словах"), training-free версия может "дотягивать" до лимита за счёт воды. SFT-версия решает проблему.
⚠️ Эффективность зависит от модели: Более сильные модели (8B vs 4B параметров) лучше интерпретируют feedback и дают точнее результат. На слабых моделях улучшение есть, но меньше.
Как исследовали
Команда из Xiamen University и Alibaba проверила гипотезу в три этапа. Сначала взяли 1000 текстов разной длины (100-400 токенов) от трёх моделей (LLaMA-3.1-8B, Qwen3-4B, Qwen3-8B) и попросили модели оценить длину своего же вывода. Результат удивил: ошибка растёт линейно с длиной. Для коротких текстов (50-150 токенов) MAE ~30, для длинных (350-450) — уже ~90 токенов. То есть модель, сгенерировав 400 токенов, может думать что написала 310 или 490.
Потом протестировали training-free подход на двух задачах: саммаризация (GovReport, 973 документа) и биографии (183 персоны). Сравнивали baseline (обычный промпт "напиши N слов"), ICL (one-shot пример), Feedback (их метод), ICL+Feedback и Markergen (конкурент с трёхступенчатой генерацией). Измеряли MAE (средняя ошибка длины) и PM (процент текстов, попавших в ±10 слов от цели).
Результаты показали прорыв: на Qwen3-8B для саммаризации PM вырос с 15% (baseline) до 58% (Feedback) на токенах, с 6% до 47% на словах. На предложениях — с 36% до 79%. Качество текста (оценка через DeepSeek-V3 по coherence, consistency, relevance) упало незначительно: с 4.96 до 4.84 по 5-балльной шкале.
Финальный тест — SFT на открытых вопросах (ELI5, 10К примеров для обучения). Обучали модель на собственных ответах с подправленными target length (Algorithm 1: если модель сгенерила 287 слов, в датасет пишем "целевая длина 287±5"). Обнаружили 4× прирост эффективности обучения: SFT+Feedback достигает результата baseline SFT за 32 шага вместо 128. При этом качество ответов (correctness, helpfulness) не падает, а PM на токенах вырастает с 30% до 48%.
Неожиданная находка: метод генерализуется на другие единицы. Обучив на токенах/словах/предложениях, модель справляется даже с подсчётом символов (character-level) — хотя на них не обучалась. Это намекает, что feedback учит не "считать слова", а "отслеживать прогресс выполнения ограничения" в целом.
Ресурсы
Can LLMs Track Their Output Length? A Dynamic Feedback Mechanism for Precise Length Regulation
Meiman Xiao, Ante Wang, Qingguo Hu, Zhongjian Miao, Huangjun Shen, Longyue Wang, Weihua Luo, Jinsong Su
Xiamen University, Alibaba International Digital Commerce Group, Li Auto Inc.
