Smart Answer: 웹사이트 검색의 AI 답변
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 선택자로 지정), 제출이나 입력 중단을 기다린 뒤 설정된 위치(대상 요소 앞, 뒤 또는 안)의 박스에 답변을 표시합니다. 기본적으로 질문처럼 보이는 입력에만 답합니다.
script 태그 속성:
- data-site-key(선택 사항) – 없으면 채팅 로더의
data-rc-site-key를 사용합니다. - data-ws-url(선택 사항) – 채팅 주소입니다. 없으면 채팅과 같은 방식으로 도출합니다.
- data-api(선택 사항) – 인터페이스 기본 주소입니다. 기본값은
https://ws.reactive.chat또는 자체 도메인입니다. - data-locale(선택 사항) – 언어입니다. 없으면
<html lang>, 그다음 브라우저를 따릅니다.
스크립트는 쿠키를 설정하지 않으며 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;
}
계정의 사용자 지정 CSS 필드에서 .rc-ai .rc-ai__teil { … }로 개별 부분을 변경합니다. 예: .rc-ai .rc-ai__hinweis { display: none; }. 보호 계층은 페이지의 #id 또는 !important 규칙까지 막지는 못합니다.
HTTP 인터페이스
서버 렌더링 검색 페이지나 자체 인터페이스용으로 인증과 쿠키 없는 공개 인터페이스가 있습니다. 주소: https://ws.reactive.chat/api/suche/SITE_KEY.
모든 엔드포인트의 공통 사항:
- CORS는 프로젝트 도메인의 출처만 허용합니다(서브도메인 포함).
Origin이 없는 서버 호출은 항상 작동합니다. - 빈도 제한: 모든 엔드포인트를 합해 방문자 주소당 분당 요청 60회입니다. 초과하면
Retry-After,X-RateLimit-*와 함께 429를 반환합니다. 서버에서 호출하면 서버 주소를 집계하므로 방문자가 많으면 브라우저의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 KB입니다.
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 KB입니다.
{"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 ms에 한 번입니다. - fertig –
{text, quellen, fortsetzung}입니다.fortsetzung은{art:"faden", id}(대화로 저장됨),{art:"neu"}또는null입니다. - fehler –
{code, text?}와code:aus,gesperrt,drossel,motor,zeit,einwilligung,ungueltig입니다.text후에fehler가 오면 텍스트를 유지합니다.
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]));
}
}
다음: 개인정보 보호 연동
최종 업데이트: