Smart Answer: odpowiedź AI w wyszukiwarce twojej strony
Jak osadzić Smart Answer – skrypt suche.js, pole w kodzie strony, publiczny interfejs HTTP dla stron wyników renderowanych na serwerze i strumień odpowiedzi przez Server-Sent Events, wygląd przez zmienne CSS i przekazanie do czatu.
Smart Answer pokazuje nad wynikami wyszukiwarki twojej strony lub pod nimi krótką odpowiedź na pytanie odwiedzającego – strumieniowo, ze źródłami z twojej bazy wiedzy i z polem na kolejne pytanie. Smart Answer to osobna usługa; korzysta z tej samej bazy wiedzy co asystent twojego czatu. Włączasz go i ustawiasz jego wygląd w koncie w sekcji Projekt → Smart Answer dla wyszukiwarki.
Osadzenie przez suche.js
Jeśli loader czatu jest już na stronie, wystarczy jedna linia:
<script src="https://cdn.reactive.chat/suche.js" async></script>
Bez widżetu czatu podajesz klucz witryny:
<script src="https://cdn.reactive.chat/suche.js" data-site-key="SITE_KEY" async></script>
Skrypt dołącza się do pól wyszukiwania twojej strony (które to pola, ustalasz w koncie jako selektor CSS), czeka na wysłanie albo przerwę w pisaniu i pokazuje odpowiedź w polu w ustawionym miejscu (przed elementem docelowym, za nim albo w nim). Domyślnie odpowiada tylko na wpisy, które wyglądają jak pytanie.
Atrybuty w tagu script:
- data-site-key (opcjonalny) – w przeciwnym razie przejmowany z loadera czatu (
data-rc-site-key). - data-ws-url (opcjonalny) – adres czatu; w przeciwnym razie wyprowadzany tak jak przy czacie.
- data-api (opcjonalny) – adres bazowy interfejsu, domyślnie
https://ws.reactive.chatalbo twoja własna domena. - data-locale (opcjonalny) – język; w przeciwnym razie
<html lang>, potem przeglądarka.
Skrypt nie ustawia cookies i zapisuje dane tylko w sessionStorage. Na potrzeby CSP potrzebuje script-src https://cdn.reactive.chat i connect-src https://ws.reactive.chat (Bezpieczeństwo i CSP).
Przekazanie do czatu
Gdy odwiedzający zada w polu kolejne pytanie, zależnie od ustawienia Dalsze pytanie rozmowa jest kontynuowana w widżecie czatu (ReactiveChat('continueConversation', id, text) albo ReactiveChat('startConversation', text)) albo pytanie dostaje odpowiedź w tym samym polu. Bez widżetu czatu na stronie kolejne pytanie zawsze zostaje w polu.
Wygląd
Pole (.rc-ai) ma własny CSS i jest chronione przed resetami twojej strony. Dostosujesz je przez zmienne o najniższej specyficzności:
.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;
}
Pojedyncze części zmieniasz przez .rc-ai .rc-ai__teil { … } w polu Własny CSS w koncie, np. .rc-ai .rc-ai__hinweis { display: none; }. Przed regułami twojej strony z #id albo !important warstwa ochronna nie chroni.
Interfejs HTTP
Dla stron wyników renderowanych na serwerze albo własnych interfejsów jest publiczny interfejs bez logowania i bez cookies pod https://ws.reactive.chat/api/suche/SITE_KEY.
Wspólne:
- CORS tylko dla pochodzeń z domen twojego projektu (łącznie z subdomenami); wywołania z twojego serwera bez
Origindziałają zawsze. - Ograniczenie: 60 zapytań na minutę i adres odwiedzającego dla wszystkich endpointów łącznie → 429 z
Retry-AfteriX-RateLimit-*. Jeśli wywołujesz z serwera, liczy się adres twojego serwera – przy wielu odwiedzających użyj więcsuche.jsw przeglądarce albo własnej domeny z kluczem proxy. - Pytania i odpowiedzi nie są zapisywane w logach dostępu.
GET /api/suche/SITE_KEY?locale=de – konfiguracja, CSS i pusty szablon pola (Cache-Control: public, max-age=60):
{"v":1,"aktiv":false}– wyłączone, zablokowane albo nieznane (404 przy nieznanym kluczu).{"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 – gotowy HTML pola dla pytania, treść żądania najwyżej 4 KB:
curl -s -X POST "https://ws.reactive.chat/api/suche/SITE_KEY" \
-H "Content-Type: application/json" \
-d '{"q":"Ile trwa wysyłka?","locale":"de"}'
{"v":1,"aktiv":true,"frage":false,"html":""}– wpis nie jest pytaniem.{"v":1,"aktiv":true,"frage":true,"html":"…","css":"<style id=\"rc-ai-css\">…</style>","skript":"…","einbettung":"…"}– wstaweinbettungna swoją stronę wyników;suche.jswypełni wtedy pole odpowiedzią.- 400
{"v":1,"error":"bad_request","field":"q"}– brakq, jest puste albo dłuższe niż 300 znaków. - 413
payload_too_large, 405 przy innej metodzie.
POST /api/suche/SITE_KEY/antwort – sama odpowiedź jako strumień Server-Sent Events, treść żądania najwyżej 8 KB:
{"q":"Ile trwa wysyłka?","locale":"de",
"visitor_id":"v_…",
"ctx":{"url":"https://shop.example/suche","title":"Wyszukiwanie"},
"folge":false,
"vorher":[{"q":"…","a":"…"}]}
- q (String, obowiązkowe, 1–300 znaków)
- locale (String, opcjonalne)
- visitor_id (String, opcjonalne,
[A-Za-z0-9_-]{1,80}) – identyfikator odwiedzającego czat, żeby przekazanie do czatu pasowało. - ctx (obiekt, opcjonalne) –
url,path,referrer,title; query i kotwica są usuwane. - folge (
true, opcjonalne) – kolejne pytanie; omija filtr pytań. - vorher (lista, opcjonalne) – najwyżej 3 wcześniejsze pary (
q≤ 300,a≤ 1500 znaków).
Odpowiedź text/event-stream:
event: status
data: {"stufe":"denkt"}
event: text
data: {"text":"Wysyłka trwa"}
event: fertig
data: {"text":"Wysyłka trwa zwykle 2–3 dni robocze.","quellen":[{"titel":"Wysyłka","url":"https://shop.example/versand"}],"fortsetzung":{"art":"faden","id":"01J…"}}
- status –
{stufe}:denkt,sucht,schreibt,wartet. Pierwsze zdarzenie to zawszedenkt. - text –
{text}: cały dotąd widoczny tekst (nie różnica), najwyżej co 150 ms. - fertig –
{text, quellen, fortsetzung};fortsetzungto{art:"faden", id}(zapisane jako rozmowa),{art:"neu"}albonull. - fehler –
{code, text?}zcode:aus,gesperrt,drossel,motor,zeit,einwilligung,ungueltig. Jeślifehlerprzyjdzie potext, zostaw tekst.
Po fertig albo fehler strumień się kończy. Także błędy przed startem przychodzą jako strumień z dokładnie jednym fehler (HTTP 404, 429, 400, 413, 503 albo 200). Bez tekstu po 45 sekundach albo bez końca po 90 sekundach przychodzi fehler zeit. Jeśli zamkniesz połączenie, odpowiedź zostaje przerwana. Proxy po drodze musi przekazywać strumień bez buforowania.
// odczyt strumienia w przeglądarce (EventSource nie obsługuje 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: 'de' }), 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]));
}
}
Dalej: Ochrona danych
Pēdējoreiz atjaunināts: