Почему Kimi K3 возвращает пустой ответ
Вызов успешен, HTTP 200. content — пустая строка. Счёт — нет. Вот точная причина, воспроизведённая на шести лимитах 2026-07-16.
Короткий ответ: ваш max_completion_tokens слишком мал. K3 всегда рассуждает перед тем, как отвечать, и рассуждения берутся из того же бюджета токенов, что и сам ответ. Поставьте потолок ниже того, сколько K3 хочет думать, — и размышления съедят его целиком, не оставив на content ничего. Вы получите finish_reason: "length", пустую строку и счёт за каждый токен рассуждений. Починка: поднимите max_completion_tokens или просто оставьте значение по умолчанию 131 072.
Замерено на api.moonshot.ai с моделью kimi-k3 2026-07-16 — вот как.
Шесть прогонов
Мы задали K3 один короткий вопрос — «Explain why the sky is blue» — на шести лимитах, не меняя больше ничего:
Рассуждения заполняют любой бюджет, который вы им дадите
Выходные токены на прогон · ответ появляется только при 2 048 · замерено 2026-07-16
api.moonshot.ai. Ниже 2 048 весь бюджет уходит на рассуждения — вы платите за каждый их токен и получаете пустую строку. Полные числа — в таблице ниже.| max_completion_tokens | finish_reason | Токены рассуждений | Возвращённый content | Тарифицировано как выход |
|---|---|---|---|---|
| 64 | length | 61 | ничего | 61 |
| 128 | length | 125 | ничего | 125 |
| 256 | length | 253 | ничего | 253 |
| 512 | length | 509 | ничего | 509 |
| 1024 | length | 1021 | ничего | 1021 |
| 2048 | stop | 1308 | 1 954 символа | 2048 |
Вчитайтесь в закономерность. На каждом лимите ниже 2048 рассуждения выбирали весь потолок с точностью до трёх токенов, и ответ так и не начинался. Последняя строка объясняет почему: на этом одном коротком вопросе модель потратила 1 308 токенов на размышления, прежде чем написать хоть слово. Любой потолок ниже — это чек за пустоту.
Заметьте и то, что сбой тихий. Ни ошибки, ни предупреждения — HTTP 200 с корректно сформированным телом ответа, у которого content просто оказался "". Если ваш код делает response.choices[0].message.content.strip() и идёт дальше, вы отправите этот баг в продакшен.
Почему так происходит
В большинстве API лимит токенов ограничивает ответ. В K3 он ограничивает размышления плюс ответ, и размышления идут первыми.
У K3 нет выключателя рассуждений — это не режим, который вы включаете, а сам способ работы модели. Каждый ответ несёт поле reasoning_content, и каждый его токен тарифицируется по выходной ставке $15.00 за 1 млн — ровно как сам ответ. Так что выставленный вами бюджет тратится на обдумывание ещё до того, как появится первый символ вашего ответа.
Поэтому ловушка особенно опасна при портировании. Код, который отлично работает с другим API — где max_tokens: 512 значит «дай короткий ответ», — здесь означает совсем другое: «думай не больше 512 токенов и остановись — неважно, успела ли ты что-то сказать».
Починка
Оставьте max_completion_tokens со значением по умолчанию 131 072, если у вас нет конкретной причины его менять. K3 останавливается сама, когда закончила; потолок — это предохранитель, а не регулятор длины.
Если ограничить расход действительно нужно, закладывайте бюджет на рассуждения плюс ответ — и проверяйте сигнатуру сбоя, а не доверяйте ответу на слово:
choice = response.choices[0]
if choice.finish_reason == "length" and not choice.message.content:
raise RuntimeError(
f"Reasoning consumed the whole budget "
f"({response.usage.completion_tokens_details.reasoning_tokens} reasoning tokens). "
f"Raise max_completion_tokens."
)
Если на самом деле вам нужен короткий ответ — попросите об этом в промпте. Не добивайтесь этого потолком токенов: в K3 он управляет тем, сколько модель может думать, а не тем, сколько она может говорить.
Какой запас закладывать?
Мы замерили: рассуждения занимают 43–77% всех выходных токенов на трёх промптах, а на одном коротком вопросе выше — 1 308 токенов. Верхний хвост распределения мы не изучали и выдумывать правило по трём точкам не станем. Честная рекомендация: значение по умолчанию существует не просто так, а любой ваш потолок должен быть в несколько раз больше, чем, по-вашему, нужно самому ответу. Что это значит для вашего счёта — в раскладке стоимости рассуждений.
Тот же баг в стриминге
Он кусается и при стриминге, причём выглядит ещё хуже: стрим просто заканчивается, так и не выдав ни одной дельты с контентом. В пяти стриминговых прогонах на тривиальном промпте с потолком 128 токенов три не выдали ни одного токена контента. Дельты рассуждений приходят, стрим закрывается — и наивный потребитель, который смотрит только на delta.content, видит пустой результат без всякого объяснения.
Если вы стримите — смотрите на finish_reason в финальном чанке и передавайте stream_options: {"include_usage": true}, чтобы видеть токены рассуждений, за которые с вас списали. Подробности — в руководстве по API.
Смежные режимы отказа
Ещё два способа, которыми K3 отказывает без ошибки, оба замерены: reasoning_effort: "low" молча принимается с HTTP 200, хотя поддерживается только max, а max_completion_tokens: 2000000 — вдвое больше контекстного окна — тоже возвращает 200. Полный набор реальных тел ошибок — в справочнике ошибок.
Попробуйте сами
Каждое число на этой странице воспроизводится примерно за минуту. EvoLink отдаёт kimi-k3 через OpenAI-совместимый эндпоинт — 10 бесплатных кредитов, регистрация из любой страны, китайский номер телефона не нужен.