ai-chat: защита от петель агента — убрать final-step lockdown, детектор токен-деградации, предупреждение о бюджете шагов, CORE-пометки в каталоге, MAX_AGENT_ST… #444
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Контекст: третий класс петли (инцидент 2026-07-10, чат
019f49d8…)После деплоя фиксов #407/#427/#431 агент (роль «Корректор», glm-5.2 через z.ai) снова «зациклился», но по-новому:
succeeded;searchInPage, 9×getNode, 1×getOutline/getPage/getCurrentPage— ни одногоcreateCommentи ни одного вызоваloadTools;toolChoice: 'none'+ FINAL_STEP_INSTRUCTION): у модели отняли инструменты посреди незаконченной работы. Модель вместо итога продолжила «работать» текстом и выродилась в токен-повтор: один текстовый блок 255 388 символов, в котором «loadTools.» написано 20 416 раз (~24 минуты генерации);maxOutputTokensнет (сознательно: tool-аргументы — это выходные токены, глобальный кап режет их посреди JSON), поэтому повтор лился, пока провайдер сам не обрезал;createComment— CORE-тул (tool-tiers.ts,CORE_TOOL_KEYS) и был доступен все 19 шагов. Идея «сначала надо loadTools» — галлюцинация модели, спровоцированная<tool_catalog>-механикой в системном промпте.Драйверы петли: (а) модель сожгла весь бюджет шагов на чтение; (б) lockdown отнял инструменты, когда работа не сделана — прямой триггер деградации; (в) без ограничителя токен-деградация ничем не ограничена; (г) модель не знала, что комментарийные тулы всегда активны.
Решение по дизайну (выбор владельца): lockdown по умолчанию выключается, но остаётся под env-фичетоггл. Кап
maxOutputTokensне вводим нигде — раз на любом шаге (включая последний) возможны tool-вызовы, кап резал бы tool-аргументы. Единственная защита от токен-болтовни — детектор деградации (п. 3), он универсальнее капа (ловит повторы на ЛЮБОМ шаге, не только финальном).Изменения (пакет)
1.
MAX_AGENT_STEPS: 20 → 50apps/server/src/core/ai-chat/ai-chat.service.ts:59. Предупреждение о бюджете (п. 4) считается от константы. Проверить спеки на захардкоженные 19/20.2. Final-step lockdown — под фичетоггл
AI_CHAT_FINAL_STEP_LOCKDOWN, по умолчанию ВЫКЛЮЧЕННе удалять, а вынести под env-переключатель по образцу
AI_CHAT_DEFERRED_TOOLS(environment.service.ts:288):isAiChatFinalStepLockdownEnabled():AI_CHAT_FINAL_STEP_LOCKDOWN, дефолт'false'→ выключен.prepareAgentStepполучает параметрfinalStepLockdownEnabled: boolean(остаётся чистой функцией):{ toolChoice: 'none', system: system + FINAL_STEP_INSTRUCTION }— как сейчас.toolChoiceне трогаем, инструменты доступны на всех 50 шагах (deferred-сужениеactiveToolsпродолжает действовать на каждом шаге, включая последний); на последнем шаге — мягкий финальный нудж вsystem(совместимо с deferred-веткой — вернуть иactiveTools, иsystem):ai-chat.service.spec.ts~315–385) параметризовать по toggle (ON — старые ожидания, OFF — нудж безtoolChoice).Документация: описать
AI_CHAT_FINAL_STEP_LOCKDOWNв.env.example(блок AI-переменных, рядом сAI_CHAT_DEFERRED_TOOLS): что делает, почему по умолчанию выключен (инцидент с токен-деградацией на отъёме тулов), когда включать (модель стабильно заканчивает ходы без текста).2a. Митигировать возвращение «пустого хода» (при toggle OFF)
Lockdown вводился, чтобы ход, потративший все шаги на тулы, не заканчивался без текста. Компенсация на персисте: в
onFinish, если ни один шаг не дал текста (stepsбезtext,finishReason— исчерпание шагов), добавлять синтетическую текстовую часть-маркер, например:UI и реплей уже умеют fallback-текст (
assistantParts/flushAssistant) — маркер делает состояние явным для пользователя и для модели на следующем ходе.3. Детектор токен-деградации в
onChunk— теперь единственная защита от болтовниinProgressTextуже накапливается вonChunk. Добавить дешёвую проверку каждые ~2 КБ прироста текста, два эвристических правила по хвосту (~3000 символов):При срабатывании — абортить ран через внутренний контроллер:
Финализация: в
ai_chat_runs.error— внятная причина, отличимая от пользовательского Stop и рестарта сервера. Опционально: перед персистом обрезать деградировавший хвостcontentдо первых N повторов + маркер — чтобы сотни КБ мусора не тащились в БД и в реплей истории.Правила — чистыми функциями + юнит-тесты (позитивные: «loadTools.\n»×N, повтор без переносов; негативные: длинные списки правок, таблицы, код).
4. Предупреждение о бюджете шагов
В
prepareAgentStep: приstepNumber >= MAX_AGENT_STEPS - 6(и не последний шаг — у него свой нудж/lockdown из п. 2) конкатенировать вsystem:Юнит-тесты границ (при 50: шаги 0–43 — чисто, 44–48 — предупреждение с убывающим N, 49 — финальный нудж или lockdown по toggle).
5. Явная пометка «CORE-тулы всегда активны» в описании loadTools и преамбуле каталога
LOAD_TOOLS_DESCRIPTION(tool-tiers.ts:82): добавитьTools NOT listed in the catalog are CORE and ALWAYS active — call them directly, NEVER via loadTools (e.g. createComment, listComments, resolveComment, editPageText, searchInPage).<tool_catalog>(ai-chat.prompt.ts:228,buildToolCatalogBlock): вnoteдобавитьcore tools are always active and are not listed here. Список core-тулов рендерить динамически изCORE_TOOL_KEYS, не хардкодить.Критерии приёмки
MAX_AGENT_STEPS = 50; спеки зелёные без захардкоженных 19/20.AI_CHAT_FINAL_STEP_LOCKDOWN: дефолт выключен — на последнем шаге тулы доступны, в system финальный нудж; приtrue— легаси-lockdown (toolChoice: 'none'+ FINAL_STEP_INSTRUCTION). Спеки параметризованы по toggle.AI_CHAT_FINAL_STEP_LOCKDOWNзадокументирован в.env.example(что/почему/когда включать).Output degeneration detected…вai_chat_runs.error, стрим корректно закрывается, лизы внешних MCP-клиентов освобождаются (существующий lifecycle onError/onAbort).CORE_TOOL_KEYS.maxOutputTokensне выставляется ни на одном шаге (tool-аргументы никогда не режутся).Не входит (отдельные темы)
createComment(защита от флуда дублей) — инциденты 03–04.07 и ночи 10.07.resolveCommentс обрезанным UUID → внятная ошибка.ai-chat: защита от петель агента — кап вывода на финальном шаге, детектор токен-деградации, предупреждение о бюджете шагов, CORE-пометки в катал…to ai-chat: защита от петель агента — убрать final-step lockdown, детектор токен-деградации, предупреждение о бюджете шагов, CORE-пометки в каталоге, MAX_AGENT_ST…