Как построить автономную 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 месяцев за счёт сокращения штата операторов.
Что входит в работу
- Аудит текущих сценариев и точек интеграции
- Проектирование архитектуры диалогового движка
- Реализация базовых сценариев (5–10 штук)
- Интеграция с каналами связи и CRM/ERP
- Настройка моделей LLM и векторизация контента
- Обучение системы на истории диалогов
- Тестирование и запуск в продакшн
- Документация и обучение вашей команды
- Поддержка на этапе стабилизации
| Этап | Длительность |
|---|---|
| Архитектура и базовый движок | 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 диалогов в день. Сертифицированные решения, полная документация и гарантия результата. Свяжитесь с нами для консультации — оценим ваш проект и предложим оптимальное решение.







