Один SSE для четырёх LLM: стриминг OpenAI, Anthropic, DeepSeek и Kimi через один бэкенд

Мы делаем чат-агрегатор, где в одном окне доступны GPT, Claude, Kimi и DeepSeek. Фронтенду нужно отдавать ответ в реальном времени — токен за токеном, как в ChatGPT. Бэкенд при этом ходит к четырём разным API, и стриминг у них устроен по-разному. Расскажу, как мы свели это к единому SSE-потоку наружу, и про две грабли, на которые наступили: рваные UTF-8 символы и парсинг чужих SSE.
Статья будет полезна всем, кто проксирует LLM через свой сервер.
Зачем вообще свой прокси
Фронтенд не должен знать ключи провайдеров и не должен ходить к ним напрямую. Все запросы идут через наш Node.js-бэкенд: он подставляет ключ, дёргает нужный API с stream: true, парсит входящий поток и отдаёт фронту унифицированные события. Плюс на бэкенде живут лимиты, учёт токенов и подмена провайдера.
Задача: «получить поток от провайдера X → распарсить → отдать фронту в едином формате».
Два разных формата стриминга
Провайдеры делятся на два лагеря.


















