Skip to content

Modul: POST /chat/stream

Streaming chat endpoint a GLC-RAG API-hoz. Ez az endpoint SSE (Server-Sent Events) formátumban küld vissza a választ, így a kliens azonnal láthatja a válasz generálását.

Leírás

A POST /chat/stream ugyanazt a request body-t használja, mint a POST /chat (channel, text, session_id; internal = JWT, public = public_widget_token). A válasz SSE (Server-Sent Events), Content-Type: text/event-stream. Internal esetén a tenant_id és user_id a JWT-ből jönnek (body-ban opcionálisak).

SSE válasz formátum

A streaming válasz három típusú eseményt tartalmaz:

1. Header event

A válasz metaadatait tartalmazza:

data: {"event_type":"header","data":{"trace_id":"...","mode":"DOC","status_code":"OK","ux_hints":{},"blocked_reason":null}}

Mezők:

  • trace_id: Egyedi nyomon követési azonosító
  • mode: Válasz típusa (DOC, CREATIVE, SHOPPING, stb.)
  • status_code: Válasz státusz (OK, NO_RESULT_DOC, POLICY_DENY, stb.)
  • ux_hints: UX tippek és beállítások
  • blocked_reason: Blokkolási ok (ha van)

2. Delta eventek

A szöveg chunkok érkezését jelzik:

data: {"event_type":"delta","data":{"text":"...szöveg chunk..."}}

Mezők:

  • text: A szöveg chunk tartalma

Fontos: A delta eventekben NEM lehet sources mező! A források csak a footer eventben jelenhetnek meg.

A válasz végén érkezik, tartalmazza a forrásokat:

data: {"event_type":"footer","data":{"sources":[...],"tool_proposal":null,"internal_debug":null}}

Mezők:

  • sources: Forrás dokumentumok listája
  • tool_proposal: Tool javaslatok (ha vannak)
  • internal_debug: Debug információk (opcionális)

Példa

Egy egyszerű streaming chat hívás internal csatornával:

Python

python
import requests

BASE_URL = "https://<your-api-host>"
JWT_TOKEN = "your-jwt-token"

url = f"{BASE_URL}/chat/stream"
payload = {
    "channel": "internal",
    "text": "Szia! Hogyan segíthetek?",
    "session_id": "my-session-123"
}

headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {JWT_TOKEN}",
    "Accept": "text/event-stream"
}

response = requests.post(url, json=payload, headers=headers, stream=True)

# Stream feldolgozás
for line in response.iter_lines():
    if line:
        data = line.decode('utf-8')
        if data.startswith("data: "):
            # Esemény típus kinyerése
            event_type = data[6:].split(":")[0]  # "header", "delta", "footer"
            event_data = data[6:].split(":")[1]   # Az adatok JSON része
            print(f"{event_type}: {event_data}")

TypeScript

typescript
const BASE_URL = "https://<your-api-host>";
const JWT_TOKEN = "your-jwt-token";

const url = `${BASE_URL}/chat/stream`;
const payload = {
    channel: "internal",
    text: "Szia! Hogyan segíthetek?",
    session_id: "my-session-123"
};

const headers = {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${JWT_TOKEN}`,
    "Accept": "text/event-stream"
};

const response = await fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(payload)
});

// Stream feldolgozás
const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    const lines = decoder.decode(value, { stream: true }).split('\n');
    for (const line of lines) {
        if (line.startsWith('data: ')) {
            const event_part = line.substring(6);  // "data: " előtag eltávolítása
            const event_type = event_part.split(":")[0];  // "header", "delta", "footer"
            const event_data = event_part.split(":")[1];   // Az adatok JSON része
            console.log(`${event_type}: ${event_data}`);
        }
    }
}

cURL

bash
curl -X POST "$BASE_URL/chat/stream" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-jwt-token" \
  -H "Accept: text/event-stream" \
  -d '{
    "channel": "internal",
    "text": "Szia! Hogyan segíthetek?",
    "session_id": "my-session-123"
  }'

PHP

php
<?php
$BASE_URL = "https://<your-api-host>";
$JWT_TOKEN = "your-jwt-token";

$url = $BASE_URL . "/chat/stream";
$payload = json_encode([
    "channel" => "internal",
    "text" => "Szia! Hogyan segíthetek?",
    "session_id" => "my-session-123"
]);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Content-Type: application/json",
    "Authorization: Bearer $JWT_TOKEN",
    "Accept: text/event-stream"
]);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);

$response = curl_exec($ch);
curl_close($ch);

// Stream feldolgozás
$lines = explode("\n", $response);
foreach ($lines as $line) {
    if (strpos($line, 'data: ') === 0) {
        $event_part = substr($line, 6);  // "data: " előtag eltávolítása
        $event_type = explode(":", $event_part)[0];  // "header", "delta", "footer"
        $event_data = explode(":", $event_part)[1];   // Az adatok JSON része
        echo "$event_type: $event_data\n";
    }
}
?>

Public channel példa

Egy egyszerű streaming chat hívás public csatornával (widget token):

Python

python
import requests

BASE_URL = "https://<your-api-host>"
WIDGET_TOKEN = "your-widget-token-id"

url = f"{BASE_URL}/chat/stream"
payload = {
    "channel": "public",
    "text": "Szia! Hogyan segíthetek?",
    "session_id": "my-session-123",
    "public_widget_token": WIDGET_TOKEN
}

headers = {
    "Content-Type": "application/json",
    "Accept": "text/event-stream"
}

response = requests.post(url, json=payload, headers=headers, stream=True)

# Stream feldolgozás
for line in response.iter_lines():
    if line:
        data = line.decode('utf-8')
        if data.startswith("data: "):
            event_type = data[6:].split(":")[0]
            event_data = data[6:].split(":")[1]
            print(f"{event_type}: {event_data}")

TypeScript

typescript
const BASE_URL = "https://<your-api-host>";
const WIDGET_TOKEN = "your-widget-token-id";

const url = `${BASE_URL}/chat/stream`;
const payload = {
    channel: "public",
    text: "Szia! Hogyan segíthetek?",
    session_id: "my-session-123",
    public_widget_token: WIDGET_TOKEN
};

const headers = {
    "Content-Type": "application/json",
    "Accept": "text/event-stream"
};

const response = await fetch(url, {
    method: "POST",
    headers: headers,
    body: JSON.stringify(payload)
});

// Stream feldolgozás
const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    const lines = decoder.decode(value, { stream: true }).split('\n');
    for (const line of lines) {
        if (line.startsWith('data: ')) {
            const event_part = line.substring(6);
            const event_type = event_part.split(":")[0];
            const event_data = event_part.split(":")[1];
            console.log(`${event_type}: ${event_data}`);
        }
    }
}

cURL

bash
curl -X POST "$BASE_URL/chat/stream" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "channel": "public",
    "text": "Szia! Hogyan segíthetek?",
    "session_id": "my-session-123",
    "public_widget_token": "your-widget-token-id"
  }'

PHP

php
<?php
$BASE_URL = "https://<your-api-host>";
$WIDGET_TOKEN = "your-widget-token-id";

$url = $BASE_URL . "/chat/stream";
$payload = json_encode([
    "channel" => "public",
    "text" => "Szia! Hogyan segíthetek?",
    "session_id" => "my-session-123",
    "public_widget_token" => $WIDGET_TOKEN
]);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Content-Type: application/json",
    "Accept: text/event-stream"
]);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);

$response = curl_exec($ch);
curl_close($ch);

// Stream feldolgozás
$lines = explode("\n", $response);
foreach ($lines as $line) {
    if (strpos($line, 'data: ') === 0) {
        $event_part = substr($line, 6);
        $event_type = explode(":", $event_part)[0];
        $event_data = explode(":", $event_part)[1];
        echo "$event_type: $event_data\n";
    }
}
?>

Tippek

  • Stream feldolgozás: A streamet soronként olvasd ki, és minden data: előtagot kezelj külön.
  • Események kezelése: Az eseményeket (header, delta, footer) külön-külön kezeld, ha szükséges.
  • Hiba kezelés: Ha a stream hiba esetén leáll, ellenőrizd a HTTP státuszkódot.
  • Rate limiting: A streaming endpointok is rate limiteltek, ha túlléped a limitet, 429-es hivatkozást kapsz.
  • Session ID: Kötelező mindkét csatornán; a kliens generálja (pl. UUID).
  • Tenant ID / User ID (internal): A backend a JWT-ből veszi; body-ban opcionálisak. Public esetén a tenant a widget tokenből oldódik fel.
  • Válasz feldolgozás: A válasz JSON formátumban érkezik minden sorban, parse-eld és kezelj a mezők alapján.
  • Trace ID: A trace_id-t használhatod a válaszok nyomon követéséhez és hibakereséshez.
  • Mode: A mode mező megadja, milyen típusú válasz érkezett (pl. DOC, CREATIVE, SHOPPING).
  • Sources csak footerben: A forrásdokumentumok csak a footer eventben jelenhetnek meg, nem a delta eventekben!

További információ

API dokumentációk

  • docs – Swagger UI. Interaktív API dokumentáció: endpointok böngészése, kérések kipróbálása a böngészőből. Mire való: chat, streaming, hitelesítés, RAG és admin API gyors tesztelése.
  • redoc – Redoc. Olvasható, struktúrált API leírás request/response sémákkal. Mire való: endpointok és adatmodellek áttekintése, integráció tervezése.
  • openapi.json – JSON API (OpenAPI 3.0 specifikáció). Géppel feldolgozható séma: endpointok, paraméterek, sémák. Mire való: kliensgenerálás, automatizált tesztek, dokumentáció- és integrációs eszközök.