Un unico stream SSE, sette provider LLM

Ho costruito un'app Next.js che supporta sette diversi provider LLM.

OpenAI, Claude, Gemini, Ollama, Mistral, Groq e Azure.

Ho stabilito una regola ferrea: il browser deve utilizzare lo stesso identico percorso di codice per ogni provider.

È difficile perché queste API non sono uguali. Utilizzano metodi di trasporto differenti. Inviavano strutture dati diverse. Alcune usano SSE, mentre altre usano NDJSON.

Se permetti a queste differenze di raggiungere la tua UI, il tuo codice diventerà un caos di istruzioni "if". Ogni volta che aggiungi un provider, il tuo frontend diventa sempre più complesso.

Ho risolto il problema creando un unico contratto. Ogni provider deve emettere questo formato verso il browser:

• data: {"delta":""} • data: {"error":""} • data: [DONE]

Il browser deve solo comprendere tre cose: delta, error e [DONE].

Ecco come l'ho costruito:

  1. Usa i generatori asincroni Tratto ogni provider come un generatore che restituisce testo semplice. Questo nasconde la complessità dell'API.

  2. Il pattern Wrapper Ho creato una funzione wrapper chiamata createSSEStream. Questo wrapper gestisce il formato di trasmissione. Assicura inoltre che lo stream termini sempre. Anche se un provider fallisce a metà operazione, il wrapper invia un errore e un segnale [DONE]. Ciò evita che il client rimanga bloccato.

  3. Raggruppare API simili OpenAI, Mistral, Groq e Azure utilizzano tutte lo stesso dialetto. Ho scritto un'unica implementazione per tutti loro. Aggiungere un nuovo provider compatibile richiede ora una sola riga di codice.

  4. Gestire i casi particolari Anthropic e Ollama funzionano in modo diverso. Anthropic utilizza eventi tipizzati specifici. Ollama utilizza NDJSON. Ho scritto dei parser personalizzati per entrambi, ma entrambi restituiscono il testo allo stesso wrapper. Il browser non noterà mai la differenza.

Privacy e semplicità L'app utilizza un modello "Bring Your Own Key".

• Gli utenti incollano la propria chiave API. • La chiave rimane nella local storage. • Il server funge da puro proxy. • La chiave non viene mai salvata in un database.

Questo approccio elimina la necessità di una gestione complessa di autenticazione o segreti. Rende l'app facile da ospitare autonomamente (self-host).

La lezione è semplice: modella ogni integrazione come un generatore di ciò che desideri effettivamente. Avvolgilo una volta sola. Lascia che la variazione risieda nei generatori, così la logica principale rimarrà pulita.

Source: https://dev.to/ikeli0320/one-sse-stream-seven-llm-providers-giving-a-nextjs-app-a-single-streaming-code-path-1fh2

Optional learning community: https://t.me/GyaanSetuAi