Streaming y el límite de 100 segundos
Por qué una petición larga sin streaming muere en el borde de red a los 100 segundos, cómo lo evita un solo campo y qué hace el medidor con un stream.
Una petición que no va en streaming no te envía absolutamente nada hasta que la respuesta entera existe. Con una respuesta de una línea eso es invisible; con una generación larga es el problema entero. Entre el momento en que tu petición llega al modelo y el momento en que el primer byte de la respuesta volvería pueden pasar minutos, y el borde de red que hay delante de este sitio permite unos 100 segundos de silencio antes de darse por vencido con la respuesta. Pasado eso, la petición muere en el borde mientras el modelo sigue escribiendo. Un solo campo lo evita, y lo que se te cobra no cambia por activarlo.
Por qué muere una petición larga sin streaming
Una petición sin streaming es una ida y vuelta con una pausa larga en medio. Tu cliente envía el body, el modelo escribe la respuesta completa, y solo cuando el último token está terminado vuelven los primeros bytes por la conexión. Entre esos dos momentos la conexión no lleva nada en absoluto, y el borde está mirando exactamente eso: unos 100 segundos de silencio es todo lo que permite antes de decidir que la respuesta no va a llegar. Lo que ves es una petición fallida. Lo que ocurrió es que la respuesta todavía se estaba escribiendo.
Una petición en streaming no tiene ninguna pausa que se pueda agotar. Los bytes salen hacia tu cliente con el primer token, y cada token posterior llega según se produce, así que la conexión nunca queda en silencio el tiempo suficiente para que el borde se dé por vencido. Esta es la parte que conviene guardar: esto no es un tiempo de espera más largo, es una respuesta que nunca se queda callada. Una generación que tarda cuatro minutos hace streaming durante cuatro minutos, y llega.
El arreglo es un solo campo
El streaming aquí no es otro endpoint, ni otra clave, ni otro precio. Es un campo del body que ya estás enviando, stream: true, y funciona igual en /v1/chat/completions y en /v1/responses.
POST /v1/chat/completions
{
"model": "astra",
"stream": true,
"messages": [
{"role": "user", "content": "Write the report."}
]
}
Los SDK oficiales escriben ese mismo campo a su manera: stream=True en Python, stream: true en Node. Lo único que cambia de tu lado es la forma de la respuesta — trozos que recorres según llegan, en vez de un objeto que esperas — y ese bucle viene ya escrito en cualquier librería cliente.
Qué hace el medidor alrededor de un stream
Hacer streaming no te deja fuera del medidor, ni te entrega una factura que no puedas comprobar. El uso llega igualmente: el último frame del stream lleva los recuentos de tokens, y en chat completions la pasarela pone stream_options.include_usage por su cuenta, así que no es algo que puedas olvidarte de pedir. El medidor liquida sobre las mismas cifras tanto si la respuesta fue en streaming como si no.
Alrededor de eso, la secuencia es la que sigue toda petición aquí. Se toma una reserva cuando la petición empieza — el saldo de tu portal se mueve entonces, no cuando cae el último token — y la liquidación ocurre sobre el uso que informa el último frame del stream, a los precios anotados en el momento de tomar la reserva. Si la conexión se corta a mitad del stream, la reserva se concilia y se libera en vez de cobrarse: los tokens que nunca llegaron a una liquidación nunca se cobran.
Tres relojes, no uno
Cuando una petición parece lenta, el portal te dice de qué clase de lentitud se trata. De cada petición se guardan tres relojes — subida, tiempo hasta el primer token y total — porque son tres problemas distintos bajo una sola palabra. Una subida larga es tu propio enlace de salida entregándonos el body, y nada de este lado la acortará. Un tiempo corto hasta el primer token con un total largo es una generación larga haciendo exactamente lo suyo, que es el caso para el que existe el streaming. Un tiempo largo hasta el primer token es el que merece que nos escribas.
Hay un número más que un cliente debería leer. Cuando una petición se rechaza con 429, la cabecera Retry-After pasa intacta — es la cabecera con la que los SDK oficiales marcan el ritmo de sus reintentos, así que un cliente que la respeta espera el intervalo que enviamos de verdad en lugar de adivinar uno.
Si la conexión se corta a mitad del stream, la reserva se concilia y se libera en vez de cobrarse: los tokens que nunca llegaron a una liquidación nunca se cobran.
Traducción automática, pendiente de revisión por un hablante nativo. La versión en inglés es la de referencia.