Source: https://aiprimetech.io/ru/blog/streaming-api-guide/ 22 июня, 2026 · 6 мин · API # Потоковая передача ответов LLM: почему она важна для UX и стоимости A Автор: [AI Prime Tech](https://aiprimetech.io/ru/) · При участии ИИ ## Те 900 мс, из-за которых наш интерфейс чата казался «сломавшимся» Несколько месяцев назад я отлаживал ассистента службы поддержки, у которого на бумаге была вполне приемлемая сквозная задержка: большинство ответов завершались за 4–7 секунд. Модель выбирала инструменты, получала контекст учётной записи и генерировала полезный ответ. Но пользователям это не нравилось. Причина была простой: первые 3.8 секунд интерфейс оставался пустым. Ни поясняющего текста рядом с индикатором загрузки, ни частичного ответа, ни признака того, что модель поняла вопрос. Только пустой пузырь сообщения ассистента. Когда мы переключили тот же эндпоинт на потоковую передачу токенов через Server-Sent Events, среднее общее время завершения почти не изменилось. Но время до первого видимого вывода для многих запросов сократилось примерно до 700–900 мс, и продукт сразу стал ощущаться быстрее. Именно поэтому потоковая передача действительно важна. Потоковая передача ответов LLM — не магия. Она не заставляет модель думать быстрее. Она не сокращает общее число токенов. Она не уменьшает ваш счёт автоматически. Но она меняет цикл взаимодействия так, что пользователи это ощущают, и даёт вашему приложению больше контроля над отменой, отображением, модерацией, учётом использования и регулированием потока при перегрузке. В этой статье мы разберём, как на самом деле работает потоковая передача через SSE, что измерять, где возникают тонкости с оплатой и какие клиентские подходы я использую в продакшен-системах. ## В чём главное преимущество потоковых ответов? Главное преимущество потоковых ответов — воспринимаемая задержка: пользователь видит первые токены через несколько сотен миллисекунд вместо того, чтобы смотреть на индикатор загрузки всё время генерации. Общее время генерации почти не меняется — меняется время до первого токена, и именно этот показатель ощущают пользователи. Ответ, который полностью завершается за 9 секунд, но начинает появляться через 400 мс, воспринимается как быстрый; тот же ответ, показанный целиком через 9 секунд, создаёт впечатление, что всё сломалось. Есть и дополнительные преимущества: потоковая передача позволяет постепенно отображать частичный результат, досрочно отменять генерацию, когда пользователь уже увидел достаточно информации, экономя выходные токены, и избегать тайм-аутов чтения на прокси при длинных ответах. Но если запомнить только одно: потоковая передача не ускоряет модель — она убирает ощущение ожидания из пользовательского опыта. ## Что на самом деле означает потоковая передача Когда вы отправляете запрос к LLM без потоковой передачи, сервер обычно ждёт, пока модель закончит генерацию ответа, а затем возвращает единый блок данных JSON: ``` { "id": "resp_123", "model": "some-model", "output_text": "Sure — here is the answer...", "usage": { "input_tokens": 812, "output_tokens": 436 } } ``` При потоковой передаче сервер отправляет события по мере появления новых частей результата. Самый распространённый способ передачи — события, отправляемые сервером (Server-Sent Events), обычно сокращённо называемые SSE. SSE — это просто ответ HTTP с длительно открытым соединением и особым типом содержимого: ``` Content-Type: text/event-stream Cache-Control: no-cache Connection: keep-alive ``` Вместо одного объекта JSON сервер отправляет последовательность небольших событий: ``` event: message.delta data: {"delta":"Sure"} event: message.delta data: {"delta":" — here"} event: message.delta data: {"delta":" is"} event: message.delta data: {"delta":" the answer..."} event: message.done data: {"finish_reason":"stop","usage":{"input_tokens":812,"output_tokens":436}} ``` Разные API используют разные имена событий и схемы, но общая структура обычно одинакова: - Открыть соединение HTTP. - Отправить метаданные запроса и промпт. - Получать последовательные фрагменты. - Добавлять фрагменты к текущему сообщению ассистента. - Получить финальное событие с причиной остановки и, зачастую, метаданными использования. - Закрыть поток. На практике «потоковая передача» в большинстве LLM не означает один токен на событие. Для эффективности провайдеры могут объединять токены во фрагменты. Вы можете получить один символ, часть слова, несколько слов или структурированное приращение JSON. Никогда не создавайте клиент, который предполагает, что каждый фрагмент — это целое слово или целое предложение. ## Задержка: общее время и время до первого токена Самое важное — различать общую задержку и время до первого токена. | Метрика | Что измеряет | Почему это важно | Время до первого байта, TTFB | Получение первого байта от сервера | Включает маршрутизацию, аутентификацию, ожидание в очереди и планирование запуска модели | Время до первого токена, TTFT | Первый сгенерированный токен или фрагмент, видимый пользователю | Главный фактор воспринимаемой отзывчивости | Токенов в секунду | Скорость генерации вывода после первого токена | Определяет, насколько быстро завершаются длинные ответы | Общее время завершения | Получение полного ответа | Важно для автоматизации, вызовов инструментов и пакетных задач | Время до получения пригодного для использования ответа | У пользователя достаточно информации, чтобы действовать | Часто наступает раньше полного завершения Для UX чата TTFT обычно важнее общего времени. Ответ, который начинает появляться через 800 мс и завершается за 8 секунд, часто воспринимается лучше, чем ответ, который появляется целиком через 4 секунд. В процессах межмашинного взаимодействия потоковая передача часто менее важна. Если следующий шаг нельзя выполнить до завершения всего объекта JSON, потоковая передача может лишь усложнить реализацию. ### Измерение TTFT в Python Вот простой подход к измерению задержки до первого фрагмента и общего времени передачи потока. Структура API намеренно сделана универсальной: адаптируйте URL и тело запроса под своего провайдера. ``` import json import time import requests url = "https://api.example.com/v1/chat/completions" payload = { "model": "sonnet-4.6", "stream": True, "messages": [ {"role": "user", "content": "Explain SSE streaming in 5 bullet points."} ] } headers = { "Authorization": "Bearer $API_KEY", "Content-Type": "application/json", "Accept": "text/event-stream", } start = time.perf_counter() first_chunk_at = None chars = 0 with requests.post(url, headers=headers, json=payload, stream=True) as r: r.raise_for_status() for raw_line in r.iter_lines(decode_unicode=True): if not raw_line: continue if not raw_line.startswith("data: "): continue data = raw_line[len("data: "):] if data == "[DONE]": break event = json.loads(data) # Provider-specific: this may be event["delta"], event["choices"][0]["delta"], etc. delta = event.get("delta", "") if delta and first_chunk_at is None: first_chunk_at = time.perf_counter() chars += len(delta) print(delta, end="", flush=True) end = time.perf_counter() print("\n\n--- metrics ---") print(f"ttft_ms={((first_chunk_at or end) - start) * 1000:.0f}") print(f"total_ms={(end - start) * 1000:.0f}") print(f"chars={chars}") ``` Распространённая ловушка: если вы тестируете потоковую передачу через локальный прокси, бессерверную функцию или обратный прокси, который буферизует ответы, вам может показаться, что модель не передаёт данные потоком. Модель может работать правильно, но ваша инфраструктура удерживает фрагменты до завершения ответа. Я сталкивался с этим в следующих случаях: - Включённая буферизация в Nginx. - Облачные функции, не поддерживающие потоковые ответы. - Промежуточное ПО для сжатия, которое ждёт накопления более крупных буферов. - Веб-фреймворки, которые формируют весь ответ перед его возвратом. - Корпоративные прокси, объединяющие небольшие фрагменты. Для Nginx часто важна эта настройка: ``` location /api/llm/stream { proxy_pass http://app_backend; proxy_http_version 1.1; proxy_buffering off; proxy_cache off; chunked_transfer_encoding on; add_header X-Accel-Buffering no; } ``` ## SSE и WebSockets SSE — не единственный способ потоковой передачи. WebSockets тоже широко используются, особенно в приложениях с двусторонним обменом. Однако для большинства интерфейсов чата с LLM SSE — более простой вариант по умолчанию. | Функция | SSE | WebSocket | Направление | От сервера к клиенту | Двустороннее | Протокол | Обычный ответ HTTP | Переключение на WebSocket | Поддержка в браузерах | Нативный EventSource; также работает с fetch потоками | Нативный WebSocket | Поведение при повторном подключении | Встроенный механизм, хотя логика приложения всё равно нужна | Реализуется вами | Совместимость с балансировщиками нагрузки | Обычно проще | Иногда требует дополнительной настройки | Лучше всего подходит для | Потоковая передача токенов, события прогресса, простой чат | Совместная работа в реальном времени, аудио, интерактивные сеансы с несколькими обменами сообщениями | Поддержка тела запроса | EventSource поддерживает только GET; используйте fetch для потоковой передачи POST | Полноценный двунаправленный обмен сообщениями В EventSource Браузерный API удобен, но поддерживает только GET-запросы. Для большинства вызовов LLM нужны тела запросов POST и заголовки авторизации, поэтому для потоковой передачи я обычно использую fetch() и ReadableStream. ## Шаблон браузерного клиента: Fetch + ReadableStream Минимальная реализация для браузера выглядит так: ``` async function streamChat({ messages, signal, onDelta, onDone }) { const res = await fetch("/api/chat/stream", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model: "gpt-5.5", stream: true, messages }), signal }); if (!res.ok) { throw new Error(`HTTP ${res.status}`); } const reader = res.body.getReader(); const decoder = new TextDecoder("utf-8"); let buffer = ""; while (true) { const { value, done } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split("\n"); buffer = lines.pop() || ""; for (const line of lines) { const trimmed = line.trim(); if (!trimmed.startsWith("data:")) continue; const data = trimmed.slice(5).trim(); if (data === "[DONE]") { onDone?.(); return; } const event = JSON.parse(data); if (event.delta) { onDelta(event.delta); } } } onDone?.(); } ``` А в интерфейсе: ``` const controller = new AbortController(); let assistantText = ""; streamChat({ messages, signal: controller.signal, onDelta(delta) { assistantText += delta; renderAssistantMessage(assistantText); }, onDone() { markMessageComplete(); } }); // Cancel button document.querySelector("#stop").onclick = () => { controller.abort(); }; ``` ### Не отображайте каждый фрагмент без оптимизации Если обновлять состояние React при получении каждого крошечного фрагмента, можно случайно создать проблему с производительностью на стороне клиента. Некоторые потоки выдают десятки фрагментов в секунду. Каждый раз повторно отрисовывать большое дерево компонентов чата — нерационально. На практике я обычно объединяю обновления интерфейса по кадрам анимации: ``` let pending = ""; let scheduled = false; function onDelta(delta) { pending += delta; if (!scheduled) { scheduled = true; requestAnimationFrame(() => { assistantText += pending; pending = ""; scheduled = false; setAssistantText(assistantText); }); } } ``` Это сохраняет плавность интерфейса и ощущение вывода в реальном времени. ## Корректная обработка частичного вывода При потоковой передаче приложение получает незавершённый текст. Это кажется очевидным, но многие ошибки возникают из-за того, что частичный вывод обрабатывается как окончательный. ### Markdown временно некорректен Во время потоковой передачи разметка Markdown может быть некорректной: ``` Here is the query: ```sql SELECT * FROM users WHERE ``` Блок кода может быть ещё не закрыт. В таблице может быть только строка заголовка. Ссылка может быть выведена лишь наполовину. Средство отображения должно уметь обрабатывать такие ситуации. Для интерфейсов чата я предпочитаю следующее: - Отображайте Markdown по мере поступления, учитывая возможную некорректность разметки. - Отключайте опасный HTML. - Не используйте ресурсоёмкую подсветку синтаксиса, пока сообщение не завершено. - Показывайте ненавязчивый индикатор генерации. - После завершения потока повторно применяйте окончательное форматирование. ### Потоковая передача JSON сложнее Если попросить модель выдать JSON и передавать его потоком, промежуточное состояние обычно представляет собой некорректный JSON. Это проблема для приложений, которым нужно обновлять структурированные интерфейсы в реальном времени. Например: ``` { "title": "Incident Summary", "severity": "high", "steps": [ "Restart ``` Это пока невозможно разобрать. Есть три распространённых подхода: - Дождаться завершения, затем выполнить разбор один раз. - Использовать JSON с разделением по строкам, где каждую завершённую строку можно разобрать независимо. - Передавать потоком семантические события, а не необработанный JSON. Для структурированной потоковой передачи я предпочитаю вывод в виде событий: ``` event: section data: {"title":"Summary"} event: bullet data: {"text":"Database failover started at 09:42 UTC."} event: bullet data: {"text":"Read latency remained elevated for 6 minutes."} ``` Этот подход требует более сложной координации, но позволяет гораздо надёжнее отображать данные. ## Что на самом деле происходит, когда пользователь нажимает «Остановить» Отмена — одно из недооценённых преимуществ потоковой передачи. При запросе без потоковой передачи пользователь может уйти со страницы, а модель продолжит генерацию на сервере. В зависимости от провайдера и вашего бэкенда эта генерация может по-прежнему расходовать выходные токены. При потоковой передаче клиент может прервать запрос HTTP: ``` const controller = new AbortController(); fetch("/api/chat/stream", { method: "POST", body: JSON.stringify(payload), signal: controller.signal }); // Later controller.abort(); ``` Но отмена не всегда мгновенно проходит через всю цепочку. В ней несколько уровней: - Браузер прерывает запрос fetch. - Бэкенд обнаруживает закрытие соединения. - Бэкенд отменяет запрос к провайдеру. - Провайдер останавливает генерацию. - Объём использования рассчитывается по уже обработанным и сгенерированным токенам. Распространённая ловушка: если бэкенд проксирует поток, но не передаёт отмену провайдеру, браузер пользователя отключается, а сервер продолжает читать вывод модели до завершения. В псевдокоде в стиле Node: ``` app.post("/api/chat/stream", async (req, res) => { const upstreamController = new AbortController(); req.on("close", () => { upstreamController.abort(); }); const upstream = await fetch(PROVIDER_URL, { method: "POST", headers: providerHeaders, body: JSON.stringify({ ...req.body, stream: true }), signal: upstreamController.signal }); res.setHeader("Content-Type", "text/event-stream"); for await (const chunk of upstream.body) { res.write(chunk); } res.end(); }); ``` В этом и заключается разница между «интерфейс остановился» и «модель остановилась». ## Потоковая передача и стоимость: что меняется, а что нет Потоковая передача меняет момент, когда вы узнаёте об объёме использования. Обычно она не меняет базовую единицу тарификации. Большинство API для LLM рассчитывают стоимость примерно по следующим категориям: - Входные токены. - Выходные токены. - Кэшированные входные токены, если применяется кэширование промптов. - Вызовы инструментов или специальные модальности — в зависимости от API. - Иногда — токены рассуждений или внутренние вычисления в рамках выделенного бюджета для определённых семейств моделей. Сама по себе потоковая передача обычно не даёт скидки. Если модель генерирует 700 выходных токенов, следует учитывать 700 выходных токенов независимо от того, поступают они постепенно или одним итоговым пакетом данных. Потоковая передача влияет на стоимость на уровне работы системы: | Сценарий | Влияние на стоимость | Пользователь отменяет генерацию после 80 токенов | Можно избежать генерации оставшейся части ответа, если отмена передаётся по всей цепочке | Интерфейс заранее определяет, что ответа уже достаточно | Приложение может намеренно остановить генерацию | Бэкенд не прерывает запрос к провайдеру | Возможно, придётся оплатить всю генерацию, несмотря на отключение клиента | Данные об использовании приходят только в финальном событии | Для прерванных потоков могут потребоваться журналы провайдера или приблизительные оценки | Длинные ответы по умолчанию передаются потоком | Пользователи могут потреблять больше, поскольку работа с интерфейсом ощущается более плавной | Вызовы инструментов до начала потоковой передачи текста | TTFT может увеличиться, но стоимость выходных токенов может остаться прежней ### Ловушка при учёте использования Многие API потоковой передачи отправляют метаданные об использовании в конце потока: ``` { "type": "message.done", "usage": { "input_tokens": 1240, "output_tokens": 389 }, "finish_reason": "stop" } ``` Если поток прерван до финального события, приложение может не получить данные об использовании. Это не обязательно означает, что использование было нулевым. Для внутреннего учёта я обычно сохраняю три поля: ``` { "request_id": "chat_01j...", "status": "client_aborted", "usage": null, "estimated_output_chars": 1842, "final_usage_received": false } ``` Затем сверяю данные, если провайдер предоставляет журналы запросов или события использования. Если нет, можно хотя бы получить приблизительную оценку для продуктовой аналитики, избегая ложной точности при расчёте оплаты. Не выставляйте конечным пользователям счета на основе оценки по количеству символов, если ваши условия явно не предусматривают такой подход. Токенизация зависит от модели и языка. ## Шаблон архитектуры бэкенда В рабочей системе путь потоковой передачи обычно выглядит так: ``` Browser | | POST /api/chat/stream v App Backend | | provider streaming request v LLM API ``` Я редко предоставляю браузерам прямой доступ к ключам провайдера. Бэкенд обеспечивает: - Аутентификацию и авторизацию. - Ограничение частоты запросов для каждого пользователя или рабочего пространства. - Сборку промпта и поиск данных. - Выполнение инструментов. - Удаление конфиденциальных данных и управление журналированием. - Переключение на резервного провайдера при сбое. - Передачу отмены по всей цепочке. - Регистрацию использования. Минимальный потоковый ответ бэкенда на Python с FastAPI: ``` import json from fastapi import FastAPI, Request from fastapi.responses import StreamingResponse import httpx app = FastAPI() PROVIDER_URL = "https://api.example.com/v1/chat/completions" @app.post("/api/chat/stream") async def chat_stream(request: Request): body = await request.json() async def event_generator(): async with httpx.AsyncClient(timeout=None) as client: async with client.stream( "POST", PROVIDER_URL, headers={ "Authorization": "Bearer YOUR_PROVIDER_KEY", "Content-Type": "application/json", "Accept": "text/event-stream", }, json={ **body, "stream": True, }, ) as upstream: async for line in upstream.aiter_lines(): if await request.is_disconnected(): break if not line: continue # Optionally transform provider-specific events here. yield line + "\n\n" return StreamingResponse( event_generator(), media_type="text/event-stream", headers={ "Cache-Control": "no-cache", "X-Accel-Buffering": "no", }, ) ``` На практике я обычно привожу события провайдеров к единой внутренней схеме: ``` { "type": "delta", "text": "partial text here" } ``` а затем: ``` { "type": "done", "finish_reason": "stop", "usage": { "input_tokens": 812, "output_tokens": 436 } } ``` Это важно, если за одним интерфейсом вы поддерживаете несколько моделей, например Claude, GPT, Gemini, Llama, Qwen или Kimi. У каждого провайдера семантика потоковой передачи немного отличается. Если нормализовать события на раннем этапе, фронтенд останется простым и предсказуемым — именно таким, каким и должен быть. ## TTFT зависит не только от модели Когда TTFT оставляет желать лучшего, люди часто первым делом винят модель. Иногда это справедливо: более крупные модели, длинные контексты и режимы с более интенсивными рассуждениями могут увеличить задержку до первого токена. Но до появления первого токена задействовано множество механизмов. На задержку влияют: - Установка TLS-соединения. - Холодные запуски бэкенда. - Формирование промпта и поиск данных. - Задержка векторной базы данных. - Вызовы инструментов до начала генерации. - Ожидание в очереди провайдера. - Обработка длинного входного контекста. - Проверки безопасности или уровни применения политик. - Буферизация на прокси. - Задержка отрисовки на клиенте. На практике трассировка должна разделять эти этапы: ``` { "trace_id": "req_abc", "timings_ms": { "auth": 12, "retrieval": 84, "prompt_build": 9, "provider_connect": 141, "ttfb": 612, "first_delta": 804, "stream_complete": 5820 } } ``` Если поиск занимает 600 мс, а первый фрагмент ответа модели приходит ещё через 250 мс, смена модели может не улучшить пользовательский опыт. Если основное время уходит на установку соединения с провайдером, может помочь повторное использование соединений. Если фронтенд ждёт целого абзаца перед отрисовкой, потоковая передача работает, но правила отображения в интерфейсе скрывают её. ## Когда не стоит использовать потоковую передачу Потоковая передача не всегда оправданна. Я не использую потоковую передачу, когда: - Ответ очень короткий, например при классификации или маршрутизации. - Запрос отправляет другой сервис, которому нужен полный JSON. - Перед отображением результат должен полностью пройти модерацию. - Запрос выполняется в очереди задач или конвейере пакетной обработки. - Фреймворк или среда хостинга делают потоковую передачу ненадёжной. - Продукту нужны ответы целиком, а не постепенно появляющийся текст. Есть и недостаток для пользовательского опыта: при потоковой передаче видно, как модель меняет направление посреди ответа. В чате пользователи в какой-то мере это терпят, но в рабочих процессах с высокой ценой ошибки это может выглядеть недостаточно профессионально. В юридических, медицинских, финансовых интерфейсах или интерфейсах со строгими требованиями соответствия можно начинать потоковую передачу только после защитных проверок либо направлять поток во внутренний буфер, прежде чем показывать безопасные фрагменты. ## Практические подходы на стороне клиента Вот подходы, которые я рекомендую для большинства чат-продуктов: ### 1. Показывайте статус до появления текста Не оставляйте сообщение ассистента пустым. Используйте явные состояния: - «Читаю контекст…» - «Ищу в документах…» - «Готовлю ответ…» - «Ещё работаю…» Это особенно полезно, когда вызовы инструментов происходят до генерации текста. ### 2. Сделайте кнопку остановки действительно работающей Кнопка остановки — не просто элемент интерфейса. При правильной реализации она позволяет экономить выходные токены. Убедитесь, что: - Браузер прерывает запрос. - Ваш бэкенд обнаруживает разрыв соединения. - Ваш бэкенд прерывает запрос к провайдеру. - Вы фиксируете запрос как отменённый. ### 3. Отрисовывайте постепенно, окончательно форматируйте после завершения Во время потоковой передачи: - Добавляйте текст. - Используйте облегчённую отрисовку Markdown. - Избегайте ресурсоёмкой подсветки синтаксиса. - Сохраняйте предсказуемое поведение прокрутки. После завершения: - Повторно разбирайте Markdown. - Добавляйте подсветку кода. - Активируйте кнопки копирования. - Добавляйте ссылки на источники, если ваша система их поддерживает. ### 4. Аккуратно сохраняйте частичные сообщения Если поток прерывается на полпути, определите, как это должно отражаться в истории диалога. Варианты: - Сохранить частичное сообщение ассистента с пометкой «прервано». - Полностью удалить его. - Позволить пользователю повторить запрос с тем же промптом. - Попросить модель продолжить на основе частичного контекста. Обычно я сохраняю частичное сообщение с заметной пометкой. Удаление без уведомления сбивает пользователей с толку, а создавать видимость завершённого ответа ещё хуже. ### 5. Нормализуйте события Ваш фронтенд не должен разбираться в пяти форматах потоковой передачи разных провайдеров. Нормализуйте их в бэкенде: ``` {"type":"delta","text":"Hello"} {"type":"tool_start","name":"search_docs"} {"type":"tool_result","name":"search_docs","status":"ok"} {"type":"done","finish_reason":"stop","usage":{"input_tokens":100,"output_tokens":50}} {"type":"error","message":"upstream timeout"} ``` Это также упрощает переключение между семействами моделей и динамическую маршрутизацию запросов. Если вы используете слой API для нескольких моделей, такая нормализация уже может быть частью вашего шлюза; иначе её стоит реализовать самостоятельно. ## Практические рекомендации - Потоковая передача улучшает воспринимаемую задержку, сокращая время до появления первого видимого результата, а не делая всю генерацию бесплатной или мгновенной. - Измеряйте TTFT, общее время до завершения и количество токенов в секунду отдельно. - SSE обычно является самым простым транспортом для потоковой передачи текста LLM; используйте fetch() потоки, когда нужны тела POST. - Следите за буферизацией в прокси и фреймворках. Многие «ошибки потоковой передачи» на самом деле связаны с буферизацией в инфраструктуре. - Считайте частичный результат невалидным: Markdown может быть незавершённым, JSON может не поддаваться разбору, а блоки кода могут оставаться незакрытыми. - Отмена снижает затраты, только если прерывание передаётся от браузера через бэкенд к провайдеру. - Метаданные об использовании часто приходят в конце потока; прерванные потоки требуют внимательного учёта. - Не перерисовывайте весь интерфейс при поступлении каждого крошечного фрагмента. Объединяйте обновления с помощью кадров анимации. - Нормализуйте специфичные для провайдеров события потока в бэкенде. - Откажитесь от потоковой передачи для коротких задач классификации, пакетных заданий, строго структурированных результатов и рабочих процессов, требующих полной модерации перед отображением. [Инференс](/ru/blog/tag/inference/)[API](/ru/blog/tag/api/) A [AI Prime Tech](https://aiprimetech.io/ru/) Этот блог публикует AI Prime Tech. Статьи готовятся с помощью ИИ; прежде чем полагаться на сведения, зависящие от версии, такие как идентификаторы моделей, цены и лимиты, сверяйте их с официальной документацией. Получите более дешёвый доступ к API Claude Один ключ API для Claude Opus 5.5, Sonnet 5, Haiku 4.5 и Fable 5.1, а также GPT-6 моделей. Оплата по мере использования, без подписки. [Получить ключ API →](/register) AI Prime Tech — независимый сторонний API-шлюз. Claude™ и Anthropic® — товарные знаки Anthropic, PBC. Связь с этой компанией или одобрение с её стороны не подразумеваются.