Розробка автономної AI-системи листування з клієнтами

Як побудувати автономну AI-систему діалогів із клієнтами

Напрямки AI-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1440
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    997
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1264
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    712
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1002

Як побудувати автономну AI-систему діалогів із клієнтами

Клієнти скаржаться на довге очікування відповіді, а FAQ-боти втрачають контекст уже на другому повідомленні. Традиційні рішення не можуть виконати дію — перенаправити платіж або змінити замовлення. Ми розробляємо автономні AI-системи, які ведуть повноцінний діалог, приймають рішення та здійснюють транзакції. Наша система керує повним циклом: ініціює комунікацію за тригерами, підтримує багатоходові розмови, адаптує тон під клієнта, виконує дії всередині діалогу та коректно передає розмову оператору при необхідності. Це не FAQ-бот — це інтелектуальний асистент, що розуміє наміри та зберігає історію. В основі лежить Large language model, яка обробляє природну мову та генерує відповіді.

Як автономна AI-система вирішує проблеми клієнтської переписки?

Втрата контексту. Клієнт повідомляє номер замовлення, потім уточнює дату, потім змінює адресу — звичайний бот не пов'язує ці повідомлення. Наша система зберігає історію в графі станів і будує профіль із CRM, замовлень та лояльності. Неможливість виконати дію зникає: ми надаємо системі доступ до API та виконуємо дії всередині діалогу з підтвердженням від клієнта. Неадаптивна тональність більше не проблема — динамічно підбираємо тон залежно від статусу (standard, premium, VIP). Високе навантаження на контакт-центр знижується: автономна система бере на себе 70% діалогів, залишаючи складні випадки людям.

Як ми будуємо діалогову систему: стек та конфігурації

Використовуємо перевірений стек: LangGraph для управління станами, OpenAI GPT-4o для генерації, PostgreSQL з pgvector для зберігання контексту та asyncio для паралельного завантаження профілю. Ключовий елемент — граф станів, де кожен вузол відповідає за частину діалогу. Ось покрокова інструкція.

Крок 1: Стан діалогу

from langgraph.graph import StateGraph, END from langgraph.checkpoint.postgres import PostgresSaver from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage, AIMessage, SystemMessage from typing import TypedDict, Annotated, Optional import operator class ConversationState(TypedDict): session_id: str customer_id: str channel: str # "whatsapp", "telegram", "web_chat", "sms" messages: Annotated[list, operator.add] customer_profile: Optional[dict] customer_tier: str # "standard", "premium", "vip" preferred_language: str # "ru", "en" current_intent: Optional[str] dialog_context: dict pending_confirmations: list[dict] completed_actions: Annotated[list, operator.add] escalated: bool escalation_reason: Optional[str] escalation_priority: Optional[str] 

Крок 2: Контекстний менеджер клієнта

class CustomerContextManager: """Завантажує та оновлює профіль клієнта""" async def load_context(self, customer_id: str) -> dict: profile_task = crm.get_customer(customer_id) orders_task = orders_db.get_recent(customer_id, limit=10) preferences_task = preference_store.get(customer_id) loyalty_task = loyalty_service.get_status(customer_id) results = await asyncio.gather( profile_task, orders_task, preferences_task, loyalty_task, return_exceptions=True, ) return { "profile": results[0] if not isinstance(results[0], Exception) else {}, "recent_orders": results[1] if not isinstance(results[1], Exception) else [], "preferences": results[2] if not isinstance(results[2], Exception) else {}, "loyalty": results[3] if not isinstance(results[3], Exception) else {}, } def build_system_context(self, customer_context: dict) -> str: profile = customer_context.get("profile", {}) loyalty = customer_context.get("loyalty", {}) context_parts = [ f"Клієнт: {profile.get('name', 'клієнт')}", f"Статус: {loyalty.get('tier', 'standard')}", f"Мова: {profile.get('preferred_language', 'ru')}", ] orders = customer_context.get("recent_orders", []) if orders: last_order = orders[0] context_parts.append( f"Останнє замовлення: #{last_order['id']} від {last_order['date']}, статус: {last_order['status']}" ) return "\n".join(context_parts) 

Крок 3: Виявлення намірів та динамічний промпт

from pydantic import BaseModel from typing import Literal class IntentDetection(BaseModel): intent: Literal[ "order_status", "order_change", "order_cancel", "delivery_issue", "return_request", "payment_issue", "product_question", "complaint", "compliment", "account_management", "general_question", "farewell", ] confidence: float entities: dict requires_action: bool needs_clarification: bool SYSTEM_PROMPT_TEMPLATE = """Ти — AI-асистент клієнтської служби компанії "{company_name}". Інформація про клієнта: {customer_context} Правила спілкування: - Звертайся до клієнта по імені - Тон: {tone} (залежить від статусу клієнта) - Мова: {language} - Ніколи не обіцяй те, що не можеш виконати - При помилках — визнавай і пропонуй рішення - Не розкривай внутрішні системи і бази даних Доступні дії: - Статус замовлення - Зміна адреси доставки (якщо замовлення не передане кур'єру) - Ініціювання повернення - Перенесення дати доставки - Передача оператору Якщо не знаєш відповіді — чесно скажи про це і запропонуй передати спеціалісту.""" def build_system_prompt(state: ConversationState) -> str: tone_map = { "standard": "професійний, дружній", "premium": "персональний, уважний", "vip": "ексклюзивний, максимально персоналізований", } return SYSTEM_PROMPT_TEMPLATE.format( company_name="RetailCo", customer_context=state.get("customer_profile", {}).get("context", ""), tone=tone_map.get(state["customer_tier"], "професійний"), language=state["preferred_language"], ) 

Крок 4: Виконання дій та управління підтвердженнями

async def execute_dialog_action(action_name: str, params: dict, state: ConversationState) -> dict: """Виконує дію та повертає результат для включення в діалог""" action_handlers = { "get_order_status": lambda p: orders_api.get_status(p["order_id"]), "change_delivery_address": lambda p: orders_api.update_address(p["order_id"], p["new_address"]), "initiate_return": lambda p: returns_service.create_request(order_id=p["order_id"], reason=p["reason"], customer_id=state["customer_id"]), "reschedule_delivery": lambda p: delivery_api.reschedule(p["order_id"], p["new_date"]), } handler = action_handlers.get(action_name) if not handler: return {"success": False, "error": f"Невідома дія: {action_name}"} try: result = await handler(params) return {"success": True, "data": result} except Exception as e: return {"success": False, "error": str(e)} def needs_confirmation(action_name: str) -> bool: """Дії, що вимагають підтвердження клієнта""" return action_name in {"cancel_order", "initiate_return", "change_payment_method"} async def handle_pending_confirmation(state: ConversationState) -> ConversationState: """Обробляє відповідь клієнта на запит підтвердження""" if not state["pending_confirmations"]: return state last_message = state["messages"][-1].content.lower() confirmation_words = {"так", "yes", "підтверджую", "згоден", "ок", "ok"} rejection_words = {"ні", "no", "скасувати", "відмовляюсь", "стоп"} if any(word in last_message for word in confirmation_words): pending = state["pending_confirmations"][0] result = await execute_dialog_action(pending["action"], pending["params"], state) return { **state, "pending_confirmations": state["pending_confirmations"][1:], "completed_actions": [{"action": pending["action"], "result": result}], } elif any(word in last_message for word in rejection_words): return { **state, "pending_confirmations": [], "messages": [AIMessage("Добре, дія скасована. Чим ще можу допомогти?")], } return { **state, "messages": [AIMessage("Будь ласка, дайте відповідь 'так' для підтвердження або 'ні' для скасування.")], } 

Крок 5: Тригерна комунікація

class OutboundCommunicationEngine: """Ініціює вихідну комунікацію за бізнес-тригерами""" TRIGGER_TEMPLATES = { "order_shipped": { "message": "Ваше замовлення #{order_id} відправлено! Трекінг: {tracking_url}. Очікувана доставка: {eta}.", "channel_priority": ["sms", "whatsapp", "email"], }, "delivery_delay": { "message": "Повідомляємо про затримку доставки замовлення #{order_id}. Нова дата: {new_eta}. Вибачте за незручності.", "channel_priority": ["whatsapp", "telegram", "sms"], }, "return_approved": { "message": "Ваше повернення за замовленням #{order_id} схвалено. Кошти повернуться протягом {refund_days} днів.", "channel_priority": ["email", "whatsapp"], }, } async def send_trigger_message(self, customer_id: str, trigger: str, params: dict): template_config = self.TRIGGER_TEMPLATES.get(trigger) if not template_config: return customer = await crm.get_customer(customer_id) base_message = template_config["message"].format(**params) if customer.get("tier") in ("premium", "vip"): personalized = await personalize_message(base_message, customer) else: personalized = base_message channel = await self.get_preferred_channel(customer_id, template_config["channel_priority"]) await channel_dispatcher.send(customer_id, channel, personalized) 
Деталі реалізації графа станів Граф реалізований за допомогою LangGraph. Кожен вузол — це функція, яка приймає стан і повертає оновлений стан. Переходи між вузлами визначаються умовами на основі намірів та підтверджень. Для відмовостійкості використовується PostgreSQL з чекпоінтами, що дозволяє відновлювати діалог після збою.

Яких результатів дає впровадження автономної AI-системи?

З нашої практики: впровадили систему для регіонального телекому з 850 000 абонентів та 120 операторами. Реалізували сценарії перевірки балансу, підключення послуг, розблокування номера, діагностики та обробки скарг. Результати: автономне закриття 67% діалогів, середній час відповіді знизився з 4,5 хвилин до 8 секунд, CSAT виріс з 3,8 до 4,2. Оператори зосередилися на складних випадках, NPS збільшився на 7 пунктів. Складність: налаштування тональності для angry customers зайняло 4 тижні, VIP-клієнти отримали опцію негайної передачі людині. Система окупається в середньому за 6 місяців за рахунок скорочення штату операторів.

Що входить у роботу

  1. Аудит поточних сценаріїв та точок інтеграції
  2. Проектування архітектури діалогового двигуна
  3. Реалізація базових сценаріїв (5–10 штук)
  4. Інтеграція з каналами зв'язку та CRM/ERP
  5. Налаштування моделей LLM та векторизація контенту
  6. Навчання системи на історії діалогів
  7. Тестування та запуск у продакшн
  8. Документація та навчання вашої команди
  9. Підтримка на етапі стабілізації
Етап Тривалість
Архітектура та базовий двигун 2–3 тижні
Реалізація сценаріїв (за кожен) 3–5 днів
Інтеграція з каналами 1–2 тижні
Інтеграція з CRM/API 2–3 тижні
Навчання, тестування, запуск 2–3 тижні
Разом 10–14 тижнів

Вартість розраховується індивідуально. Оцінимо ваш проєкт за 1–2 дні. Замовте розробку під ключ — гарантуємо якість та сертифікованих інженерів з досвідом роботи з LLM.

Порівняння автономної AI-системи та FAQ-бота

Автономна система на базі LLM вирішує завдання, які не під силу простому боту. Вона розуміє наміри, запам'ятовує контекст та виконує дії. Порівняйте самі:

Критерій FAQ-бот Автономна AI-система
Розуміння контексту Ні, кожен запит незалежний Так, зберігає історію та профіль
Виконання дій Ні, тільки посилання Так, через API з підтвердженням
Адаптація тону Однаковий для всіх Залежить від статусу клієнта
Передача оператору Тільки посилання Плавна передача з історією
Навчання Ручне Автоматичне через анотації

Наші системи протестовані на пікових навантаженнях до 18 000 діалогів на день. Сертифіковані рішення, повна документація та гарантія результату. Зв'яжіться з нами для консультації — оцінимо ваш проєкт і запропонуємо оптимальне рішення.