Чем мы можем помочь?

Кратко опишите вопрос; мы ответим по электронной почте.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.
На главную

Smart Answer: ответ ИИ в поиске по сайту

Встраивание Smart Answer: скрипт suche.js, блок в разметке, публичный HTTP-интерфейс для поисковых страниц с серверным рендерингом, поток ответа через SSE, 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-селектором в аккаунте), ждёт отправки или паузы ввода и показывает ответ в блоке в указанном месте (перед целевым элементом, после него или внутри). По умолчанию отвечает только на ввод, похожий на вопрос.

Атрибуты тега скрипта:

Скрипт не устанавливает 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.

Общее для всех конечных точек:

GET /api/suche/SITE_KEY?locale=de — конфигурация, CSS и пустой шаблон блока (Cache-Control: public, max-age=60):

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"}'

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":"…"}]}

Ответ 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…"}}

После 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]));
  }
}

Далее: Интеграция конфиденциальности

Обновлено: