Nhận phản hồi dạng luồng (SSE)
Hiển thị tiến trình và chữ chạy dần thay vì chờ toàn bộ câu trả lời.
Thêm header Accept: text/event-stream (hoặc query ?stream=1) vào cùng request /agent/process.
Máy chủ trả về chuỗi sự kiện Server-Sent Events:
curl -N -X POST https://api.aivigo.tech/api/v1/agent/process \
-H "Authorization: Bearer $AIVIGO_API_KEY" \
-H "Accept: text/event-stream" -H "Content-Type: application/json" \
-d '{ "input": { "type": "text", "text": "tư vấn sữa cho bé 2 tuổi" }, "user": { "ref": "kh001" } }'Các sự kiện
| Sự kiện | Dữ liệu | Dùng để |
|---|---|---|
session | session_id | Lưu phiên ngay từ đầu |
transcript | { text } | (Giọng nói) hiển thị lời người dùng vừa nói |
classified | Ý định nhận ra | Hiển thị "đang tìm sản phẩm…" |
routed | { agent, routed_by, intent } | Biết trợ lý chuyên môn nào xử lý |
delta | { text } | Đoạn chữ mới — nối vào bong bóng chat |
reply | Response đầy đủ (như dạng JSON) | Vẽ khối UI, nút, âm thanh |
done | { turn_id } | Kết thúc lượt |
error | { code, status, detail, errors? } | Lỗi trong khi xử lý |
Máy chủ gửi dòng chú thích : ping mỗi 10 giây để giữ kết nối qua proxy — bỏ qua dòng này.
event: routed
data: {"agent":"sales","routed_by":"intent_owner","intent":"shopping.advice"}
event: delta
data: {"text":"Với bé 2 tuổi, "}
event: reply
data: {"turn_id":"…","status":"completed","reply":{"text":"…","ui":[…]}}
event: done
data: {"turn_id":"…"}Không phải lượt nào cũng có delta — khi trợ lý chạy quy trình nghiệp vụ (tạo đơn, tra cứu), câu trả lời đến một lần ở reply.
Luôn dùng reply làm kết quả cuối cùng.
Đọc luồng trong JavaScript
EventSource của trình duyệt chỉ hỗ trợ GET, vì vậy dùng fetch (trên server Node.js 18+):
const res = await fetch(url, { method: 'POST', headers: { ...headers, Accept: 'text/event-stream' }, body });
const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
let buf = '';
for (;;) {
const { value, done } = await reader.read();
if (done) break;
buf += value;
let i;
while ((i = buf.indexOf('\n\n')) >= 0) {
const chunk = buf.slice(0, i);
buf = buf.slice(i + 2);
const event = /^event: (.*)$/m.exec(chunk)?.[1];
const data = /^data: (.*)$/m.exec(chunk)?.[1];
if (!event || !data) continue; // dòng ": ping"
onEvent(event, JSON.parse(data));
}
}