Інтеграція AI-асистента для підтримки користувачів на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Інтеграція AI-асистента для підтримки користувачів на сайті
Середня
~1-2 тижні
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Інтеграція AI-асистента для підтримки користувачів

AI-асистент для підтримки — це крок вище звичайного чат-бота. Він знає вашу документацію, базу знань та статуси конкретних користувачів. Коли користувач запитує «чому не працює експорт», асистент шукає відповідь у вашому Help Center, перевіряє тариф користувача та дає конкретну відповідь, а не шаблонну.

RAG архітектура для підтримки

RAG (Retrieval-Augmented Generation) — модель не знає ваш продукт, але при кожному запиті їй дають релевантні куски документації з векторної бази:

Запитання користувача
       ↓
Векторизація запитання (embedding)
       ↓
Пошук подібних чанків у Vector DB
       ↓
LLM отримує: запитання + контекст документації
       ↓
Відповідь на основі вашого контенту

Стек для реалізації:

Компонент Варіанти
Vector DB Pinecone, Weaviate, Qdrant, pgvector
Embeddings OpenAI text-embedding-3-small, Cohere, Ollama (self-hosted)
LLM GPT-4o-mini, Claude 3.5 Haiku
Оркестрація LangChain.js, LlamaIndex, або без фреймворка

Індексація бази знань

import OpenAI from 'openai';
import { QdrantClient } from '@qdrant/js-client-rest';

const openai = new OpenAI();
const qdrant = new QdrantClient({ url: 'http://localhost:6333' });

// Підготовка колекції
await qdrant.createCollection('support-docs', {
  vectors: { size: 1536, distance: 'Cosine' },
});

// Індексація статей
async function indexArticle(article) {
  // Розділяємо на чанки по 500 токенів з перекриттям 100
  const chunks = splitIntoChunks(article.content, { size: 500, overlap: 100 });

  const embeddings = await openai.embeddings.create({
    model: 'text-embedding-3-small',
    input: chunks.map(c => c.text),
  });

  const points = chunks.map((chunk, i) => ({
    id: generateId(),
    vector: embeddings.data[i].embedding,
    payload: {
      text: chunk.text,
      articleId: article.id,
      articleTitle: article.title,
      category: article.category,
      url: article.url,
    },
  }));

  await qdrant.upsert('support-docs', { points });
}

Пошук та генерація відповіді

async function answerQuestion(userId, question) {
  // Контекст користувача з БД
  const user = await db.users.findById(userId);
  const userContext = `
    Користувач: ${user.name}
    Тариф: ${user.plan}
    Дата реєстрації: ${user.createdAt}
    Останні 3 звернення: ${user.recentTickets.join(', ')}
  `;

  // Векторний пошук
  const queryEmbedding = await openai.embeddings.create({
    model: 'text-embedding-3-small',
    input: question,
  });

  const results = await qdrant.search('support-docs', {
    vector: queryEmbedding.data[0].embedding,
    limit: 4,
    score_threshold: 0.75, // Ігнорувати нерелевантне
  });

  const context = results.map(r =>
    `[${r.payload.articleTitle}](${r.payload.url})\n${r.payload.text}`
  ).join('\n\n---\n\n');

  // Генерація відповіді
  const response = await openai.chat.completions.create({
    model: 'gpt-4o-mini',
    stream: true,
    messages: [
      {
        role: 'system',
        content: `Ви асистент технічної підтримки.
Відповідайте ТІЛЬКИ на основі наданої документації.
Якщо відповіді немає в документації, скажіть це явно та запропонуйте створити квиток.
Завжди посилайтеся на джерело (посилання на статтю).

Контекст користувача:
${userContext}`,
      },
      {
        role: 'user',
        content: `Запитання: ${question}\n\nРелевантна документація:\n${context}`,
      },
    ],
    max_tokens: 600,
    temperature: 0.2,
  });

  return {
    stream: response,
    sources: results.map(r => ({ title: r.payload.articleTitle, url: r.payload.url })),
  };
}

Handoff до живого оператора

Коли бот не може допомогти — передача до оператора:

const ESCALATION_TRIGGERS = [
  'хочу поговорити з людиною',
  'оператор',
  'скарга',
  'повернення грошей',
  'видалити акаунт',
];

function shouldEscalate(message, confidenceScore) {
  const lowerMessage = message.toLowerCase();
  const hasKeyword = ESCALATION_TRIGGERS.some(t => lowerMessage.includes(t));
  const lowConfidence = confidenceScore < 0.6;

  return hasKeyword || lowConfidence;
}

async function handleMessage(userId, message) {
  const { answer, confidence, sources } = await answerQuestion(userId, message);

  if (shouldEscalate(message, confidence)) {
    await createSupportTicket(userId, message);
    return {
      type: 'escalation',
      message: 'Передаю ваш запит оператору. Середній час відповіді — 2 години.',
      ticketId: ticket.id,
    };
  }

  await logConversation(userId, message, answer);
  return { type: 'answer', content: answer, sources };
}

Оновлення бази знань

Коли документація оновлюється — потрібно переіндексувати:

// Webhook від CMS при оновленні статті
app.post('/webhooks/docs-updated', async (req, res) => {
  const { articleId, action } = req.body;

  if (action === 'delete') {
    await qdrant.delete('support-docs', {
      filter: { must: [{ key: 'articleId', match: { value: articleId } }] },
    });
  } else {
    const article = await fetchArticle(articleId);
    // Видаляємо старі чанки
    await qdrant.delete('support-docs', {
      filter: { must: [{ key: 'articleId', match: { value: articleId } }] },
    });
    // Переіндексуємо
    await indexArticle(article);
  }

  res.json({ ok: true });
});

Аналітика та поліпшення

Логуємо всі діалоги та збираємо зворотний зв'язок:

// Після кожної відповіді пропонуємо оцінку
function renderFeedback(messageId) {
  return (
    <div className="feedback">
      <button onClick={() => submitFeedback(messageId, 'helpful')}>Допомогло</button>
      <button onClick={() => submitFeedback(messageId, 'not-helpful')}>Не допомогло</button>
    </div>
  );
}

// Тижневий звіт: топ-20 запитань без хорошої відповіді
SELECT question, COUNT(*) as count
FROM support_conversations
WHERE feedback = 'not-helpful'
GROUP BY question
ORDER BY count DESC
LIMIT 20;

Терміни

  • RAG-асистент з базою знань (до 500 статей) — 5–7 днів
  • Персоналізація за контекстом користувача — плюс 1–2 дні
  • Handoff до оператора + система квитків — плюс 2–3 дні
  • Аналітика діалогів та дашборд — плюс 3–4 дні