Практическое руководство

Почему модель нарушает лимит символов и как исправить это кодом

Почему модель нарушает лимит символов и как исправить это кодом
Temporary fallback cover; replace in editorial pass.
Уровень: с нуля Время чтения: до 10 минут Тема: надёжная генерация строк
Самое важное из мира AI — в канале MAX AgentLabОтдельные разборы, инструменты и практические схемы Читайте Agent Lab в Telegram Разборы, кейсы и новости о практических AI-агентах без лишней воды.

Языковая модель умеет хорошо писать текст, но не является точным счётчиком символов. Если попросить её создать рекламный заголовок длиной до 60 символов, она может прислать строку на 61, 68 или даже больше знаков. Это не обязательно ошибка модели: генерация текста и строгая проверка длины — разные задачи.

Надёжный подход строится вокруг простого правила: модель предлагает варианты, а программа принимает решение. Код считает длину каждой строки, отбрасывает неподходящие варианты и при необходимости отправляет их на доработку.

Почему модель нарушает лимит символов

Для человека просьба «напиши до 60 символов» выглядит однозначно. Для модели это инструкция на естественном языке, а не встроенное ограничение вывода. Модель предсказывает последовательность токенов, ориентируясь на смысл, стиль и контекст. Символы для неё не являются главным объектом планирования.

Есть несколько причин, по которым результат может выйти за границу:

  • модель оценивает длину приблизительно;
  • один токен не равен одному символу или одному слову;
  • пробелы, кавычки, тире и знаки препинания тоже входят в строку;
  • кириллица, эмодзи и составные Unicode-символы могут вести себя неожиданно для разных способов подсчёта;
  • модель иногда добавляет пояснения, нумерацию или Markdown-разметку.

Поэтому инструкция в запросе полезна, но недостаточна. Она помогает получить больше подходящих вариантов, однако гарантия появляется только после программной проверки.

Правильно сформулируйте задачу

Сначала определите, что именно считается длиной. В большинстве рекламных задач нужен обычный размер строки в символах, включая пробелы. Это правило следует явно описать в запросе и повторить в коде.

Создай 12 рекламных заголовков на русском языке.

Тема: приложение для планирования задач.
Лимит: не более 60 символов на заголовок.
Считай пробелы и знаки препинания.
Верни только JSON-массив строк без нумерации и пояснений.
Старайся держать каждый вариант в диапазоне от 45 до 60 символов.

Запросить 12 вариантов при необходимости одного — важная часть конвейера. Запас позволяет отфильтровать слишком длинные, слишком короткие или неудачные строки, не заставляя модель идеально попасть в ограничение с первой попытки.

Посчитайте длину кодом

Ниже — минимальная проверка на Python. Она не обращается к API и безопасна для локального запуска: команда только создаёт список примеров и печатает результаты.

candidates = [
    "Планируйте задачи спокойно и без лишнего шума",
    "Все дела под контролем в одном приложении",
    "Соберите рабочий день за несколько минут",
]

limit = 60

for text in candidates:
    print(f"{len(text):>3} символов | {'OK' if len(text) <= limit else 'СЛИШКОМ ДЛИННО'} | {text}")

В Python функция len() возвращает количество элементов строки. Для обычного текста на русском языке этого достаточно, если бизнес-правило действительно означает количество символов в строке.

Если нужно принимать только строки в заданном диапазоне, добавьте нижнюю границу:

min_length = 45
max_length = 60

valid = [
    text for text in candidates
    if min_length <= len(text) <= max_length
]

print(valid)

Такой фильтр не меняет текст и не пытается «умно» обрезать его посередине. Он просто отделяет подходящие варианты от тех, которые требуют доработки.

Сделайте проверку частью конвейера

Рабочий поток можно представить так:

  1. сформировать запрос с запасом вариантов;
  2. получить структурированный ответ;
  3. проверить формат и тип каждого элемента;
  4. посчитать длину кодом;
  5. отфильтровать подходящие строки;
  6. неподходящие варианты отправить на доработку или запросить новую партию.

Пример функции, которая проверяет список кандидатов:

def split_by_length(candidates, minimum, maximum):
    valid = []
    invalid = []

    for candidate in candidates:
        if not isinstance(candidate, str):
            invalid.append(candidate)
            continue

        if minimum <= len(candidate) <= maximum:
            valid.append(candidate)
        else:
            invalid.append(candidate)

    return valid, invalid


valid, invalid = split_by_length(
    candidates,
    minimum=45,
    maximum=60,
)

print("Подходящие:", valid)
print("На доработку:", invalid)

Преимущество такого разделения в том, что программа не смешивает успешные и проблемные результаты. Подходящие строки можно передать дальше, а список ошибок — использовать в следующем запросе.

Отправьте длинные варианты на доработку

Если после первой генерации недостаточно подходящих вариантов, передайте модели только проблемные строки и точное требование. Не просите переписать весь список без необходимости: так проще сохранить удачные варианты.

Исправь только следующие заголовки.

Требование:
- каждый результат должен быть длиной от 45 до 60 символов;
- пробелы и знаки препинания считаются;
- смысл и рекламный тон нужно сохранить;
- верни только JSON-массив строк.

Заголовки для исправления:
["Здесь находится слишком длинный пример заголовка для проверки"]

После доработки снова выполните ту же проверку. Никогда не считайте, что повторный запрос автоматически гарантирует правильную длину.

Пример цикла с ограниченным числом попыток

def collect_valid(candidates, minimum, maximum, target_count):
    valid, invalid = split_by_length(candidates, minimum, maximum)

    attempts = 0
    max_attempts = 2

    while len(valid) < target_count and invalid and attempts < max_attempts:
        # Здесь должен быть новый вызов модели,
        # который возвращает исправленные строки.
        revised = [
            text[:maximum].rstrip()
            for text in invalid
        ]

        valid, invalid = split_by_length(revised, minimum, maximum)
        attempts += 1

    return valid[:target_count], invalid

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

Что делать с Unicode и «видимыми» символами

Обычная проверка длины подходит, когда лимит задан как количество элементов строки. Но иногда продукт считает не символы, а видимые знаки, графемы или байты. Это разные правила.

Например, эмодзи может состоять из нескольких Unicode-кодовых точек, хотя пользователь воспринимает его как один видимый знак. Если интерфейс или рекламная площадка применяет собственную методику подсчёта, используйте именно её правила и соответствующую библиотеку.

Практическое правило: зафиксируйте один измеритель длины в техническом задании. Нельзя проверять результат в Python по одному правилу, а затем отправлять его в систему, где применяется другое.

Безопасные команды для локальной проверки

Если Python уже установлен, сохраните пример в файл, например check_length.py, и запустите его командой:

python3 check_length.py

Команда не устанавливает пакеты, не удаляет файлы и не отправляет данные в сеть. Для проверки версии интерпретатора можно использовать:

python3 --version

Если Python не установлен, тот же принцип можно проверить в браузерной консоли JavaScript:

const candidates = [
  "Планируйте задачи спокойно и без лишнего шума",
  "Все дела под контролем в одном приложении"
];

const limit = 60;

for (const text of candidates) {
  console.log(text.length, text.length <= limit, text);
}

Для большинства строк свойство length удобно, но для сложных эмодзи оно может считать UTF-16-кодовые единицы, а не визуальные символы. Это ещё одна причина заранее определить правило подсчёта.

Проверка результата перед публикацией

Перед передачей заголовков в рекламную систему проверьте не только длину:

  • ответ действительно распарсен как массив строк;
  • внутри строк нет нумерации, кавычек JSON или пояснений;
  • нет пустых значений и дубликатов;
  • каждая строка соответствует языку и теме кампании;
  • используется тот же способ подсчёта, что и у принимающей системы;
  • после любой автоматической правки проверка запускается повторно.

Полезно сохранять причину отбраковки: «слишком длинно», «слишком коротко», «не строка» или «дубликат». Это облегчает диагностику, если конвейер внезапно перестал выдавать достаточное количество вариантов.

Типовые ошибки

Ошибка 1. Полагаться только на инструкцию в запросе

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

Ошибка 2. Обрезать строку без проверки смысла

Срез по позиции может удалить окончание слова, отрицание или важный призыв к действию. Используйте обрезание только как аварийную меру и проверяйте результат человеком или отдельным правилом.

Ошибка 3. Считать слова вместо символов

Заголовок из десяти коротких слов может быть короче заголовка из пяти длинных слов. Если лимит задан в символах, проверяйте символы.

Ошибка 4. Забыть про пробелы и пунктуацию

Пробел после слова, кавычки и восклицательный знак тоже занимают место. Считайте уже готовую строку, а не приблизительную длину черновика.

Ошибка 5. Не ограничить число повторных попыток

Если модель снова и снова возвращает неподходящие строки, бесконечный цикл увеличит задержку и расход ресурсов. Задайте максимальное число итераций и предусмотрите понятный отказ.

Ограничения подхода

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

Кроме того, разные платформы могут по-разному считать Unicode-символы, переносы строк или специальные знаки. Если строка уходит во внешнюю систему, сверяйтесь с её актуальными правилами. В этом материале нет предположений о конкретной рекламной площадке: пример показывает общий конвейер.

Наконец, фильтрация может удалить все варианты. Поэтому полезно запрашивать запас, иметь повторный запрос на доработку и явно сообщать оператору, если после заданного числа попыток подходящих строк не найдено.

Итог

Причина, по которой модель нарушает лимит символов, проста: она генерирует текст, а не выполняет строгую проверку длины. Надёжная архитектура разделяет эти задачи.

  1. Попросите больше вариантов, чем нужно.
  2. Получите структурированный ответ без лишнего текста.
  3. Посчитайте длину каждой строки кодом.
  4. Отфильтруйте неподходящие варианты.
  5. Отправьте отбракованные строки на доработку.
  6. Повторите проверку перед публикацией.

Дополнительные материалы: все практические guides и глоссарий терминов.