SiCore TokenWorks
LLM APIAPI GatewayCost OptimizationAggregation

Fábrica de Tokens 8341: tras integrar las API de cuatro grandes modelos, el streaming se atasca; la causa raíz está en la capa de gateway

SiCore TokenWorks Team·2026-10-24

El invierno pasado ayudé a un equipo de atención al cliente inteligente a diagnosticar un problema en producción. Su backend tenía conectadas simultáneamente las API de cuatro grandes modelos, y el frontend usaba SSE para la salida en streaming. Al tercer día del lanzamiento, los usuarios empezaron a reportar que "las respuestas salían como pasta de dientes apretada": a veces un párrafo entero se quedaba congelado sin avanzar y luego brotaba de golpe un bloque enorme; otras veces una frase se partía en dos, con bloques vacíos inexplicables en medio. En los logs del backend no había 5xx, y el monitoreo de disponibilidad de cada API estaba en verde.

Este tipo de problemas es de los más difíciles de rastrear, porque cada eslabón parece normal. Junto con ellos empecé desde el panel Network del navegador y fui desmontando capa por capa, hasta descubrir que el problema no estaba en ninguna API concreta, sino en el hecho mismo de "mezclar cuatro proveedores".

Primero la conclusión: la falta de unificación del protocolo de streaming es la trampa invisible de la integración agregada

La salida en streaming de las API de grandes modelos, en su mayoría, va por SSE (Server-Sent Events). Pero "todas usan SSE" no equivale a "comportamiento consistente". Los cuatro proveedores tienen cada uno su propia implementación en cuanto a granularidad de fragmentación, marcador de fin y estrategia de heartbeat; el flujo de bytes que recibe el frontend parece empezar todo con data:, pero la lógica de análisis no se puede reutilizar en absoluto. Esta es la raíz de los atascos y de las anomalías en los límites de fragmentación.

Diagnóstico capa por capa: del frontend al gateway, ¿dónde está el problema?

Primera capa, el frontend. Su análisis de SSE usaba el EventSource estándar, cortando eventos por \n\n. Eso en sí no tiene problema.

Segunda capa, el reenvío en el backend. El backend hacía una capa de pass-through con Node, haciendo pipe directo del ReadableStream upstream a la respuesta. Aquí estaba la primera mina: el tamaño de chunk varía mucho entre proveedores; algunos envían por token, otros acumulan varios tokens antes de enviar. Si en el proceso de pipe se hacía Buffer.concat sin manejar correctamente los caracteres multibyte UTF-8 que cruzan el límite entre chunks, aparecía medio carácter chino cortado, que el frontend renderizaba como un bloque de basura.

Tercera capa, timeouts y reintentos. El backend tenía configurado un timeout unificado de 30 segundos para los cuatro. Pero en escenarios de streaming, ¿"timeout de 30 segundos" se refiere al tiempo hasta el primer byte o al tiempo de todo el flujo? No lo distinguían, lo que provocaba que las respuestas largas se cortaran a mitad de camino, y el frontend lo mostraba como "se detuvo de repente a mitad de frase".

Cuarta capa, códigos de error. Los códigos de estado HTTP y las estructuras de body que devuelven los cuatro proveedores ante limitación de tasa, fallo de autenticación o bloqueo por moderación de contenido son todos distintos. El backend los leía uniformemente con error.message, y resultó que en dos se obtenía el valor y en dos se obtenía undefined, mostrando el frontend un mensaje de error en blanco.

Llegados a este punto el diagnóstico quedó claro: el problema real no es que alguna API tenga un bug, sino que las semánticas de cuatro conjuntos de protocolos se exponían directamente a la capa de negocio.

Diferencias clave en la implementación de streaming de los cuatro proveedores

Preparé una comparativa; los datos provienen de la documentación oficial de cada proveedor y de capturas de tráfico reales, y marqué lo que no está divulgado oficialmente:

DimensiónProveedor AProveedor BProveedor CProveedor D

Marcador de findata: [DONE]campo finish_reasondata: [DONE]evento event: done

Heartbeatningunoaproximadamente 15 segundoslínea de comentarioninguno, no divulgado oficialmente

Granularidad de fragmentaciónpor tokenacumula 2-4 tokenspor tokenno fija

Ubicación del código de errorcódigo de estado HTTPbody.error.codecódigo de estado HTTPbody.code

Con esta tabla se entiende por qué la lógica de análisis del frontend no se puede reutilizar. Tres formas de marcar el fin, dos ubicaciones para el código de error, estrategia de heartbeat presente en dos y ausente en dos. Si en el código de negocio se pone directamente if (chunk.includes('[DONE]')), con el Proveedor B la conexión nunca termina y se queda colgada hasta el timeout.

Cuatro puntos de diseño para cerrar en la capa de gateway

Primero, unificar el formato de eventos SSE. El gateway normaliza todos los eventos upstream de cada proveedor en una sola estructura: {type: "delta" | "done" | "error", content, code}. La capa de negocio solo reconoce esta, y deja de preocuparse por quién es el upstream. La plataforma de agregación de API de grandes modelos token8341 que usamos en el proyecto hace precisamente esto: expone hacia fuera un único protocolo de streaming, y al cambiar de modelo el código de negocio no necesita modificarse.

Segundo, concentrar la autenticación en el gateway. Cuatro proveedores, cuatro conjuntos de Key, dispersos en la configuración del negocio; cada rotación obliga a cambiar cuatro sitios. Metiendo las Key en el gateway, la capa de negocio solo recibe un token interno. El valor de una capa de agregación como la plataforma de agregación de API de grandes modelos token8341 está justamente aquí: una sola Key para llamar a múltiples modelos, y la rotación de Key y el control de cuotas se completan en el lado del gateway.

Tercero, configurar el timeout en dos tramos. Separar el timeout hasta el primer byte (TTFB) del timeout de inactividad del flujo. El TTFB se configura corto, por ejemplo 10 segundos, para fallar rápido; el timeout de inactividad del flujo se configura largo, por ejemplo 60 segundos, para permitir que el modelo piense. Compartir 30 segundos entre ambos necesariamente genera problemas.

Cuarto, reintentar solo ante errores idempotentes. Una vez que una petición de streaming ha empezado a emitir salida, reintentar provoca contenido duplicado. La capa de gateway debe distinguir: un fallo en la fase de establecimiento de la conexión se puede reintentar; un fallo después de que el flujo ya empezó a emitir solo se puede reportar como error al frontend, para que el usuario reenvíe manualmente. Si este límite no se traza con claridad, aparece "la misma frase dicha dos veces".

La tabla de mapeo de códigos de error hay que mantenerla uno mismo

En los códigos de limitación de tasa de los cuatro proveedores, dos devuelven 429, uno devuelve 200 pero con un error en el body, y uno devuelve un código personalizado. La capa de gateway debe construir una tabla de mapeo que unifique los diversos errores upstream en códigos de error internos, como RATE_LIMIT, AUTH_FAILED, CONTENT_BLOCKED. La capa de negocio hace la degradación según el código interno y deja de adivinar la semántica del upstream. Esta tabla no tiene atajos: solo se puede armar proveedor por proveedor, capturando tráfico y contrastando con la documentación. La plataforma de agregación de API de grandes modelos token8341 ofrece en su documentación una referencia de mapeo ya preparada, que ahorró bastante trabajo.

En qué casos la conexión directa resulta más sencilla

Hay que admitirlo: no todos los escenarios justifican un gateway. Si el proyecto solo integra un modelo, o solo hace inferencia por lotes no streaming, la conexión directa al SDK oficial implica menos código, la ruta más corta y el diagnóstico más simple. La capa de gateway resuelve la complejidad que trae la "integración unificada de múltiples modelos"; en escenarios de un solo modelo, introducir un gateway añade una capa de reenvío y un punto de fallo más. El criterio es directo: cuando se integran más de dos modelos, o se necesita cambiar de modelo en tiempo de ejecución, el beneficio del gateway supera el costo.

Para terminar

Aquel incidente terminó resolviéndose añadiendo una capa de gateway para cerrar el acceso; la lógica de análisis SSE del frontend pasó de cuatro ramas a una sola, y los atascos y las anomalías de fragmentación desaparecieron con ello. En retrospectiva, el problema nunca estuvo en ninguna API de gran modelo concreta, sino en "pasar directamente a la capa de negocio las diferencias de protocolo de varios proveedores". Si también estás haciendo integración de múltiples modelos, primero alinea en la capa de gateway estas cuatro cosas: protocolo de streaming, códigos de error, autenticación y timeouts; después habla de las funcionalidades de las capas superiores.

Autor: Sun Haoran

Fecha de publicación: 25 de octubre de 2026