Руководство и понимание

Потоковый учет токенов в шлюзе AI API: окончательное использование, отмены и частичные ответы

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

Потоковые ответы LLM легко проксировать, но сложно правильно выставить счета. Если шлюз AI API перенаправляет события, отправленные сервером, клиенту, но рассматривает первые фрагменты как запись об использовании, аналитика арендаторов будет отклоняться. Отклонение обычно проявляется в таких спорах, как: «пользователь увидел только половину ответа», «провайдер выставил счет больше, чем показывает наша панель мониторинга», «квота была освобождена слишком рано» или «по истечении времени ожидания были созданы токены, но нет строки счета».

Основная проблема заключается в том, что потоковые вызовы не являются одним событием. Это последовательность: запрос принят, восходящий поток открыт, байты доставлены, отчет об окончательном использовании, остановка провайдера, отключение клиента, тайм-аут шлюза и оплата. Надежный шлюз должен моделировать эти состояния явно, а не предполагать, что завершенный HTTP-ответ является единственным успешным путем.

Режим отказа: потоковая передача скрывает границы учета

Непотоковое завершение обычно возвращает один объект ответа с метаданными об использовании. Шлюз может нормализовать это использование, записать строку в реестр, обновить квоту и предоставить аналитику за один проход.

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

Факт: документы OpenAI указывают, что вызывающие потоковую передачу данные об использовании должны устанавливать stream_options с помощью include_usage. OpenAI также предоставляет конечные точки использования и затрат на уровне организации, однако отмечает, что использование и затраты не всегда могут идеально согласовываться для финансовых целей.

Факт: Антропная потоковая передача использует события, отправляемые сервером, такие как message_start, content_block_delta, message_delta и message_stop. Информация об использовании message_delta является накопительной, поэтому шлюз не должен суммировать каждую разницу использования.

Факт. API потоковой передачи в стиле Gemini и Vertex могут предоставлять инкрементные фрагменты, а SDK также могут предоставлять агрегированный объект ответа. Для шлюзов этот агрегированный путь может быть лучшим источником завершенного использования, чем только видимые фрагменты.

Используйте конечный автомат потока, а не логический флаг успеха

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

<ул>
  • принято: шлюз аутентифицировал ключ, приписал арендатора и создал строку открытой книги.
  • first_byte_sent: хотя бы одно выходное событие достигло нижестоящего клиента.
  • provider_completed: вышестоящий поставщик выдал обычный сигнал остановки или завершил объект ответа.
  • client_aborted: нисходящий сокет закрыт до нормального завершения шлюза.
  • provider_error: вышестоящий поставщик возвратил ошибку после начала потока или до прибытия окончательного использования.
  • gateway_timeout: шлюз применил свой бюджет задержки и завершил запрос.
  • согласовано: шлюз конвертировал использование в стоимость арендатора и потребление квоты.
  • выверено: более поздние данные об использовании или расходах поставщика подтвердили или скорректировали строку.
  • Эта модель предотвращает распространенную ошибку аналитики: помечать каждый поток, создавший текст, как «успешный и точный». Поток может быть полезен пользователю, неполным от провайдера, оцененным для биллинга и одновременно ожидающим сверки.

    Рекомендуемые поля бухгалтерской книги

    Сохраняйте строку времени запроса небольшой, но явной:

    {
      "request_id": "gw_req_...",
      "tenant_id": "tenant_123",
      "api_key_id": "key_456",
      "provider": "openai|anthropic|gemini|...",
      «provider_request_id»: ноль,
      "модель": "идентификатор-модели-поставщика",
      "состояние": "принято",
      «поток»: правда,
      «input_tokens»: ноль,
      «output_tokens_billed»: ноль,
      «output_tokens_delivered_estimate»: 0,
      «provider_usage_source»: ноль,
      "billing_status": "pending_reconciliation",
      «client_abort_at»: ноль,
      «provider_completed_at»: ноль,
      "settled_at": ноль,
      «класс_ошибки»: ноль
    

    Важным разделением является output_tokens_billed и output_tokens_delivered_estimate. Пользователям важно, что достигло их приложения. Финансы заботятся о том, сколько выставит счет провайдеру. Эти цифры могут отличаться после отключений, потоков вызовов инструментов, скрытых токенов рассуждения, кэшированных токенов, остановок безопасности или тайм-аутов шлюза.

    Правила захвата, специфичные для поставщика

    Независимый от поставщика API, совместимый с OpenAI, полезен для разработчиков приложений, но адаптеру шлюза по-прежнему требуются правила учета, специфичные для поставщика.

    Потоковое вещание, совместимое с OpenAI

    Для маршрутов OpenAI предоставьте опцию шлюза, которая позволяет создавать отчеты об использовании восходящего потока, где это поддерживается. Распространенным шаблоном является принятие значения по умолчанию на уровне шлюза, например:

    {
      «поток»: правда,
      "stream_options": {
        «include_usage»: правда
      }
    

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

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

    Антропный стриминг

    Совокупное использование Anthropic требует другого правила. Если шлюз видит три события message_delta с числом выходных токенов 10, 25 и 40, количество выходных токенов равно 40, а не 75.

    let lateUsage = null;
    for await (const событие anthropicStream) {
      if (event.type === "message_delta" && event.usage) {
        if (latestUsage && event.usage.output_tokens 

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

    Потоковое вещание в стиле Gemini и Vertex

    Gemini поддерживает фрагменты потоковой передачи, чтобы уменьшить задержку. В SDK в стиле Vertex потоковая передача может предоставлять как асинхронный поток, так и объект агрегированного ответа. Шлюз должен сохранять этот агрегированный путь, когда он доступен.

    conststreamingResult = await model.generateContentStream(request);
    for await (const chunk ofstreamingResult.stream) {
      впередЧанк (кусок);
      countDeliveredBytesOrText (кусок);
    }
    constагрегированный = ожидание потокового результата.ответ;
    SettleFromAggregatedUsage(aggregated);

    Рекомендация: избегайте построения всего учета из видимых фрагментов, если SDK предоставляет заполненную запись ответа. Чанки предназначены для задержки. Конечный объект зачастую лучше подходит для выставления счетов и аналитики.

    Обрабатывать отключения клиентов как первоклассные учетные события

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

    Шлюз должен сделать явный выбор политики:

    <ул>
  • Немедленно отменить исходный поток: сокращается ненужная генерация и затраты поставщика, но может нарушить рабочие процессы, когда серверной части все еще нужен результат после отключения пользовательского интерфейса.
  • Продолжить работу в фоновом режиме: можно сохранить работу для потребителей на стороне сервера, но пользователь может не видеть все созданные и выставленные счета токены.
  • Поведение в зависимости от маршрута: отмените для интерактивного чата, продолжите для рабочих процессов, аналогичных работе, и сделайте настройку видимой для клиентов.
  • Практическое значение по умолчанию для интерактивной потоковой передачи — отмена восходящего потока при отключении нижестоящего клиента, а затем пометка строки реестра как client_aborted. Если окончательное использование происходит во время отмены, расчет производится на основе этого авторитетного использования. Если нет, отметьте строку оценка или pending_reconciliation, а не притворяйтесь, что она точна.

    downstream.on("close", async () => {
      если (!providerCompleted) {
        ledger.markClientAborted(requestId);
        await upstream.abort().catch(() => {
          ledger.emit("upstream_cancel_failed", requestId);
        });
      }
    });

    Рекомендация: указывайте прозрачные метки выставления счетов, такие как final, provider_reconciled, estimated, waived или pending_reconciliation. Это более оправданно, чем показывать каждый потоковый вызов как сразу точный.

    Применение квоты во время трансляции

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

    Используйте два механизма вместе:

    <ол>
  • Предварительное резервирование. Зарезервируйте расчетный максимум в зависимости от модели, запрошенного максимального количества токенов, политики клиента и текущего баланса.
  • Проверка давления потоковой передачи: оценивайте доставленные выходные данные во время трансляции и останавливайте, если запрос пересекает настроенную границу безопасности.
  • Это механизм контроля, а не окончательный законопроект. Поставщики могут подсчитывать кэшированные токены, токены обоснования, мультимодальные токены или скрытые токены иначе, чем оценщик шлюза.

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

    События наблюдения, которые выявляют ошибки учета

    Ошибки потокового выставления счетов легче отлаживать, если шлюз отправляет целевые события, а не только общие журналы запросов. Добавьте такие события, как:

    <ул>
  • final_usage_missing: поток завершился без авторизованного использования.
  • cumulative_usage_regressed: совокупное количество токенов перемещено назад.
  • stream_ended_without_stop_event: обычного маркера остановки поставщика не обнаружено.
  • aborted_after_provider_completion: поставщик завершил работу, но нижестоящий клиент закрылся до того, как шлюз завершил пересылку.
  • settled_from_estimate: в реестре арендаторов использовалась оценка, поскольку окончательное использование было недоступно.
  • reconciliation_adjusted_usage: позже в отчетах поставщика строка была изменена.
  • Факт: Семантические соглашения OpenTelemetry GenAI рекомендуют использовать информацию об использовании, возвращаемую поставщиком, для потоковой передачи ответов, если она доступна, и предостерегают от сообщения показателей использования, если количество токенов невозможно получить эффективно или точно.

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

    Тестирование соответствия для учета потоковой передачи

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

    <ул>
  • Обычный поток: прибывает окончательное использование, наблюдается событие остановки, реестр фиксируется как окончательный.
  • Поток вызовов инструментов: дельты вызовов инструментов пересылаются, использование фиксируется, структурированные метаданные не нарушают подсчет токенов.
  • Остановка безопасности или отказа: поставщик останавливается раньше, использование по-прежнему регулируется правильно.
  • Принудительное отключение клиента: нисходящий поток закрывается после частичного вывода; восходящий поток отменяется или продолжается в соответствии с политикой.
  • Восходящий 5xx после частичного вывода: шлюз фиксирует частичную доставку и не помечает запрос как чистый успешный.
  • Тайм-аут шлюза перед окончательным использованием: строка становится приблизительной или ожидает сверки.
  • Отсутствует конечное событие: адаптер выдает final_usage_missing и избегает точных меток платежа.
  • Эти тесты должны проверять переходы между состояниями, поля реестра, создаваемые наблюдаемые события и дальнейшее поведение. Побайтовой совместимости потоков недостаточно; побочные эффекты бухгалтерского учета являются частью контракта.

    Контрольный список практической реализации

    <ул>
  • Создайте строку журнала использования перед отправкой восходящего запроса.
  • Сохранять идентификаторы арендатора, ключа, пользователя, модели, маршрута, поставщика и запроса во время запроса.
  • Включите окончательные отчеты об использовании поставщика, если это поддерживается, например OpenAI-совместимый stream_options.include_usage.
  • Для кумулятивных поставщиков сохраняйте последнее значение использования вместо суммирования событий.
  • Сохранять объекты агрегированных ответов, когда их предоставляют SDK.
  • Отслеживайте доставленные результаты отдельно от использования, выставленного поставщиком услуг.
  • При отключении отмените восходящий поток в соответствии с политикой маршрутизации и отметьте client_aborted.
  • Используйте прозрачные статусы выставления счетов: окончательный, расчетный, ожидающий сверки, сверка поставщика или отказ.
  • Создавать события наблюдения, специфичные для бухгалтерского учета.
  • Позднее выполните сверку с отчетами об использовании или расходах поставщика, если они доступны, сохраняя при этом атрибуцию арендаторов во время запроса.
  • Что показать арендаторам

    Арендаторам не нужны все внутренние события, но им нужны честные ярлыки. Полезная таблица использования может показать:

    <ул>
  • Статус: окончательный, расчетный или сверенный.
  • Результат запроса: выполнен, клиент прерван, ошибка поставщика или тайм-аут шлюза.
  • Доставленный результат: приблизительный текст или байты, отправленные клиенту.
  • Оплачиваемые токены: нормализованное поставщиком использование, используемое для расчета стоимости.
  • Корректировка: любая последующая разница в сверке.
  • Такая конструкция снижает неоднозначность поддержки. Если пользователь увидел только часть ответа, на информационной панели можно будет объяснить, завершил ли поставщик уже работу, отменен ли входной шлюз и является ли плата окончательной или ориентировочной.

    Рекомендации и прогнозы

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

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

    Практическое заключение

    Если ваш шлюз поддерживает потоковую передачу, проведите аудит сегодня по одному пути: принудительно отключите клиента после первых нескольких фрагментов и проверьте строку реестра. Если там написано «успех» с точным количеством токенов, вероятно, ваша аналитика лжет.

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

    Связанная литература

    FAQ

    Часто задаваемые вопросы

    Должен ли счет за шлюз передавать потоковые ответы на основе предполагаемого количества токенов?
    При необходимости используйте оценки для защиты квот в режиме реального времени, но рассчитывайте точную стоимость арендатора на основе данных об использовании, возвращаемых поставщиком, если таковые имеются. Если окончательное использование отсутствует, пометьте строку как расчетную или ожидающую сверки.
    Почему доставленные выходные токены могут отличаться от выставленных счетов?
    Клиент может отключиться, у шлюза может истечь тайм-аут, провайдер может подсчитать скрытые рассуждения или мультимодальные токены, или провайдер может завершить генерацию после того, как пользователь перестанет получать байты. Отслеживайте поставленную продукцию отдельно от использования, выставленного поставщиком услуг.
    Какова наиболее распространенная ошибка учета потоковой передачи Anthropic?
    Суммирование совокупных событий использования. Счетчики использования Anthropic message_delta являются накопительными, поэтому шлюз должен хранить последнее значение, а не добавлять каждое событие.
    Что должно произойти, если браузер отключится во время трансляции?
    Для интерактивных маршрутов практическим по умолчанию является отмена восходящего запроса, пометка строки реестра как client_aborted и расчет только на основе использования авторитетного поставщика, если он поступает. В противном случае отметьте строку с оценкой или ожиданием сверки.