Satu aliran SSE, tujuh pembekal LLM

Saya membina aplikasi Next.js yang menyokong tujuh pembekal LLM yang berbeza.

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

Saya menetapkan satu peraturan ketat: Pelayar mesti menggunakan laluan kod yang sama tepat untuk setiap pembekal.

Ini sukar kerana API ini tidak sama. Mereka menggunakan kaedah penghantaran yang berbeza. Mereka menghantar bentuk data yang berbeza. Ada yang menggunakan SSE manakala yang lain menggunakan NDJSON.

Jika anda membiarkan perbezaan ini sampai ke UI anda, kod anda akan menjadi berserabut dengan pernyataan "if". Setiap kali anda menambah pembekal, bahagian hadapan (frontend) anda akan menjadi semakin kompleks.

Saya menyelesaikan masalah ini dengan mencipta satu kontrak tunggal. Setiap pembekal mesti mengeluarkan format ini ke pelayar:

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

Pelayar hanya perlu memahami tiga perkara: delta, error, dan [DONE].

Berikut adalah cara saya membinanya:

  1. Gunakan Async Generators Saya melayan setiap pembekal sebagai penjana (generator) yang menghasilkan teks biasa. Ini menyembunyikan kerumitan API tersebut.

  2. Corak Wrapper (The Wrapper Pattern) Saya mencipta satu fungsi wrapper yang dipanggil createSSEStream. Wrapper ini menguruskan format wayar (wire format). Ia juga memastikan aliran (stream) sentiasa berakhir. Walaupun pembekal gagal di tengah jalan, wrapper tersebut akan menghantar ralat dan isyarat [DONE]. Ini menghalang klien daripada tergantung (hanging).

  3. Mengelompokkan API yang Serupa OpenAI, Mistral, Groq, dan Azure semuanya menggunakan dialek yang sama. Saya menulis satu pelaksanaan untuk kesemuanya. Menambah pembekal serasi yang baharu kini hanya memerlukan satu baris kod.

  4. Mengendalikan Pencilan (Handling Outliers) Anthropic dan Ollama berfungsi secara berbeza. Anthropic menggunakan acara bertipe (typed events) yang khusus. Ollama menggunakan NDJSON. Saya menulis parser tersuai untuk mereka, tetapi kedua-duanya menghasilkan teks ke dalam wrapper yang sama. Pelayar tidak akan menyedari perbezaannya.

Privasi dan Kesederhanaan Aplikasi ini menggunakan model "Bring Your Own Key".

• Pengguna menampal kunci API mereka sendiri. • Kunci tersebut kekal dalam storan tempatan (local storage). • Pelayan bertindak sebagai proksi tulen. • Kunci tersebut tidak pernah disimpan dalam pangkalan data.

Pendekatan ini menghapuskan keperluan untuk pengurusan pengesahan (auth) atau rahsia yang kompleks. Ia memudahkan aplikasi untuk dihoskan sendiri (self-host).

Pengajarannya mudah: Modelkan setiap integrasi sebagai penjana bagi apa yang anda sebenarnya mahukan. Bungkus (wrap) ia sekali. Biarkan variasi wujud dalam penjana supaya logik utama anda kekal bersih.

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

Komuniti pembelajaran pilihan: https://t.me/GyaanSetuAi