AS
beginner⏱ 9 мин

Что реально уходит, когда вы нажимаете Send

🔍

Что происходит

Один и тот же вопрос в двух чат-приложениях — разные ответы. Даже если в обоих выбран «один и тот же» Claude или GPT. Первое объяснение, которое приходит в голову, неверное: «модель сегодня в другом настроении». Модель тут ни при чём — приложения отправили разные запросы.

Ваш вопрос — это только одна строка в запросе. В том же запросе передаются история переписки, системные инструкции, определения инструментов и десяток параметров.

🤔

До определения

Пользователь набрал одну строку: «Почему небо голубое?». Ниже — то, что реально ушло на сервер (сокращено):

{
  "model": "<id модели>",
  "max_tokens": 200,
  "system": "Ты отвечаешь кратко и по-русски.",
  "messages": [
    {"role": "user", "content": "Почему небо голубое?"}
  ]
}

Системная инструкция «отвечай кратко» пользователь не писал — её добавило приложение. Именно поэтому приложения отвечают по-разному на один и тот же вопрос.

📖

Определение

API-запрос — это JSON-документ, который приложение отправляет провайдеру по HTTP; модель не видит «ваш вопрос» — она видит только этот документ.

Роль сообщения (role) — поле, указывающее, от кого реплика: системные/developer-инструкции, пользователь, ассистент. От роли зависит вес, который модель придаёт реплике.

💡

Mental model

Представьте, что вы диктуете письмо секретарю. Секретарь — приложение. Он берёт ваш текст, прикладывает к нему устав компании (system), предыдущую переписку (history) и инструкцию «какие инструменты разрешены» (tools), а затем отдаёт всё это в модель.

Ограничение аналогии: секретарь ничего не переписывает и не «понимает» — он механически собирает JSON. Ровно поэтому баг в сборке запроса выглядит как «странное поведение модели».

⚙️

Under the hood

Что лежит в запросе (упрощённо, по документации двух провайдеров):

  • model — id модели;
  • messages — массив реплик {role, content}. У OpenAI роли: developer | system | user | assistant | tool | function; у Anthropic в messages — user | assistant, а системный промпт передаётся отдельным top-level параметром system;
  • инструкции: у Anthropic system — отдельное поле; у OpenAI-моделей нового поколения (o1 и новее) инструкции передаются ролью developer — она используется вместо роли system и имеет приоритет выше пользовательских сообщений;
  • лимиты генерации: у Anthropic max_tokens — обязательный параметр; у OpenAI — max_tokens/max_completion_tokens;
  • параметры сэмплинга: temperature доступен не везде (у Anthropic он deprecated для моделей после Opus 4.6);
  • stream — включить потоковую доставку (SSE);
  • tools — описания инструментов, которые модель может попросить вызвать (мир 7).

В ответ приходит JSON: текст, stop_reason/finish_reason и usage — сколько токенов вошло и вышло (у OpenAI — prompt_tokens/completion_tokens и cached_tokens в details, у Anthropic — input_tokens/output_tokens). Токенам и счётчикам посвящён мир 2.

🔬

Inspect

Ответ на минимальный запрос (структура по документации; значения сокращены):

{
  "role": "assistant",
  "content": [{"type": "text", "text": "..."}],
  "stop_reason": "end_turn",
  "usage": {"input_tokens": 21, "output_tokens": 57}
}

Поле usage содержит точные размеры входа и выхода; при разборе стоимости и лимитов на него смотрят в первую очередь.

✋

Попробуйте сами

Соберите тело запроса для своего вопроса и отправьте его. Единственные подстановки — ключ ($ANTHROPIC_API_KEY) и id модели из личного кабинета провайдера — реальных креденшелов в уроке нет:

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "'"$MODEL_ID"'",
    "max_tokens": 200,
    "system": "Ты отвечаешь кратко.",
    "messages": [{"role": "user", "content": "Почему небо голубое?"}]
  }' | python3 -m json.tool

Затем замените system на пользовательское сообщение и сравните ответ. Вы только что изменили приоритет инструкции, не меняя «вопрос».

💥

А теперь сломаем

Уберите max_tokens из запроса к Anthropic. Запрос упадёт с ошибкой 400: параметр обязателен. Теперь добавьте temperature к модели, которая его не поддерживает (выпущенной после Opus 4.6) — снова ошибка. Модель не сломалась: ошибку содержит код, собирающий API-вызов, а не текст пользователя.

Ещё один случай без сообщения об ошибке: две подряд реплики одной роли. Anthropic их объединяет в одну — история, которую вы «передали», отличается от той, что увидела модель.

🩺

Диагностика

Симптом: «тот же вопрос — другой ответ» или «после обновления библиотеки всё сломалось».

  1. Посмотрите на фактически отправляемый JSON (лог/curl -v/mitm-прокси в dev).
  2. Сравните: совпадают ли роли, порядок сообщений, системные инструкции, значения параметров.
  3. Проверьте usage в ответе — не превышает ли вход ожидаемый размер (лишняя история/tools).

Не начинайте с «промпт плохой»: сначала проверьте, что промпт вообще дошёл в том виде, в котором вы его задумали.

⚖️

С чем это путают

  • «Промпт» и «запрос». Ваш текст — часть запроса. Запрос шире: инструкции, история, параметры, инструменты.
  • Модель и продукт вокруг неё. Модель — предиктор токенов по входному документу; чат-приложение, гарнес и API — разные обёртки с разной сборкой запроса (CONTEXT.md §4).
  • system у разных провайдеров. У Anthropic — top-level поле; у OpenAI — роль (в новых моделях её место занимает developer). Не переносите примеры между провайдерами дословно.
✅

Проверка

  1. (scenario) Инструкция должна быть выше пользовательских, API — OpenAI-совместимый, модель новая (o1+). Какую роль использовать для инструкции?
  2. (multiple) Что из перечисленного может находиться внутри API-запроса к модели?
  3. (scenario) Два приложения с одной моделью отвечают по-разному. Что проверить первым?

Полный набор — 01-what-happens-on-send.quiz.json.

📌

Что помнить

  1. Модель видит не ваш текст, а JSON-документ, собранный приложением.
  2. Роли и системные инструкции — механизм управления приоритетом, а не «часть промпта».
  3. max_tokens и доступность temperature зависят от провайдера и модели.
  4. usage в ответе — точные размеры входа и выхода.
  5. Первый шаг любой диагностики — посмотреть фактический JSON запроса.
📚

Sources

  • claude-messages-api — Anthropic Messages API: system top-level, роли, max_tokens обязателен, temperature deprecated после Opus 4.6, объединение подряд идущих реплик (verified 2026-10-04).
  • openai-python-sdk — роли Chat Completions; developer «replace the previous system messages» для o1+ (verified 2026-10-04).
  • openai-openapi — структура usage (prompt_tokens/completion_tokens/total_tokens, cached_tokens, reasoning_tokens), finish_reason (verified 2026-10-04).

Проверка

Вопрос 1 из 3Сценарий

Инструкция приложения должна иметь приоритет выше пользовательских сообщений. API — OpenAI-совместимый, модель нового поколения (o1 и новее). Какую роль использовать для этой инструкции?