Smart Answer: відповідь ШІ в пошуку сайту
Вбудовування Smart Answer: скрипт suche.js, блок у розмітці, публічний HTTP-інтерфейс для серверних сторінок пошуку, потік відповіді Server-Sent Events, CSS-змінні та передача до чату.
Smart Answer показує коротку відповідь на запитання відвідувача над або під результатами пошуку сайту — потоком, із джерелами з бази знань і полем наступного запитання. Smart Answer — окремий сервіс, що використовує ту саму базу знань, що й асистент чату. Вмикається й оформлюється в обліковому записі в розділі Проєкт → Smart Answer для пошуку на сайті.
Вбудовування через suche.js
Якщо завантажувач чату вже на сторінці, достатньо одного рядка:
<script src="https://cdn.reactive.chat/suche.js" async></script>
Без віджета чату передайте ключ сайту:
<script src="https://cdn.reactive.chat/suche.js" data-site-key="SITE_KEY" async></script>
Скрипт підключається до полів пошуку сторінки (їх ви визначаєте CSS-селектором в обліковому записі), чекає надсилання або паузи введення й показує відповідь у блоці в заданому місці (перед, після або всередині цільового елемента). Стандартно відповідає лише на введення, схоже на запитання.
Атрибути тегу скрипту:
- data-site-key (необов’язковий) — інакше береться із завантажувача чату (
data-rc-site-key). - data-ws-url (необов’язковий) — адреса чату; інакше виводиться як для чату.
- data-api (необов’язковий) — базова адреса інтерфейсу, стандартно
https://ws.reactive.chatабо ваш власний домен. - data-locale (необов’язковий) — мова; інакше
<html lang>, потім браузер.
Скрипт не задає cookie й зберігає дані лише в sessionStorage. Для CSP потрібні script-src https://cdn.reactive.chat і connect-src https://ws.reactive.chat (Безпека й CSP).
Передача до чату
Якщо відвідувач ставить уточнювальне запитання в блоці, то, залежно від налаштування Уточнювальне запитання, розмова продовжується у віджеті чату (ReactiveChat('continueConversation', id, text) або ReactiveChat('startConversation', text)) або відповідь з’являється в тому самому блоці. Без віджета чату на сторінці уточнювальне запитання завжди залишається в блоці.
Оформлення
Блок (.rc-ai) має власний CSS і захищений від скидань стилів сторінки. Його можна налаштувати змінними з найнижчою специфічністю:
.rc-ai {
--rc-ai-akzent: #0a7cff;
--rc-ai-hg: var(--karte, #fff);
--rc-ai-text: #1d1d1f;
--rc-ai-rand: #e3e3e8;
--rc-ai-radius: 10px;
--rc-ai-schrift: inherit;
--rc-ai-abstand: 20px;
--rc-ai-schriftgroesse: 16px;
--rc-ai-zeilenhoehe: 1.6;
}
Окремі частини змінюються через .rc-ai .rc-ai__teil { … } у полі Власний CSS облікового запису, наприклад .rc-ai .rc-ai__hinweis { display: none; }. Захисний шар не захищає від правил сторінки з #id або !important.
HTTP-інтерфейс
Для сторінок пошуку, сформованих сервером, або власних інтерфейсів є публічний інтерфейс без автентифікації й cookie за адресою https://ws.reactive.chat/api/suche/SITE_KEY.
Спільне для всіх кінцевих точок:
- CORS лише для джерел із доменів проєкту (піддомени включено); виклики з вашого сервера без
Originзавжди працюють. - Обмеження: 60 запитів за хвилину на адресу відвідувача для всіх кінцевих точок разом → 429 із
Retry-AfterіX-RateLimit-*. Під час виклику з сервера рахується адреса сервера, тому для багатьох відвідувачів використовуйтеsuche.jsу браузері або власний домен з ключем проксі. - Запитання й відповіді не записуються в журнали доступу.
GET /api/suche/SITE_KEY?locale=de — конфігурація, CSS і порожній шаблон блоку (Cache-Control: public, max-age=60):
{"v":1,"aktiv":false}— вимкнено, заблоковано або невідомо (404 для невідомого ключа).{"v":1,"aktiv":true,"sprache":"de","konfig":{…},"css":"…","vorlage":"<div class=\"rc-ai\" …>","skript":"https://cdn.reactive.chat/suche.js"}
POST /api/suche/SITE_KEY — готовий HTML блоку для запитання, тіло щонайбільше 4 КБ:
curl -s -X POST "https://ws.reactive.chat/api/suche/SITE_KEY" \
-H "Content-Type: application/json" \
-d '{"q":"How long does shipping take?","locale":"en"}'
{"v":1,"aktiv":true,"frage":false,"html":""}— введення не є запитанням.{"v":1,"aktiv":true,"frage":true,"html":"…","css":"<style id=\"rc-ai-css\">…</style>","skript":"…","einbettung":"…"}— вставтеeinbettungна сторінку пошуку;suche.jsзаповнить блок відповіддю.- 400
{"v":1,"error":"bad_request","field":"q"}—qвідсутнє, порожнє або довше за 300 символів. - 413
payload_too_large, 405 для будь-якого іншого методу.
POST /api/suche/SITE_KEY/antwort — сама відповідь як потік Server-Sent Events, тіло щонайбільше 8 КБ:
{"q":"How long does shipping take?","locale":"en",
"visitor_id":"v_…",
"ctx":{"url":"https://shop.example/search","title":"Search"},
"folge":false,
"vorher":[{"q":"…","a":"…"}]}
- q (рядок, обов’язковий, 1–300 символів)
- locale (рядок, необов’язковий)
- visitor_id (рядок, необов’язковий,
[A-Za-z0-9_-]{1,80}) — ID відвідувача чату, щоб передача до чату відповідала йому. - ctx (об’єкт, необов’язковий) —
url,path,referrer,title; запит і якір видаляються. - folge (
true, необов’язковий) — уточнювальне запитання; обходить фільтр запитань. - vorher (список, необов’язковий) — щонайбільше 3 попередні пари (
q≤ 300,a≤ 1500 символів).
Відповідь text/event-stream:
event: status
data: {"stufe":"denkt"}
event: text
data: {"text":"Shipping usually takes"}
event: fertig
data: {"text":"Shipping usually takes 2–3 working days.","quellen":[{"titel":"Shipping","url":"https://shop.example/shipping"}],"fortsetzung":{"art":"faden","id":"01J…"}}
- status —
{stufe}:denkt,sucht,schreibt,wartet. Перша подія завждиdenkt. - text —
{text}: весь видимий на цей момент текст (не різниця), щонайчастіше кожні 150 мс. - fertig —
{text, quellen, fortsetzung};fortsetzung—{art:"faden", id}(збережено як розмову),{art:"neu"}абоnull. - fehler —
{code, text?}ізcode:aus,gesperrt,drossel,motor,zeit,einwilligung,ungueltig. Якщоfehlerнадходить післяtext, залиште текст на місці.
Після fertig або fehler потік завершується. Помилки до початку теж надходять потоком з рівно однією fehler (HTTP 404, 429, 400, 413, 503 або 200). Якщо тексту немає 45 секунд або завершення немає 90 секунд, надходить fehler zeit. Закриття з’єднання перериває відповідь. Проксі на шляху має передавати потік без буферизації.
// read the stream in the browser (EventSource cannot POST)
const r = await fetch('https://ws.reactive.chat/api/suche/SITE_KEY/antwort', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ q: frage, locale: 'en' }), credentials: 'omit'
});
const leser = r.body.getReader(); const dec = new TextDecoder(); let puffer = '';
for (;;) {
const { value, done } = await leser.read(); if (done) break;
puffer += dec.decode(value, { stream: true });
let i; while ((i = puffer.indexOf('\n\n')) >= 0) {
const block = puffer.slice(0, i); puffer = puffer.slice(i + 2);
const ev = /^event: (.*)$/m.exec(block), da = /^data: (.*)$/m.exec(block);
if (ev && da) zeige(ev[1], JSON.parse(da[1]));
}
}
Оновлено: