> ## 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.

# Как выглядит отказ модели OpenAI?

> Когда модель GPT отклоняет запрос, нарушающий политику использования провайдера, она возвращает статус 200 с кратким отказом, без ошибки и категории. Ознакомьтесь с телом ответа и узнайте, как его обнаружить.

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

Когда модель GPT получает запрос, нарушающий политику использования провайдера, она **не возвращает ошибку**. API отвечает с кодом HTTP 200, `finish_reason` имеет значение `stop`, а содержимое представляет собой отказ, написанный самой моделью, например «Я не могу помочь с этим…».

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

## Тело ответа с отказом

Ниже приведен реальный непотоковый отказ от `/v1/chat/completions` (содержимое заменено нейтральным примером):

```json theme={null}
{
  "model": "gpt-5.6-terra",
  "object": "chat.completion",
  "created": 1789712872,
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "I can't help with that request. I can, however, help with a related topic or a rewritten version that stays within the usage policy."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 35,
    "completion_tokens": 54,
    "total_tokens": 89
  }
}
```

| Поле            | Как выглядит отказ                                                                                                                                 |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| HTTP-статус     | `200`                                                                                                                                              |
| `finish_reason` | `stop`, как и в обычном ответе                                                                                                                     |
| `message`       | Только `role` и `content`; отдельного поля `refusal` **нет**                                                                                       |
| Начальные слова | Обычно `I can't…` или `Sorry, I can't…`; на китайском — `抱歉，我不能…`                                                                                  |
| Язык            | Соответствует prompt: на prompt на китайском языке обычно возвращается отказ на китайском                                                          |
| Длина           | В основном 50–120 tokens; темы, связанные с личным благополучием, сопровождаются рекомендациями по поддержке и могут достигать примерно 400 tokens |
| Тарификация     | Тарифицируется в обычном порядке по фактическому количеству входных и выходных tokens                                                              |

## Почему категория отсутствует

Для запросов, нарушающих правила, чат-API OpenAI **позволяет модели принять решение не отвечать** вместо возврата ошибки. Он не сообщает, какая именно категория была затронута (например, контент для взрослых, сцены насилия или причинение себе вреда), и не указывает степень серьезности.

Это отличается от ошибки. При ошибке вы получаете статус, отличный от 200, и объект `error`. При отказе же вы получаете **успешный вызов**, содержимое которого просто не является тем, что вы запрашивали.

## Перевод и структурированный вывод

В задачах пакетного перевода и извлечения данных от модели обычно требуется фиксированный формат, например массив JSON. Когда пакет вызывает отказ, модель возвращает обычное предложение, поэтому его парсинг как JSON завершается с ошибками вроде `Unrecognized token 'I'` или `Expecting value`.

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

<Info>
  APIYI включил автоматическое переключение при сбое для безопасности контента в **запросах без потоковой передачи**. Если один официальный маршрут активирует фильтр контента — для prompt или для сгенерированного вывода, — запрос автоматически повторяется через другой официальный маршрут без необходимости повторных попыток с вашей стороны. После переключения большинство запросов возвращают обычный результат; небольшая часть все еще может быть отклонена самой моделью — именно этот случай и описан на данной странице.
</Info>

## Как это обнаружить и обработать

<Steps>
  <Step title="Сначала проверьте формат вывода">
    Если вы запрашивали JSON, парсите его как JSON; если запрашивали фиксированное количество элементов, проверьте их число. Если формат не совпадает, считайте вызов «результат отсутствует» и не используйте полученный контент в качестве вывода.
  </Step>

  <Step title="Затем проверьте, не является ли это отказом">
    Если формат не совпадает, проверьте, не представляет ли собой контент короткое предложение, начинающееся с `I can't`, `Sorry` или подобных фраз. Если это так, то это почти наверняка отказ, а не отклонение модели от формата.
  </Step>

  <Step title="Не повторяйте запрос без изменений">
    Повторная отправка того же контента без изменений, скорее всего, приведет к аналогичному отказу, при этом каждая попытка тарифицируется.
  </Step>

  <Step title="Разделите пакет, чтобы найти конкретные элементы">
    Отправьте неудавшийся пакет повторно меньшими частями, чтобы выяснить, какие именно элементы вызывают отказ; остальные обычно обрабатываются успешно. Для элементов, вызвавших отказ, скорректируйте формулировку и попробуйте снова.
  </Step>

  <Step title="Архивируйте неудачные случаи, затем решите, стоит ли сменить модель">
    Ведите внутренний архив неудачных случаев (входные данные, время запроса, ID запроса, возвращенный контент), анализируйте, на каких типах контента концентрируются отказы, и затем рассмотрите возможность повторной отправки этого контента с использованием другой модели.
  </Step>
</Steps>

<Tip>
  Мы рекомендуем сделать цепочку «архивация неудачных случаев → анализ → повторная попытка с другой моделью» стандартным процессом. Отказы обычно группируются вокруг нескольких типов контента, поэтому архив позволяет легко увидеть закономерность. Это избавляет от повторных ручных проверок и предотвращает повторную оплату за один и тот же контент.
</Tip>

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

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

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

REFUSAL_PREFIXES = ("I can't", "I can’t", "Sorry", "I'm sorry", "I’m sorry", "抱歉")

def translate_batch(lines):
    prompt = "Translate each subtitle line below into English. Output a JSON array only:\n" + json.dumps(lines, ensure_ascii=False)
    resp = client.chat.completions.create(
        model="gpt-5.6-terra",
        messages=[{"role": "user", "content": prompt}],
    )
    text = resp.choices[0].message.content or ""
    try:
        result = json.loads(text)
        if isinstance(result, list) and len(result) == len(lines):
            return result
    except json.JSONDecodeError:
        pass

    # No usable result: record it for later analysis or a retry with another model
    with open("failed_cases.jsonl", "a", encoding="utf-8") as f:
        f.write(json.dumps({
            "time": time.strftime("%Y-%m-%d %H:%M:%S %z"),
            "request_id": resp.id,
            "is_refusal": text.strip().startswith(REFUSAL_PREFIXES),
            "input": lines,
            "output": text,
        }, ensure_ascii=False) + "\n")
    return None
```

## Запросы с потоковой передачей

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

* краткий отказ, в последнем событии которого `finish_reason` установлено в `content_filter`; или
* часть уже доставленного контента, заканчивающуюся на `finish_reason: "content_filter"`.

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

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

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

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

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

  <Accordion title="Как получить категорию отказа?">
    OpenAI chat API не возвращает ее. Если для вашего рабочего процесса требуются категории, классифицируйте контент самостоятельно перед отправкой или разбирайте архивные неудачные запросы вручную.
  </Accordion>
</AccordionGroup>

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

<CardGroup cols={2}>
  <Card title="Обработка ответов" icon="braces" href="/ru/api-capabilities/openai/response-handling">
    Единый подход к парсингу ответов с потоковой передачей и без нее
  </Card>

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