Jak przesyłać odpowiedzi LLM strumieniowo za pomocą SSE i fragmentów z danymi o zużyciu

Tłumaczenie automatyczne

Ten artykuł został automatycznie przetłumaczony z angielskiego oryginału.

Aby przesyłać odpowiedź LLM strumieniowo, parsuj protokół zdarzeń serwera, składaj delty treści i aktualizuj ekran, gdy dociera tekst nadający się do wyświetlenia. Wiele interfejsów API korzysta z Server-Sent Events, czyli SSE. Jeden odczyt HTTP może zawierać część zdarzenia lub kilka zdarzeń. Zdarzenie może zawierać wiele tokenów modelu.

Implementacje klienta potrzebują buforowania i obsługi zakończenia, a także szybkiej pierwszej aktualizacji.

Parsuj zdarzenia przed danymi modelu

Format SSE używa wierszy takich jak data: i kończy zdarzenie pustym wierszem. Odczyty sieciowe mogą dzielić te wiersze lub łączyć kilka zdarzeń. Buforuj niekompletny tekst, rozpoznawaj kompletne zdarzenia, a następnie parsuj dane zgodnie z formatem konkretnego API. Wiele wierszy data: należy do jednego zdarzenia.

W OpenAI Chat Completions treść dociera jako delty, które klient składa w wiadomość. Obsługuj delty wywołań narzędzi lub delty strukturalne zgodnie z ich polami, zamiast traktować każde zdarzenie jak zwykły tekst. Znacznik [DONE] jest konwencją API, a nie ogólnym wymaganiem SSE.

Przydatna kolejność przetwarzania po stronie klienta:

  1. Dekoduj przychodzące bajty bez utraty znaku UTF-8 podzielonego między odczyty.
  2. Buforuj dane do uzyskania kompletnego zdarzenia SSE.
  3. Interpretuj zdarzenie według schematu wybranego API.
  4. Dodaj treść lub pola strukturalne do składanej odpowiedzi.
  5. Zaktualizuj ekran przy odpowiedniej granicy buforowania.

Oddziel wyświetlanie, zakończenie i zużycie

Wyświetlaj zwykły tekst jak najszybciej, gdy to możliwe. Buforuj niekompletne konstrukcje Markdown lub wiersze kodu, jeśli natychmiastowe formatowanie powoduje powtarzające się zmiany układu. Rejestruj początek żądania i pierwszą wygenerowaną treść oddzielnie od otwarcia połączenia lub zdarzenia zawierającego tylko metadane.

W Chat API OpenAI ustawienie stream_options: {"include_usage": true} żąda końcowego fragmentu z danymi o zużyciu przed [DONE]. Ten fragment ma pustą tablicę wyborów. Przerwane lub anulowane strumienie mogą nigdy go nie dostarczyć, dlatego braku danych o zużyciu nie można interpretować jako zera tokenów.

Serwery zgodne z OpenAI mogą implementować inne formaty danych lub inaczej obsługiwać zakończenie. Testuj fragmentację zdarzeń, wiele zdarzeń w jednym odczycie, puste delty, anulowanie, błędy serwera i brak końcowych danych o zużyciu na implementacji o ustalonej wersji. Zachowuj już otrzymany tekst i odróżniaj niekompletną odpowiedź od pomyślnego zakończenia.

Przewodnik inżynierski: przesyłanie strumieniowe w praktyce łączy zachowanie klienta z TTFT, TPOT i planowaniem fazy prefill.