Nega zamonaviy AI xizmatlari foydalanuvchini 15 soniya kutishga majbur qilmasdan, matnni so'zma-so'z ko'z o'ngimizda chiqaradi? Bugun biz Server-Sent Events (SSE) texnologiyasini o'rganamiz, JavaScript da ReadableStream oqimini o'qishni va avto-skroll hamda kod bloklariga ega professional chat interfeysini quramiz.
Oddiy javobdan farqli o'laroq, server Content-Type: text/event-stream sarlavhasini yuboradi va aloqani uzmasdan ochiq ushlab turadi:
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
data: {"token": "Salom"}
data: {"token": " mening"}
data: {"token": " do'stim!"}
data: [DONE]
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({ prompt: "Salom" })
});
const reader = response.body.getReader();
const decoder = new TextDecoder("utf-8");
while (true) {
const { done, value } = await reader.read();
if (done) break; // Oqim yakunlandi
const chunk = decoder.decode(value);
chatBox.innerText += chunk; // Tokenni ekranga qo'shish
}
Yangi tokenlar qo'shilgan sari ekran avtomatik pastga tushib borishi shart:
chatBox.scrollTop = chatBox.scrollHeight;
Model hali yozayotganini ko'rsatuvchi miltillovchi belgi:
.cursor {
animation: blink 1s infinite;
}
Foydalanuvchi xabarlari o'ngda (ajralib turuvchi rang), AI xabarlari esa chapda (och fonda).
Agar matnni shunchaki innerText orqali chiqarsak, kod bloklari (```python) va jadvallar xunuk matn holida qoladi.
Yechim: marked.js kutubxonasi orqali markdownni HTML teglarga (<pre><code>) aylantirish!
// Tokenlar to'plami HTML ga aylanadi
let rawText = "";
function onChunkReceived(token) {
rawText += token;
// marked() matnni toza HTML ga o'giradi
messageElement.innerHTML = marked.parse(rawText);
// Kod bloklarini chiroyli bo'yash
hljs.highlightAll();
}
[
{
"role": "system",
"content": "Sen Target School IT yordamchisisan."
},
{
"role": "user",
"content": "Mening ismim Ali."
},
{
"role": "assistant",
"content": "Salom Ali! Qanday yordam berishim mumkin?"
},
{
"role": "user",
"content": "Mening ismim nima edi?"
}
]
Til modeli so'rovlar orasida hech narsani eslab qolmaydi! Har bir yangi savolda frontend brauzer butun yozishmalar tarixini qaytadan serverga yuboradi.
Xavf: Agar suhbat 100 ta xabarga yetsa, barcha tarixni yuborish tokenlarni tugatib qo'yadi. Shu sababli faqat oxirgi 10 ta xabarni qoldirish (Sliding Window) kerak.
Agar model noto'g'ri mavzuda yozishni boshlasa yoki 2000 so'zlik ortiqcha gapga ketsa, foydalanuvchi uni darhol to'xtatishi kerak. Bu token xarajatini va vaqtni tejaydi.
let controller = null;
function sendMessage() {
controller = new AbortController(); // Yangi kontroller
fetch('/api/chat', {
method: 'POST',
signal: controller.signal // Signalni ulaymiz!
});
}
function stopGeneration() {
if (controller) {
controller.abort(); // Tarmoq so'rovi uziladi!
console.log("Generatsiya to'xtatildi!");
}
}
Dars papkasidagi laboratoriya stendida quyidagilar sinab ko'riladi:
lab/index.html ni oching.