May
22

Cum faci un chatbot inteligent de la zero în 2026

05/22/2026 12:00 AM by Admin in Ai & automatizare

Cum faci un chatbot inteligent de la zero în 2026

Termenul „chatbot inteligent" sună intimidant. Cei mai mulți oameni îl asociază imediat cu ChatGPT, cu modele AI gigantice, cu costuri lunare și cu echipe întregi de ingineri. Realitatea este însă mult mai prietenoasă: un chatbot care răspunde rapid, precis și relevant la nouăzeci la sută dintre întrebările unui vizitator obișnuit poate fi construit într-un singur weekend, cu HTML, CSS și JavaScript pur, fără niciun cost, fără server complicat și fără API extern. Acest ghid îți arată exact cum.

Vom porni de la ideea că nu ai nevoie de AI real pentru un chatbot util. Vom defini ce înseamnă „inteligență" în contextul unui asistent virtual de site, vom proiecta arhitectura completă, vom scrie codul împreună și vom acoperi capcanele pe care le va întâlni orice dezvoltator care își construiește primul chatbot. La final, vei avea un chatbot funcțional pe care îl poți publica pe site-ul tău și care va răspunde mai bine decât te-ai aștepta.

De ce un chatbot rule-based bate de obicei AI-ul pe site-urile mici și medii

Există o presupunere greșită că un chatbot trebuie să folosească un model de limbaj mare pentru a fi util. În realitate, pentru majoritatea cazurilor de pe site-urile de business, prezentare sau e-commerce, un sistem rule-based bine construit oferă o experiență mai bună decât un model AI generic. Motivul este simplu: pe site-ul tău nu vrei ca botul să răspundă creativ la „cum optimizez SEO-ul" — vrei să trimită utilizatorul direct la pagina ta de servicii sau la articolul potrivit. Un model AI poate inventa răspunsuri, poate halucina linkuri inexistente, poate da sfaturi care contrazic tonul brandului tău. Un sistem rule-based răspunde exact ce ai programat să răspundă.

Aici sunt cele patru avantaje concrete care contează în 2026. Primul este costul zero — nu plătești pentru fiecare conversație, nu ai limită de mesaje, nu primești o factură neașteptată la sfârșitul lunii. Al doilea este viteza de răspuns sub o sutime de secundă, comparativ cu cele între unu și trei secunde ale unui apel API către un model AI. Al treilea este predictibilitatea totală — știi exact ce va răspunde botul la fiecare scenariu, ceea ce este vital pentru brand și pentru conformitate. Al patrulea este confidențialitatea — mesajele utilizatorilor nu pleacă nicăieri de pe site-ul tău, ceea ce contează enorm pentru GDPR. Dacă vrei să-ți generezi rapid politica de confidențialitate care să acopere astfel de aspecte, ai unealta gratuită Privacy Policy Generator.

Limitarea unui chatbot rule-based este reală și onestă: nu va înțelege întrebări complet noi, formulate ambiguu, fără să fi anticipat structura lor. Dar, după cum vei vedea, această limitare se diminuează dramatic prin trei tehnici simple pe care le vom acoperi: normalizarea textului, scoringul ponderat al cuvintelor cheie și sistemul de prioritate ca tie-breaker.

Arhitectura unui chatbot inteligent — patru fișiere și o idee

Un chatbot rule-based bine proiectat trăiește în doar patru fișiere. Această simplitate este o caracteristică, nu un compromis. Cu cât arhitectura este mai curată, cu atât este mai ușor să-l întreții, să-l extinzi și să-l înțelegi peste șase luni când vei vrea să-i adaugi un intent nou.

Primul fișier este index.html — scheletul vizibil al chatbotului, structura paginii care găzduiește interfața de chat. Al doilea este style.css — designul vizual, totul de la culoare la animații. Al treilea este chat.js — logica propriu-zisă: cum citește mesajele, cum decide ce să răspundă, cum afișează răspunsurile. Al patrulea, și cel mai important, este knowledge.js — baza de cunoștințe care conține toate intenturile și răspunsurile.

Separarea aceasta între logică și date este crucială. Codul JavaScript din chat.js nu se schimbă aproape niciodată. Toate modificările zilnice se fac în knowledge.js. Asta înseamnă că o persoană care nu știe programare poate adăuga sau modifica răspunsuri fără să strice nimic. Și înseamnă că poți reutiliza același cod pentru o pizzerie, pentru o clinică, pentru un magazin online — schimbi doar fișierul cu cunoștințe.

Knowledge base — inima chatbotului

Knowledge base-ul este locul unde se petrece toată „inteligența" botului. O structură bine gândită aici face diferența între un chatbot care frustrează utilizatorii și unul care îi încântă. Iată cum arată structura unui knowledge base modern, scrisă ca obiect JavaScript pentru a evita restricțiile de tip CORS pe care browserele moderne le impun când deschizi fișiere direct de pe disc.

const KNOWLEDGE = {
  bot_name: "Aria",
  greeting: "Salut! Cu ce te pot ajuta astăzi?",
  default: "Nu am înțeles. Încearcă să reformulezi.",
  quick_replies: [
    "Ce poți face?",
    "Care e programul?",
    "Cum te contactez?"
  ],
  responses: [
    {
      intent: "salut",
      priority: 2,
      keywords: ["salut", "buna", "hei", "alo", "hello"],
      replies: [
        "Salut! Cu ce te ajut?",
        "Bună! Spune, ce te interesează?"
      ]
    },
    {
      intent: "program",
      priority: 0,
      keywords: ["program", "ora", "deschis", "inchis", "cand"],
      replies: [
        "Suntem deschiși L-V între 9 și 18."
      ]
    }
  ]
};

Observă trei lucruri importante despre această structură. Mai întâi, fiecare intent are un nume identificator (intent) care nu este văzut de utilizator, dar îți permite ție să-l referențiezi în loguri, în analiză și în extensii viitoare. Apoi, există un câmp priority care va servi ca tie-breaker în situațiile când două intenturi au scoruri egale — vom vedea mai jos cum se folosește corect. Și, în sfârșit, fiecare intent are mai multe variante de răspuns în array-ul replies; chatbotul alege aleatoriu una, ceea ce împiedică senzația de robotică repetitivă atunci când utilizatorul pune aceeași întrebare de două ori.

O greșeală frecventă a începătorilor este să pună prea puține cuvinte cheie pe intent. Pentru un intent solid, gândește-te la cel puțin opt-zece variante, inclusiv abrevieri, sinonime și formulări naturale. Pentru intentul „program" de mai sus, în realitate vei vrea: „program", „ora", „deschis", „inchis", „cand deschideti", „pana cand", „luni", „marti", „duminica", „weekend", „sambata". Cu cât acoperi mai multe formulări, cu atât botul tău va părea mai inteligent.

Normalizarea textului — primul pas către inteligență reală

Pentru ca botul să trateze identic „SALUT!" și „salut" și „Salut...", textul trebuie normalizat înainte de orice comparație. În limba română, normalizarea trebuie să facă două lucruri suplimentare față de engleză: să scoată diacriticele și să curețe punctuația specifică. Iată funcția exactă care face acest lucru.

function normalize(text) {
  return text
    .toLowerCase()
    .replace(/[ăâ]/g, 'a')
    .replace(/[î]/g, 'i')
    .replace(/[șş]/g, 's')
    .replace(/[țţ]/g, 't')
    .replace(/[^a-z0-9\s]/g, ' ')
    .replace(/\s+/g, ' ')
    .trim();
}

Această funcție de zece linii este probabil cea mai importantă bucată de cod din întregul chatbot. Fără ea, „Câtă pizza?" ar fi tratat ca un șir complet diferit de „cata pizza", iar utilizatorul român care scrie corect cu diacritice ar primi răspunsul default. Cu ea, ambele variante devin „cata pizza" și pot fi comparate cu keyword-urile din knowledge base, care, de asemenea, sunt scrise fără diacritice pentru consistență.

Există o subtilitate: normalizarea trebuie aplicată simetric — atât pe mesajul utilizatorului, cât și pe fiecare keyword în momentul comparației. Dacă normalizezi doar mesajul și uiți să normalizezi keyword-urile, „program" din knowledge base nu va prinde nimic. Acest tip de bug subtil este motivul pentru care normalizarea este, de obicei, prima funcție pe care o testezi separat înainte să construiești restul.

Algoritmul de matching — cum decide botul ce să răspundă

Acum că avem textul normalizat și o bază de cunoștințe, întrebarea este: cum alegem cel mai bun răspuns? Algoritmul corect este surprinzător de simplu și se numește „matching ponderat prin scor". Pentru fiecare intent din knowledge base, calculăm un scor în funcție de câte keyword-uri prind în mesajul utilizatorului. Câștigă intentul cu scorul cel mai mare.

function findIntent(userMessage) {
  const normalizedMsg = normalize(userMessage);
  let bestScore = 0;
  let bestIntent = null;
 
  for (const rule of KNOWLEDGE.responses) {
    let score = 0;
    for (const keyword of rule.keywords) {
      const nKw = normalize(keyword);
      if (normalizedMsg.includes(nKw)) {
        score += nKw.length;
      }
    }
    if (score > bestScore) {
      bestScore = score;
      bestIntent = rule;
    }
  }
  return bestIntent;
}

Cheia inteligenței acestui algoritm este linia score += nKw.length. În loc să adăugăm un punct fix pentru fiecare keyword găsit, ponderăm scorul cu lungimea keyword-ului. De ce? Pentru că un keyword mai lung este mai specific. Cuvântul „certificat ssl" prinde doar mesaje care vorbesc exact despre certificate SSL. Cuvântul „ssl", de unul singur, ar putea prinde și „SSL nu funcționează", și „ce e SSL", și „certificatul SSL al site-ului meu a expirat". Vrem ca keyword-urile lungi să bată keyword-urile scurte, pentru că ele indică o intenție mai clară.

Un alt detaliu important este verificarea score > bestScore, nu >=. În caz de egalitate, păstrăm primul găsit. Asta înseamnă că ordinea intenturilor în knowledge base contează, dar conta mai mult înainte să introducem sistemul de prioritate, despre care vorbim imediat. Pentru o introducere completă în alte aspecte tehnice care influențează un site modern, vezi PHP 8: Funcții și Best Practices 2026, unde discutăm best practices similare pentru cod curat.

Prioritatea ca tie-breaker — capcana în care cad toți începătorii

Aici venim la o nuanță care îți va salva ore de debugging. Sistemul de prioritate trebuie să fie un tie-breaker, nu un bonus universal. Versiunea naivă pe care o vezi în multe tutoriale arată așa:

let score = calculateKeywordScore(rule);
score += rule.priority;  // GREȘIT!
if (score > bestScore) { ... }

Această implementare are un bug subtil dar grav. Dacă utilizatorul scrie ceva complet străin de orice intent — să zicem „cum se face o supă de pui" — niciun keyword nu va prinde, scorul brut va fi zero pentru toate intenturile, dar prioritatea va fi adăugată oricum. Rezultatul: mesajul cade pe primul intent cu cea mai mare prioritate, indiferent de conținut. Utilizatorul primește un răspuns despre contact când a întrebat despre supă. Soluția corectă este să adăugăm prioritatea doar dacă scorul brut este pozitiv:

let rawScore = calculateKeywordScore(rule);
if (rawScore === 0) continue;  // niciun keyword găsit, sărim
let score = rawScore + rule.priority;
if (score > bestScore) { ... }

Cu această reparație, prioritatea face ce trebuie să facă: în caz de scoruri brute apropiate, intentul mai important câștigă, dar mesajele cu adevărat străine cad pe răspunsul default, unde le este locul.

Conflicte între intenturi — cea mai mare problemă pe termen lung

Pe măsură ce knowledge base-ul crește, vei observa fenomenul cel mai frustrant al chatboturilor rule-based: două intenturi se „bat" pentru aceeași frază. De exemplu, intentul „securitate" și intentul „wordpress" pot ambele să conțină keyword-ul „plugin securitate", iar utilizatorul care întreabă „vreau un plugin de securitate" primește un răspuns nedeterminist, în funcție de ordinea intenturilor în fișier.

Soluția nu este complicată, dar trebuie aplicată sistematic. Înainte să adaugi un keyword nou la un intent, verifică dacă acel keyword nu există deja la alt intent. Dacă există, decide editorial cine ar trebui să-l dețină și șterge-l din celălalt. Această disciplină se numește „ownership keyword" — fiecare frază aparține unui singur intent, fără ambiguitate. Iată un script simplu pe care îl rulezi periodic pentru a detecta conflictele.

function findDuplicateKeywords(kb) {
  const owners = {};
  for (const rule of kb.responses) {
    for (const kw of rule.keywords) {
      const normalized = kw.toLowerCase().trim();
      if (!owners[normalized]) owners[normalized] = [];
      owners[normalized].push(rule.intent);
    }
  }
  const conflicts = {};
  for (const [kw, intents] of Object.entries(owners)) {
    if (intents.length > 1) conflicts[kw] = intents;
  }
  return conflicts;
}

Apelezi findDuplicateKeywords(KNOWLEDGE) în consola browserului și primești înapoi un obiect cu toate conflictele. Apoi alegi pentru fiecare cui îi aparține și cureți. Pentru un proiect serios, vei rula acest test ca parte a fluxului tău de validare ori de câte ori modifici knowledge base-ul.

Interfața vizuală — designul care convertește vizitatori în utilizatori

Codul perfect nu valorează nimic dacă utilizatorul nu deschide chatul. Designul interfeței trebuie să transmită trei lucruri instantaneu: aceasta este o aplicație de chat (recunoscută vizual), este disponibilă acum (indicator de status), și este prietenoasă (avatar uman sau simbolic, culori calde). Iată scheletul HTML minimal pentru o astfel de interfață:

<div class="chat-app">
  <div class="chat-header">
    <div class="avatar">🤖</div>
    <div class="header-text">
      <h1>Aria</h1>
      <p>Asistent virtual</p>
    </div>
    <div class="status">Online</div>
  </div>
  <div class="messages" id="messages"></div>
  <div class="quick-replies" id="quick-replies"></div>
  <div class="input-area">
    <input id="input" placeholder="Scrie un mesaj...">
    <button id="send">➤</button>
  </div>
</div>

Cele patru zone — antet, mesaje, sugestii rapide și input — formează un layout pe care utilizatorii îl recunosc instantaneu din experiența cu WhatsApp, Messenger și alte aplicații similare. Această familiaritate este un activ. Nu reinventa roata; folosește pattern-ul stabilit. Apoi, pe partea de CSS, două detalii fac diferența între un chat amatorist și unul profesionist: animația de „typing" cu trei puncte care pulsează când botul „gândește", și animația subtilă de slide-in pentru fiecare mesaj nou. Pentru o explicație completă a tehnicilor moderne de animație și layout, vezi CSS Modern: Tehnici avansate pentru 2026.

Pentru optimizarea performanței interfeței, asigură-te că minifici fișierele CSS și JS înainte să le pui în producție. Ai unelte gratuite dedicate pentru asta: CSS Minifier și JavaScript Minifier. Reducerea dimensiunii fișierelor încarcă mai rapid chatbotul, ceea ce contează enorm la prima impresie.

Quick replies — secretul îmbunătățirii dramatice a UX-ului

Multe chatboturi eșuează nu din cauza algoritmului, ci pentru că utilizatorul nu știe ce să întrebe. Soluția este să-i arăți, nu să aștepți să ghicească. Quick replies — butoanele cu întrebări preformulate care apar imediat după mesajul de salut — rezolvă această problemă elegant. Utilizatorul vede instantaneu trei sau patru opțiuni reprezentative și poate da click direct, fără să mai scrie nimic.

function renderQuickReplies() {
  const container = document.getElementById('quick-replies');
  container.innerHTML = '';
  KNOWLEDGE.quick_replies.forEach(text => {
    const btn = document.createElement('button');
    btn.className = 'quick-reply';
    btn.textContent = text;
    btn.onclick = () => {
      sendMessage(text);
      container.innerHTML = '';
    };
    container.appendChild(btn);
  });
}

După primul click pe un quick reply, butoanele dispar — semnal că utilizatorul a trecut la modul „conversație liberă". Aceasta este o decizie de UX subtilă dar importantă: nu-l copleși cu opțiuni o dată ce el a luat decizia să interacționeze activ.

Persistența conversației — utilizatorul care se întoarce

Imaginează-ți scenariul: utilizatorul deschide chatul, scrie câteva mesaje, primește răspunsuri utile, apoi schimbă din greșeală pagina sau apasă refresh. La revenire, toată conversația dispare. Frustrare imediată. Soluția este simplă — sessionStorage sau localStorage. Iată cum salvezi automat istoricul.

let history = [];
 
function saveHistory() {
  try {
    sessionStorage.setItem('chat_history', JSON.stringify(history));
  } catch (e) { /* storage plin, ignorăm */ }
}
 
function loadHistory() {
  try {
    const saved = sessionStorage.getItem('chat_history');
    if (saved) history = JSON.parse(saved);
  } catch (e) { history = []; }
}

Diferența între sessionStorage și localStorage este aceasta: primul păstrează datele cât tabul browserului este deschis, al doilea le păstrează permanent (sau până când utilizatorul șterge cache-ul). Pentru un chat de site, sessionStorage este de obicei alegerea corectă — nu vrei să-i amintești utilizatorului peste o săptămână că a întrebat ceva. Pentru un asistent personal sau un dashboard, localStorage are sens.

Knowledge base extins — sugestii de articole și unelte legate

Un chatbot devine cu adevărat valoros când nu doar răspunde la întrebări, ci și recomandă resurse suplimentare. Dacă utilizatorul întreabă despre viteza site-ului, răspunsul ideal nu este doar „verifică viteza", ci „verifică viteza cu unealta X, iar dacă vrei să înțelegi de ce contează, citește articolul Y". Această tehnică se numește „cross-linking inteligent" și transformă chatbotul dintr-un FAQ static într-un ghid activ.

Iată cum extinzi structura unui intent pentru a include resurse legate:

{
  intent: "viteza_site",
  priority: 0,
  keywords: ["viteza", "lent", "incarca greu", "site lent"],
  replies: [
    "Pentru a verifica viteza, folosește unealta noastră de la /page-speed-checker. Pentru detalii complete, citește ghidul nostru despre Core Web Vitals."
  ],
  tools_suggested: ["/page-speed-checker", "/pagespeed-insights-checker"],
  articles_suggested: ["/blog/optimizare-viteza-site-core-web-vitals-2026"]
}

Câmpurile tools_suggested și articles_suggested nu sunt folosite direct de algoritmul de matching, dar pot fi exploatate de logica de afișare pentru a adăuga automat butoane sau linkuri sub răspunsul textual. Astfel păstrezi separarea curată între date și prezentare, dar îți permiți flexibilitate mare în UX. Pentru un audit complet al site-ului tău și verificarea performanței, poți folosi Page Speed Checker, iar pentru analize aprofundate PageSpeed Insights Checker.

Logarea întrebărilor fără răspuns — instrumentul tău de îmbunătățire continuă

Cea mai valoroasă funcționalitate a unui chatbot rule-based, paradoxal, este capacitatea sa de a admite că nu știe. Atunci când utilizatorul pune o întrebare care cade pe răspunsul default, acea întrebare trebuie logată undeva pentru analiză ulterioară. În browser, fără server, poți folosi localStorage ca buffer și un endpoint backend simplu pentru sincronizare.

function logUnknown(message) {
  try {
    const log = JSON.parse(localStorage.getItem('unknown_log') || '[]');
    log.push({
      timestamp: new Date().toISOString(),
      message: message
    });
    if (log.length > 100) log.shift();
    localStorage.setItem('unknown_log', JSON.stringify(log));
  } catch (e) {}
}

Săptămânal, ca administrator, citești acest log (manual din DevTools sau printr-un export automat) și analizezi întrebările care au eșuat. Vei descoperi pattern-uri: utilizatori care folosesc abrevieri pe care nu le-ai anticipat, sinonime regionale, formulări neașteptate. Adaugi keyword-urile lipsă la intenturile existente, sau creezi intenturi complet noi pentru pattern-uri repetate. Acest ciclu de îmbunătățire continuă este ceea ce face diferența între un chatbot mediocru și unul excelent — și nu necesită niciun fel de AI.

Capcanele cele mai frecvente și cum să le eviți

După ce am construit zeci de chatboturi rule-based, am identificat trei capcane în care cad aproape toți dezvoltatorii la primul proiect. Prima este keyword-urile prea scurte — folosirea de cuvinte de două sau trei litere ca „cv" sau „da" în knowledge base. Acestea prind substring-uri în cuvinte care nu au nicio legătură: „cv" prinde „cvartet", „da" prinde „dar", „dat", „data". Soluția este să folosești întotdeauna keyword-uri de minimum patru caractere, sau să adaugi un strat de tokenizare care verifică limitele de cuvânt.

A doua capcană este uitarea testelor de regresie. Adaugi un keyword nou pentru a rezolva o problemă, dar nu testezi că celelalte funcționează în continuare. Două săptămâni mai târziu descoperi că ai stricat trei intenturi vechi. Soluția este să menții un fișier simplu de teste — o listă de zece până la treizeci de fraze tipice, fiecare cu intentul așteptat — pe care îl rulezi după fiecare modificare.

A treia capcană este interfața care nu reține contextul. Utilizatorul scrie „cât costă livrarea", primește răspunsul, apoi scrie „și pentru zona Mamaia?" — botul răspunde default pentru că nu mai are contextul „livrare". Soluția pentru această problemă necesită fie adăugarea contextului în knowledge base (un câmp follow_ups), fie introducerea unei memorii pe durata conversației, în care ultimele două sau trei intenturi sunt păstrate ca tie-breakers pentru intenturile următoare. Aceasta este o tehnică avansată care merită un articol separat, dar este bine să fii conștient de ea de la început.

Deployment — cum publici chatbotul pe site-ul tău

Cea mai mare frumusețe a unui chatbot construit cu HTML, CSS și JavaScript pur este că deployment-ul este trivial. Nu ai nevoie de server, nu ai nevoie de bază de date, nu ai nevoie de domain DevOps. Tot ce trebuie să faci este să încarci cele patru fișiere pe hostingul tău, fie prin FTP, fie prin panoul de control al hostingului, și să incluzi index.html ca iframe într-o pagină dedicată — sau, mai elegant, să copiezi conținutul JavaScript și CSS direct în template-ul site-ului tău și să-l afișezi ca un widget flotant în colțul din dreapta-jos.

Pentru cei care preferă o instalare separată, calea standard este să creezi un subdomeniu sau o subdiectorie dedicată — de exemplu chat.site-ul-tau.ro — și să încarci acolo fișierele. Dacă nu ai încă hosting potrivit pentru un astfel de proiect, citește comparația noastră detaliată Hosting ieftin vs. Hosting bun: Teste comparative 2026 înainte să alegi. Pentru a verifica că hostingul tău răspunde cum trebuie după instalare, poți folosi Server Status Checker.

Un aspect tehnic important: dacă vrei să deschizi pur și simplu fișierul HTML local cu dublu-click pentru testare, asigură-te că incluzi knowledge base-ul ca fișier JavaScript (knowledge.js cu const KNOWLEDGE = {...}), nu ca JSON încărcat prin fetch. Browserele moderne, inclusiv Chrome și Safari, blochează cererile fetch din protocolul file:// din motive de securitate (politica CORS). Pe server real cu protocol HTTP, ambele variante funcționează, dar pentru testare locală fără server, varianta cu fișier JS este obligatorie. Pentru documentația oficială a acestei politici de securitate, vezi CORS pe MDN.

Integrare cu alte sisteme — pași către un asistent complet

Odată ce ai chatbotul funcțional, există trei direcții naturale de extindere. Prima este conectarea cu bara de căutare a site-ului tău — dacă o căutare returnează zero rezultate, afișezi un mesaj de tip „nu am găsit, dar asistentul nostru te poate ajuta" cu un buton care deschide chatul cu întrebarea precompletată. Această tehnică recuperează vizitatorii frustrați și îi convertește în interacțiuni utile.

A doua direcție este integrarea cu sistemul de tickete sau email. Dacă utilizatorul scrie „vreau să vorbesc cu un om", chatbotul îi afișează formularul de contact direct în chat sau, mai sofisticat, trimite automat un email către echipa ta cu istoricul conversației atașat. Acest tip de „escalare elegantă" este una dintre semnăturile chatboturilor profesionale.

A treia direcție, mai avansată, este sistemul hibrid — pentru întrebările pe care chatbotul rule-based nu le poate rezolva, în loc să afișeze răspunsul default, apelezi un model AI extern (de exemplu Claude, GPT-4 sau Gemini) cu un buget limitat. Această abordare combină avantajele ambelor lumi: viteza și predictibilitatea regulilor pentru optzeci la sută din cazuri, plus flexibilitatea AI-ului pentru restul. Costul rămâne controlat pentru că AI-ul este invocat doar în cazuri reale de eșec. Pentru documentația oficială a Anthropic API, vezi docs.anthropic.com, iar pentru OpenAI, platform.openai.com/docs.

Securitate și conformitate — aspecte care nu sunt opționale în 2026

Chiar și un chatbot care rulează 100% în browser are obligații de conformitate. Dacă logezi conversațiile (chiar și pentru îmbunătățire), trebuie să informezi utilizatorul în politica de confidențialitate. Dacă folosești cookies pentru a păstra istoricul, trebuie să afișezi o bară de cookies conformă cu GDPR. Pentru ambele, ai unelte gratuite: Privacy Policy Generator îți generează automat politica de confidențialitate adaptată site-urilor cu chatbot, iar Generator Bară Cookies îți creează banner-ul GDPR compatibil.

Pe partea de securitate tehnică, două lucruri sunt obligatorii. Întâi, validează și sanitizează tot ce vine de la utilizator înainte de a-l afișa. Dacă utilizatorul scrie <script>alert('XSS')</script> și tu pui acel text direct în innerHTML, ai un atac XSS în chatul tău. Folosește textContent pentru mesajele utilizatorului, sau o funcție de escape ca encodeURIComponent înainte de inserare. Al doilea aspect este să nu pui niciodată chei API sau credențiale în JavaScript-ul client — orice valoare scrisă acolo este vizibilă pentru oricine inspectează codul în DevTools. Pentru a verifica că site-ul tău nu are vulnerabilități cunoscute, rulează periodic un audit cu Blacklist Lookup și Google Malware Checker.

Întreținerea pe termen lung — disciplinele care fac diferența

Un chatbot rule-based nu este un proiect „setezi și uiți". Pentru a-l păstra util în timp, trei discipline săptămânale fac toată diferența. Prima este review-ul logului de întrebări fără răspuns, despre care am vorbit mai sus — cincisprezece minute pe săptămână adăugând keyword-uri lipsă cresc dramatic acuratețea. A doua este testarea de regresie după fiecare modificare — niciodată să nu adaugi un keyword nou fără să verifici că toate scenariile vechi funcționează în continuare. A treia este analiza intenturilor cele mai folosite — dacă observi că nouăzeci la sută dintre interacțiuni cad pe trei intenturi specifice, fă acele intenturi prioritate maximă în UX (de exemplu, transformă-le în quick replies).

În timp, vei dezvolta intuiție pentru ce tip de modificări dau rezultate mai bune. Vei observa că adăugarea unui keyword nou bate aproape întotdeauna refacerea designului. Vei descoperi că răspunsurile cu link concret la o unealtă convertesc mult mai bine decât răspunsurile vagi. Vei vedea că tonul cald și autentic — „mă bucur că întrebi", „cu plăcere te ajut" — face utilizatorii să se întoarcă. Aceste lecții sunt aurul real al construirii unui chatbot, și ele nu vin din articole, ci din observarea conversațiilor reale.

Exemplu complet — chatbotul într-un singur fișier HTML, gata de testat

Teoria este utilă, dar codul rulabil bate teoria. Mai jos găsești un chatbot funcțional complet, într-un singur fișier HTML — toate cele patru componente (structura, stilul, knowledge base-ul și logica) sunt împachetate împreună pentru testare rapidă. Copiază tot blocul de cod, salvează-l ca chatbot.html pe calculatorul tău și deschide-l cu dublu-click în browser — sau, mai rapid, lipește-l direct în HTML Previewer de pe seotoolpro.ro și vezi rezultatul instant, fără să salvezi nimic local.

<!DOCTYPE html>
<html lang="ro">
<head>
<meta charset="UTF-8">
<title>Aria - Chatbot Demo</title>
<style>
  * { box-sizing: border-box; margin: 0; padding: 0; }
  body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    background: linear-gradient(135deg, #0a1628 0%, #134e4a 100%);
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
  }
  .chat-app {
    width: 100%;
    max-width: 420px;
    height: 600px;
    background: #fff;
    border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.3);
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  .chat-header {
    background: #0a1628;
    color: #fff;
    padding: 16px;
    display: flex;
    align-items: center;
    gap: 12px;
  }
  .avatar {
    width: 40px; height: 40px;
    background: #14b8a6;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
  }
  .header-text h1 { font-size: 16px; }
  .header-text p { font-size: 12px; color: #5eead4; }
  .status {
    margin-left: auto;
    font-size: 11px;
    color: #2dd4bf;
    display: flex;
    align-items: center;
    gap: 4px;
  }
  .status::before {
    content: "";
    width: 8px; height: 8px;
    background: #2dd4bf;
    border-radius: 50%;
  }
  .messages {
    flex: 1;
    overflow-y: auto;
    padding: 16px;
    background: #f0fdfa;
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
  .msg {
    max-width: 80%;
    padding: 10px 14px;
    border-radius: 16px;
    font-size: 14px;
    line-height: 1.4;
    animation: slideIn 0.3s ease;
  }
  @keyframes slideIn {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
  }
  .msg.bot {
    background: #fff;
    color: #115e59;
    align-self: flex-start;
    border: 1px solid #ccfbf1;
  }
  .msg.user {
    background: #14b8a6;
    color: #fff;
    align-self: flex-end;
  }
  .typing {
    background: #fff;
    align-self: flex-start;
    padding: 12px 16px;
    border-radius: 16px;
    border: 1px solid #ccfbf1;
  }
  .typing span {
    display: inline-block;
    width: 6px; height: 6px;
    background: #14b8a6;
    border-radius: 50%;
    margin: 0 2px;
    animation: bounce 1.4s infinite;
  }
  .typing span:nth-child(2) { animation-delay: 0.2s; }
  .typing span:nth-child(3) { animation-delay: 0.4s; }
  @keyframes bounce {
    0%, 80%, 100% { transform: scale(0.6); opacity: 0.5; }
    40% { transform: scale(1); opacity: 1; }
  }
  .quick-replies {
    padding: 0 16px 8px;
    background: #f0fdfa;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
  .quick-reply {
    background: #fff;
    border: 1px solid #5eead4;
    color: #115e59;
    padding: 6px 12px;
    border-radius: 16px;
    font-size: 12px;
    cursor: pointer;
    transition: all 0.2s;
  }
  .quick-reply:hover {
    background: #14b8a6;
    color: #fff;
    border-color: #14b8a6;
  }
  .input-area {
    display: flex;
    padding: 12px;
    background: #fff;
    border-top: 1px solid #ccfbf1;
    gap: 8px;
  }
  .input-area input {
    flex: 1;
    border: 1px solid #ccfbf1;
    border-radius: 20px;
    padding: 10px 16px;
    font-size: 14px;
    outline: none;
  }
  .input-area input:focus { border-color: #14b8a6; }
  .input-area button {
    background: #14b8a6;
    color: #fff;
    border: none;
    width: 40px; height: 40px;
    border-radius: 50%;
    cursor: pointer;
    font-size: 16px;
    transition: background 0.2s;
  }
  .input-area button:hover { background: #115e59; }
</style>
</head>
<body>

<div class="chat-app">
  <div class="chat-header">
    <div class="avatar">🤖</div>
    <div class="header-text">
      <h1>Aria</h1>
      <p>Asistent virtual</p>
    </div>
    <div class="status">Online</div>
  </div>
  <div class="messages" id="messages"></div>
  <div class="quick-replies" id="quickReplies"></div>
  <div class="input-area">
    <input id="input" placeholder="Scrie un mesaj..." autocomplete="off">
    <button id="send">➤</button>
  </div>
</div>

<script>
const KNOWLEDGE = {
  greeting: "Salut! Sunt Aria. Cu ce te pot ajuta astăzi?",
  default: "Nu sunt sigură că am înțeles. Poți reformula sau alege una dintre opțiunile de mai sus.",
  quick_replies: ["Ce poți face?", "Program", "Contact", "Preturi"],
  responses: [
    {
      intent: "salut", priority: 2,
      keywords: ["salut", "buna", "hei", "alo", "hello", "ciao"],
      replies: ["Salut! Cu ce te ajut?", "Bună! Spune, ce te interesează?"]
    },
    {
      intent: "capacitati", priority: 1,
      keywords: ["ce poti face", "ce stii", "cu ce ma ajuti", "ce faci"],
      replies: ["Pot răspunde la întrebări despre program, contact, prețuri și servicii. Întreabă-mă orice!"]
    },
    {
      intent: "program", priority: 0,
      keywords: ["program", "ora", "deschis", "inchis", "cand lucrati", "orar"],
      replies: ["Suntem deschiși Luni-Vineri, 9:00-18:00. Sâmbătă 10:00-14:00, Duminică închis."]
    },
    {
      intent: "contact", priority: 0,
      keywords: ["contact", "telefon", "email", "adresa", "cum va contactez"],
      replies: ["Ne găsești la [email protected] sau la 0721.234.567. Răspundem în maxim 24h."]
    },
    {
      intent: "preturi", priority: 0,
      keywords: ["pret", "preturi", "cost", "cat costa", "tarif", "oferta"],
      replies: ["Prețurile încep de la 99 RON/lună pentru pachetul Basic. Vrei să-ți trimit oferta completă pe email?"]
    },
    {
      intent: "multumire", priority: 1,
      keywords: ["multumesc", "mersi", "thanks", "ms"],
      replies: ["Cu plăcere! Mai pot ajuta cu ceva?", "Oricând! Spune dacă mai ai întrebări."]
    },
    {
      intent: "la_revedere", priority: 1,
      keywords: ["pa", "la revedere", "bye", "noapte buna"],
      replies: ["O zi bună! Te aștept oricând.", "Pa! Revino când ai nevoie."]
    }
  ]
};

function normalize(text) {
  return text.toLowerCase()
    .replace(/[ăâ]/g, "a").replace(/[î]/g, "i")
    .replace(/[șş]/g, "s").replace(/[țţ]/g, "t")
    .replace(/[^a-z0-9\s]/g, " ")
    .replace(/\s+/g, " ").trim();
}

function findIntent(msg) {
  const nMsg = normalize(msg);
  let best = null, bestScore = 0;
  for (const rule of KNOWLEDGE.responses) {
    let raw = 0;
    for (const kw of rule.keywords) {
      const nKw = normalize(kw);
      if (nMsg.includes(nKw)) raw += nKw.length;
    }
    if (raw === 0) continue;
    const score = raw + (rule.priority || 0);
    if (score > bestScore) { bestScore = score; best = rule; }
  }
  return best;
}

function addMessage(text, who) {
  const div = document.createElement("div");
  div.className = "msg " + who;
  div.textContent = text;
  document.getElementById("messages").appendChild(div);
  div.scrollIntoView({ behavior: "smooth" });
}

function showTyping() {
  const div = document.createElement("div");
  div.className = "typing";
  div.id = "typing";
  div.innerHTML = "<span></span><span></span><span></span>";
  document.getElementById("messages").appendChild(div);
  div.scrollIntoView({ behavior: "smooth" });
}

function removeTyping() {
  const t = document.getElementById("typing");
  if (t) t.remove();
}

function botReply(text) {
  showTyping();
  setTimeout(() => {
    removeTyping();
    const intent = findIntent(text);
    const reply = intent
      ? intent.replies[Math.floor(Math.random() * intent.replies.length)]
      : KNOWLEDGE.default;
    addMessage(reply, "bot");
  }, 600);
}

function sendMessage(text) {
  if (!text.trim()) return;
  addMessage(text, "user");
  document.getElementById("input").value = "";
  document.getElementById("quickReplies").innerHTML = "";
  botReply(text);
}

function renderQuickReplies() {
  const c = document.getElementById("quickReplies");
  KNOWLEDGE.quick_replies.forEach(t => {
    const b = document.createElement("button");
    b.className = "quick-reply";
    b.textContent = t;
    b.onclick = () => sendMessage(t);
    c.appendChild(b);
  });
}

document.getElementById("send").onclick = () =>
  sendMessage(document.getElementById("input").value);
document.getElementById("input").addEventListener("keypress", e => {
  if (e.key === "Enter") sendMessage(e.target.value);
});

addMessage(KNOWLEDGE.greeting, "bot");
renderQuickReplies();
</script>

</body>
</html>

Acest exemplu este complet autonom — nu are nicio dependență externă, nu apelează niciun API și nu folosește librării. Toate cele patru componente discutate în articol (HTML, CSS, knowledge base, logică) sunt prezente într-o formă minimală dar funcțională, cu șapte intenturi reale: salut, capacități, program, contact, prețuri, mulțumire și la revedere. Animațiile de typing, slide-in pentru mesaje noi și quick replies sunt toate active.

Cum testezi chatbotul în 30 de secunde fără să instalezi nimic

Cea mai rapidă cale de a vedea chatbotul în acțiune este să folosești unealta HTML Previewer de pe seotoolpro.ro. Procesul este următorul: copiezi tot blocul de cod de mai sus, deschizi pagina previzualizatorului, lipești codul în câmpul de input și apeși butonul de previzualizare. În câteva secunde vei vedea chatbotul activ direct în browser, gata de testat. Poți încerca diverse formulări — „salut", „cât costă", „care e programul vostru", „mulțumesc" — pentru a vedea cum reacționează algoritmul de matching.

După testarea inițială, începe iterația. Modifică keyword-urile din KNOWLEDGE.responses, adaugă intenturi noi pentru cazurile tale specifice de business, schimbă culorile din CSS pentru a se potrivi cu brandul tău. Fiecare modificare se vede instant în previzualizator. Când ești mulțumit de rezultat, salvează fișierul ca chatbot.html și încarcă-l pe hostingul tău — gata, ai un chatbot live pe site. Pentru a optimiza codul final înainte de producție, folosește HTML Compressor pentru a reduce dimensiunea fișierului cu 30-40%, ceea ce înseamnă încărcare mai rapidă pentru vizitatori.

Concluzie — chatbotul ca instrument de creștere a site-ului

Un chatbot inteligent nu este un truc tehnic, ci un instrument de creștere a site-ului tău. Răspunde la întrebările repetitive ale vizitatorilor, îi ghidează către uneltele și articolele relevante, reduce sarcina echipei tale de suport, crește timpul petrecut pe site și — cel mai important — transformă vizitatorii pasivi în utilizatori activi. Toate acestea, cu o investiție inițială de câteva zile de dezvoltare și costuri operaționale zero.

Frumusețea abordării rule-based este că poți începe simplu și crește incremental. Versiunea minimă cu zece intenturi pe care o lansezi luni viitoare este deja utilă. Peste șase luni, după zeci de iterații bazate pe loguri reale, vei avea un asistent virtual care îți cunoaște site-ul mai bine decât majoritatea angajaților. Și totul, fără să plătești niciun cent pentru AI extern.

Pasul următor este al tău. Deschide un editor de text, creează cele patru fișiere, copiază codul din acest ghid și începe să-ți modelezi propriul chatbot pe domeniul tău. Pentru subiecte conexe care îți vor crește expertiza, citește Cum te ajută AI să domini Google în 2026, unde discutăm despre cum integrezi inteligența artificială în strategia SEO completă, și Checklist lansare site: 25 de lucruri de bifat 2026, pentru a te asigura că lansezi chatbotul tău pe un site optimizat în toate aspectele tehnice și SEO.



Try Pro Calculatoare Inteligente Practice! CLICK HERE

Get MTDb.ro -Filme si Seriale, Trailere, Actori si Stiri din Cinema - CLICK HERE
leave a comment
Please post your comments here.

Comentarii 0

Lasă un comentariu

0 / 2000

Comentariile sunt moderate înainte de publicare.

Se încarcă comentariile…