> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apiyi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Чем отличаются запросы с потоковой передачей и без неё при фильтрации контента?

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

## Краткий ответ

<Info>
  **Один и тот же контент может завершиться совершенно по-разному в режиме потоковой передачи и без него при срабатывании фильтра контента:**

  1. **Без потоковой передачи**: когда официальный маршрут активирует фильтр безопасности контента, APIYI **автоматически повторно генерирует запрос через другой официальный маршрут**. Ваш клиент получает полный результат, при этом **тарификация происходит только один раз**.
  2. **С потоковой передачей**: вывод отправляется клиенту по мере генерации, поэтому **переключить маршрут в процессе потока невозможно**. Запрос завершается с `finish_reason: "content_filter"`, а уже сгенерированная часть **тарифицируется в обычном порядке**.
  3. **Как выбрать**: используйте потоковую передачу для контента, отображаемого пользователям посимвольно/по токенам (чат, ответы агента); используйте режим без потоковой передачи для контента, который программа обрабатывает только после полного завершения (сценарии, раскадровки, перевод, структурированные данные).
</Info>

## Два этапа, на которых происходит фильтрация

Фильтр безопасности контента провайдера может сработать на двух этапах, и оба они проявляются в режиме потоковой передачи:

| Когда                                         | Что вы видите в stream                                                                                                                                                  | Типичное время                              |
| --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
| **Этап запроса** (проверка входных данных)    | Контент представляет собой одно предложение, `I'm sorry, but I cannot assist with that request.` (около 15 tokens), где `finish_reason` имеет значение `content_filter` | Несколько секунд                            |
| **Этап генерации** (проверка выходных данных) | Модель уже сгенерировала часть контента и прерывается, при этом `finish_reason` имеет значение `content_filter`                                                         | Зависит от того, сколько было сгенерировано |

В обоих случаях HTTP-статус равен `200`, и stream штатно завершается с `data: [DONE]`. **В журналах ошибок HTTP ничего не появляется**; только последнее событие в stream сообщает о том, что произошло.

## Потоковая передача против непотоковой

|                                   | Потоковая передача `stream: true`                                                                                                   | Непотоковая передача `stream: false`                                         |
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| Действия платформы при фильтрации | Вывод уже начался, поэтому маршрут переключить невозможно                                                                           | Автоматически выполняется повторная генерация на другом официальном маршруте |
| Что получает ваш клиент           | Обрезанный частичный ответ или однострочный отказ                                                                                   | Полный результат, `finish_reason: "stop"`                                    |
| Тарификация                       | Тарифицируются фактические входные и выходные tokens обрезанного запроса; продолжения или повторные попытки тарифицируются отдельно | Тарифицируется только успешная попытка                                       |
| Обработка на стороне клиента      | Обнаружить `content_filter`, очистить текст, затем продолжить или повторить попытку                                                 | Не требуется                                                                 |
| Лучше всего подходит для          | Контента, отображаемого token за token                                                                                              | Контента, используемого после полного завершения                             |

<Note>
  Автоматическое переключение при сбое для непотоковых запросов значительно повышает вероятность успеха, но она не составляет 100%. Контент, который явно нарушает правила использования поставщика, все равно может быть отклонен самой моделью на другом маршруте; структуру такого ответа см. в [Как выглядит отказ модели OpenAI?](/ru/faq/openai-content-safety-refusal).
</Note>

## Результаты тестирования

2026-09-25 (UTC+8) мы отправили один и тот же набор сценариев раскадровки фильма в `gpt-5.6-terra` в обоих режимах с одинаковыми параметрами (`max_tokens=35000`, `temperature=0`, `reasoning_effort=high`):

| Тема сценария                                                           | Потоковая передача                                                          | Без потоковой передачи |
| ----------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------------------- |
| Поединки боевых искусств с подробным описанием приемов, травм и падений | **5/5 прервано на этапе генерации** (около 1700 tokens)                     | **4/4 завершено**      |
| Экшен и военные сцены с кровопролитием и гибелью                        | **10/10 заблокировано на этапе запроса** (фиксированный однострочный отказ) | **6/6 завершено**      |
| Повседневная жизнь и мистика                                            | 8/8 завершено без сбоев                                                     | —                      |

Повторная отправка того же контента в режиме потоковой передачи дает практически аналогичный результат. **Срабатывание фильтрации зависит главным образом от контента, а не от везения.**

## Как выглядит прерванный stream

Последнее событие, содержащее `choices`, не содержит контента, только причину завершения:

```text theme={null}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"gpt-5.6-terra","choices":[{"delta":{},"finish_reason":"content_filter","index":0}],"usage":null}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","model":"gpt-5.6-terra","choices":[],"usage":{"prompt_tokens":27831,"completion_tokens":6966,"total_tokens":34797}}
data: [DONE]
```

<Warning>
  **Когда вывод обрывается на этапе генерации, отказ на английском языке добавляется прямо в конец собранного текста без переноса строки.** Например, раскадровка на китайском языке обрывается на середине предложения, и сразу за ней следует `I'm sorry, but I cannot assist with that request.`

  Если вы передадите этот текст без изменений в запрос на продолжение, модель увидит отказ в своем контексте, и вероятность повторной блокировки возрастет. **Удалите это предложение перед продолжением.**
</Warning>

## Как выбрать

<CardGroup cols={2}>
  <Card title="Используйте потоковую передачу" icon="zap">
    * Чат, служба поддержки и ответы агентов, где пользователям нужно видеть вывод немедленно
    * Сценарии, в которых пользователи могут остановить генерацию на полпути
    * Повседневное общение редко вызывает срабатывание фильтрации контента, поэтому удобство потоковой передачи важнее
  </Card>

  <Card title="Используйте режим без потоковой передачи" icon="package">
    * Сценарии, раскадровки, главы книг и другие объемные творческие тексты
    * Пакетный перевод, извлечение информации, структурированный JSON
    * Результаты, которые парсятся и сохраняются перед показом пользователям
    * **Контент, который с высокой вероятностью затрагивает деликатные сюжетные темы** (драки, травмы, преступления)
  </Card>
</CardGroup>

Один продукт может **использовать оба подхода**: передавать чат в потоковом режиме, а сценарии или раскадровки генерировать без потоковой передачи. Для последних просто установите `stream` в `false`, оставив все остальное без изменений.

Запрос без потоковой передачи возвращает ответ только после того, как он сгенерирован полностью. Длинные ответы моделей рассуждений могут занимать от 30 до 100 секунд и более, поэтому установите клиентский таймаут для таких запросов **как минимум на 300 секунд**; см. [Как избежать таймаутов API?](/ru/faq/timeout-configuration). Если вашему интерфейсу требуется индикация прогресса, показывайте состояние «генерация» и выводите результат, как только он будет готов.

## Если вам необходимо использовать stream

<Steps>
  <Step title="Записывайте finish_reason во время чтения stream">
    Если `finish_reason` в последнем событии, содержащем `choices`, равен `content_filter`, ответ был отфильтрован. Не полагайтесь на код состояния HTTP.
  </Step>

  <Step title="Удаляйте завершающий отказ">
    Когда вывод прерывается на этапе генерации, текст заканчивается отказом на английском языке. Удалите его перед тем, как решить, что делать с частичным выводом.
  </Step>

  <Step title="Повторите попытку без потоковой передачи">
    Отправьте усеченную часть повторно в виде непотокового запроса, чтобы платформа могла автоматически переключить маршруты. Это оказывается успешным гораздо чаще, чем продолжение с потоковой передачей.
  </Step>

  <Step title="Перефразируйте, если блокировки продолжаются">
    Если для той же задачи завершается сбоем даже непотоковый запрос, опишите чувствительные детали более общими словами и повторите попытку. Не отправляйте тот же контент повторно без изменений.
  </Step>
</Steps>

Вот минимальный пример: чтение stream, удаление отказа при фильтрации и затем повторная попытка без потоковой передачи.

```python theme={null}
import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["APIYI_API_KEY"], base_url="https://api.apiyi.com/v1")

REFUSAL = "I'm sorry, but I cannot assist with that request."

def generate(messages, model="gpt-5.6-terra"):
    stream = client.chat.completions.create(
        model=model,
        messages=messages,
        stream=True,
        stream_options={"include_usage": True},
    )
    parts, finish = [], None
    for chunk in stream:
        if not chunk.choices:
            continue
        choice = chunk.choices[0]
        if choice.delta and choice.delta.content:
            parts.append(choice.delta.content)
            print(choice.delta.content, end="", flush=True)
        if choice.finish_reason:
            finish = choice.finish_reason

    text = "".join(parts)
    if finish != "content_filter":
        return text

    # Filtered: strip the trailing refusal and retry without streaming so the platform can switch routes
    partial = text.removesuffix(REFUSAL)
    print(f"\n[Cut off by content filter after {len(partial)} characters; retrying without streaming]")
    resp = client.chat.completions.create(model=model, messages=messages, timeout=600)
    return resp.choices[0].message.content
```

<Tip>
  В этом примере весь ответ просто генерируется заново без потоковой передачи, что является самым простым подходом. Если в вашем рабочем процессе необходимо сохранить частичный вывод, передайте `partial` в качестве контекста и попросите модель продолжить, но отправьте это продолжение также без потоковой передачи.
</Tip>

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

<AccordionGroup>
  <Accordion title="Тарифицируется ли прерванный запрос с потоковой передачей?">
    Да. Провайдер фактически сгенерировал этот контент, поэтому он тарифицируется за фактические входные и выходные tokens. Для контента, который может вызывать срабатывание фильтрации, режим без потоковой передачи обходится дешевле: тарифицируется только успешная попытка.
  </Accordion>

  <Accordion title="Можно ли отключить фильтрацию контента?">
    Нет. Фильтрация применяется провайдером, и APIYI не может отключить её или изменить степень её строгости. Платформа может лишь повторить отфильтрованный запрос без потоковой передачи по другому официальному маршруту.
  </Accordion>

  <Accordion title="Почему один и тот же контент иногда проходит, а иногда обрывается?">
    Строгость фильтрации между официальными маршрутами несколько различается, к тому же модель каждый раз формулирует ответ по-разному, поэтому пограничный контент в один раз может пройти, а в другой — оборваться. Явно чувствительный контент блокируется всегда.
  </Accordion>

  <Accordion title="Почему платформа не повторяет запросы с потоковой передачей автоматически?">
    Обрыв на этапе генерации происходит уже после того, как контент был отправлен, и ваш клиент уже получил и отобразил первую половину. Повторная генерация с нуля по другому маршруту в этот момент не будет соответствовать тому, что уже было показано. Поэтому запросы с потоковой передачей должны обрабатываться вашим клиентом, как только он обнаружит `content_filter`.
  </Accordion>
</AccordionGroup>

## Связанные документы

<CardGroup cols={2}>
  <Card title="Как выглядит отказ модели OpenAI?" icon="message-square-x" href="/ru/faq/openai-content-safety-refusal">
    Формат ответа и его обнаружение при отказе самой модели
  </Card>

  <Card title="Вызовы с потоковой передачей и без потоковой передачи" icon="audio-lines" href="/ru/faq/streaming-vs-non-streaming">
    Интеграция, тарификация и распространенные заблуждения для обоих режимов
  </Card>

  <Card title="Как избежать тайм-аутов API?" icon="timer" href="/ru/faq/timeout-configuration">
    Настройки тайм-аута для длинных ответов без потоковой передачи
  </Card>

  <Card title="Безопасность контента и соответствие требованиям" icon="shield-check" href="/ru/faq/content-safety">
    Политика платформы в отношении безопасности контента и соответствия требованиям
  </Card>
</CardGroup>
