Skip to content

GLM-5.1 упирается в 32k output cap OpenCode: сессия без результата маскируется как HUNG POST #161

Closed

Description

@axisrow

Проблема

При реальном прогоне library_fine на zai-coding-plan/glm-5.1 OpenCode иногда исчерпывает внутренний per-step output budget ровно в 32 000 токенов, закрывает ход без tool call, файла и финального ответа, а benchmark классифицирует это как:

зависший POST /message: ответа провайдера не было, сессия закрылась без результата

Эта формулировка неверна: провайдер ответил и usage получен. Фактическая сигнатура соответствует finish_reason=length / исчерпанию output budget в OpenCode.

Доказательства

Сохранённые прогоны в data/main.db

Отчёты 290, 296, 298: 12 копий library_fine на zai-coding-plan/glm-5.1.

  • 5 успешных;
  • 7 ошибок с одинаковым HUNG_POST_REASON;
  • во всех 7 ошибках output_tokens + reasoning_tokens = 32 000;
  • ни одного артефакта или финального результата.
report/run elapsed, s output reasoning completion
290/2 915.1 33 31 967 32 000
290/3 691.2 52 31 948 32 000
290/4 565.6 20 31 980 32 000
290/5 703.4 67 31 933 32 000
296/1 357.6 36 31 964 32 000
296/3 377.6 13 31 987 32 000
298/2 470.1 61 31 939 32 000

Успешные копии длились 515.4–1077.0 с, ошибочные — 357.6–915.1 с. Поэтому простой wall-clock cutoff не отличает зависание от медленного успешного выполнения.

Два свежих повторных прогона

Оба выполнены с --no-save на OpenCode 1.17.18:

repeat elapsed, s input output reasoning completion result
1 457.1 9 877 33 31 967 32 000 no artifact
2 517.7 9 814 29 31 971 32 000 no artifact

Для контроля простые задачи на той же модели и провайдере проходят:

  • hello_world: 21.9 с;
  • fast_sort: 19.4 с;
  • stock_downloader: 151.3 с.

Это не общий отказ Z.AI и не отсутствие ответа на любой prompt.

Воспроизведение

python bench.py \
  --project library_fine \
  -p zai-coding-plan \
  -m glm-5.1 \
  -n 1 \
  --no-save \
  --base-port 4096 \
  --timeout 1000 \
  "<prompt from reports 290/296/298 in data/main.db>"

В окружении локальной диагностики proxy-переменные были очищены.

Точный prompt хранится в reports.raw_json отчётов 290, 296, 298.

Почему это не обычный сетевой сбой Z.AI

В проблемных копиях:

  • есть ненулевой input/output/reasoning usage;
  • completion всегда заканчивается ровно на 32 000;
  • нет ECONNRESET, JSON parse error или provider network error;
  • сессия доходит до terminal/idle, но без результата.

Это отличается от #160: там glm-5v-turbo не отдаёт ни одного события и usage отсутствует.

Upstream

Сигнатура напрямую совпадает с открытыми issue OpenCode:

Локальная причина неправильной диагностики

  1. POST /message не завершается за 30 с → post_hung=True.
  2. Benchmark правильно продолжает ждать SSE/terminal state.
  3. OpenCode заканчивает ход без файла/финального текста.
  4. При code=0 + post_hung + no artifact benchmark заменяет результат на HUNG_POST_REASON.
  5. Terminal finish_reason не сохраняется, поэтому реальная причина length теряется.

Ожидаемое поведение benchmark

  1. Сохранять terminal finish_reason и сигнал MessageOutputLengthError, если он есть.
  2. При finish=length и отсутствии результата сразу возвращать отдельную точную причину, например:
    output budget OpenCode исчерпан (32 000), модель не завершила действие.
  3. Не называть это отсутствием ответа провайдера.
  4. Не ждать общий wall-clock timeout после получения terminal length.
  5. Добавить CLI/config для явной передачи OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX.
  6. Провести A/B live-test 32 000 против 65 536.
  7. Опциональный first-action watchdog держать отдельной страховкой: длительности успешных и ошибочных запусков пересекаются.

Тесты

Связанные issue

Activity

  1. axisrow commented on Jul 20, 2026

    @axisrow
    OwnerAuthor

    Реализация готова в рабочем дереве (без коммита/PR).

    Что сделано:

    • добавлен --output-token-max INT, значение явно передаётся в OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX для каждого opencode serve;
    • terminal finish=length и MessageOutputLengthError теперь сохраняются и классифицируются как отдельная ошибка лимит ответа OpenCode исчерпан, а не как отсутствие ответа провайдера;
    • при terminal length ожидание потерянного session.idle прекращается;
    • добавлен opt-in --first-action-timeout SECONDS; watchdog считает только первый text/tool/question основного assistant и игнорирует user prompt, title-agent и reasoning;
    • finish_reason и first_action_elapsed сохраняются в отчёт.

    Live A/B: OpenCode 1.17.18, zai-coding-plan/glm-5.1, тот же полный library_fine prompt, -n 1 --no-save --timeout 1000, proxy env очищен.

    режим elapsed input output reasoning completion результат
    default 32k 596.0s 45,650 9,029 26,298 35,327 success + artifact
    --output-token-max 65536 959.9s 66,072 11,689 51,094 62,783 success + artifact

    Default-прогон в этот раз прошёл, что подтверждает стохастичность: ранее 9 независимых запусков завершались ровно на 32,000 completion. Для 65k OpenCode log показывает около 784s до первого tool action. 62,783 — aggregate completion всего прогона, не доказательство per-step usage, но результат согласуется с тем, что повышенный потолок снимает прежний 32k барьер.

    Live watchdog-проверка с --first-action-timeout 5 завершила такой же тяжёлый запуск ошибкой за 34.1s вместо 600–1000s. Задержка выше 5s объясняется существующим POST read timeout 30s.

    Проверка:

    • focused: 367 passed, 13 subtests passed;
    • full: 912 passed, 15 skipped, 119 subtests passed;
    • python3 -m py_compile bench.py;
    • git diff --check.

    Live-прогоны были --no-save; изменения data/main.db не включены в реализацию.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions