# Склейка оборванных ответов языковой модели: как мы дописываем

> 2026-09-25 · AI Release · @ai_release1

> #LLM #finish_reason #чат-бот

### ⚡ Главное за 5 секунд - Суть: в русскоязычном сервисе с несколькими языковыми моделями в одном чате модель оборвала ответ на середине слова из-за потолка max_tokens, и для восстановления целостности пришлось построить механизм продолжения и склейки. - Где доступно: кейс опубликован на Habr 24 сентября, время чтения — 3 минуты, просмотров — 8K. - Ограничение: продолжений не больше четырёх, чтобы один вопрос не превратился в бесконечную переписку; сами обрывы не исчезли. ### 🔍 Что обнаружено У каждого запроса к модели есть потолок max_tokens. В сервисе он составлял 1200 токенов: на английском это примерно 900 слов, а на русском кириллица съедает больше токенов, и 1200 токенов хватало примерно на полторы тысячи знаков. Когда ответ упирается в потолок, модель возвращает finish_reason: "length" (у некоторых поставщиков — max_tokens), и это единственный признак обрыва. Поднятие потолка до 2400 токенов проблему не решило: ответ всё равно может оказаться длиннее, а каждый лишний токен увеличивает резервируемую сумму. Сервер отдаёт клиенту флаг truncated, если finish_reason сообщил об упоре в потолок. Клиент сам отправляет модели служебную просьбу продолжить с того же места и прикладывает конец уже написанного: сервер режет сообщение до 6000 знаков, поэтому берутся последние 5800. Продолжения ограничены четырьмя. Самое сложное — склейка: первая версия просто прибавляла продолжение, и появлялись артефакты вроде «102. ии102. ии и нейросети» или «Лучшие сервиЛучшие сервисы». В итоге получилась функция из трёх правил: убрать повтор конца написанного (с проверкой границы слова для коротких совпадений до 12 символов), заменить оборванную строку новой, если модель начала её заново, и добавить перенос строки, если модель начала со следующего пункта, таблицы или заголовка. Функцию прогнали на 13 случаях из реальных обрывов и придуманных краевых; та же функция стоит на сервере, чтобы в истории чата ответ лежал одной записью. ### 💡 Почему это важно Без такого механизма любая длинная генерация может оказаться бесполезной: пользователь получает обрывок вместо списка из ста пунктов, а в истории чата — несколько кусков вместо цельного ответа. Проверка finish_reason в каждом ответе дешевле, чем потом разбираться со скриншотами от пользователей. Механизм уже используется в сервисе, и хотя обрывы не исчезли, человек получает цельный ответ, а в журнале лежит одна аккуратная запись. ### 🧩 Контекст Всё началось со скриншота от партнёра: модель начала отвечать списком из ста пунктов и оборвалась на середине слова. В админке лежал тот же обрывок — ни ошибки, ни предупреждения. После этого выяснили причину в потолке max_tokens, подняли его до 2400 и добавили продолжение. Отдельно пришлось разбираться с деньгами: каждое продолжение — отдельный платный запрос, сумма резервируется до вызова, списывается по фактическому usage, а резерв возвращается при ошибке. Модели с обязательными рассуждениями тратят часть потолка на reasoning, поэтому обрыв у них наступает раньше, чем можно предположить по длине видимого ответа.

[Источник](https://habr.com/ru/articles/1086420/)
