AI-консьерж для отеля: система ассистента гостей
Гость пишет в WhatsApp в 23:40: «Где ближайший ресторан с видом на море, открытый сейчас?». Ресепшн занят поздними заездами. Стандартный чат-бот с кнопками вернёт меню навигации. Мы предлагаем AI-консьержа, который ответит конкретно, с учётом местоположения отеля, текущего времени и предпочтений гостя из профиля. Это решение сокращает нагрузку на front desk до 74% и повышает NPS гостей на 12 пунктов.
По данным Hospitality Tech Report, внедрение AI-консьержа снижает нагрузку на ресепшн на 70–80%.
Как работает AI-консьерж?
Система объединяет несколько источников данных: база знаний отеля (услуги, правила, инфраструктура), внешние API (погода, рестораны, достопримечательности через Google Places), PMS-система (данные о брони и госте) и история диалогов. Каждый запрос обогащается контекстом — номер, даты заезда/выезда, язык гостя, предпочтения. Используется RAG-пайплайн: извлечение релевантных фрагментов из Chroma (коллекция с embeddings от text-embedding-3-small) и генерация ответа через Claude или GPT. Для критичных запросов (жалобы, health issues) настроен fallback на живого консьержа через webhook в PMS.
Retrieval-Augmented Generation позволяет динамически подключать внешние данные без переобучения модели.
Почему RAG, а не fine-tuning?
Fine-tuning модели на Q&A отеля даёт закреплённые ответы, но не позволяет динамически подключать внешние данные (погода, отзывы, текущее расписание). RAG с Chroma и 1536-dim embeddings обрабатывает 180+ вопросов за <200 мс, поддерживает обновление контента без переобучения. Для бутик-отеля (80 номеров) затраты на инференс — $0.002 за запрос, что в 10 раз дешевле fine-tuned GPT-3.5.
Архитектура системы
Код ниже реализует ядро ассистента с инструментами извлечения информации, получения погоды, создания заявок. Используется LLM с tool use — agentic loop, который сам решает, какие инструменты вызвать.
from anthropic import Anthropic
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
import httpx
from datetime import datetime
import json
client = Anthropic()
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
class HotelConciergeAssistant:
def __init__(self, hotel_id: str, hotel_config: dict):
self.hotel_id = hotel_id
self.config = hotel_config # координаты, язык, категория отеля
self.vectorstore = Chroma(
collection_name=f"hotel_{hotel_id}_kb",
embedding_function=embeddings,
)
self.conversations: dict[str, list] = {}
self.tools = self._define_tools()
def _define_tools(self) -> list[dict]:
return [
{
"name": "search_hotel_knowledge",
"description": "Поиск информации о services, amenities, rules, events отеля",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Поисковый запрос"},
"category": {
"type": "string",
"enum": ["services", "dining", "spa", "transport", "policies", "events", "local"],
}
},
"required": ["query"],
},
},
{
"name": "get_local_recommendations",
"description": "Рекомендации ресторанов, достопримечательностей, магазинов в окрестностях",
"input_schema": {
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["restaurant", "cafe", "bar", "attraction", "museum", "shopping", "beach"],
},
"open_now": {"type": "boolean"},
"radius_meters": {"type": "integer", "default": 1000},
},
"required": ["category"],
},
},
{
"name": "get_weather",
"description": "Текущая погода и прогноз",
"input_schema": {
"type": "object",
"properties": {
"days_ahead": {"type": "integer", "default": 0},
},
},
},
{
"name": "create_service_request",
"description": "Создаёт заявку на услугу: уборка, доставка еды, трансфер, будильник",
"input_schema": {
"type": "object",
"properties": {
"service_type": {
"type": "string",
"enum": ["housekeeping", "room_service", "taxi", "wake_up_call", "luggage", "maintenance"],
},
"details": {"type": "string"},
"time": {"type": "string", "description": "ISO datetime или 'now'"},
},
"required": ["service_type"],
},
},
]
async def _execute_tool(self, tool_name: str, tool_input: dict, guest_id: str) -> str:
if tool_name == "search_hotel_knowledge":
results = self.vectorstore.similarity_search(
tool_input["query"], k=4,
filter={"category": tool_input["category"]} if tool_input.get("category") else None
)
return "\n\n".join([doc.page_content for doc in results]) or "Информация не найдена"
elif tool_name == "get_local_recommendations":
# Интеграция с Google Places API
async with httpx.AsyncClient() as http:
resp = await http.get(
"https://maps.googleapis.com/maps/api/place/nearbysearch/json",
params={
"location": f"{self.config['lat']},{self.config['lng']}",
"radius": tool_input.get("radius_meters", 1000),
"type": tool_input["category"],
"opennow": tool_input.get("open_now", False),
"language": "ru",
"key": self.config["google_places_key"],
}
)
places = resp.json().get("results", [])[:5]
return json.dumps([{
"name": p["name"],
"rating": p.get("rating"),
"address": p.get("vicinity"),
"open_now": p.get("opening_hours", {}).get("open_now"),
"price_level": p.get("price_level"),
} for p in places], ensure_ascii=False)
elif tool_name == "get_weather":
async with httpx.AsyncClient() as http:
resp = await http.get(
"https://api.openweathermap.org/data/2.5/forecast",
params={
"lat": self.config["lat"],
"lon": self.config["lng"],
"appid": self.config["openweather_key"],
"units": "metric",
"lang": "ru",
"cnt": 8 * (tool_input.get("days_ahead", 0) + 1),
}
)
data = resp.json()
forecasts = data["list"][:3]
return json.dumps([{
"time": f["dt_txt"],
"temp": f["main"]["temp"],
"description": f["weather"][0]["description"],
"wind": f["wind"]["speed"],
} for f in forecasts], ensure_ascii=False)
elif tool_name == "create_service_request":
# Отправляем в PMS через webhook
request_id = await self._send_pms_request(guest_id, tool_input)
return f"Заявка #{request_id} принята. Ожидаемое время: 15–20 минут."
return "Инструмент недоступен"
async def _send_pms_request(self, guest_id: str, service: dict) -> str:
"""Отправляет заявку в Property Management System"""
async with httpx.AsyncClient() as http:
resp = await http.post(
f"{self.config['pms_url']}/api/service-requests",
headers={"Authorization": f"Bearer {self.config['pms_token']}"},
json={
"guest_id": guest_id,
"hotel_id": self.hotel_id,
"service_type": service["service_type"],
"details": service.get("details", ""),
"requested_time": service.get("time", "now"),
"source": "ai_concierge",
}
)
return resp.json().get("request_id", "N/A")
async def chat(self, guest_id: str, message: str, guest_profile: dict) -> str:
"""Основной диалог с гостем"""
history = self.conversations.get(guest_id, [])
# Системный промпт с контекстом гостя
system = f"""Ты — виртуальный консьерж отеля «{self.config['hotel_name']}» (5 звёзд, {self.config['city']}).
Гость: {guest_profile.get('name', 'Уважаемый гость')}
Номер: {guest_profile.get('room', '?')}
Заезд: {guest_profile.get('check_in', '?')} — Выезд: {guest_profile.get('check_out', '?')}
Язык: {guest_profile.get('language', 'ru')}
Текущее время: {datetime.now().strftime('%H:%M')}
Будь внимателен, конкретен и проактивен. Предлагай релевантные услуги отеля когда уместно.
Если гость просит что-то организовать — используй инструменты для создания заявки."""
history.append({"role": "user", "content": message})
# Agentic loop с инструментами
messages = history.copy()
while True:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
system=system,
tools=self.tools,
messages=messages,
)
if response.stop_reason == "end_turn":
assistant_text = response.content[0].text
history.append({"role": "assistant", "content": assistant_text})
self.conversations[guest_id] = history[-20:] # храним 20 сообщений
return assistant_text
# Обрабатываем вызовы инструментов
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = await self._execute_tool(block.name, block.input, guest_id)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result,
})
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
Как внедрить AI-консьержа: 5 шагов
- Аудит инфраструктуры: оценка текущего PMS, каналов связи, нагрузок на ресепшн.
- Сбор базы знаний: подготовка 100–200 Q&A, описаний услуг, правил, меню.
- Настройка RAG-пайплайна: индексация в Chroma, создание embeddings.
- Интеграция каналов: подключение WhatsApp, Telegram, веб-чата через API.
- Тестирование и запуск: A/B-тестирование на малой группе гостей, затем полный rollout.
Технические детали для DevOps
Развёртывание: Kubernetes (EKS/GKE) с Triton Inference Server для LLM, vLLM для оптимизации инференса. Мониторинг: Weights & Biases для метрик accuracy, latency p99, токенов. CI/CD через GitLab CI с автоматическим обновлением базы знаний.Практический кейс: наш клиент — boutique-отель, 80 номеров
Проблема: ресепшн не справлялся с потоком однотипных вопросов в мессенджерах (WhatsApp + Telegram). 60–70% обращений — «во сколько завтрак», «есть ли парковка», «как добраться до центра». Сотрудники тратили до 12 минут на ответ в непик.
Реализация:
- База знаний отеля: 180 Q&A, описание услуг, меню ресторана — проиндексировано в Chroma с embeddings 1536-dim.
- Интеграция с Google Places API для локальных рекомендаций.
- Webhook в PMS (Opera) для создания заявок на услуги.
- WhatsApp Business API через 360dialog.
- Fallback на живого консьержа при
requires_human: true.
Результаты за 3 месяца:
| Метрика | До | После |
|---|---|---|
| Доля автоматизированных обращений | 0% | 74% |
| Среднее время ответа | 8–12 мин | 45 сек |
| Нагрузка на ночную смену | 2 ч/ночь | 0 ч |
| Оценка качества ответов (гостями) | — | 4.6/5.0 |
| NPS взаимодействовавших с AI | база +12 пунктов vs не взаимодействовавших |
Закажите демо-версию, чтобы оценить эффект на вашем отеле.
Что входит в работу: deliverables
- Полная документация архитектуры и API (OpenAPI specs).
- Исходный код модулей (LLM, RAG, интеграции).
- Развёртывание на bare-metal или в Kubernetes (Triton Inference Server, vLLM).
- Мониторинг latency p99, accuracy, safety через Weights & Biases.
- Обучение персонала (администраторы, операторы).
- Техническая поддержка 30 дней после запуска.
Типичные ошибки при внедрении
- Hallucination на редких вопросах: решается добавлением confidence threshold < 0.7 → fallback.
- Prompt injection: гость может попытаться изменить системный промпт. Защита — строгая изоляция инструкций и валидация input-фильтров.
- Overloading LLM: без rate limiting и кэширования частых запросов (“завтрак”) стоимость инференса растёт. Наше решение — кэш с TTL 5 мин на identical queries.
Сравнение AI-консьержа vs обычного чат-бота
| Параметр | Чат-бот с кнопками | AI-консьерж (RAG + LLM) |
|---|---|---|
| Понимание естественного языка | Ограниченное (intent) | Полное (NLU) |
| Персонализация | Нет | Да (профиль, история) |
| Интеграция с внешними данными | Нет | Погода, Places, PMS |
| Создание заявок | Только через UI | Голосом/текстом |
| Стоимость за 1К запросов | $0.02 (сервер) | ~$0.20 (LLM) |
| Время настройки под отель | 1–2 дня | 1–2 недели |
Сроки ориентировочно
- Базовый ассистент с FAQ + Chroma: от 1 недели.
- WhatsApp/Telegram интеграция: от 3 до 5 дней.
- Google Places + погода: от 2 до 3 дней.
- PMS-интеграция (Opera, Fidelio, Apaleo): от 1 до 2 недель.
- Полная система с аналитикой: от 4 до 6 недель.
Стоимость рассчитывается индивидуально под конфигурацию отеля. Оценим проект за 2 рабочих дня — свяжитесь с нами для аудита текущей IT-инфраструктуры. Опыт нашей команды — 5+ лет в hospitality-автоматизации и 50+ внедрённых AI-проектов. Гарантируем NDA для всех данных гостей.







